基于PyQt5实现一个串口接数据波形显示工具
目录
- 工具简述
- 主程序代码
- Qt Designer设计UI界面
- 程序运行效果
工具简述
基于PyQt5开发UI界面使用QtDesigner设计,需要使用到serial模块(串口库)和pyqtgraph(图形库)。上位机通过串口接收来自MCU发送数据,解析出每一个数据项并以波形图的方式显示。本例程下位机是Raspberry Pi Pico发送HMC5883L地磁模块数据,数据项有x,y,z,h等,数据格式’$$:x,y,z,h’。
主程序代码
import sys import numpy as np from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import * import serial import serial.tools.list_ports from ui_main import Ui_MainWindow import pyqtgraph as pg class AppMainWindow(QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super(AppMainWindow, self).__init__(parent) self.setupUi(self) self.setWindowTitle("串口数据波形显示工具") self.PosX = 0 self.dataIndex = 0 # 数据列表当前索引 self.dataMaxLength = 10000 # 数据列表最大长度 self.dataheader = b'$$:' # 数据帧开头 self.dataX = np.zeros(self.dataMaxLength, dtype=float) self.dataY = np.zeros(self.dataMaxLength, dtype=float) self.dataZ = np.zeros(self.dataMaxLength, dtype=float) self.dataH = np.zeros(self.dataMaxLength, dtype=float) self.mSerial = serial.Serial() self.ScanComPort() self.SelectComPort() self.btnScanPort.clicked.connect(self.ScanComPort) self.btnOpenPort.clicked.connect(self.OpenComPort) self.btnClosePort.clicked.connect(self.CloseComPort) self.cmbComPort.currentIndexChanged.connect(self.SelectComPort) self.mTimer = QTimer() self.mTimer.timeout.connect(self.ReceiverPortData) self.plotM.setAntialiasing(True) # self.plotM.setBackground() self.canvasX = self.plotM.plot(self.dataX, pen=pg.mkPen(color='r', width=1)) self.canvasY = self.plotM.plot(self.dataY, pen=pg.mkPen(color='g', width=1)) self.canvasZ = self.plotM.plot(self.dataZ, pen=pg.mkPen(color='b', width=1)) self.canvasH = self.plotM.plot(self.dataH, pen=pg.mkPen(color='y', width=1)) def ScanComPort(self): self.cmbComPort.clear() self.portDict = {} portlist = list(serial.tools.list_ports.comports()) for port in portlist: self.portDict["%s" % port[0]] = "%s" % port[1] self.cmbComPort.addItem(port[0]) if len(self.portDict) == 0: QMessageBox.critical(self, "警告", "未找到串口设备!", QMessageBox.Cancel, QMessageBox.Cancel) pass def SelectComPort(self): if len(self.portDict) > 0 : self.labComPortName.setText(self.portDict[self.cmbComPort.currentText()]) else: self.labComPortName.setText("未检测到串口设备!") pass def OpenComPort(self): self.mSerial.port = self.cmbComPort.currentText() self.mSerial.baudrate = int(self.cmbBaudrate.currentText()) if self.mSerial.isOpen(): QMessageBox.warning(self, "警告", "串口已打开", QMessageBox.Cancel, QMessageBox.Cancel) else: try: self.btnOpenPort.setEnabled(False) self.mSerial.open() self.mSerial.flushInput() self.mSerial.flushOutput() self.mTimer.start(1) except: QMessageBox.critical(self, "警告", "串口打开失败!", QMessageBox.Cancel, QMessageBox.Cancel) self.btnOpenPort.setEnabled(True) print(self.mSerial) pass def CloseComPort(self): self.mTimer.stop() if self.mSerial.isOpen(): self.btnOpenPort.setEnabled(True) self.mSerial.flushInput() self.mSerial.flushOutput() self.mSerial.close() pass def ReceiverPortData(self): ''' 接收串口数据,并解析出每一个数据项更新到波形图 数据帧格式'$$:95.68,195.04,-184.0\r\n' 每个数据帧以b'$$:'开头,每个数据项以','分割 ''' try: n = self.mSerial.inWaiting() except: self.CloseComPort() if n > 0: # 端口缓存内有数据 try: self.recvdata = self.mSerial.readline(1024) # 读取一行数据最大长度1024字节 if self.recvdata.decode('UTF-8').startswith(self.dataheader.decode('UTF-8')): rawdata = self.recvdata[len(self.dataheader) : len(self.recvdata) - 2] data = rawdata.split(b',') # print(rawdata) if self.dataIndex < self.dataMaxLength: # 接收到的数据长度小于最大数据缓存长度,直接按索引赋值,索引自增1 # print(rawdata, rawdata[0], rawdata[1], rawdata[2], self.dataX[self.dataIndex], self.dataY[self.dataIndex], self.dataZ[self.dataIndex]) self.dataX[self.dataIndex] = float(data[0]) self.dataY[self.dataIndex] = float(data[1]) self.dataZ[self.dataIndex] = float(data[2]) self.dataH[self.dataIndex] = float(data[3]) self.dataIndex = self.dataIndex + 1 else: # 寄收到的数据长度大于或等于最大数据缓存长度,丢弃最前一个数据新数据添加到数据列尾 self.dataX[:-1] = self.dataX[1:] self.dataY[:-1] = self.dataY[1:] self.dataZ[:-1] = self.dataZ[1:] self.dataH[:-1] = self.dataH[1:] self.dataX[self.dataIndex - 1] = float(data[0]) self.dataY[self.dataIndex - 1] = float(data[1]) self.dataZ[self.dataIndex - 1] = float(data[2]) self.dataH[self.dataIndex - 1] = float(data[3]) # 更新波形数据 self.canvasX.setData(self.dataX) self.canvasY.setData(self.dataY) self.canvasZ.setData(self.dataZ) self.canvasH.setData(self.dataH) # self.canvasX.setPos(self.PosX, 0) # self.canvasY.setPos(self.PosX, 0) # self.canvasZ.setPos(self.PosX, 0) except: pass pass def SendPortData(self): pass if __name__ == "__main__": app = QApplication(sys.argv) win = AppMainWindow() win.show() sys.exit(app.exec_())
Qt Designer设计UI界面
程序运行效果
到此这篇关于基于PyQt5实现一个串口接数据波形显示工具的文章就介绍到这了,更多相关PyQt5数据波形显示工具内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
赞 (0)