pyqt实现星三角减压启动

这个对于plc上实现是非常容易得。它本来就是逻辑控制器,如果用代码实现它,该怎么做呢?这个实现起来看似简单,实则是有不少坑的(大神除外)。我一直想用类来封装,让它继承QObject,为啥非要继承QObject,而不集成python自己的object,因为在Qobject里有自己的定时器,这样就容易实现定时功能啦。开始我想把这个类都放在一个大定时器里或线程里,发现这个会不停地执行,如果要去处理,又有加入不少逻辑,看起来很不爽。解决方案是界面里放个定时器,它的功能就是监控状态,并对状态做出处理,如更新界面,对下位机做出处理。先设计两个类Input,InOut两个类,InPut类用来接受,比如启动,停止,设置时间间隔等,Inout类用来对plc进行输出控制,代码如下:

输入类:

class InPut:
    __slots__=["start","stop","fault","interval"]
    def __init__(self,start:bool=None,stop:bool=None,fault:bool=None,timeflag:bool = None,interval:int = 3000):
        self.start: bool = start
        self.stop: bool = stop
        self.fault: bool = fault
        self.interval: bool = interval

输入输出类:

class InOut:
    def __init__(self,mainout,starout,tranout,byte:bytearray):
        '''
           :param mainout:
           :param starout:
           :param tranout:
           :param byte:
        '''
        self.__mainout = mainout
        self.__starout = starout
        self.__tranout = tranout
        self.__byte = byte
    def main_out_state(self):return self.get_bool(self.__byte,self.__mainout//8,self.__mainout%8)
    def star_out_state(self):return self.get_bool(self.__byte,self.__starout//8,self.__starout%8)
    def tran_out_state(self):return self.get_bool(self.__byte,self.__tranout//8,self.__tranout%8)

    def set_main_out(self,val):self.set_bool(self.__byte,self.__mainout//8,self.__mainout%8,val)
    def set_star_out(self,val):self.set_bool(self.__byte,self.__starout//8,self.__starout%8,val)
    def set_tran_out(self,val):self.set_bool(self.__byte,self.__tranout//8,self.__tranout%8,val)
    @staticmethod
    def get_bool(bytearray_: bytearray, byte_index: int, bool_index: int) -> bool:
        index_value = 1 << bool_index
        byte_value = bytearray_[byte_index]
        current_value = byte_value & index_value
        return current_value == index_value
    @classmethod
    def set_bool(cls,bytearray_: bytearray, byte_index: int, bool_index: int, value: bool):
        if value not in {0, 1, True, False}:
            raise TypeError(f"Value value:{value} is not a boolean expression.")
        current_value = cls.get_bool(bytearray_, byte_index, bool_index)
        index_value = 1 << bool_index

        # check if bool already has correct value
        if current_value == value:
            return
        if value:
            # make sure index_v is IN current byte
            bytearray_[byte_index] += index_value
        else:
            # make sure index_v is NOT in current byte
            bytearray_[byte_index] -= index_value

下面是降压启动类;


class Motor(QObject):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.flag = False

    def startStop(self,input:InPut,inout: InOut):
        if input.start:
            print("启动条件满足",not inout.main_out_state(),not inout.star_out_state(),not input.fault)
            if all([not inout.main_out_state(),not inout.star_out_state(),not inout.tran_out_state(),not input.fault]):
                inout.set_main_out(True)
                inout.set_star_out(True)
                inout.set_tran_out(False)
                print("星启动")

            if inout.main_out_state() and inout.star_out_state():
                self.time_id = self.startTimer(input.interval)
                self.flag = True
                print("定时器启动")
        if input.stop:
            if self.flag:
                self.killTimer(self.time_id)
            inout.set_main_out(False)
            inout.set_star_out(False)
            inout.set_tran_out(False)
            print("停止")
        self.inout = inout

    def checkState(self,input:InPut,inout: InOut):
        if input.fault:
            inout.set_main_out(False)
            inout.set_star_out(False)
            inout.set_tran_out(False)
            print("故障停止")



    def timerEvent(self, event):
        self.inout.set_star_out(False)
        self.inout.set_tran_out(True)
        self.killTimer(self.time_id)
        self.flag = False
        print("三角启动")

下面是对该类进行测试:



from PySide6.QtWidgets import *
from PySide6.QtCore import *
from snap7 import util



class Ui_Form(object):
    def setupUi(self, Form):
        if not Form.objectName():
            Form.setObjectName(u"Form")
        Form.resize(848, 447)
        self.btn_start = QPushButton(Form)
        self.btn_start.setObjectName(u"btn_start")
        self.btn_start.setGeometry(QRect(70, 50, 75, 23))
        self.btn_stop = QPushButton(Form)
        self.btn_stop.setObjectName(u"btn_stop")
        self.btn_stop.setGeometry(QRect(70, 90, 75, 23))
        self.formLayoutWidget = QWidget(Form)
        self.formLayoutWidget.setObjectName(u"formLayoutWidget")
        self.formLayoutWidget.setGeometry(QRect(420, 30, 211, 211))
        self.formLayout = QFormLayout(self.formLayoutWidget)
        self.formLayout.setObjectName(u"formLayout")
        self.formLayout.setContentsMargins(0, 0, 0, 0)
        self.lab1 = QLabel(self.formLayoutWidget)
        self.lab1.setObjectName(u"lab1")

        self.formLayout.setWidget(0, QFormLayout.FieldRole, self.lab1)

        self.lab2 = QLabel(self.formLayoutWidget)
        self.lab2.setObjectName(u"lab2")

        self.formLayout.setWidget(1, QFormLayout.FieldRole, self.lab2)

        self.lab3 = QLabel(self.formLayoutWidget)
        self.lab3.setObjectName(u"lab3")

        self.formLayout.setWidget(2, QFormLayout.FieldRole, self.lab3)

        self.lab4 = QLabel(self.formLayoutWidget)
        self.lab4.setObjectName(u"lab4")

        self.formLayout.setWidget(3, QFormLayout.FieldRole, self.lab4)


        self.retranslateUi(Form)
        self.btn_start.clicked["bool"].connect(Form.btn_start_click)
        self.btn_stop.clicked.connect(Form.btn_stop_click)

        QMetaObject.connectSlotsByName(Form)
    # setupUi

    def retranslateUi(self, Form):
        Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))
        self.btn_start.setText(QCoreApplication.translate("Form", u"START", None))
        self.btn_stop.setText(QCoreApplication.translate("Form", u"STOP", None))
        self.lab1.setText(QCoreApplication.translate("Form", u"TextLabel", None))
        self.lab2.setText(QCoreApplication.translate("Form", u"TextLabel", None))
        self.lab3.setText(QCoreApplication.translate("Form", u"TextLabel", None))
        self.lab4.setText(QCoreApplication.translate("Form", u"TextLabel", None))
    # retranslateUi


class Ui(QWidget,Ui_Form):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.bytes = bytearray(1)
        self.input = InPut()
        self.inout = InOut(0,1,2,self.bytes)
        self.motor = Motor()
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.on_timer)
        self.timer.start(200)

    def on_timer(self):
        self.motor.checkState(self.input,self.inout)

        tex1="主接触器启动" if self.inout.main_out_state() else "主接触器停止"
        self.lab1.setText(tex1)

        tex2 = "星接触器启动" if self.inout.star_out_state() else "星接触器停止"
        self.lab2.setText(tex2)

        tex3 = "三角接触器启动" if self.inout.tran_out_state() else "三角接触器停止"
        self.lab3.setText(tex3)

        tex4 = "设备正常" if not self.input.fault else "设备故障"
        self.lab4.setText(tex4)

        print(self.bytes)


    def btn_start_click(self):
        self.input.start = True
        self.input.stop = False
        self.motor.startStop(self.input,self.inout)


    def btn_stop_click(self):
        self.input.start = False
        self.input.stop = True
        self.motor.startStop(self.input, self.inout)

    def btn_main_click(self,state):
        util.set_bool(self.bytes,0,0,state)
        print("main",state)

    def btn_star_click(self,state):
        util.set_bool(self.bytes, 0, 1, state)
        self.input.timeflag = state
        print("star", state)

    def btn_tran_click(self,state):
        util.set_bool(self.bytes, 0, 2, state)
        print("tran", state)
    def le_enter_event(self):
        ...
    def btn_fault_click(self,state):
        self.input.fault=state
        print("fault",state)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)

    win = Ui()
    win.show()

    sys.exit(app.exec())





 运行结果:

上面代的motor类再次优化一下,这样更简洁。代码复制后可以直接测试

from PySide6.QtCore import QObject
class InOut:
    def __init__(self,mainout,starout,tranout,byte:bytearray):
        '''
           :param mainout:
           :param starout:
           :param tranout:
           :param byte:
        '''
        self.__mainout = mainout
        self.__starout = starout
        self.__tranout = tranout
        self.__byte = byte
    def main_out_state(self):return self.get_bool(self.__byte,self.__mainout//8,self.__mainout%8)
    def star_out_state(self):return self.get_bool(self.__byte,self.__starout//8,self.__starout%8)
    def tran_out_state(self):return self.get_bool(self.__byte,self.__tranout//8,self.__tranout%8)

    def set_main_out(self,val):self.set_bool(self.__byte,self.__mainout//8,self.__mainout%8,val)
    def set_star_out(self,val):self.set_bool(self.__byte,self.__starout//8,self.__starout%8,val)
    def set_tran_out(self,val):self.set_bool(self.__byte,self.__tranout//8,self.__tranout%8,val)
    @staticmethod
    def get_bool(bytearray_: bytearray, byte_index: int, bool_index: int) -> bool:
        index_value = 1 << bool_index
        byte_value = bytearray_[byte_index]
        current_value = byte_value & index_value
        return current_value == index_value
    @classmethod
    def set_bool(cls,bytearray_: bytearray, byte_index: int, bool_index: int, value: bool):
        if value not in {0, 1, True, False}:
            raise TypeError(f"Value value:{value} is not a boolean expression.")
        current_value = cls.get_bool(bytearray_, byte_index, bool_index)
        index_value = 1 << bool_index

        # check if bool already has correct value
        if current_value == value:
            return
        if value:
            # make sure index_v is IN current byte
            bytearray_[byte_index] += index_value
        else:
            # make sure index_v is NOT in current byte
            bytearray_[byte_index] -= index_value

class InPut:
    __slots__=["start","stop","fault","interval"]
    def __init__(self,start:bool=None,stop:bool=None,fault:bool=None,timeflag:bool = None,interval:int = 3000):
        self.start: bool = start
        self.stop: bool = stop
        self.fault: bool = fault
        self.interval: bool = interval


class Motor(QObject):
    def __init__(self,intput:InPut=None,inout:InOut=None,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.flag = False
        self.input: InPut = intput
        self.inout: InOut = inout

    def startStop(self):
        if self.input.start:
            print("启动条件满足",not self.inout.main_out_state(),not self.inout.star_out_state(),not self.input.fault)
            if all([not self.inout.main_out_state(),not self.inout.star_out_state(),not self.inout.tran_out_state(),not self.input.fault]):
                self.inout.set_main_out(True)
                self.inout.set_star_out(True)
                self.inout.set_tran_out(False)
                print("星启动")

            if self.inout.main_out_state() and self.inout.star_out_state():
                self.time_id = self.startTimer(self.input.interval)
                self.flag = True
                print("定时器启动")
        if self.input.stop:
            if self.flag:
                self.killTimer(self.time_id)
            self.inout.set_main_out(False)
            self.inout.set_star_out(False)
            self.inout.set_tran_out(False)
            print("停止")


    def checkState(self):
        if self.input.fault:
            self.inout.set_main_out(False)
            self.inout.set_star_out(False)
            self.inout.set_tran_out(False)
            print("故障停止")

    def timerEvent(self, event):
        self.inout.set_star_out(False)
        self.inout.set_tran_out(True)
        self.killTimer(self.time_id)
        self.flag = False
        print("三角启动")



from PySide6.QtWidgets import *
from PySide6.QtCore import *
from snap7 import util



class Ui_Form(object):
    def setupUi(self, Form):
        if not Form.objectName():
            Form.setObjectName(u"Form")
        Form.resize(848, 447)
        self.btn_start = QPushButton(Form)
        self.btn_start.setObjectName(u"btn_start")
        self.btn_start.setGeometry(QRect(70, 50, 75, 23))
        self.btn_stop = QPushButton(Form)
        self.btn_stop.setObjectName(u"btn_stop")
        self.btn_stop.setGeometry(QRect(70, 90, 75, 23))
        self.formLayoutWidget = QWidget(Form)
        self.formLayoutWidget.setObjectName(u"formLayoutWidget")
        self.formLayoutWidget.setGeometry(QRect(420, 30, 211, 211))
        self.formLayout = QFormLayout(self.formLayoutWidget)
        self.formLayout.setObjectName(u"formLayout")
        self.formLayout.setContentsMargins(0, 0, 0, 0)
        self.lab1 = QLabel(self.formLayoutWidget)
        self.lab1.setObjectName(u"lab1")

        self.formLayout.setWidget(0, QFormLayout.FieldRole, self.lab1)

        self.lab2 = QLabel(self.formLayoutWidget)
        self.lab2.setObjectName(u"lab2")

        self.formLayout.setWidget(1, QFormLayout.FieldRole, self.lab2)

        self.lab3 = QLabel(self.formLayoutWidget)
        self.lab3.setObjectName(u"lab3")

        self.formLayout.setWidget(2, QFormLayout.FieldRole, self.lab3)

        self.lab4 = QLabel(self.formLayoutWidget)
        self.lab4.setObjectName(u"lab4")

        self.formLayout.setWidget(3, QFormLayout.FieldRole, self.lab4)


        self.retranslateUi(Form)
        self.btn_start.clicked["bool"].connect(Form.btn_start_click)
        self.btn_stop.clicked.connect(Form.btn_stop_click)

        QMetaObject.connectSlotsByName(Form)
    # setupUi

    def retranslateUi(self, Form):
        Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))
        self.btn_start.setText(QCoreApplication.translate("Form", u"START", None))
        self.btn_stop.setText(QCoreApplication.translate("Form", u"STOP", None))
        self.lab1.setText(QCoreApplication.translate("Form", u"TextLabel", None))
        self.lab2.setText(QCoreApplication.translate("Form", u"TextLabel", None))
        self.lab3.setText(QCoreApplication.translate("Form", u"TextLabel", None))
        self.lab4.setText(QCoreApplication.translate("Form", u"TextLabel", None))
    # retranslateUi


class Ui(QWidget,Ui_Form):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.btn_fault = QPushButton("故障测试",self)
        self.btn_fault.setCheckable(True)
        self.btn_fault.move(100,200)
        self.btn_fault.clicked[bool].connect(self.btn_fault_click)

        self.bytes = bytearray(1)
        input = InPut()
        inout = InOut(0,1,2,self.bytes)
        self.motor = Motor(input,inout)
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.on_timer)
        self.timer.start(200)

    def on_timer(self):
        self.motor.checkState()

        tex1="主接触器启动" if self.motor.inout.main_out_state() else "主接触器停止"
        self.lab1.setText(tex1)

        tex2 = "星接触器启动" if self.motor.inout.star_out_state() else "星接触器停止"
        self.lab2.setText(tex2)

        tex3 = "三角接触器启动" if self.motor.inout.tran_out_state() else "三角接触器停止"
        self.lab3.setText(tex3)

        tex4 = "设备正常" if not self.motor.input.fault else "设备故障"
        self.lab4.setText(tex4)

        print(self.bytes)


    def btn_start_click(self):
        self.motor.input.start = True
        self.motor.input.stop = False
        self.motor.startStop()


    def btn_stop_click(self):
        self.motor.input.start = False
        self.motor.input.stop = True
        self.motor.startStop()




    def btn_fault_click(self,state):
        self.motor.input.fault=state
        print("fault",state)






if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)

    win = Ui()
    win.show()

    sys.exit(app.exec())





  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值