pycharm + PyQt5 读取串口并显示数据和图像

本文介绍如何使用Python进行数据采集,通过串口读取数据,利用PyQt5和SQLite实现数据的本地存储及图形化展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     万恶的项目上有一点需求,需要我们收集底层采集到的数据,本地存储,再发送到云端,被迫搬砖写了个小型的UI,记录下。

     首先是环境,开发的工具是Pycharm,python的解释器使用 anaconda3,辅助包主要是PyQt5,会稍微用到一点QTDesigner(不用也可以),数据库使用的是SQlite,数据库的查看工具是DB Browser。流程如下

      一、环境配置

      安装pycharm很简单,就不说了,但是这里一定要安装专业版的,因为社区版的pycharm再使用数据库时非常不方便。安装好之后我们按照下图配置环境 File - settings - project - Project interpreter 

      点击加号,输入pyqt,把圈中的两个包都安装上,后边需要用到的包也是同样的安装方法。注意解释器呀,要用anaconda3的,可以少安装很多东西。

      二、UI界面

      环境配好就可以动手写东西了,首先分析需求,我们要采集数据,然后再界面上显示数据,并做出图像,所以,首先要有数据和UI界面,这里先做界面。

      正常来讲,UI界面应该单独的放在一个模块里,然后在主模块中调用,这里我写的不好,就直接写在一起了,界面的主要部分如下所示:

	operatorLayout = QHBoxLayout()
	temperatureLayout = QHBoxLayout()
	pressureLayout = QHBoxLayout()
	flowLayout = QHBoxLayout()
	addressLayout = QHBoxLayout()
	# 传感器显示布局
	self.temperature = QLabel('0')
	self.temperature.setFixedWidth(200)
	self.temperature_status = QLineEdit('NO')
	self.temperature_status.setFixedWidth(200)
	self.pressure = QLabel('0')
	self.pressure.setFixedWidth(200)
	self.pressure_status = QLineEdit('NO')
	self.pressure_status.setFixedWidth(200)
	self.flow = QLabel('0')
	self.flow.setFixedWidth(200)
	self.flow_status = QLineEdit('NO')
	self.flow_status.setFixedWidth(200)
	self.address = QLabel('0')
	self.address.setFixedWidth(200)
	self.address_status = QLineEdit('NO')
	self.address_status.setFixedWidth(200)
	# 所有的状态标签
	temperature_show1 = QLabel("温度传感器:")
	temperature_show2 = QLabel("温度传感器工作状态:")
	pressure_show1 = QLabel("压力传感器:")
	pressure_show2 = QLabel("压力传感器工作状态:")
	flow_show1 = QLabel("流量传感器:")
	flow_show2 = QLabel("流量传感器工作状态:")
	address_show1 = QLabel("地址信息  :")
	address_show2 = QLabel("角度传感器工作状态:")
	# 添加布局,使用的是水平布局,然后垂直摆放
	temperatureLayout.addWidget(temperature_show1)
	temperatureLayout.addWidget(self.temperature)
	temperatureLayout.addWidget(temperature_show2)
	temperatureLayout.addWidget(self.temperature_status)
	pressureLayout.addWidget(pressure_show1)
	pressureLayout.addWidget(self.pressure)
	pressureLayout.addWidget(pressure_show2)
	pressureLayout.addWidget(self.pressure_status)
	flowLayout.addWidget(flow_show1)
	flowLayout.addWidget(self.flow)
	flowLayout.addWidget(flow_show2)
	flowLayout.addWidget(self.flow_status)
	addressLayout.addWidget(address_show1)
	addressLayout.addWidget(self.address)
	addressLayout.addWidget(address_show2)
	addressLayout.addWidget(self.address_status)
	
	self.prevButton = QPushButton("前一页")
	self.nextButton = QPushButton("后一页")
	self.switchPageButton = QPushButton("Go")
	self.switchPageLineEdit = QLineEdit('0')
	self.switchPageLineEdit.setFixedWidth(40)
	
	switchPage = QLabel("转到第")
	page = QLabel("页")
	operatorLayout.addWidget(self.prevButton)
	operatorLayout.addWidget(self.nextButton)
	operatorLayout.addWidget(switchPage)
	operatorLayout.addWidget(self.switchPageLineEdit)
	operatorLayout.addWidget(page)
	operatorLayout.addWidget(self.switchPageButton)
	operatorLayout.addWidget(QSplitter())
	
	# 状态布局
	statusLayout = QHBoxLayout()
	self.totalPageLabel = QLabel()
	self.totalPageLabel.setFixedWidth(70)
	self.currentPageLabel = QLabel()
	self.currentPageLabel.setFixedWidth(70)
	
	self.totalRecordLabel = QLabel()
	self.totalRecordLabel.setFixedWidth(70)
	
	statusLayout.addWidget(self.totalPageLabel)
	statusLayout.addWidget(self.currentPageLabel)
	statusLayout.addWidget(QSplitter())
	statusLayout.addWidget(self.totalRecordLabel)
	
	# 设置表格属性
	self.tableView = QTableView()
	# 表格宽度的自适应调整
	self.tableView.horizontalHeader().setStretchLastSection(True)
	self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
	
	# 创建图形
	self.graphicsView = pg.GraphicsLayoutWidget()
	
	# 创建界面
	mainLayout = QVBoxLayout(self)
	mainLayout.addLayout(operatorLayout)
	mainLayout.addWidget(self.tableView)        #加入表格
	mainLayout.addLayout(temperatureLayout)
	mainLayout.addLayout(pressureLayout)
	mainLayout.addLayout(flowLayout)
	mainLayout.addLayout(addressLayout)
	mainLayout.addWidget(self.graphicsView)     #加入曲线
	mainLayout.addLayout(statusLayout)
	self.setLayout(mainLayout)

      这段代码看不懂关系也不大,完全可以用QTDesigner来画。

      三、数据采集

      使用python做数据采集需要使用 serial 这个包,然后只需要行代码就可以读取。

