免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

基于Python与PyQt5的示波器自动化测试平台实战

基于Python与PyQt5的示波器自动化测试平台实战 简介这套基于Python和PyQt5开发的自动化测试工具专门面向使用泰克MDO3014等MDO3000系列示波器的硬件测试与软件开发人员解决仪器控制、波形抓取与日志记录相互割裂、难以同步查看的问题。软件支持在图形界面中实时查看并保存示波器波形也能实时读取和显示运行日志、导出日志窗口内容同时提供单次循环执行测试用例的机制测试用例需由使用者自行编写因此保留了较高的可扩展性便于结合项目实际进行二次开发。源码中详细演示了常用界面控件的Python调用方法对学习PyQt5界面编程以及搭建仪器自动测控框架都有直接帮助。压缩包共16个文件涵盖Python脚本、界面定义、工程配置、说明文档和演示图片等主要类型整体大小仅139KB小巧完整。目前已有3653人学习适合具备一定Python基础、希望在示波器自动化方向快速落地的开发者参考。 做硬件测试这一行最烦的不是测不出来而是同一个波形你一天要测两百遍。开发板改一版电源纹波、时钟抖动、串口时序这些指标全要回归一遍人工盯着示波器读数再填Excel填到最后手都酸了还容易抄错。我前年带的一个小项目就是用Python加PYQT5把一台泰克示波器改造成了能自动跑测试、自动出报表的黑盒这套自动化测试方案从需求确认到落地前后花了不到三周今天把这个项目的完整思路和踩坑过程整理出来给准备做仪器自动化或者测试平台的朋友做个参考。这套方案核心就是三层Python负责业务逻辑和仪器通信通过VISA库走SCPI指令控制泰克示波器PYQT5负责做桌面端界面把示波器状态、测试参数、测量结果都放上去底层就是标准仪器控制协议不绑定具体型号。做完之后一键启动、串行跑完几十个测试项、自动保存波形截图和测量数据整个过程不需要人守着适合产线测试、研发验证、实验室定期校准这类场景也适合刚接触PyQt5和SCPI的同学作为练手项目。1. 项目概述与方案选型思路1.1 为什么选了Python而不是LabVIEW做仪器自动化最传统的路子是LabVIEW确实成熟泰克官方也有一堆现成例程但如果你的测试逻辑比较复杂要接数据库、要自定义报表、要对接内部研发的算法脚本LabVIEW的图形化编程就有点施展不开了。Python这边生态最合适pyvisa库把VISA读写封装得明明白白numpy处理波形数据极其顺手reportlab或pandas可以解决报告输出整个链路都是文本代码放到Git里diff起来也清晰。我用的是pyvisa配合NI-VISA后端。安装方式很简单pip install pyvisa再装一个NI-VISA的运行时驱动示波器通过USB或者网线连上电脑代码里第一件事就是枚举资源import pyvisa rm pyvisa.ResourceManager() print(rm.list_resources())能看到类似 USB0::0x0699::0x0368::C010263::INSTR 这样的地址就说明链路已经通了。这里有个经验如果只是临时读取数据用pyvisa-py这个纯python后端也能跑但它不支持全部VISA特性遇到USBTMC的某些操作会报超时。正经做项目直接装NI-VISA省心。1.2 界面层为什么锁定PYQT5界面这块我在tkinter和PyQt5之间犹豫过。tkinter够轻自带库不用装但做复杂交互界面是真的累表格组件、样式美化都要自己折腾。PyQt5虽然是第三方库胜在控件齐全QTableWidget、QComboBox、QTabWidget这些都是成熟组件信号槽机制和仪器这种异步事件多的场景配合得特别好。举个例子示波器测量过程中采集线程每秒钟回传一次数据放到QTableWidget里刷新如果用tkinter你得自己处理线程安全、事件循环稍不留神就崩。在PyQt5里做一个自定义信号线程里emit一下槽函数里更新界面干净利落后面我会详细讲这部分代码。1.3 泰克示波器通信链路基础泰克示波器支持SCPI标准指令这是仪器界的通用普通话。不管你是TBS系列还是MDO4000系列控制逻辑都差不多先发配置命令再发查询命令仪器返回结果。核心控制流程我总结成一句话选通道、设触发、开采集、等状态、读数据。对应到SCPI指令就是scope.write(ACQuire:STATE ON) # 开启采集 scope.write(DATa:SOUrce CH1) # 选择读取通道 scope.write(ACQuire:STOPAfter SEQuENCE) # 单次采集 scope.write(ACQuire:STATE RUN) # 触发采集 while scope.query(ACQuire:STATE?) ! 0: time.sleep(0.05) data scope.query_binary_values(CURVe?, datatypeb, containernp.array)CURVe? 是示波器返回波形数据的关键指令返回的字节数组经过缩放因子的折算就还原成真实的电压值了。2. 环境搭建与硬件联调踩坑2.1 Python、PyQt5与pyvisa的安装细节Python版本我建议装3.8或3.9不是说新版3.12不行而是很多仪器厂商的SDK、旧项目里的依赖还停留在3.9之前的兼容水平没必要拿项目稳定性赌版本。PyQt5的安装看起来就一条命令pip install pyqt5但不少人在这一步就卡过尤其是网络不好的时候下载一半就断了。注意装PyQt5建议先换国内镜像源比如pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple装完立刻验证from PyQt5.QtWidgets import QApplication能不能导入能导入再继续不要等写到一半才发现环境有问题。装完之后把pyvisa也装上pip install pyvisa如果选择NI-VISA作为后端还需要去官网下载运行时安装包。这里有个小习惯把依赖列表写进requirements.txt先把版本号固定下来比如PyQt55.15.10、pyvisa1.14.1避免后面队友复现环境时装上不兼容的大版本。2.2 示波器连接方式选择泰克示波器常见的连接方式有三种USBUSBTMC、网口LAN、GPIB。从自动化角度我强烈建议优先用网口。原因很直接USB的USBTMC驱动在Windows上偶尔会掉重新枚举要拔线重插产线环境没人愿意天天弯腰插拔网口稳定得多还能用socket方式直接连跨机器部署也方便。用网口连接在pyvisa里有两种路径一种是安装NI-VISA后把示波器IP填进VISA资源池用TCPIP0::192.168.1.100::inst0::INSTR访问另一种是泰克自带的VXI-11协议同样基于网口。我实测下来VXI-11模式在局域网内非常稳定几百次连续读取没出现过掉线。2.3 最小通信Demo拿到示波器第一件事先让它自己报个名字确认链路没问题import pyvisa rm pyvisa.ResourceManager() scope rm.open_resource(TCPIP0::192.168.1.100::inst0::INSTR) scope.timeout 3000 print(scope.query(*IDN?))看到类似 TEKTRONIX,MDO3024,... 的返回这条链路就可以用了。注意scope.timeout一定要设置默认值偏小示波器忙的时候查询会等很久超时太短直接抛异常。我习惯把它调到3000毫秒既不会等太久也不会掩盖真正的通信故障。3. PYQT5界面设计与核心交互实现3.1 界面布局测试控制台怎么分区域我的界面设计比较朴素主要分三个区域。左侧是参数配置区用QFormLayout摆放各种QComboBox和QLineEdit比如选择通道、选择测量项、填入幅度上下限中间是控制区放置启动测试、暂停、停止按钮和一个显示实时状态的QTextBrowser右侧是结果区用一个QTableWidget列出所有测试项的执行状态和测量值。这样的布局逻辑是让操作人员从左到右、从上到下完成任务先配置再启动最后看结果符合产线操作习惯。实测下来一个不太熟练的测试员也能在五分钟内学会。结果区里我用背景色标出PASS和FAIL绿色通过、红色不通过不用看具体数值就能一眼发现问题项。3.2 下拉框闪退与超链接点击的实战处理写这个项目时正好踩过QComboBox下拉框闪退这个坑。现象是点击下拉箭头菜单还没展开整个程序就没了。排查下来有几种情况一种是在Linux下缺少xcb系统库另一种是Windows环境PyQt5插件加载路径不对。解决方案通常是安装pyqt5-tools补全插件或者在代码开头用QApplication.addLibraryPath()指定插件目录保证Qt能找到platform plugin。这里提醒一下别一遇到闪退就重装Python先看程序日志和Qt插件的加载情况很多闪退都是插件路径问题。还有一个需求经常被问到QTextBrowser里的日志信息比如错误提示希望用户点一下某个超链接就自动打开对应的波形截图。QTextBrowser本身不直接支持点击回调但只要连接anchorClicked信号几行代码就能实现self.log_browser.anchorClicked.connect(self._open_link) def _open_link(self, url): os.startfile(url.toString())这样在日志里拼接出 点击查看截图 用户一点就能直接打开截图比单独去文件夹里翻方便多了。3.3 多线程采集避免界面卡死示波器测量一个波形短则几百毫秒长则几秒如果在主线程里同步等待界面必然卡成未响应这是初学PyQt5最容易犯的错。我的做法是单独建一个QThread子类把示波器控制、数据读取、结果判定全部丢进去通过自定义信号把测量结果发回主线程。class TestThread(QThread): result_ready pyqtSignal(dict) def run(self): # 这里执行示波器测量流程 self.result_ready.emit({item: Vpp, value: 3.32})这样界面的刷新只发生在信号槽过程中主线程窗口保持流畅即使示波器卡住界面上的停止按钮也仍然能响应可以及时终止任务。还有一点要注意不要在子线程里直接调用QTableWidget的更新接口Qt的界面对象不是线程安全的必须通过信号槽回到主线程再改界面。4. 自动化测试流程实现与报表输出4.1 测试项与参数的组织方式自动化测试的第一步是把测试需求结构化。我的做法是用一个配置文件不用数据库因为测试项一般就几十个用JSON或YAML足够清晰又能放进Git做版本管理。每个测试项包含测试名称、测量类型峰峰值、频率、上升时间等、通道、上下限以及读取前置条件。{ test_items: [ {name: 3V3电源纹波, channel: CH1, measure: PKPK, min: 0.0, max: 0.05}, {name: 时钟频率, channel: CH2, measure: FREQ, min: 99.0, max: 101.0} ] }这样写的好处是被测板子的指标变了只改配置文件代码一行都不用动。我曾经遇到过客户临时调整极限值现场改JSON重跑一遍十分钟就出结果印象很深。4.2 波形数据读取与测量参数获取泰克示波器做自动测量有两种方式。一种是直接用MEASUrement命令让示波器自己计算参数比如先发MEASUrement:MEAS1:TYPE PKPK再发MEASUrement:MEAS1:VALUE?读结果这种方式省事适合只需要一个数值的场景。另一种是读原始波形数据自己用numpy算比如需要计算上升时间、频谱分析等示波器内置测量覆盖不到的任务就得走这条路。我项目里两种都用了。读数用内置测量拿到峰峰值和频率同时把原始波形读回来用numpy再算一个均值、标准差跟示波器的结果交叉验证防止示波器自动测量在某些毛刺信号下误判。这一招在之后的客户测试中确实救过场示波器给的Vpp明显虚高原始数据一分析发现是毛刺差点把合格产品误杀。4.3 结果判定、截图保存与报告生成每项测完之后拿测量值和上下限比较得出PASS或FAIL然后存到结果列表实时在界面上用颜色标记。截图这块用泰克的硬拷贝指令把波形图直接存成PNG留档用。scope.write(SAVE:IMAGe D:/test_results/case01.png)一份完整的测试报告包括测试时间、被测设备编号、每项测量值、判定结果和波形截图路径。我最终输出了CSV和HTML两种格式CSV方便后续数据分析HTML直接打开就能看还能嵌入图片适合发给不在现场的人审核。报告里我还加了一列测试耗时方便评估整批测试效率后期优化瓶颈一眼就能看出来。5. 常见问题排查与避坑记录5.1 典型问题速查表问题现象可能原因解决办法QComboBox点击闪退Qt插件缺失或环境变量未设置安装pyqt5-tools检查QApplication插件路径示波器连接报超时网口不通或timeout设置过小ping示波器地址把scope.timeout调到3000以上读取CURVe?返回乱码数据编码格式参数未匹配确认DATa:ENCdg设置与解析方式一致界面卡死无响应示波器操作放在了主线程改用QThread后台执行全部仪器操作测试结果偶尔不对示波器测量未稳定就取值读取前增加状态查询与等待逻辑5.2 几个值得展开的坑第一个是示波器连接断线重连。产线长时间运行偶尔会出现设备连接被重置的情况我的处理是给连接层加了一个重试装饰器捕获VISA异常后自动重新open_resource连续重试三次六成概率能自动恢复剩下的才需要人工介入。实测跑了三天的连续老化测试这种自动恢复机制救了至少两次班次。第二个是数据量和界面刷新速度的矛盾。默认读10000个点可能不觉得卡但如果界面上还要实时绘图20000个点以上用matplotlib刷新就会明显掉帧。我的建议是界面绘图只做缩略图分辨率降到500到1000个点原始数据只存盘不画这样显示流畅度和数据完整度都能兼顾。第三个是仪器状态机的复位。一套测试跑下来几十项如果某项异常退出示波器可能还停留在某个奇怪状态不恢复的话后面的项全错。我每次测试开始前都会强制执行硬复位指令然后重新配置测量参数宁可多花一两秒也要保证初始状态干净。5.3 关于测试夹具与被测设备的联动如果只是控制示波器这套系统还闭环不了。很多实际项目测试前要先把DUT上电、给激励信号。这块我在方案里留了扩展位预留了GPIO控制接口可以用串口或继电器板卡控制夹具的上电时序通过Python的serial库读写把上电-激励-测量-断电-判定整条链路串起来。有条件的朋友可以进一步接扫码枪被测设备贴的条码扫一下报告里自动带出序列号可追溯性会好很多。这套设计对新产品导入也很有帮助。当测试方案要换被测板子时只需要改配置文件里的通道映射和阈值再更新一下夹具上电时序脚本代码本身基本不用动。我后来把同样的架构复用到直流电源和信号源的自动化测试上只替换了底层发命令的部分说明界面配置仪器驱动这种分层写法是能沉淀成通用平台的。最后说点实际的体会。这种Python界面仪器的组合最花时间的往往不是业务代码而是各种边缘情况网线松了、示波器固件升级了、被测板子批次换了导致信号形态变了这些才是自动化项目真正的拦路虎。所以一开始设计的时候一定要把日志、状态恢复、断线重连这些东西放在和功能代码同等重要的位置不要等产线跑挂了再补。如果你正准备搭一套自己的仪器自动化测试系统建议从一台示波器、一个简单的界面、三个测量项开始先把最小闭环跑通再逐步往上加东西。尽量把所有参数都放到配置文件里不要把阈值写死在代码里这样后面维护起来会轻松太多。我在实际使用中还发现一个有用的习惯每次测试结束把示波器的当前配置导出一份文件留作调试依据出问题的时候比靠回忆靠谱得多。本文还有配套的精品资源点击获取
返回列表