0


基于PyQT5解析串口数据并通过GUI显示应用开发-Python

解析串口数据并通过GUI显示应用开发-Python

​ 本片文章主要介绍如何通过Python开发一款UI界面的应用,该应用能实现对来自串口数据的接收和解析,将解析后的数据显示在UI界面上,同时实现数据帧接收频率的计算与超时接收的监测。环境:PyCharm Community Edition 2021.2、Python 3.7.6(高版本在安装pyqt5-tools是会出现报错)

在这里插入图片描述

一、GUI绘制

1.1、安装UI设计的第三方库

首先安装PyQT5,可以在window的命令提示符从清华源进行安装

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple PyQT5

再安装pyqt5-tools包,这个第三方库包含qtdesinger工具

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyqt5-tools

在这里插入图片描述

1.2、在Pycharm中配置外部工具环境

  • 先点击Pycharm右上角的齿轮按键,进入设置页面

在这里插入图片描述

  • 在工具->外部工具->“+”图标,添加外部工具

在这里插入图片描述

添加qtdesinger工具(绘制ui文件),变量配置如下

在这里插入图片描述

D:\APP\Python3.7.6\Lib\site-packages\qt5_applications\Qt\bin\designer.exe  (这个找到自己designer.exe所在的目录)
$FileDir$\$FileName$
$FileDir$

同样添加pyuic5工具(将制作的ui文件,转化成Py文件),变量配置如下

D:\APP\Python3.7.6\Scripts\pyuic5.exe   (这个找到自己pyuic5.exe所在的目录)
$FileName$ -o $FileNameWithoutExtension$.py
$FileDir$

最后添加pyrcc工具,变量配置如下

D:\APP\Python3.7.6\Scripts\pyuic5.exe    (这个找到自己pyuic5.exe所在的目录)
$FileName$ -o $FileNameWithoutExtension$.py ,working directory:$FileDir$
D:\APP\Python3.7.6\Scripts                (这个找到自己py安装的目录)

1.3、利用qtdesinger绘制UI界面

首先从 工具->External Tools->qtdesinger,启动qtdesinger

在这里插入图片描述

可以创建一个Main Window窗口,在窗口内部绘制UI界面

在这里插入图片描述

这里就不具体地用文字描述整个ui界面的搭建过程,就简单介绍一下整个界面和需要使用的组件,以及需要修改的属性。QT Desinger的界面如下,上方是一些调整组件布局的工具;左侧是ui界面上的一些组件(按键、标签、文本框之类的);可以将左侧的组件拖到中间的界面,然后通过上方的布局工具,调整这些工具的位置;当选中一个组件后,可以通过右侧的属性框,修改组件的一些属性(这里建议把所有组件的Name都改一下,方便后面程序设计好找到对应的组件)

在这里插入图片描述

将设计好的ui文件保存到工程所在的目录下面

1.4、测试UI界面

右击ui文件 -> External Tools -> pyuic5,将刚刚保存的ui文件转成py文件
在这里插入图片描述

在生成的py文件后面添加如下程序,

if __name__ =="__main__":import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = Ui_MainInfo()# 这里需要根据自己的ui类名称进行修改
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

右击运行该文件的结果

在这里插入图片描述

二、串口数据接收与解析

2.1、安装串口第三方库

Python使用串口需要安装pyserial库

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyserial

2.2、串口的使用

测试用例

import serial#导入串口通信库from time import sleep

ser = serial.Serial()defport_open_recv():#对串口的参数进行配置
    ser.port='com3'
    ser.baudrate=9600
    ser.bytesize=8
    ser.stopbits=1
    ser.parity="N"#奇偶校验位
    ser.open()if(ser.isOpen()):print("串口打开成功!")else:print("串口打开失败!")#isOpen()函数来查看串口的开闭状态defport_close():
    ser.close()if(ser.isOpen()):print("串口关闭失败!")else:print("串口关闭成功!")defsend(send_data):if(ser.isOpen()):
        ser.write(send_data.encode('utf-8'))#编码print("发送成功",send_data)else:print("发送失败!")if __name__ =='__main__':
    port_open_recv()whileTrue:
        a=input("输入要发送的数据:")
        send(a)
        sleep(0.5)#起到一个延时的效果,这里如果不加上一个while True,程序执行一次就自动跳出了

