[原创]PyQT基于Modbus_tk开发Modbus上位机

4 篇文章 0 订阅

一句废话:之前说不搞PyQT了,可是python的库实在太强大,QT的界面实在太方便,二者结合,实在太牛逼,我还是继续踏实地往下做吧


Pycharm新建工程,就不细表了。安装一些依赖库,WIN+R调出cmd,输入
pip3 install modbus_tk 就OK了
但是有个问题,pip安装的库默认在python安装路径下,而Pycharm新建工程则默认去识别当前工程所在的目录包含的库。因此,会出现无法import库的情况,更改如下
在这里插入图片描述
选择Python路径作为project interpreter,一切OK

PyQT界面设计

开工,在Qt Designer下绘制UI,如下图
在这里插入图片描述
此时在工程目录下,会出现相应的ui文件,比如我的是MBcomQT.ui,右键选择PyUIC,将会在当前工程目录下,生成 MBcomQT.py:
在这里插入图片描述
大致看一下生成的文件内容:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'MBcomQT.ui'
#
# Created by: PyQt5 UI code generator 5.6
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.setEnabled(True)
        MainWindow.resize(800, 600)
        #还有很多

该py文件由ui文件自动生成,每次QT的Ui改动,记得生成一次py文件就好。
然后,在主文件中包含文件,新建窗口类包含Ui类就好。如下:

from MBcomQT import Ui_MainWindow
###
#此处省略N行无关代码
###

class MyWindow(QMainWindow,Ui_MainWindow):
    def __init__(self):
        super(MyWindow,self).__init__()
        self.inspectData = {'adcValue':0,'adcRefValue':0,'pTomValue':0,'meaPlsCnt':0,'refPlsCnt':0,'meaTRatio':0}
###
#此处再省略N行无关代码
###

最简单的测试代码可以这样写,

import sys
from MBcomQT import Ui_MainWindow
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import QtCore, QtGui

class MyWindow(QMainWindow,Ui_MainWindow):
    def __init__(self):
        super(MyWindow,self).__init__()
        self.setupUi(self)
        
if __name__ == "__main__":
    app = QApplication(sys.argv)
    myshow = MyWindow()
    myshow.show()

    print('程序终止')

    sys.exit(app.exec_())
  • 出错:
    这个时候会报错,原因是在Ui生成的py文件末尾,有rc文件的引用,而这个文件并不存在,即缺少相应的rc文件

  • 办法:
    在PyCharm的Terminal下,输入
    pyrcc5 -o MBcomSrc_rc.py MBcomSrc.qrc
    在这里插入图片描述

  • 关于UI文件中用到图标资源的几点注意(本处非必要,可略过不看)
    在这里插入图片描述
    所有的图标资源都在这里管理,点开铅笔
    在这里插入图片描述
    这几个小图标分别是:新建资源文件、打开资源文件、移除资源文件;添加前缀、添加文件、删除文件。见名知意,不再赘述。只是想说的是,这里的前缀决定了图标的索引,举个例子:
    在这里插入图片描述
    我的文件结构是,主py文件与icons文件夹并列,所有ico和png都在icons文件夹下。因此,前缀应该是./,文件路径是icons/logo.ico即从工程目录开始,以 ./icons/logo.ico来索引资源,以此类推
    到这里,软件的基本操作就算告一段落了,下面讲点业务上的事情


Modbus Python库

1. modbus_tk的基本使用
可以参考另一篇文章
python下通过modbus_tk实现modbus主机

2.业务逻辑
如前面UI所示,有端口选择框和一些pushbutton,主要有 建立连接BuidLink、观测数据InspectData、清除数据ClearData和远端加热FarHeat。这些pushbutton都连接了相应的槽函数,分别如下:

self.timeThread.oneSecondTriger.connect(self.timeUpdate)
self.pushButton_BuidLink.clicked.connect(self.MBusBuidLink)
self.pushButton_InspectData.clicked.connect(self.InspectData)
self.pushButton_ClearData.clicked.connect(self.TextBrowserClear)
self.pushButton_FarHeat.clicked.connect(self.FarHeatCtrl)

列出几个关键的函数:

def InspectData(self):
    try:
        x = self.MBusMaster.execute(35, cst.READ_HOLDING_REGISTERS, 25, 11)
        self.inspectData['adcValue']    = AddrIntToFloat(x[0],x[1])
        self.inspectData['adcRefValue'] = AddrIntToFloat(x[2],x[3])
        self.inspectData['pTomValue']   = AddrIntToFloat(x[4],x[5])
        self.inspectData['meaPlsCnt']   = (x[6] << 8)| (x[7])
        self.inspectData['refPlsCnt']   = (x[8] << 8)| (x[9])
        self.inspectData['meaTRatio']   = x[10]
        print(self.inspectData)
        self.TextBrowserAdd()
    except modbus_tk.modbus_rtu.ModbusInvalidResponseError as err:
        print(err)

