恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
从零搭建仪器自动化测试系统:SCPI、VISA与PyVISA实战
首页
资讯中心
/
从零搭建仪器自动化测试系统:SCPI、VISA与PyVISA实战
从零搭建仪器自动化测试系统:SCPI、VISA与PyVISA实战
发布时间:2026/9/8 22:27:49
在硬件研发实验室里待过的人对测试就是要盯着看这件事应该都不陌生。示波器放桌边、万用表插好线、信号源调好参数人往那一坐隔几分钟看一眼读数十几分钟记一次数据。白天还好一旦做老化测试、循环耐久、整夜拷机人就变成了人肉传感器——熬到凌晨两点也要爬起来抄数抄完又怕抄错第二天还要核对一遍。这正是我一直在做的事的出发点用自动化测试脚本把盯仪器这件事彻底接管让每台仪器真正听指挥。你发它一条指令它还你一个准确结果不需要情绪、不会走神、更不用睡觉。这篇文章会从最底层的原因讲起带着实际踩坑经验聊清楚怎么从零搭建一套能稳定跑过夜的仪器自动化测试系统。适合被重复性硬件测试耗干精力的研发工程师、测试开发也适合想引入自动化测试但不清楚从哪落手的产线朋友。1. 测试还在靠人盯先想清楚你到底痛在哪1.1 人工盯守真正消耗的不是时间而是判断力我见过太多测试工程师的困境表面看是时间被占满本质上是人的注意力被错误地分配了。比如一个电源模块的老化验证要求每15分钟记录一次输入电压、输出电压、电流和温升一共跑12小时意味着要记录48轮数据。这期间你不能离开太久、不能睡死过去因为万一仪器报警或者数值偏离你需要第一时间知道。问题是这48轮记录里99%的数据是正常的真正需要人干预的可能只有那么一两次。你盯着屏幕三小时可能只为了等那个异常出现的瞬间——这不是测试这是消耗。另一个被忽略的问题是数据密度低。人手工记录的采样频率是分钟级的但很多物理量在秒级甚至毫秒级就有关键变化。比如充电曲线在进入恒压阶段的那个转折点或者继电器闭合瞬间的电压跌落手工记录根本抓不到。等你看到数据的时候过程已经结束了只能凭经验猜当时发生了什么。这还只是研发场景产线场景更残酷台架上的FCT测试测试员手动放板、按键、看PASS还是FAIL一台设备小批量生产几百片板子重复劳动量和人为误判都是隐形成本。还有一点很少被量化就是可追溯性。纸质记录单很容易出问题字迹看不清、时间写错、换班交代不清。线上表格好一些但如果是人工copy到电脑一样有抄错的风险。真正的痛点是当你在分析一个产品异常需要一个完整的、带时间戳的、每个读数都对应到具体操作步骤的记录时人工数据几乎不可用。自动化测试解决的不只是效率它解决的是一致性、完整性和可追溯性这是人工盯守永远做不到的。1.2 自动化测试的投入产出怎么算当然不是说所有测试都要上自动化做技术方案最忌讳的就是盲目跟风。我建议先算一笔账一个测试项目如果满足重复次数多超过3轮单次耗时超过1小时数据需要量化记录要后期画曲线、做统计中的任意两条自动化就值得做。反过来如果只是偶尔测一次、数据看一眼就够、不需要存档那就手动测别折腾。自动化的核心逻辑是把你从人-仪器-数据这个闭环里摘出去。人工测试时人既是测试执行者又是数据读取者还是异常判断者自动化之后仪器直接对接脚本脚本直接把结果落盘人只负责审异常、处理边界情况。这也是我理解的传统测试与自动化测试融合——不是用自动化完全替代人而是让机器做机器擅长的事。传统的测试经验仍然非常重要因为设计测试用例、判断关键参数、分析异常曲线这些能力必须来自懂业务的人。在投入产出这块还要考虑一个隐性收益自动化测试可以7x24小时运行。我做过一个很典型的例子一块板卡需要做500次开关机循环每次循环之间要求等2分钟让电容充分放电手工做下来要连续两天坐在那操作机器人一晚上就跑完了。第二天早上你只需要来看结果。这种类型的收益比单纯省几个工时更有价值因为你把测试周期压缩了项目整体进度也变快了。2. 想让仪器听指挥先懂控制协议和连接方式2.1 SCPI、VISA、GPIB这些名词其实一句话能讲清很多人一听到仪器自动化就头大觉得要学一堆协议、寄存器、硬件接口。其实真正需要理解的只有三层。最底层是物理连接比如GPIB线、USB线、网线、串口线这是仪器和你电脑之间传输数据的管道。第二层是VISA虚拟仪器软件架构它相当于一个中间翻译官帮你屏蔽掉不同接口的差异。有了VISA你无论用USB连着仪器还是用网线连着仪器写的代码几乎是一样的。最上层是SCPI可编程仪器标准命令这是仪器通用的普通话。比如你给仪器发一行*IDN?它就会返回自己的型号和序列号发一行:MEAS:VOLT:DC?它就返回当前测到的直流电压值。这三层的关系可以类比成SCPI是标准规范的对话内容VISA是帮助你打电话的电话交换机物理接口就是你手中的电话。所以你看真正写代码的时候你只需要知道SCPI命令和VISA这个API就够底层怎么传数据其实不用太关心。我之所以强调这个原理是因为很多网上教程一上来就教大家装库、写代码却不解释为什么要写ResourceManager()、为什么仪器地址是TCPIP0::192.168.1.10::inst0::INSTR。等你换了台仪器、换了连接方式一旦出问题就完全抓瞎。理解这三层模型之后遇到问题你就能判断是物理层没连通是VISA驱动没装好还是SCPI命令发得不对排查范围一下就缩小了。2.2 四种连接方式实测对比USB、LAN、GPIB、串口怎么选仪器连接方式没有绝对的好坏只有适不适合你的场景。我把实践中的感受整理成一张表连接方式优点缺点适合场景USBUSBTMC/串口转USB即插即用连接方便速度快线缆距离有限不同厂商驱动差异大研发台架单机控制临时接一台仪器调试LANVXI-11/LXI可跨房间远程控制标准化程度高不受USB驱动问题困扰初始IP配置有点门槛个别老仪器的网络接口不稳多台仪器组网、测试柜集中管理、远程监控GPIB老牌仪器接口抗干扰强多台级联方便工业现场存量最多需要额外PCIe/USB转GPIB控制器线缆贵速率不算快产线存量老仪器比较多设备更新周期长串口RS-232协议简单很多老式电源、温箱都支持点对点速率低地线电位问题要小心老式仪表、简单指令收发嵌入式设施自带的设备选型建议其实很简单。如果你是研发阶段在自己工位上做优先用USB或LAN推荐LAN因为网络接口不受线缆插拔次数影响稳定很多。如果是产线要看你们已有的设备资源。我遇到过不少工厂几台几十万的进口设备用了十几年全是GPIB接口这种情况下果断上一块USB-GPIB控制器成本不高存量设备全部焕发第二春。还有一种情况要注意同一台仪器可能同时支持多接口。这时候建议只连一种不要把USB和LAN同时接上否则某些开源库在资源枚举时会识别出多个会话你写着写着就晕了。我的习惯是台架调试用USB项目正式跑批用LAN两种方式在代码层面切换也就是换个地址字符串而已。2.3 为什么我推荐 Python PyVISA而不是 LabVIEW在仪器测控这块LabVIEW是很多老一辈工程师的习惯选择图形化编程、厂商驱动插件多确实在初期搭界面很爽。但用它维护一个不断变化的测试项目真的很痛苦版本管理不方便.vi文件很难做diff多人协作基本靠复制粘贴许可证价格也不便宜再加上它的编程思路和主流代码世界差别非常大团队里想找个能改LabVIEW的人越来越难。这些都已经是行业共识了。还有一类方案是用仪器厂商自带的软件比如是德科技的BenchVue、泰克的OpenChoice这些软件拿来单台仪器演示、导个波形的确不错但想把它编排成一套自定义流程、接入你自己的数据库、失败后自动重试几乎不可能。它们的设计目标从来不是定制化自动化测试框架。我最终选择的是Python PyVISA这套组合。PyVISA是Python世界访问VISA的标准库封装得很漂亮代码写起来非常直观import pyvisa rm pyvisa.ResourceManager() print(rm.list_resources())四行代码就能列出所有连上的仪器。Python的优势不用多说代码即文档一个人写完团队都能review做数据分析、画曲线、接AI后处理生态都是现成的。热词里经常提到的AI自动化测试自己搭建agent进行自动化测试在Python生态里做起来也顺手因为你要采集的数据本来就已经数字化了直接喂给统计分析或机器学习就是一步的事。另外提一句接口自动化测试框架。有些做软件测试的朋友习惯用Java搭接口自动化测试框架来测云平台后端API逻辑上跟仪器自动化是相通的——把被测对象抽象成可调用的接口只是咱们这里的接口是VISA/Socket对面是物理仪器他们是HTTP/REST对面是Web服务。二者思维完全一样所以做过接口自动化的人学起仪器自动化会非常快反过来也一样。3. 从零搭一套仪器自动化测试环境、用例与数据落盘3.1 5分钟接上第一台仪器环境安装与最小验证脚本先给你一个能最快见到效果的路径照着做基本5分钟内就能让仪器开口说话。第一步装Python这个不用多说。第二步装PyVISA和PyVISA-pypip install pyvisa pyvisa-py这里有个容易踩的坑。PyVISA本身只是API层它下面还需要一个VISA实现作为后端。你可以装NI-VISA这种商业实现功能全、兼容性好但体积大也可以装PyVISA-py这个纯Python实现轻量、免注册对绝大多数仪器都够用。我的建议是如果只是用USB或LAN连比较标准的仪器先上PyVISA-py如果遇到一些比较偏门的仪器连不上再补装NI-VISA因为它的底层驱动更全。第三步把仪器接上电脑然后在你Python环境里运行import pyvisa rm pyvisa.ResourceManager() resources rm.list_resources() print(resources) # 输出示例: (USB0::0x2A8D::0x5101::MY57201234::INSTR,)看到仪器地址之后写一个最经典的三行代码inst rm.open_resource(USB0::0x2A8D::0x5101::MY57201234::INSTR) print(inst.query(*IDN?)) # 输出示例: Keysight Technologies,DSOX1204G,MY57201234,02.42*IDN?是SCPI标准命令用于查询仪器身份所有SCPI兼容仪器都必须实现它。如果这段代码跑通了恭喜你你已经迈出仪器自动化的第一步——仪器已经听指挥了。第一个卡点通常是list_resources()返回空。原因基本都是后端问题。如果装了PyVISA-py确保你在创建ResourceManager时没指定到NI-VISA后端如果两个后端都装了可以显式指定rm pyvisa.ResourceManager(py) # 强制使用PyVISA-py后端Linux下另外要处理USB权限问题常见做法是给/dev/usbtmc*配置udev规则放权或者临时用sudo跑脚本验证是不是权限问题。这个我后面章节还会细说。3.2 把测试步骤变成测试用例动作、采集、断言、记录连上仪器只是热身真正的自动化测试核心是把你脑子里的测试步骤结构化地写出来。我习惯把每个测试用例拆成四段动作、采集、断言、记录。动作是你要让仪器干什么采集是你要读什么数据断言是数据是否合格记录是无论如何都把过程留档。举个例子我现在要测一台可编程电源的输出精度。测试计划是设定输出5V稳定后测实际输出电压要求偏差不超过±0.5%。用PyVISA写出来是这样import pyvisa import time import csv rm pyvisa.ResourceManager(py) psu rm.open_resource(TCPIP0::192.168.1.100::inst0::INSTR) # 动作设置输出电压为 5V psu.write(:OUTP ON) psu.write(:VOLT 5.0) # 关键等待电压稳定不要马上读 time.sleep(2) # 或者 psu.query(*OPC?) 等仪器返回操作完成标志 # 采集读回实际电压 actual_v float(psu.query(:MEAS:VOLT:DC?)) # 断言误差是否在允许范围内 tolerance 5.0 * 0.005 passed abs(actual_v - 5.0) tolerance # 记录无论通过与否都记录到 CSV with open(output_accuracy.csv, a, newline) as f: writer csv.writer(f) writer.writerow([time.strftime(%Y-%m-%d %H:%M:%S), 5.0, actual_v, passed])看到没有整段代码就是四段式。这个模式虽然简单但把测试设计表达得非常清楚。后来我搭自动化测试框架本质上也是把这四段做成更通用的组件让上层做设备管理、用例调度、数据汇总但每一笔业务逻辑还是逃不出这四个动作。这里有两个细节很重要。第一个是等待稳定这个动作。很多仪表上电后有建立时间你写完指令立刻读读到的可能是旧值或者过渡值。最稳妥的方式是用SCPI同步命令*OPC?它会在仪器完成所有未执行操作后返回1。如果你的仪器支持用*OPC?永远比time.sleep()精确因为它是仪器告诉我好了而不是我猜它好了。第二个细节是读取浮点数时记得转类型SCPI查询返回的是字符串如果你要做算术比较float()这一部别省。3.3 数据落盘与自动报告边测边写断点不丢测试数据是所有自动化系统里最容易糊弄过去的部分很多初学者图省事等全部测完了再把列表里的数据一次性写文件。这个习惯非常危险。假设你的测试跑到第50个小时电脑蓝屏、仪器断连、代码抛异常内存里的数据全部消失前面50个小时等于白跑。我在实际项目里定的规矩是每跑完一个测试用例立刻写入持久化存储绝不让数据在内存里过夜。存储选型我分三个层次。最轻量的是CSV适合单个测试任务格式简单Excel能直接打开。再往上我用SQLite内置在Python标准库适合多轮测试、多台仪器、需要长期追溯的场景它的表结构好查好统计。如果公司有数据平台可以再往上推InfluxDB这类时序数据库但那一般是设备规模很大、要上可视化监控大屏之后才需要考虑的事情。写完原始数据之后还要生成一份人看得懂的报告。我的习惯是每次跑完自动生成一个HTML或Markdown的汇总报告里面包含测试时间范围、测试仪器列表、总用例数、通过数、失败数、失败明细和关键波形图。这样早上到公司打开报告一分钟就知道昨晚跑得怎么样而不是去翻几百行的日志文件。报告里我还一定会附上产品序列号和仪器校准有效期这两个字段目的是留追溯链条。将来这批板子如果市场反馈有问题你能快速调出这批板子是某天某台仪器测的、仪器当时校准在有效期内的完整证据链。自动化测试的价值不只在当下提高效率更在于未来帮你减少扯皮。4. 多台仪器协同才算指挥从单机脚本到测试阵列4.1 多仪器协同的复杂度主要在同步和依赖关系单台仪器的自动化本质是request-response一问一答。但真实测试场景里经常需要同时用好几种设备可编程电源负责供电电子负载负责拉载万用表负责测电压温度巡检仪负责记录温升。这时候复杂度就上来了。第一个问题是依赖关系。比如你必须在电源输出稳定后才能让电子负载启动必须在温度稳定后才能记录数据。这些依赖如果在代码里不明确表达跑久了就会出现这次测的是正常值、那次测的是还没稳定时的异常值的情况数据一会好一会坏。第二个问题是同步。多台仪器之间需要微秒级同步的场景在硬件触发里有明确需求比如你要观察信号源发出脉冲瞬间示波器采集到的波形这时候信号源和示波器的触发必须同时开始。软件上能做到的时间戳同步精度一般在毫秒级靠先给A发指令再给B发指令的顺序方式会有几十上百毫秒的误差对很多测量来说是致命的。所以我在项目里的选型原则很简单能用软件同步解决的就用软件也就是通过时间戳和严格顺序控制只有当测量需求精确到亚毫秒级才使用仪器的硬件触发接口比如示波器后面板的TRIGGER OUT接到信号源的TRIGGER IN。软件同步投入小、调试方便硬件同步一根线就搞定但要仔细看手册确认触发电平和极性。还有一个工程上的坑多台仪器同时操作代码容易变成大泥球。我的办法是为每台仪器写一个独立的仪器驱动类比如class PowerSupply、class ElectronicLoad类里面封装连接、基础操作、状态查询。上层用例只跟这几个类打交道不直接写SCPI命令。这样某台仪器掉了、换了型号只需要改这个类测试用例一行都不用动。这也是为什么我说每台仪器听指挥的前提是先把每台仪器都包装成一个听指挥的数字员工。4.2 一个完整的电池充放电自动化测试实例纸上谈兵没意思我用一个大家可能都见过的场景完全展开做一颗锂电池的循环寿命测试需要交替进行恒流恒压充电和恒流放电总共10个循环记录每个循环的充进去多少容量、放出来多少容量。硬件连接可编程电源作为充电设备电子负载作为放电设备万用表并联在电池端测开路电压一个继电器/接触器来控制电池接入充电回路还是放电回路。这个场景里控制逻辑的关键点是安全顺序切换负载之前必须先让电源输出置零否则继电器切换瞬间容易打火拉弧。代码骨架大致长这样import pyvisa, time, csv rm pyvisa.ResourceManager() psu rm.open_resource(TCPIP0::192.168.1.100::inst0::INSTR) # 可编程电源 load rm.open_resource(TCPIP0::192.168.1.101::inst0::INSTR) # 电子负载 dmm rm.open_resource(USB0::0x2A8D::0x9802::MY零件::INSTR) # 万用表 def charge_step(voltage4.2, current0.5, cutoff_current0.05): # 动作电源设成CV模式目标电压4.2V限流0.5A psu.write(f:VOLT {voltage}) psu.write(f:CURR {current}) psu.write(:OUTP ON) # 等待充电截止电流逐步下降到 cutoff_current while True: current_now float(psu.query(:MEAS:CURR?)) if current_now cutoff_current: break time.sleep(5) psu.write(:OUTP OFF) def discharge_step(load_current1.0, cutoff_voltage2.8): # 动作电子负载开启CC模式电流1A截止电压2.8V load.write(f:CURR {load_current}) load.write(f:VOLT {cutoff_voltage}) load.write(:INP ON) # 接入负载 while True: v float(load.query(:MEAS:VOLT?)) if v cutoff_voltage: break time.sleep(5) load.write(:INP OFF) for cycle in range(1, 11): charge_step() time.sleep(5) # 静置 discharge_step() # 读取本循环容量写入记录 capacity float(load.query(:MEAS:CHARGE?)) with open(cycle_test.csv, a, newline) as f: writer csv.writer(f) writer.writerow([time.time(), cycle, capacity])这段代码只是一个演示骨架真实项目里还要加入温度保护、循环次数统计、异常退出处理、看门狗复位等。但你可以看到所谓多仪器指挥中心其实就是写清楚每一步先做什么、后做什么、等什么条件、出现异常怎么退出。特别是安全条件锂电池测试如果温度过高必须立即断开这种保护要放在脚本最前面并且建议在硬件层面也加一路独立保护继电器别只依赖软件。这个例子跑通之后你对让每台仪器听指挥的理解会瞬间落地不是把每台仪器当成孤岛而是把它们组织成一支有先后顺序、有安全机制、有数据汇报的编队。4.3 从听指令到有判断轻量agent与AI辅助测试热词里反复出现自己搭建agent进行自动化测试AI自动化测试我不打算给你画太大饼就说在仪器测试现场轻量agent能落地的几个方向。第一个是状态巡检agent。让脚本每隔一段时间自动检查所有仪器的连接状态发现某台仪器掉线就自动重连、自动补测或暂停并发通知不需要人一直守在边上。第二个是异常判读agent。比如充电曲线本来应该是指数上升如果某个点突然跌落脚本自动判断为疑似异常记录上下文并触发复测而不是傻傻地等循环跑完再去翻数据。第三个是参数自整定。比如做环境试验时自动根据上一轮温度曲线调整PID参数让温箱更快到稳定点。这些所谓的agent背后并不一定要上大模型很多时候用规则统计就够。但有一点很关键数据要先积累下来AI才有东西可分析。所以我的建议永远是先把基础自动化跑通让每台仪器都稳定地、结构化地吐数据再谈智能化。说白了AI是建立在干净数据之上的锦上添花数据流都断断续续agent只会放大错误。顺带说一句软件开发领域流行的Selenium、Appium这些UI自动化测试框架解决的是网页和App的自动化不是仪器控制。两者目标一致——用代码驱动被测对象不依赖人肉点击和盯守——但工具链完全不同别搞混了。5. 实战常见问题与排查技巧让脚本稳定跑过夜5.1 识别不到仪器、连接失败怎么排查这是新手最容易卡住的第一关。list_resources()返回空或者open_resource()报超时先用这张表来顺现象可能原因排查动作list_resources() 为空VISA后端驱动没装好USB线是纯充电线仪器未开机重新安装PyVISA-py或NI-VISA换一根带数据功能的USB线确认仪器面板亮open_resource 报超时仪器地址写错LAN口IP不在同一网段防火墙拦截ping一下仪器IP确认PC和仪器IP在同一网段暂时关闭系统防火墙Linux下USB权限报错当前用户没有 /dev/usbtmc 的读写权限临时 sudo 验证写udev规则给usbtmc设备设置0666权限提示会话已经打开上次脚本异常退出没释放资源重开Python进程或者等待几十秒再跑我遇到过最奇葩的一次是连续换了三根USB线都识别不到设备最后发现是仪器背面设成了USB与LAN同时禁用的远程控制模式。所以当一切排查都无效时先看看仪器面板有没有Remote/Local状态切换很多时候仪器自己的一设置比电脑端问题更隐蔽。5.2 读取数据卡住、解析报错超时与字符问题读数据卡住是最耗人意志力的问题之一。你发一条查询命令仪器没反应代码就一直堵在那里直到超时异常。我建议所有query()都设置一个合理的超时时间inst.timeout 5000 # 单位毫秒5秒这样即使仪器卡住了脚本最多等5秒就会抛异常你能在异常里做重试或记录。不要把timeout设成00在PyVISA里的意思是永不超时一旦仪器死机你的脚本就永远挂在那晚上的批跑也就全废了。还有一类问题是解析报错。SCPI返回的字符串往往带换行符和可能的提示符比如返回5.003E00\n直接丢进float()会报错。正确做法是value float(inst.query(:MEAS:VOLT:DC?).strip())先把空白字符清干净。有些仪器读数据时还会把上次的残留字节一起吐出来比如你连续读两次第一次的返回值夹杂着第二次的内容。这种情况下可以在每次读之前加一句inst.clear()清空缓冲区或者用inst.flush()。但要小心clear()在某些仪器上会丢同步状态需要在稳定延时后才调用。5.3 长时间跑批不稳定复用、加锁、自动重连跑一个8小时的批处理前半小时一切正常跑着跑着链接断了或者内存涨了这种问题最抓狂。我总结三条经验。第一是复用ResourceManager。千万不要在循环里面反复ResourceManager()每创建一个都是一次系统级资源分配长时间跑必然导致句柄泄漏。正确做法是模块初始化时创建一次全局复用程序结束时才释放。第二是注意并发锁。如果你有多个线程同时操作同一台仪器SCPI会话是不保证线程安全的必须加锁。我的习惯是每一台仪器资源对应一个threading.Lock()所有对该仪器的读写都在with锁内完成。否则你会在日志里看到两条指令交错执行仪器完全懵掉返回的数据对不上号。第三是自动重连机制。长时间跑批USB偶发抖动、网线被踢了一下仪器连接就断了总不能每次都手动重启脚本。我一般会在测每个用例前加一个检查如果连接异常尝试close后用原地址重新opendef safe_operation(func): def wrapper(*args, **kwargs): for attempt in range(3): try: return func(*args, **kwargs) except pyvisa.errors.VisaIOError: inst.close() time.sleep(2) inst.open(resource_address) # 重新连接 raise return wrapper这个装饰器模式很轻量碰到偶发断线能自动恢复跑批的可靠性会高很多。5.4 工程化避坑清单最后把我在项目里积累的经验浓缩成一份清单每次做仪器自动化测试都对着检查一遍仪器地址不写死在代码里放配置文件YAML或JSON换设备不用改脚本。断言阈值、循环次数等参数全部配置化别用魔法数字。所有日志同时带时间戳、仪器地址和产品序列号方便定位。数据边测边写绝不攒在内存里最后一次性落盘。异常退出时最后写入一条状态记录比如测试因XX中断于第X个循环。脚本加看门狗机制如果长时间没有新日志自动重启脚本或发告警。产线环境脚本要尽量减少依赖不要为了优雅引入一堆库出了依赖问题反而更麻烦。在仪器命令层统一封装上层永远只跟自己的仪器类打交道。每台仪器测试前的配置初始化保证前一轮测试的残留设置不会影响下一轮。这套清单帮我省掉了大量半夜被电话叫醒的次数。很多问题不是一开始就能考虑到的而是在一次次的跑批失败中补出来的。所以我建议你第一版不要求全跑通主流程之后再根据真实踩坑去补充这些卫生习惯。我自己做仪器自动化这几年最大的体会是自动化测试不会让测试工程师失业它只是把我们从用眼睛盯数据这种低水平重复劳动里解放出来让我们有精力去做真正需要判断力的事情——设计更严格的测试项、分析异常数据背后的原因、把产品质量往上推一个台阶。如果你也想让手边的仪器听指挥别想太多就挑一台最常用的仪器从*IDN?开始先让它回你一句话后面的事情自然就会越跑越顺。