import serial
serialport = serial.Serial(GL.comport, int(GL.baudrate) ,timeout=0.5,parity=serial.PARITY_NONE, rtscts=1)
class WorkThread(QThread):
    receive = pyqtSignal()
    def run(self):
        while True:
            if (GL.bytes == 51):
                data = serialport.readline()
            if data != '':
                data1 = data.decode()
                data1 = data1.strip().split()
                data1 = [str(i) for i in data1[:6]]
                GL.data2 = data1
                self.receive.emit()   #发送消息

      首先载入serial,定义串口为 serialport ,然后写一个QThread的子类,使用另外一个线程做数据的读取(因为主线程是UI的显示,如果直接使用主线程读取,会造成阻塞)。这里使用了 pyqt 的消息和槽的机制,发送一个 receive 消息,然后再UI的初始化中绑定这个消息和处理方法(也就是槽),最后编写处理该消息的槽。

      四、存入数据库并画图

      有了UI界面、又完成了数据采集,我们就可以将数据存入数据库,并使用它们来画图了

 def update_data(self):
        time = QDateTime.currentDateTime()
        timeDisplay = time.toString("yyyyMMdd hh:mm:ss dddd")
        if GL.data2 != []:
            self.temperature.setText(GL.data2[0])
            self.pressure.setText(GL.data2[1])
            self.flow.setText(GL.data2[2])
            self.address.setText(GL.data2[5])
            # 获取采集数据
            GL.list[0] = int(GL.list[0] + 1)
            GL.list[1] = timeDisplay[9:17]
            GL.list[2] = int(GL.data2[1])
            GL.list[3] = int(GL.data2[0])
            GL.list[4] = int(GL.data2[2])
            GL.list[5] = GL.data2[5]
 
            GL.x_plot.append(GL.list[0])
            GL.y_plot.append(GL.list[2])
            GL.blue_plot.append(GL.list[3])
        if len(GL.x_plot) == 100:
            GL.x_plot = [0]
            GL.y_plot = [0]
            GL.blue_plot = [0]                        # 用刚刚采集到的100个点,画图
 
        self.plt.clear()
        self.plt.plot( GL.x_plot,GL.y_plot, pen= pg.mkPen(color='r', width=3),name="Red curve")
        self.plt.plot( GL.x_plot,GL.blue_plot, pen= pg.mkPen(color='b', width=3),name="Blue curve")
        self.db.open()
        query = QSqlQuery()
        # 存入数据库
        sql_1 = """insert into device(id,time,name,sex,age,deparment) values(%d,"%s",%d,%d,%d,"%s")""" % (GL.list[0], GL.list[1], GL.list[2], GL.list[3], GL.list[4], GL.list[5])
        query.exec(sql_1)
        self.db.close()

      上边这段代码就是刚才的 receive 消息对应的槽函数,当接收到receive消息时,我们将串口读到的数据存入全局变量,然后将全局变量按照顺序丢到数据库中。当然,要想使用数据库,肯定要在开头创建一个,如下:

def createTableAndInit(self):
    # 添加数据库
    self.db = QSqlDatabase.addDatabase('QSQLITE')
    # 设置数据库名称
    self.db.setDatabaseName('./db/database2.db')
    # 判断是否打开
    if not self.db.open():
        return False
    # 声明数据库查询对象
    query = QSqlQuery()
    # 创建表
    query.exec("create table device(id int , time int  , name vchar, sex vchar, age int, deparment int )")
    # 添加记录
    sql = "insert into device(id,time,name,sex,age,deparment) values(%d,%d,%d,%d,%d,%d)"%(GL.list[0],GL.list[1],GL.list[2],GL.list[3],GL.list[4],GL.list[5])
    query.exec(sql)
    return True

     如此,我们就完成了数据的采集、存储和显示。

     当然,这个代码可以优化的地方有很多,望能指正。