常用接口函数

ser.isOpen():查看端口是否被打开。
ser.open() :打开端口‘。
ser.close():关闭端口。
ser.read():从端口读字节数据。默认1个字节。
ser.read_all():从端口接收全部数据。
ser.write("hello"):向端口写数据。
ser.readline():读一行数据。
ser.readlines():读多行数据。
in_waiting():返回接收缓存中的字节数。
flush():等待所有数据写出。
flushInput():丢弃接收缓存中的所有数据。
flushOutput():终止当前写操作,并丢弃发送缓存中的数据。

2.3、数据帧的解析

数据帧的内容如下,一共有12个数据,我们需要获取以逗号分割,等号后面的数据。所以提出数据的思路就不难看出,先将字符串以逗号分割生成12个列表(每个列表的内容也是字符串),再对每个列表的内容以等于号进行分割,取等号后面的内容,具体实现程序如下。

sen1_d=6553,sen2_d=69,sen3_d=23,sen4_d=6553,sen5_d=49,sen6_d=23,sen7_d=6553,sen8_d=31,sen9_d=142,sen10_d=6553,sen11_d=21,sen12_d=6553
defprocess(message:str):
    res =list()if message.count("=")==12:
        message_list = message.split(",")for x in message_list :
            res.append(x.split("=")[1])return res

if __name__ =="__main__":
    test ="sen1_d=6553,sen2_d=69,sen3_d=23,sen4_d=6553,sen5_d=49,sen6_d=23,sen7_d=6553,sen8_d=31,sen9_d=142,sen10_d=6553,sen11_d=21,sen12_d=6553"
    res_list = process(test)print(len(res_list))print(res_list)

三、多任务创建

3.1、启动UI界面

创建main.py文件,所需的第三方库,以及自己创建的ui界面和数据帧处理函数

import sys
import time
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from MainInfo import Ui_MainInfo
import serial#导入串口通信库
import data_process

创建自己的ui界面类,该类需要继承

QMainWindow

类和自己设计

Ui_MainInfo

类,并在初始化函数定义自己需要使用的变量、通过连接槽关联两个线程(串口接收数据线程、监测是否超时线程)以及按键连接函数的具体实现,具体程序实现如下:

classMyMainForm(QMainWindow, Ui_MainInfo):def__init__(self, parent=None):super(MyMainForm, self).__init__(parent)
        self.setupUi(self)# 定义变量
        self.com ="com3"
        self.baud =115200
        self.switch_state =bool(0)
        self.count =0# 计算两个有效数据帧的时间差
        self.start_time = time.time()
        self.end_time = time.time()
        self.time =0
        self.receive_message =""# 监测串口已打开时,多长时间没有手有效数据帧
        self.check_time_start = time.time()
        self.check_time_end = time.time()
        self.limit_time =6.0
        self.check =0# 连接槽关联连接按键
        self.connect_button.clicked.connect(self.connection_button_cliked)
        self.set_limit_time_button.clicked.connect(self.set_limit_time)# 连接槽关联线程
        self.thread = process_task()
        self.thread.start()
        self.thread.sig.connect(self.update_info)
        self.check_thread = check_task()
        self.check_thread.start()# 显示默认参数
        self.com_value.setText(f"{self.com}")
        self.baud_value.setText(f"{self.baud}")
        self.limit_time_value.setText(f"{self.limit_time}")defupdate_info(self,info):
        self.receive_message = info
        temp_list = data_process.process(self.receive_message)iflen(temp_list)==12:print(self.receive_message)
            self.end_time = time.time()
            self.time = self.end_time - self.start_time
            if self.count ==0:
                self.count =1else:
                self.fps_value.setText(str(self.time))
            self.f1_value.setText(temp_list[5])
            self.f2_value.setText(temp_list[4])
            self.f3_value.setText(temp_list[3])
            self.f4_value.setText(temp_list[2])
            self.f5_value.setText(temp_list[1])
            self.f6_value.setText(temp_list[0])
            self.r1_value.setText(temp_list[11].split('\\')[0])
            self.r2_value.setText(temp_list[10])
            self.r3_value.setText(temp_list[9])
            self.r4_value.setText(temp_list[8])
            self.r5_value.setText(temp_list[7])
            self.r6_value.setText(temp_list[6])
            self.start_time = time.time()
            self.check_time_start = time.time()
            self.check =1# print(f"context:{self.receive_message},type = {type(self.receive_message)}")defconnection_button_cliked(self):if self.switch_state ==0:
            self.connect_button.setText("断开")
            self.baud =int(self.baud_value.text())
            self.com =str(self.com_value.text())
            self.message.append(f"com:{self.com},baud:{self.baud}")
            port_open_recv(self.com,self.baud)
            self.message.append("Connected")
            self.check =0else:
            self.connect_button.setText("连接")
            ser.close()
            self.message.append("Disconnect")
        self.switch_state =bool(1- self.switch_state)defset_limit_time(self):
        self.limit_time =float(self.limit_time_value.text())
        self.message.append(f"下限时间修改为:{self.limit_time}")

