我正在尝试循环读取寄存器值(modbus)。您能告诉我单击停止按钮后如何停止while循环吗?
这是我尝试过的,但是程序崩溃了:
import os
import struct
import sys
import time
import serial
if sys.version > "3":
import binascii
import minimalmodbus
running = 1 # Global flag
#gui
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(632, 449)
self.EXIT_btn = QtWidgets.QPushButton(Dialog)
self.EXIT_btn.setGeometry(QtCore.QRect(530, 410, 75, 23))
self.EXIT_btn.setObjectName("EXIT_btn")
self.ComChoice = QtWidgets.QSpinBox(Dialog)
self.ComChoice.setGeometry(QtCore.QRect(470, 26, 42, 22))
self.ComChoice.setObjectName("ComChoice")
self.Choice_label = QtWidgets.QLabel(Dialog)
self.Choice_label.setGeometry(QtCore.QRect(506, 20, 101, 20))
self.Choice_label.setObjectName("Choice_label")
self.ComChoice_2 = QtWidgets.QSpinBox(Dialog)
self.ComChoice_2.setGeometry(QtCore.QRect(470, 86, 42, 22))
self.ComChoice_2.setObjectName("ComChoice_2")
self.Meter_Id = QtWidgets.QLabel(Dialog)
self.Meter_Id.setGeometry(QtCore.QRect(506, 80, 101, 20))
self.Meter_Id.setObjectName("Meter_Id")
self.Volt = QtWidgets.QLabel(Dialog)
self.Volt.setGeometry(QtCore.QRect(28, 20, 60, 21))
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(True)
font.setUnderline(True)
font.setWeight(75)
self.Volt.setFont(font)
self.Volt.setObjectName("Volt")
self.lcdNumber = QtWidgets.QLCDNumber(Dialog)
self.lcdNumber.setGeometry(QtCore.QRect(30, 50, 64, 23))
self.lcdNumber.setObjectName("lcdNumber")
self.lcdNumber_2 = QtWidgets.QLCDNumber(Dialog)
self.lcdNumber_2.setGeometry(QtCore.QRect(30, 110, 64, 23))
self.lcdNumber_2.setObjectName("lcdNumber_2")
self.lcdNumber_3 = QtWidgets.QLCDNumber(Dialog)
self.lcdNumber_3.setGeometry(QtCore.QRect(30, 80, 64, 23))
self.lcdNumber_3.setObjectName("lcdNumber_3")
self.Connect_Button = QtWidgets.QPushButton(Dialog)
self.Connect_Button.setGeometry(QtCore.QRect(532, 160, 75, 23))
self.Connect_Button.setObjectName("Connect_Button")
self.Connect_Button.clicked.connect(self.start)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.EXIT_btn.setText(_translate("Dialog", "Exit"))
self.Choice_label.setText(_translate("Dialog", "בחר יציאת COM"))
self.Meter_Id.setText(_translate("Dialog", "כתובת מונה"))
self.Volt.setText(_translate("Dialog", "מתחים"))
self.Connect_Button.setText(_translate("Dialog", "התחבר"))
def start(self):
while running ==1:
#Com setup
instrument = minimalmodbus.Instrument('com4',1) # port name, slave adress
instrument.debug = True #debug
instrument.serial.baudrate = 19200 # Baud
instrument.serial.bytesize = 8
instrument.serial.parity = serial.PARITY_NONE
instrument.serial.stopbits = 1
instrument.serial.timeout = 0.05 # seconds
instrument.mode = minimalmodbus.MODE_RTU # rtu or ascii mode
clear_buffers_before_each_transaction= 'True' # clear Buffers
BYTEORDER_BIG= 'True'
v1 = instrument.read_register(1,2,3)
self.lcdNumber.display(v1)
v2 = instrument.read_register(2,2,3)
self.lcdNumber_2.display(v2)
v3 = instrument.read_register(3,2,3)
self.lcdNumber_3.display(v3)
self.EXIT_btn.clicked.connect(self.stop)
def stop(self):
global running
runnig=0
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
答案 0 :(得分:0)
您需要为此使用多线程,因为循环将无限期地运行。
本文在这里说明了如何很好地将线程实现到PyQt5中:
https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/
答案 1 :(得分:0)
由于主循环阻塞了事件循环,因此不应在主线程中运行较长的循环,在这种情况下,必须在另一个线程中执行并通过信号发送信息。
import sys
import serial
if sys.version > "3":
import binascii
import minimalmodbus
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(632, 449)
self.EXIT_btn = QtWidgets.QPushButton(Dialog)
self.EXIT_btn.setGeometry(QtCore.QRect(530, 410, 75, 23))
self.EXIT_btn.setObjectName("EXIT_btn")
self.ComChoice = QtWidgets.QSpinBox(Dialog)
self.ComChoice.setGeometry(QtCore.QRect(470, 26, 42, 22))
self.ComChoice.setObjectName("ComChoice")
self.Choice_label = QtWidgets.QLabel(Dialog)
self.Choice_label.setGeometry(QtCore.QRect(506, 20, 101, 20))
self.Choice_label.setObjectName("Choice_label")
self.ComChoice_2 = QtWidgets.QSpinBox(Dialog)
self.ComChoice_2.setGeometry(QtCore.QRect(470, 86, 42, 22))
self.ComChoice_2.setObjectName("ComChoice_2")
self.Meter_Id = QtWidgets.QLabel(Dialog)
self.Meter_Id.setGeometry(QtCore.QRect(506, 80, 101, 20))
self.Meter_Id.setObjectName("Meter_Id")
self.Volt = QtWidgets.QLabel(Dialog)
self.Volt.setGeometry(QtCore.QRect(28, 20, 60, 21))
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(True)
font.setUnderline(True)
font.setWeight(75)
self.Volt.setFont(font)
self.Volt.setObjectName("Volt")
self.lcdNumber = QtWidgets.QLCDNumber(Dialog)
self.lcdNumber.setGeometry(QtCore.QRect(30, 50, 64, 23))
self.lcdNumber.setObjectName("lcdNumber")
self.lcdNumber_2 = QtWidgets.QLCDNumber(Dialog)
self.lcdNumber_2.setGeometry(QtCore.QRect(30, 110, 64, 23))
self.lcdNumber_2.setObjectName("lcdNumber_2")
self.lcdNumber_3 = QtWidgets.QLCDNumber(Dialog)
self.lcdNumber_3.setGeometry(QtCore.QRect(30, 80, 64, 23))
self.lcdNumber_3.setObjectName("lcdNumber_3")
self.Connect_Button = QtWidgets.QPushButton(Dialog)
self.Connect_Button.setGeometry(QtCore.QRect(532, 160, 75, 23))
self.Connect_Button.setObjectName("Connect_Button")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.EXIT_btn.setText(_translate("Dialog", "Exit"))
self.Choice_label.setText(_translate("Dialog", "בחר יציאת COM"))
self.Meter_Id.setText(_translate("Dialog", "כתובת מונה"))
self.Volt.setText(_translate("Dialog", "מתחים"))
self.Connect_Button.setText(_translate("Dialog", "התחבר"))
class Dialog(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.setupUi(self)
self.Connect_Button.clicked.connect(self.start)
self.EXIT_btn.clicked.connect(self.stop)
self.m_thread = QtCore.QThread(self)
self.m_thread.start()
self.m_modbus_worker = ModbusWorker()
self.m_modbus_worker.dataChanged.connect(self.on_dataChanged)
self.m_modbus_worker.moveToThread(self.m_thread)
@QtCore.pyqtSlot()
def start(self):
QtCore.QTimer.singleShot(0, self.m_modbus_worker.do_work)
@QtCore.pyqtSlot()
def stop(self):
self.m_thread.requestInterruption()
@QtCore.pyqtSlot(list)
def on_dataChanged(self, values):
for w, value in zip((self.lcdNumber, self.lcdNumber_2, self.lcdNumber_3), values):
w.display(value)
def closeEvent(self, event):
super(Dialog, self).closeEvent(event)
self.stop()
self.m_thread.quit()
self.m_thread.wait()
class ModbusWorker(QtCore.QObject):
dataChanged = QtCore.pyqtSignal(list)
@QtCore.pyqtSlot()
def do_work(self):
instrument = minimalmodbus.Instrument("com4", 1) # port name, slave adress
instrument.debug = True # debug
instrument.serial.baudrate = 19200 # Baud
instrument.serial.bytesize = 8
instrument.serial.parity = serial.PARITY_NONE
instrument.serial.stopbits = 1
instrument.serial.timeout = 0.05 # seconds
instrument.mode = minimalmodbus.MODE_RTU # rtu or ascii mode
clear_buffers_before_each_transaction = "True" # clear Buffers
BYTEORDER_BIG = "True"
while not QtCore.QThread.currentThread().isInterruptionRequested():
data = [instrument.read_register(i + 1, 2, 3) for i in range(3)]
self.dataChanged.emit(data)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())