### 回答1: PyCharm是一个Python集成开发环境(IDE),而PyQt则是一个用于创建Python图形用户界面(GUI)的工具包。串口调试是指通过串行通信接口来与设备进行通信的过程。 在PyCharm中使用PyQt进行串口调试实现波形显示,可以按照以下步骤进行: 1. 首先,确保已经正确安装了PyCharmPyQt。可以在PyCharm中创建一个新的Python项目。 2. 导入所需的模块,在代码中加入以下语句: ``` from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtSerialPort import QSerialPort, QSerialPortInfo import pyqtgraph as pg ``` 3. 创建一个窗口,用于显示波形。可以使用PyQt中的QtWidgets模块创建一个窗口对象,使用pg模块中的PlotWidget来绘制波形图。例如: ``` app = QtWidgets.QApplication([]) win = pg.PlotWidget() win.show() ``` 4. 打开串口设置相关参数。使用QSerialPort模块来打开串口设置波特率、数据位、校验位等参数。例如: ``` serial_port = QSerialPort() serial_port.setPortName("COM1") # 设置串口号 serial_port.setBaudRate(9600) # 设置波特率 serial_port.setDataBits(QSerialPort.DataBits(8)) # 设置数据位 serial_port.setParity(QSerialPort.Parity(0)) # 设置校验位 ``` 5. 实现串口数据接收更新波形显示。通过连接信号槽函数,可以实现当串口接收到数据时,自动更新波形显示。例如: ``` def update_waveform(): data = serial_port.readAll().data() # 读取串口数据 # 在波形图中添加数据点 win.plot(range(len(data)), [data[i] for i in range(len(data))]) serial_port.readyRead.connect(update_waveform) # 接收到串口数据时调用update_waveform函数 ``` 6. 打开串口启动事件循环。使用open()方法打开串口,然后调用exec_()方法启动事件循环以保持程序运行。例如: ``` serial_port.open(QtCore.QIODevice.ReadWrite) # 打开串口 app.exec_() # 启动事件循环 ``` 通过以上步骤,就可以在PyCharm中实现使用PyQt进行串口调试实现波形显示。当程序运行时,串口接收到的数据会被读取绘制成波形图显示在窗口中。 ### 回答2: PyCharm是一种集成开发环境,适用于Python的编程调试。PyQt是Python的一种GUI编程框架,可以用来创建图形用户界面。串口调试是指使用串口通讯协议进行数据传输调试。波形显示是一种将数据以波形形式展示的方式。 在PyCharm中使用PyQt进行串口调试,可以通过以下步骤实现波形显示: 1. 导入必要的库: ```python import serial # 用于串口通信 from PyQt5.QtWidgets import QApplication, QMainWindow # 用于创建GUI窗口 from pyqtgraph import PlotWidget, plot # 用于绘制波形图 from PyQt5 import QtGui # 用于绘制图形界面 ``` 2. 创建GUI窗口: ```python class MyWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("串口波形显示") self.graphWidget = PlotWidget(self) self.setCentralWidget(self.graphWidget) ``` 3. 初始化串口: ```python ser = serial.Serial('COM1', 9600) # 假设串口号为COM1,波特率为9600 ``` 4. 获取数据更新波形图: ```python def update(): data = ser.readline().decode().strip() # 读取串口接收到的数据 # 在此对数据进行处理,如解析转换 # 绘制波形图 pass ``` 5. 启动GUI窗口更新波形图: ```python if __name__ == '__main__': app = QApplication([]) window = MyWindow() timer = QtCore.QTimer() timer.timeout.connect(update) timer.start(0) window.show() app.exec() ``` 以上为使用PyCharmPyQt实现串口调试波形显示的基本步骤。根据具体需求,可以对代码进行优化扩展,实现更多功能,如设置坐标轴范围、改变波形样式等。 ### 回答3: PyCharm是一种集成开发环境(IDE),可用于编写、调试运行Python代码。它提供了许多功能,包括代码自动补全、调试器版本控制集成,使开发人员能够更轻松地创建管理Python项目。 PyQt是一种用于创建图形用户界面(GUI)的Python绑定库,它基于Qt框架。借助PyQt,开发人员可以使用Python编写跨平台的应用程序,包括窗口、按钮、文本框等各种GUI元素。 串口调试是通过串行通信接口与外部设备进行通信调试的过程。在PyCharm中,我们可以使用PySerial库来实现串口调试。PySerial提供了一组简便的函数来操作串口,包括打开串口、设置波特率、发送接收数据等。 波形显示是一种可视化方式,用于展示信号随时间变化的图形。在PyCharm中,我们可以使用Matplotlib库来实现波形显示。Matplotlib提供了一些图形绘制函数,我们可以将接收到的数据进行处理后,在图形上动态显示出来,从而实现波形显示。 使用PyCharmPyQtPySerial,我们可以创建一个串口调试程序,其中PyQt用于创建GUI界面,PySerial用于串口通信,Matplotlib用于绘制波形。在程序中,我们可以通过GUI界面设置串口参数,打开串口,发送接收数据将接收到的数据实时绘制成波形显示。这样,我们就可以方便地进行串口调试,同时可视化地观察信号的变化情况。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值