返回列表 发新帖我要提问本帖赏金: 51.00元(功能说明)

使用python+qt做一个串口波形调试工具

[复制链接]
 楼主| 穿西装的强子 发表于 2025-1-17 11:38 | 显示全部楼层 |阅读模式
<
本帖最后由 穿西装的强子 于 2025-1-20 11:35 编辑

#申请原创# #技术资源# @21小跑堂
我们经常会用到串口打印一些数据,有时候不直观,通过曲线观察会更加清晰明了,网上有很多工具,但是总感觉不适合自己,那就让我们自己做一个适合自己的串口波形调试工具;
为什么用到Python:
Python 是一种高级编程语言,因其简洁的语法和代码可读性而广受欢迎。
  • 易学易用:

    • Python 有相对简单的语法,这使得它成为初学者学习编程的理想选择。
    • 它减少了编写程序所需的代码量,因此开发人员可以更专注于解决问题。
  • 跨平台支持:

    • Python 可以在多种操作系统上运行,如 Windows、macOS、Linux 和 Unix。
    • 编写的 Python 程序无需修改即可在不同平台上运行(大多数情况下)。
  • 丰富的标准库和第三方模块:

    • Python 拥有一个庞大的标准库,提供了许多功能,比如文件 I/O、系统调用、数**算等。
    • 大量的第三方库和框架让开发者能够快速实现各种复杂功能,例如网络爬虫、数据可视化、机器学习等。
  • 面向对象和支持多种编程范式:

    • Python 支持面向对象编程,同时也兼容过程化编程和函数式编程风格。
    • 这种灵活性允许开发者根据项目需求选择最合适的编程方式。
  • 社区支持和资源丰富:

    • Python 拥有一个活跃且友好的社区,为新手和专业人士提供帮助。
    • 社区成员不断贡献新的库、工具和教程,有助于持续学习和发展。
  • 适用于多种应用领域:

    • Python 广泛应用于 Web 开发、自动化脚本、数据分析、人工智能、机器学习等领域。
    • 它也是科学计算、教育和其他专业领域的首选语言之一。
  • 动态类型系统:

    • Python 是一种解释型语言,具有动态类型系统,这意味着变量不需要显式声明类型,简化了编码过程。
    • 不过这也可能带来性能上的劣势,因为相比静态类型语言,它的执行速度较慢。
  • 良好的集成能力:

    • Python 可以轻松与其他语言编写的代码集成,如 C/C++、Java 等。
    • 这对于需要高性能部分或已有大型代码库的项目来说非常有用。
  • 开源和免费:

    • Python 是开源软件,意味着它是免费使用的,并且用户可以根据需要查看和修改源代码。
python+qt能够跨平台和丰富的库资源,让我们开发效率事半功倍;


设计思路


1.界面内容
串口选择,波特率选择,停止位、奇偶校验等串口功能;
串口打开按键
多曲线选择
实时曲线界面
2.设计流程

3.开始编程
界面设计,设计2个combobox,一个作为串口选择,已添加打开软件自动搜索添加到combobox内,一个作为波特率选择;设计1个按键,打开/关闭串口;设计4个checkbox,选择4个曲线的开关,默认为打开
  1. self.setGeometry(400, 200, 800, 660)  # 位置和大小
  2.         self.setMinimumSize(QtCore.QSize(self.app_w, self.app_h))
  3.         self.setMaximumSize(QtCore.QSize(self.app_w, self.app_h))
  4.         ports = serial.tools.list_ports.comports()

  5.         #### Create Gui Elements ###########
  6.         self.mainbox = QtWidgets.QWidget()
  7.         self.setCentralWidget(self.mainbox)
  8.         self.mainbox.setLayout(QtWidgets.QVBoxLayout())

  9.         self.combex = QtWidgets.QComboBox(self.mainbox)
  10.         for port, desc, hwid in sorted(ports):
  11.             self.combex.addItem(port)
  12.         self.ser =serial.Serial()
  13.         self.ser.close()
  14.         self.combex.setGeometry(10, 0, 100, 20)
  15.         
  16.         self.baud = QtWidgets.QComboBox(self.mainbox)
  17.         self.baud.setGeometry(120, 0, 100, 20)
  18.         baud = [9600,19200,38400,57600,115200,230400,460800,921600]
  19.         for i in baud:
  20.             self.baud.addItem(str(i))
  21.         self.baud.setCurrentIndex(4)
  22.         
  23.         self.open = QtWidgets.QPushButton("打开串口",self.mainbox)
  24.         self.open.clicked.connect(self.open_serial)
  25.         self.open.setGeometry(230, 0, 100, 20)
  26.         
  27.         self.check1 = QtWidgets.QCheckBox("曲线1",self.mainbox)
  28.         self.check1.setGeometry(340, 0, 50, 20)
  29.         self.check1.setStyleSheet("background-color: yellow;")
  30.         self.check1.setChecked(True)
  31.         self.check1.stateChanged.connect(self.on_checkbox_state_changed)  # 连接信号与槽函数

  32.         self.check2 = QtWidgets.QCheckBox("曲线2",self.mainbox)
  33.         self.check2.setGeometry(400, 0, 50, 20)
  34.         self.check2.setStyleSheet("background-color: red;")
  35.         self.check2.setChecked(True)
  36.         self.check2.stateChanged.connect(self.on_checkbox_state_changed)  # 连接信号与槽函数
  37.         
  38.         self.check3 = QtWidgets.QCheckBox("曲线3",self.mainbox)
  39.         self.check3.setGeometry(460, 0, 50, 20)
  40.         self.check3.setStyleSheet("background-color: green;")
  41.         self.check3.setChecked(True)
  42.         self.check3.stateChanged.connect(self.on_checkbox_state_changed)  # 连接信号与槽函数
  43.         
  44.         self.check4 = QtWidgets.QCheckBox("曲线4",self.mainbox)
  45.         self.check4.setGeometry(520, 0, 50, 20)
  46.         self.check4.setStyleSheet("background-color: blue;")
  47.         self.check4.setChecked(True)
  48.         self.check4.stateChanged.connect(self.on_checkbox_state_changed)  # 连接信号与槽函数

  49.         self.label = QtWidgets.QLabel("协议示例:   printf("<plots,%d,%d,%d,%d>",p1,p2,p3,p4);   ",self.mainbox)
  50.         self.label.setGeometry(10, 30, 400, 20)

  51.         self.canvas = pg.GraphicsLayoutWidget(self.mainbox)
  52.         self.canvas.setGeometry(0, 60, 800, 600)  # 设置位置和大小