以及

def FarHeatCtrl(self):
    if self.pushButton_FarHeat.text() == '远端加热':
        self.pushButton_FarHeat.setText('中断加热')
        self.label_PortHeatInfo.setText('加热中')
        self.graphicsView_Heat.setStyleSheet("background-color: rgb(255, 0, 0);")
        try:
            print(self.MBusMaster.execute(35, cst.WRITE_MULTIPLE_REGISTERS, 9, output_value=[1]))
        except modbus_tk.modbus_rtu.ModbusInvalidResponseError as err:
            print(err)
    else:
        self.pushButton_FarHeat.setText('远端加热')
        self.label_PortHeatInfo.setText('未加热')
        self.graphicsView_Heat.setStyleSheet("background-color: rgb(184, 134, 11);")
        try:
            print(self.MBusMaster.execute(35, cst.WRITE_MULTIPLE_REGISTERS, 9, output_value=[0]))
        except modbus_tk.modbus_rtu.ModbusInvalidResponseError as err:
            print(err)

着重说一下,多线程的刷新问题,关于Python多线程以及PyQT多线程,可参考这篇文章:Python多线程与PyQT多线程实例讲解
在UI中,有checkbox,这个是否勾选将决定线程是否向从机读数据。代码如下:

class MBThread(QThread):
    oneSecondTriger = pyqtSignal()

    def __init__(self):
        super(MBThread,self).__init__()

    def run(self):
        while True:
            self.oneSecondTriger.emit()
            time.sleep(1)

槽函数定义

def timeUpdate(self):
    self.label_Time.setText(time.strftime('%H:%M:%S'))
    if self.checkBox_Refresh.isChecked() == True:
        try:
            x = self.MBusMaster.execute(35, cst.READ_HOLDING_REGISTERS, 4, 2)  
            self.rh = AddrIntToFloat(x[0], x[1])
            x = self.MBusMaster.execute(35, cst.READ_HOLDING_REGISTERS, 5, 2)  
            self.t = AddrIntToFloat(x[0], x[1])
        except modbus_tk.modbus_rtu.ModbusInvalidResponseError as err:
            print(err)
    else:
        self.rh = 0
        self.t = 0

    self.label_RHValue.setText(str(round(self.rh,2)))
    self.label_TValue.setText(str(round(self.t,2)))

当然,在类内部构造函数,应该做相应的初始化工作的

self.timeThread = MBThread()
self.timeThread.oneSecondTriger.connect(self.timeUpdate)
self.timeThread.start()

好的,运行测试

细节功能就不一一展示了。

  • 收尾
    将上述工程文件打包生成exe,也是一堆坑,可参考下面这篇文章
    生成exe

好,本篇结束

  • 7
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
PyQt可以与Modbus通信,以实现在GUI界面中使用Modbus协议进行数据交互。在使用PyQt进行Modbus通信时,可以参考以下步骤: 1. 导入所需的模块和类: ``` from PyQt5.QtCore import QThread, pyqtSignal from PyQt5.QtWidgets import QMainWindow, QApplication ``` 2. 创建一个继承自QThread的线程类,用于在后台进行Modbus通信: ``` class ModbusThread(QThread): dataReceived = pyqtSignal(str) def __init__(self): super(ModbusThread, self).__init__() def run(self): # 在这里编写Modbus通信的代码 # 可以使用第三方库,如pymodbus # 接收到数据后,通过dataReceived信号发送给主线程 self.dataReceived.emit(data) ``` 3. 在主窗口类中,创建一个ModbusThread对象,并连接其dataReceived信号到一个槽函数,用于处理接收到的数据: ``` class MyWindow(QMainWindow): def __init__(self): super(MyWindow, self).__init__() self.modbusThread = ModbusThread() self.modbusThread.dataReceived.connect(self.handleData) def handleData(self, data): # 在这里处理接收到的数据 # 可以更新UI界面或进行其他操作 pass ``` 4. 在需要的地方,启动ModbusThread线程: ``` self.modbusThread.start() ``` 这样,就可以在PyQt中使用Modbus协议进行数据通信了。请注意,以上代码只是一个示例,实际使用时需要根据具体的需求进行修改和完善。 #### 引用[.reference_title] - *1* *2* *3* [[原创]PyQT基于Modbus_tk开发Modbus上位机](https://blog.csdn.net/ysgjiangsu/article/details/84633954)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值