【PyQt5】串口数据实时绘图

常见的串口调试助手一般只有简单的文本界面,偶然看到 Arduino IDE 自带的串口绘图工具,觉得用户设计挺友好。想着利用一下周末空闲时间,用 PyQt5 实现一个串口数据实时绘图小工具,在这里记录一下。

目录

1 用户界面

2 串口通信

3 实时绘图


1 用户界面

        使用 Qt Designer 可以快速地设计用户界面,界面主体是绘制曲线的区域,下面放置两个 ComboBox,分别用于设置串口号和波特率,然后在右下角放一个按钮。

        波特率下拉框勾选 editable,以支持自定义波特率,然后添加一些 ComboBox 项目,使用预览模式修改字体样式。

        保存 ui 文件,使用 pyuic 工具进行转换。接着创建新的 py 文件,调用 setupUi() 函数实现 ui 界面。

from PyQt5 import Qt, QtGui, QtCore, QtWidgets
from ui_SerialPlot import Ui_Form


class SerialPlot(Qt.QWidget):
    def __init__(self):
        super().__init__()
        self.ui = Ui_Form()
        self.ui.setupUi(self)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = SerialPlot()
    window.show()
    sys.exit(app.exec_())

2 串口通信

        串口通信部分用到了 QSerialPort 和 QSerialPortInfo,使用以下语句导入:

from PyQt5.QtSerialPort import QSerialPort, QSerialPortInfo

在启动程序的时候,遍历一次串口信息,然后使用 addItem() 函数添加识别到的串口号到 ComboBox 中。

def __init__(self):
    # ...

    # 定义串口对象
    self.COM = QSerialPort()
    self.port_list = QSerialPortInfo.availablePorts()

    # 读取串口信息,并选择第一个串口
    for com_port in self.port_list:
        self.ui.comport_comboBox.addItem(com_port.portName())
    self.COM.setPortName(self.port_list[0].portName())

    # 设置回调函数
    self.ui.comport_comboBox.activated[str].connect(self.on_comport_changed)
    self.ui.baudrate_comboBox.activated[str].connect(self.on_baudrare_changed)

    # ...

def on_comport_changed(self, com_port):
    self.COM.setPortName(com_port)

def on_baudrare_changed(self, baud_item):
    baud_rate = int(baud_item.split(' ')[0])
    self.COM.setBaudRate(baud_rate)

定义 on_pushbutton 函数,用于打开和关闭串口, 使用定时器每隔 100ms 读取一次串口数据。

def __init__(self):
    # ...

    # 串口相关
    self.open_status = 'closed'
    self.timer = QtCore.QTimer()
    self.timer.timeout.connect(self.on_timeout)
    self.ui.pushButton.clicked.connect(self.on_pushbuton)

    # ...

def on_pushbutton(self):
    if self.open_status == 'closed':
        if not self.COM.open(QSerialPort.ReadWrite):
            return
        self.timer.start(100)
        self.ui.pushButton.setText('STOP')
        self.open_status = 'opened'
    else:
        self.COM.close()
        self.timer.stop()
        self.ui.pushButton.setText('START')
        self.open_status = 'closed'

def on_timeout(self):
    rcv_data = self.COM.readAll()
    if len(rcv_data) >= 2:
        print(int.from_bytes(bytes(rcv_data[0:2]), 'little'))

3 实时绘图

        绘图部分用到了 pyqtgraph 库,使用以下语句导入:

import pyqtgraph as pg

在 __init__() 函数中定义 xdata 和 ydata,分别记录横轴和纵轴数据,并创建 PlotWidget 绘图控件到主窗口中。

def __init__(self):
    # ...

    # 创建 PlotWidget 对象
    self.plotwidget = pg.PlotWidget(self, background='w')
    self.plotwidget.setGeometry(QtCore.QRect(10, 10, 480, 270))

    # 曲线相关
    self.xdata = []
    self.ydata = []
    self.time = 0
    self.pen = pg.mkPen(color='#bc5001', width=2)
    self.curve = self.plotwidget.Plot(self.xdata, self.ydata, pen=self.pen)

    # ...

最后修改之前的 on_timeout() 函数,更新曲线数据。

def on_timeout(self):
    rcv_data = self.COM.readAll()
    if len(rcv_data) >= 2:
        value = int.from_bytes(bytes(rcv_data[0:2]), 'little')
        self.xdata.append(self.time * 0.100)
        self.ydata.append(value)
        self.time += 1
        self.curve.setData(self.xdata, self.ydata)

用 numpy 库随机模拟一些数据,测试一下绘图效果,大功告成。

  • 10
    点赞
  • 97
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洋洋Young

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值