然后在

if __name__ == "__main__":

实例化

MyMainForm

对象并启动界面

if __name__ =="__main__":#固定的,PyQt5程序都需要QApplication对象。sys.argv是命令行参数列表,确保程序可以双击运行
    app = QApplication(sys.argv)#初始化
    myWin = MyMainForm()# 将窗口控件显示在屏幕上
    myWin.show()# 程序运行,sys.exit方法确保程序完整退出。
    sys.exit(app.exec_())

3.2、创建串口接收任务

MyMainForm

类的初始化函数中已经连接并启动了

process_task

线程,这里就需要具体实现

process_task

的内容,首先

process_task

类需要继承

QThread

类,并重写

run

函数,在

run

函数中实现自己设计的功能,具体程序实现如下:

classprocess_task(QThread):
    sig = pyqtSignal(str)def__init__(self, parent=None):super(process_task, self).__init__(parent)
        self.receistr =" "defrun(self):# 需要执行的内容whileTrue:
            time.sleep(0.01)# 提供读取串口是否被打开时间,以免闪退if ser.isOpen():
                self.receistr = ser.readline()# 发出信号
                self.sig.emit(str(self.receistr))else:pass

3.3、创建接收超时监测任务

超时监测任务的创建方式和串口接收数据的任务创建方式相同,需要在

run

函数里面具体实现自己的功能,这里我是在run函数里面判断串口是否打开,如果打开则开始监测时间,如果实现超过设定的时间,则在ui界面给出相应的提示。

classcheck_task(QThread):def__init__(self, parent=None):super(check_task, self).__init__(parent)defrun(self):# 需要执行的内容whileTrue:
            time.sleep(0.01)# 提供读取串口是否被打开时间,以免闪退if ser.isOpen():# 监测时间
                myWin.check_time_end = time.time()if myWin.check_time_end - myWin.check_time_start > myWin.limit_time :if myWin.check ==1:
                        myWin.message.append("接收超时")
                        myWin.check_time_start = time.time()else:pass

四、将py文件转为exe文件

4.1、安装第三方工具库

py文件转为exe文件需要依赖pyinstaller第三方库实现,所以首先通过命令输入以下命令安装第三方库

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyinstaller

4.2、执行命令生成exe文件

第三方库安装完成后,通过命令行进入py文件所在目录,然后执行一下命令

在这里插入图片描述

pyinstaller -F main.py
# 依据自己的py文件名

然后可以在工程文件的dist目录下找到刚才生成的exe文件

在这里插入图片描述

然后双击可以正常运行

在这里插入图片描述

标签: python qt PyQT5

本文转载自: https://blog.csdn.net/qq_46384359/article/details/127296683
版权归原作者 ViTO_2001 所有, 如有侵权,请联系我们删除。

“基于PyQT5解析串口数据并通过GUI显示应用开发-Python”的评论:

还没有评论