基于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)

相关推荐

  • PyQt5+serial模块实现一个串口小工具

    目录 串口简述 serial模块 参数 方法 使用模板 串口工具示例 串口简述 异步串行是指UART(Universal Asynchronous Receiver/Transmitter),通用异步接收/发送.UART是一个并行输入成为串行输出的芯片,通常集成在主板上.UART包含TTL电平的串口和RS232电平的串口. TTL电平是3.3V的,而RS232是负逻辑电平,它定义+5+12V为低电平,而-12-5V为高电平,MDS2710.MDS SD4.EL805等是RS232接口,EL806

  • PyQt5使用pyqtgraph绘制波形图

    目录 主程序代码 UI界面设计 控件提升 UI设计文件 UI生成文件 运行效果 主程序代码 import sys import numpy as np from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import * import pyqtgraph as pg from ui_demo02 import Ui_MainWindow class GraphDemowWindow(QMainWind

  • Python PyQt5中窗口数据传递的示例详解

    目录 单一窗口数据传递 多窗口数据传递:调用属性 多窗口数据传递:信号与槽 开发应用程序时,若只有一个窗口则只需关心这个窗口里面的各控件之间如何传递数据.如果程序有多个窗口,就要关心不同的窗口之间是如何传递数据. 单一窗口数据传递 对于单一窗口的程序来说,一个控件的变化会影响另一个控件的变化通过信号与槽的机制就可简单解决. import sys from PyQt5.QtWidgets import QWidget, QLCDNumber, QSlider, QVBoxLayout, QAppl

  • 基于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

  • 基于PyQt5制作一个数据图表生成器

    我的需求:手动配置X轴.Y轴.图表标题等参数自动通过Pyecharts模块生成可视化的html数据图表,并将浏览器图表展示到UI界面上. 制作出图表后的效果展示如下: 另外,生成后的图表结果会使用 html 的形式保存下来. 导入 UI 界面相关的 PyQt5 第三方模块库. from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * 若是使用PyQt5的版本是5.10.1以上,则需要单独安

  • 基于PyQT5制作一个课堂点名系统

    刷抖音的时候发现一个老师在用的课堂点名系统.用PyQt5实现了一下同款,导入学生姓名,测试了一下完美运行. 操作效果展示: 完整源代码块还是放在了文章的最后面 使用的时候准备好学生姓名的文件,使用导入数据的按钮直接导入就可以开始点名了.新建一个文本文档,将姓名设置设置好,姓名文件示例如下. 使用系统库或者第三方库都比较常规,这里就不一一介绍了. from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore im

  • 基于PyQt5制作一个动态指针时钟

    想实现这样一个功能,然后pyqt5中又没有现成的组件可以使用,于是就想着只能通过绘图的方式来实现.说到绘图的话,turtle框架无疑是最常见的选择,但其实通过pyqt5的QPainter组件也是可以实现的.而且最后呈现出来的效果还是挺漂亮的. 实现思路:通过使用pyqt5的QPainter组件来绘制好时钟的图表,最后通过定时器不断的改变当前当前时间在图表上面的显示位置.这样最终就实现了一个指针时钟在不断的走动的过程. 和前面的UI应用一样,我们用到的UI相关的组件库还是这三个. from PyQ

  • 基于Python实现一个简易的数据管理系统

    目录 创建mysql数据表 增删改查 启动应用  为了方便的实现记录数据.修改数据没有精力去做一个完整的系统去管理数据.因此,在python的控制台直接实现一个简易的数据管理系统,包括数据的增删改查等等.只需要在控制台层面调用相应的功能调用查询.修改等功能,这里记录一下实现过程. 创建mysql数据表 使用比较熟悉的数据库客户端来进行操作,这里使用的是navicate客户端来创建好相应的数据表. 创建数据库并指定编码字符集. CREATE DATABASE `data_boc` CHARACTE

  • 基于PyQT5制作一个二维码生成器

    个性化二维码的exe桌面应用的获取方式我放在文章最后面了,注意查收.通过执行打包后的exe应用程序可以直接运行生成个性化二维码. 开始之前先来看一下通过二维码生成器是如何生成个性化二维码的. 其中使用的python包和之前的GUI应用制作使用的模块是一样的. # -*- coding:utf-8 -*- import os import sys from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore im

  • 基于PyQt5制作一个gif动态图片生成器

    这个小工具制作的目的是为了将多张图片组合后生成一张动态的GIF图片.设置界面化的操作,只需要将选中的图片导入最后直接生成动态图片. 导入界面相关的第三方库 from PyQt5.QtWidgets import * from PyQt5.QtGui import * 动态图片处理模块 import imageio 应用操作相关库 import sys import os from datetime import datetime 这是用图片生成器生成的一张GIF图片,大家在生成时尽量选择两张大小

  • 基于PyQt5制作一个windows通知管理器

    前几天看到一个python框架win10toast,它可以用来做windows的消息通知功能.通过设定通知的间隔时间来实现一些事件通知的功能,比如可以可以提醒一头扎进代码编写过程的我们按时喝水. 界面布局采用的依旧是pyqt5的ui设计,使用界面化直接设置好想要提示的内容和时间就可以给我们定时的发通知了. UI相关的部分的还是这几个常用的组件包. from PyQt5.QtGui import * # UI 界面相关 from PyQt5.QtCore import * # 核心组件包 from

  • 基于PyQT5制作一个敏感词检测工具

    设计思路:根据敏感词库文件筛选,查看输入的文本中是否包含敏感词汇.从而过滤出相关的敏感词. 导入应用相关的模块. import os import logging import sys 导入UI界面相关的模块. from PyQt5.QtWidgets import QApplication,QWidget,QVBoxLayout,QTextEdit,QGridLayout,QLineEdit,QPushButton,QFileDialog from PyQt5.QtGui import QIc

  • 基于PyQT5制作一个桌面摸鱼工具

    目录 前言 按键功能控制 主要功能 核心代码 前言 现在我能一整天都严肃地盯着屏幕,看起来就像在很认真地工作, 利用摸鱼,打开小说,可实行完美摸鱼,实时保存进度 用PYQT5 Mock一个摸鱼软件 类似于Thief 按键功能控制 q 退出 B 书签功能 F 增加字体大小 Shift F 减小字体 O 打开文件,现在仅仅支持 utf8格式的txt文件 主要功能 FlameLess Window 无边框窗口 一键快速退出 ini 文件读写 右键上下文菜单 核心代码 pyqt 实现功能还是比较顺畅的,

随机推荐