初始化4个曲线参数
设置曲线最大100个数据宽度,设置4个曲线颜色

  1.         # Line plot
  2.         self.cpuplot = self.canvas.addPlot(title=" ", axisItems={'bottom': TimeAxisItem(orientation='bottom')})
  3.         self.p1 = self.cpuplot.plot(pen='y')
  4.         self.p2 = self.cpuplot.plot(pen='r')
  5.         self.p3 = self.cpuplot.plot(pen='g')
  6.         self.p4 = self.cpuplot.plot(pen='b')
串口打开按键功能
打开串口并创建dataUpdate_thead线程,该线程为串口协议处理
  1. def open_serial(self):
  2.         #self.p1.setVisible(not self.p1.isVisible())
  3.         if self.ser.is_open == True:
  4.             self.ser.close()
  5.             self.open.setText('打开串口')
  6.             self.combex.setEnabled(True)
  7.             self.baud.setEnabled(True)
  8.         else:
  9.             print(self.combex.currentText())
  10.             self.ser = serial.Serial(self.combex.currentText(), int(self.baud.currentText()))
  11.             if(self.ser.is_open == True):
  12.                 self.open.setText('关闭串口')
  13.                 self.combex.setEnabled(False)
  14.                 self.baud.setEnabled(False)
  15.                 self.stop = 0
  16.                 self.t = threading.Thread(target=dataUpdate_thead, args=(self,))
  17.                 self.t.daemon = True
  18.                 self.t.start()  # 线程执行
协议处理线程
协议使用的字符串形式, printf(\"<plots,%d,%d,%d,%d>\",p1,p2,p3,p4); 以此作为协议处理;
判定起始数据<,开始接收字符,未开始,则字符丢弃;判定>为结束字符,结束后开始处理内容;
将字符串通过“,”字符进行split,得到5个字符串,1个固定字符和4个数据;
判定字符串长度和校验固定字符,校验完成后将4个数据放入曲线buffer内,设置到曲线内即可;
  1. def dataUpdate_thead(self):
  2.     start = 0
  3.     strs = ''
  4.     process= []
  5.     while True:  # 为了方便测试,让数据不停的更新
  6.         if self.stop == 1 or self.ser.isOpen() == False:
  7.             return
  8.         data = self.ser.read().decode()
  9.         if data == '<':
  10.             start = 1
  11.             strs = ""
  12.         elif data == '>':
  13.             start = 0
  14.             split_list = strs.split(',')
  15.             process.clear()
  16.             for base in split_list:
  17.                 process.append( base.strip())
  18.                
  19.             strs = ""
  20.             if len(process) == 5 and process[0] == "plots"  :
  21.                 current_time = int(time.time() * 1000)
  22.                 y1, y2, y3, y4 = map(int, [element.strip() for element in process[1:5]])

  23.                 self.X.append(current_time)
  24.                 self.Y.append(y1)
  25.                 self.Y2.append(y2)
  26.                 self.Y3.append(y3)
  27.                 self.Y4.append(y4)
  28.                 # 只在需要绘制时转换为数组
  29.                 self.xdata = np.array(self.X)
  30.                 self.ydata = np.array(self.Y)
  31.                 self.ydata2 = np.array(self.Y2)
  32.                 self.ydata3 = np.array(self.Y3)
  33.                 self.ydata4 = np.array(self.Y4)
  34.                 self.p1.setData(self.xdata, self.ydata)
  35.                 self.p2.setData(self.xdata, self.ydata2)
  36.                 self.p3.setData(self.xdata, self.ydata3)
  37.                 self.p4.setData(self.xdata, self.ydata4)
  38.               <blockquote>
以上曲线绘制软件就完成;
以下是完成后的界面;自适应范围







本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

打赏榜单

旋转跳跃 打赏了 1.00 元 2025-01-23
理由:真干货阿

21小跑堂 打赏了 50.00 元 2025-01-20
理由:恭喜通过原创审核!期待您更多的原创作品~~

评论

基于python+qt实现一个串口数据波形显示工具,实现效果较好,步骤清晰。  发表于 2025-1-20 16:57
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

259

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部