尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

LabVIEW通用测试流程框架:从架构设计到产线落地的完整实践

LabVIEW通用测试流程框架:从架构设计到产线落地的完整实践 搞测试测量系统集成的工程师应该都经历过这种循环每个新项目过来一看测试项、判定逻辑、仪器类型全都不一样于是又从头搭一遍界面、写一遍流程控制、调一遍数据记录。设备换了、通讯方式换了、报表格式换了但底层那套逻辑——先初始化、再跑测试项、采集数据、判断OK还是NG、把结果存下来——翻来覆去就那几件事。我手里这套LabVIEW通用测试流程框架就是从四五个实际项目中沉淀出来的所有模块都在产线上跑过没有一个是demo状态。这篇就把它的设计思路、架构取舍和落地细节完整拆开讲适合正在做测试台架、产线功能测试或者老化测试系统的朋友参考。1. 每个项目测试流程都不一样这种通用到底通在哪里先说个反直觉的结论通用框架不是把测试流程写死成一种恰恰相反它是把流程运行的环境和流程本身彻底拆开。流程由配置文件和数据来决定框架只负责当一个稳定的运行时。1.1 测试流程差异的真实面貌我做过的项目里测试流程的差异可以大到什么程度有的产品只需要一个工位插上电读几个电压值五分钟出结果有的产品要经过上位机通讯、三四个仪器轮询、十几道测试步骤、循环老化N个小时途中还得允许操作员插拔产品暂停流程。更头疼的是同一个项目里不同型号的产品测试步骤数量都不一样——第一版产品测10项第二版硬件改版后变成14项中间还插了两项新加的校准。这还只是流程本身的差异。再往下拆仪器资源差异更大有的项目用串口读功率计有的用Modbus TCP读温控器有的用VISA控制电源有的干脆用DIO板卡采集开关信号。判定逻辑也是五花八门有的要取峰值有的要算平均值有的要跟标准值比上下限有的还要看曲线斜率。1.2 不变的那部分才是框架该管的但这些项目里完全不变的东西也很多。我列一下恒定的骨架大家对照自己项目看看是不是这样启动流程初始化界面、加载配置文件、初始化仪器、检查硬件连接状态主流程执行一个接一个地执行测试步骤每个步骤都有输入参数、输出结果数据流转测试数据要有统一的存放位置界面、记录、判定逻辑都要能拿到结果判定每个步骤判定Pass/Fail最终汇总出整机结论数据落盘原始数据、测试时间、操作员、产品序列号都要记录下来收尾关闭仪器、生成报表、复位系统这些环节才是通用框架的职责边界。至于具体读哪个寄存器电压上限是3.3还是5.0——这些属于项目的个性部分应该由配置文件或者具体的步骤子VI来解决而不是写死进框架里。可以这么理解框架是后厨的管理系统管的是点单、叫号、出菜、收台这些流程运转而每道菜是红烧肉还是清蒸鱼那是具体交给哪个厨师步骤VI的事。我后厨的管理规则不变换菜谱只需要换厨师、换配料单。2. 框架落地前的架构选型状态机、生产者消费者与JKI/CSM的取舍这块我踩过不少弯路。最早做第一个测试软件的时候就是while循环加一个大case结构所有界面事件、仪器通讯、数据更新全部堆在同一个循环里。项目小的时候没问题一旦测试步骤多起来系统里到处是bug——点个按钮界面卡住、仪器还没回数据界面就超时了、数据记录和界面刷新抢资源。后来才老老实实做架构选型。2.1 状态机的两个主流方向传统case结构与JKI状态机LabVIEW里做流程控制最基础的就是while循环加条件结构配合移位寄存器保存状态。这个方案的好处是直观坏处是状态多了之后case结构里分支根本没法维护——每个状态还得处理跳转到其他所有状态的可能性代码看起来像一团乱麻。后来我用过JKI状态机。它的核心思想是用队列传递状态消息每个状态只负责处理自己该做的事做完之后往队列里塞下一条状态命令。这样做的好处有三个状态之间的跳转关系被队列消息解耦了新增一个状态不影响其他状态的代码每个状态的处理程序变成独立分支代码可读性大大提升可以在运行时动态往队列里塞命令——比如操作员按暂停键就是往队列里塞一条暂停命令当前步骤执行完自然停住JKI状态机特别适合测试系统这种流程相对线性、但需要随时响应外部干预的场景。我在框架里的主流程执行就是借鉴了这个思路不过队列没有完全照搬JKI的做法后面会细说。2.2 生产者消费者模式在框架里真正的用途很多LabVIEW教程讲生产者消费者说来说去就是避免UI卡顿。这话没错但太窄了。在测试框架里生产者和消费者的价值是职责分离和资源隔离。我的框架里最少有三条队列在同时跑UI消息队列前面板按钮事件、操作员指令开始、暂停、停止、手动下一步测试命令队列主流程状态机要执行的步骤命令序列测试数据队列各测试步骤采集到的原始数据统一由记录线程写入文件或者数据库UI循环只管把操作员的操作变成消息发出去不直接去动仪器测试主循环只管按命令序列执行测试步骤把数据扔到数据队列里不等界面刷新也不管数据落盘数据记录循环从队列里取数据批量写入文件。三条循环各干各的自然就不存在互相等待的问题。这里有个容易犯的错很多人把测试数据队列当成数据缓存攒一批才写一次。这个思路没问题但是队列一定要有上限或者定期清空否则操作员跑十几个小时老化测试队列越堆越多内存直接爆掉。我的做法是数据记录循环只管从队列取取完立即写文件queue里不会有积压。2.3 为什么不建议一上来就上Actor Framework现在LabVIEW社区不少人推Actor Framework说是做大型架构的正路。我承认AF在处理复杂分布式系统的时候确实强但对于大多数测试测量项目来说它有两个问题一是学习曲线太高团队新人上手慢二是调试不方便Actor之间的消息传递隔了一层出问题难以定位。测试系统的第一需求是可追溯、可干预、能快速定位问题。状态机加生产者消费者这套组合拳能覆盖绝大多数项目的需求而且出bug的时候看队列里的消息记录问题一目了然。我的建议是项目规模没到需要分布式部署的地步别为了架构而架构。3. 核心设计把测试步骤抽象成可配置的数据与可复用的小VI框架最关键的一块是测试步骤的抽象。设计得好加一个新的测试项只需要写一两个子VI加一行配置设计得不好每个项目还是得从头写流程逻辑。3.1 每个测试步骤的长相统一的VI接口约定LabVIEW没有传统语言里那种接口和继承但我们可以通过约定连线板的接线规范来模拟。我的做法是建立一个测试步骤模板VI所有具体测试步骤VI都复制这个模板来改写内部逻辑而输入输出接线保持一致。模板VI的连线板定义如下输入端一测试步骤参数簇一个Cluster里面包含步骤ID、步骤名称、测试限值、超时时间等字段输入端二全局数据总线一个包含产品序列号、当前产品型号、环境温度等公共信息的簇输出端一测试结果簇包含测试值、判定结果Pass/Fail、错误信息、扩展数据输出端二运行状态用于告知主流程是正常结束、需要重试、还是需要跳过这样一个约定接口就完成了。主流程状态机拿到一条步骤命令后根据步骤ID在配置表中找到对应的子VI路径动态调用后把参数簇和数据总线传进去拿到结果簇再决定下一步往队列里塞什么命令。3.2 流程不写死在代码里用配置表驱动流程有了统一的步骤VI接口接下来就是把流程本身数据化。我用的是一张XML配置表也可以用JSON、数据库表或者INI文件效果一样每个测试步骤占一行字段包括字段含义示例StepID步骤唯一标识S001StepName步骤名称读取设备型号VIName对应子VI名称ReadDeviceModel.viParamCluster参数簇内容COM Port3, Timeout2000msFailAction失败后的动作RetryOnce / Skip / Stop / ContinueNextStepID下一步骤IDS002主流程执行时状态机从配置表中顺序读取步骤也可以按FailAction动态跳转。流程如果改版比如量产阶段发现某个测试项要删掉不需要动任何代码只改配置表就行。说实话这个设计最直接的收益不是省代码而是让调试和验收变得可控。产线上调试的时候现场工程师可以直接打开配置表屏蔽某个步骤、调整超时时间、修改判定阈值不用等开发人员重新改代码重新编译。这对项目交付节奏的帮助太大了。3.3 测试步骤的重试、跳过与异常处理这是流程健壮性的关键流程框架不能光考虑顺利跑完的情况。实际产线上仪器偶发超时、通讯瞬间干扰、产品本身接触不良——什么情况都可能发生。我在框架里明确区分了两种非正常路径步骤判定失败Fail这个步骤测出来的值超限了属于产品或者测试条件的正常反馈。此时按FailAction字段处理重试、跳过还是整机判NG由配置决定。步骤执行异常Error子VI报错了比如串口打不开、VISA超时、数据格式非法。这是系统级问题不能简单按Fail处理。我的框架里Error会触发一次异常登记记录错误代码和现场数据然后询问主流程重试N次、暂停等待人工处理、还是终止整条测试。这两个路径一定要在框架设计阶段就分开。如果混在一起会出现一个很尴尬的情况产品本身是好的但仪器通讯抖了一下结果被判定成NG报废了。分开之后可以在重试逻辑里加自动复位仪器再重测的策略把偶发干扰的影响降到最低。4. 代码组织与多工位扩展从单流水线到多工位并行框架搭好之后紧接着面临两个现实问题代码文件怎么管理、多个测试工位怎么办。这两个问题处理不好框架再漂亮也落不了地。4.1 用lvlib管理框架层级避免VI文件一团乱麻LabVIEW项目里最怕的就是VI文件全部堆在一个文件夹里命名还自由发挥。到后期根本分不清哪个VI是干嘛的改一个地方不知道会影响谁。我的方案是用lvlibLabVIEW库强制分层Framework.lvlib框架核心层。主状态机、队列管理、数据记录、异常处理、配置加载——这些VI带锁禁止使用者改动Steps.lvlib测试步骤层。所有具体测试项子VI放这里它们只依赖Framework层提供的公共接口Hardware.lvlib硬件驱动层。VISA串口通讯、Modbus通讯、板卡采集等全部封装成统一接口UI.lvlib界面层。前面板程序和相关事件处理Config配置层。XML配置文件、参数模板这个分层的规则很严格Steps只能调用Framework和HardwareUI只能通过队列消息跟Framework交互Hardware不依赖任何上层模块。这样做的最大好处是替换硬件驱动或者新增测试步骤的时候改动范围是可控的不会牵一发动全身。4.2 多工位支持一套软件框架跑多个测试工位热搜词里有labview编程实现多个相同测试工位写在同一个软件这个问题我正好遇到过。客户产线上三个工位测同一种产品要我写一套软件同时跑三路。最笨的方案是代码复制三份界面堆三个一样的控件程序集里三个状态机并行。但这样后期维护是三倍工作量改一个判定逻辑要同步改三处迟早出纰漏。我的做法是在框架里把工位抽象成一个运行实例。具体来说每个工位有一份独立的状态上下文一个保存当前步骤、当前产品序列号、当前重试次数、当前累计结果的簇存放于独立的移位寄存器三个工位共用同一套状态机代码但各自有自己的队列实例UI上用选项卡控件每个选项卡对应一个工位显示各自的实时状态和数据硬件资源分两类管理独占型资源比如每工位单独一台串口仪器每个工位持有自己的句柄共享型资源比如一台公用的打印机、公用的数据库连接加一个资源锁同一时间只允许一个工位使用这样一套框架跑四个工位改动配置只需要加一个工位的配置段不需要复制代码。新增工位时只需要在配置表里定义一个工位ID→队列句柄→状态上下文的映射。5. 数据记录、报表生成与代码保护测试系统的最后一公里流程跑通了数据也测出来了但测试系统最终给人看的东西是报告。数据记录做不好前面所有工作都白费。5.1 数据落盘CSV、HTML报表与Access数据库怎么选关于数据记录我见到的项目需求大概分三类要原始数据的完整可追溯比如质量部门审计要求每个产品有完整的原始测试记录。这种情况我用CSV一行一条记录测试时间、序列号、测试项、测试值、判定结果全部拼进去。CSV的好处是任何工具都能打开Excel、JMP、Python都能直接分析。要好看的对客户报告产线出货要附一张测试报告。这种情况我直接用LabVIEW生成HTML文件。界面上放一个模板把测试数据填进去生成一个带样式的网页文件打印成PDF就能给客户。比生成Word报表简单得多因为LabVIEW操作Word的报表生成工具包效率不高。要内部数据库查询有些客户要求所有测试记录进数据库方便追溯平台查询。这里可以用LabVIEW Database Connectivity Toolkit连Access或SQL Server。操作不复杂创建连接、执行INSERT语句、关闭连接注意定期做事务提交批量写入比逐条写入快很多。我自己在产线项目里的默认组合是原始数据全量存CSV最保险汇总结果存Access库方便查询需要给客户看的报告用HTML生成快捷美观。三个各干各的互不干扰。5.2 部署打包VISA运行时怎么带、DLL封装到底值不值热搜里有labview 程序打包如何打包visa驱动这是交付时最简单又最容易漏的一步。用LabVIEW打包成EXE的时候在附加安装程序里一定要勾选NI-VISA运行时。很多项目开发机上跑得好好的一拷到产线工控机就没有仪器了十有八九就是VISA运行时没打包进去。另外一个经常被问的问题是LabVIEW要封装DLL才能保护代码吗。我的看法是分两层如果只是防止现场误改LabVIEW项目选项里勾选生成时移除框图VI源码就会变成不可查看的这个对大多数项目够用了。如果客户是竞争同行要求核心算法不能泄露那封装DLL是值得的。做法是把核心判定算法编译成DLLLabVIEW通过调用库函数节点来调用。但注意DLL要处理好32位和64位的问题——LabVIEW本身是32位就有对应32位DLL别打包完了调用报无法加载库文件。我的建议是框架层和核心算法层在代码管理成熟度不够时不着急封装DLL先用移除框图保护等框架稳定了再把核心逻辑抽出来封装成DLL减少被逆向的风险。6. 实际项目里的坑流程框架最容易翻车的地方框架能跑起来只是及格要在产线上长期稳定运行才是真正的考验。最后分享三个我真实踩过、也花了最多精力才解决的坑。6.1 队列状态残留测试跑久了出现灵异现象框架上线第三周客户反馈测试跑了一百多个产品之后偶尔会出现在界面点开始没反应、或者数据记录到别的产品上了的情况。排查了半天发现问题出在队列上——异常终止上一轮测试的时候队列里还残留了几条命令没消费完下一轮测试开始旧命令和新命令混在一起导致状态机乱跳。解决办法是在每轮测试开始时强制清场把测试命令队列里的残留消息全部丢弃重置状态上下文把队列引用重新初始化。另外在状态机的初始化分支里加一个断言——进入新流程前队列必须为空否则报错。这个小改动之后再也没出过灵异现象。6.2 仪器通讯超时Modbus设备假死导致整个流程挂起另一个高频问题来自仪器通讯。项目里有一台Modbus TCP温控器偶尔会出现网络抖动设备没响应。我最初代码里没有对Modbus读操作设置明确超时结果一卡就是好几分钟流程整个挂住操作员不知道是设备坏了还是程序死了。这个问题的根源在于LabVIEW的Modbus库函数如果底层TCP连接半开而设备不响应默认行为是无限期等待。解决措施有三层所有硬件通讯节点从VISA串口到Modbus TCP统一设置超时时间我一般设3000ms超时后不要直接报错停机而是走异常登记→自动重试路径重试三次再上报重试仍然失败时尝试先关闭通讯连接再重新打开很多Modbus设备的假死通过重置连接能恢复这套组合拳之后设备偶发断连不会再导致整条产线停下来等工程师手动处理。6.3 框架的进化方式别一上来就想做通用最后给个真诚的建议如果你只有一个项目在手先别急着开发通用框架。我做第一版所谓通用框架的时候其实是把第一个项目的代码加了一堆开关试图覆盖各种可能性。结果开关太多自己都搞不清楚哪些参数是有效的。真正让框架变通用的是第二个、第三个项目做完之后——有了对比才知道哪些是项目特性哪些是所有项目的共性。框架是在项目迭代中长出来的不是凭空设计出来的。我现在的习惯是拿到新项目先评估差异点如果框架里没有现成的抽象宁可先为这个项目写一个专用实现等项目结束复盘时再决定要不要反哺框架。这样框架的每一次升级都有实际需求支撑不会变成一堆没人能维护的摆设。这套框架的核心价值说穿了就是把测试工程从面向单个项目开发变成面向配置搭建。流程的改动不再需要重新编译、重新部署甚至现场工程师自己就能调整。做测试系统集成这个行当项目永远在变但底层那套让人安心的骨架值得好好沉淀下来。
返回列表