ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

告别VeriStand、dSPACE和LabVIEW:自主可控测试系统迁移实战

告别VeriStand、dSPACE和LabVIEW:自主可控测试系统迁移实战 干了十多年台架测试和HIL仿真VeriStand、dSPACE、LabVIEW这三个名字基本焊死在我的工作流里。从最早用LabVIEW搭数据采集界面到拿VeriStand搭实时仿真环境再陪着dSPACE的ControlDesk一点点调ECU模型说实话这些工具在特定场景下确实能打。但最近一两年我越来越多地听到、也越来越多地亲历一个现实授权费用一年比一年离谱版本一升级旧工程就报错核心代码被锁在专有环境里想自己动手做二次开发处处受制。于是我们团队花了大半年做了一次认真的评估最终决定把几条核心产线测试系统从这三件套上迁移出来走一条完全自主可控的技术路线。这篇文章没有劝退谁的意思只想把我踩过的坑、验证过的方案、以及那些经常被忽略的细节记录下来给正在考虑同类替换的同行一个参照。1. 为什么这代测试人开始认真考虑替换1.1 三件套各自的看家本领先说VeriStand。NI的VeriStand定位是实时测试和硬件在环HIL的集成环境最擅长把Simulink模型、FPGA和各类IO板卡快速拉进一个实时系统里配合Test Sequence做自动化测试。它的优点是IO实时性高、模型集成方便界面拖拽也能快速出工程。缺点同样明显整个系统越用越像一个黑盒工程文件、编译链、目标机部署全都绑在NI的专有生态里版本稍有变动旧工程就可能起不来。dSPACE则是汽车电子HIL领域的老牌标杆。ControlDesk做在线调参和可视化AutomationDesk做测试序列和自动化配套的实时硬件SCALEXIO系列覆盖从部件到整车的仿真场景。精度、可靠性、技术支持都没得挑但价格也是三件套里最高的且硬件和软件深度绑定换一块采集板往往意味着整套配置要跟着动长期维护成本相当可观。LabVIEW反而是这三者里大家“最日常”的工具。G语言的图形化编程在快速搭数据采集界面、串口调试、仪器控制这些场景里效率确实高前面板拖两个控件就能出一个人机界面。但它最大的问题也来自这种图形化形态工程规模一大连线图变成蜘蛛网版本兼容性混乱打包发布时对运行时引擎Runtime Engine的依赖更是祖传难题。网上随手一搜LabVIEW卡启动界面、安装路径不对、运行时版本冲突的提问从来没断过这本身就说明问题有多普遍。1.2 逼着团队做评估的现实问题我们评估的起点其实非常朴素产线上有几十套测试台架底层用的IO板卡和仪器来自不同厂商而上位机软件几乎都是基于LabVIEW或VeriStand的专有环境开发的。这几年陆续出现了几个让人不得不认真对待的问题。首先是授权成本和合规风险。商业工具基本都是按核心数、按功能模块、按年付费模块越买越多费用就越滚越大。一旦审计发现某个操作端少了授权还得赶紧补。这对多台台架的企业来说是一笔相当大的持续支出。其次是版本升级的连锁反应。NI和dSPACE的版本路线图不完全由用户决定某个大版本升级后原来自写的脚本、模型接口、驱动配置往往需要重新适配。我们遇到过因为统一升级LabVIEW大版本导致一批老VI必须重写的情况工作量不比推倒重来小。而旧版本在维护期结束之后官方不再提供兼容修复这种“被迫升级”的压力很磨人。第三是可维护性和二次开发的天花板。测试系统做久了必然会遇到标准工具不覆盖的场景比如自定义报文解析、私有协议处理、与公司内部数据库/工单系统打通。在封闭生态里做这些扩展非常艰难要么依赖对方提供的API要么就得靠非官方手段去碰一些底层细节稳定性完全没有保证。当这些问题累积起来“自主可控”就不再是一句口号而是实打实的研发投入产出比问题。我们最终的目标也很明确把测试系统的核心能力掌握在自己手里实时、IO、界面、用例、报表全链路都能自己改、自己扩、自己维护同时保留对国外硬件和仪器的兼容能力。2. 自主可控方案的整体架构与选型思路2.1 先想清楚替代的边界动手之前最重要的一件事是搞清楚“替代”到底替到什么程度。我们内部把需求拆成了三个层次不同层次的替代难度和周期完全不同。第一层是“表层替代”也就是人机界面、数据记录、报表生成这些上位机功能从LabVIEW搬到新平台但底层硬件和IO驱动仍然是原有的商业方案。这一层的价值是让现场操作更自由、报表更好定制但底层依赖还在替换收益有限。第二层是“接口层替代”把VISA、DAQmx这类仪器驱动接口替换成开源或跨平台的访问方式让应用代码不再绑死在特定厂商的运行时上。这个层次开始有难度但收益也非常明显因为仪器的SCPI指令集本身就是行业标准理论上只要会发指令换什么工具都无所谓。第三层是“实时层替代”把VeriStand和dSPACE所负责的实时仿真、IO调度、故障注入这一整套能力用开源实时操作系统加自研调度逻辑来实现。这是难度最大、周期最长的一层但也是真正摆脱“卡脖子”的关键。我们当时的策略是三步并作两步先把第一层和第二层做实让所有现有测试台架都能迁移到新上位机平台同时并行对第三层做技术验证找到一个硬件平台跑通实时闭环。事实证明这个节奏是对的——如果一开始就冲着第三层去半年之内大概率交不出一个能用的成果。2.2 技术栈选型每一层替换成什么、为什么上位机应用层我们的选择是Python加QtPySide6/PyQt另外保留C给真正需要高性能的处理模块。选Python不是因为LabVIEW不好而是我们需要一个文本化、可自动化测试、可接入现代CI流程的语言生态。Python在数据处理、数据库、网络通信上有大量成熟库团队招人也容易工程师能看到代码逻辑不用对着满屏连线猜前一个工程师的想法。界面层用PySide6配合PyQtGraph做波形显示。PyQtGraph的性能处理和交互手感在工业数据显示场景下完全够用而且它的绘图接口很底层可以自定义配色、线宽、抗锯齿策略比原生控件灵活得多。更关键的是Qt的模型视图框架天然适合做多页面、多工位的复杂工程界面模块划分比LabVIEW前面板加子VI的组合清晰很多。实时层是我们投入最多的一块。主流开源实时方案里Linux加PREEMPT_RT内核补丁是目前社区最活跃、资料最全的路线它的调度延迟能控制在几十微秒级别对于大多数电机台架、ECU HIL场景已经够用。Xenomai和RTAI在某些极端实时场景下延迟更可控但驱动生态和社区活跃度稍弱。我们最终选择PREEMPT_RT为主原因是开发方便、可调试性好且遇到问题能找到的参考资料最多。IO和通信层板卡层面尽量选国内厂商的PCIe/PXIe板卡它们的Linux驱动和C/C API现在都相当完善如果是EtherCAT总线设备就自己部署一个开源主站通过共享内存或者环形缓冲区把实时数据和上位机应用解耦。仪器仪表层面则保留SCPI协议直接访问TCP/IP和USB-TMC都是标准接口天然不依赖某个厂商的专有运行时。2.3 一套可落地的最小架构示例把上面的选型落到具体结构大致是四层最底层是实时目标机跑PREEMPT_RT系统负责IO采集、PWM输出、信号激励、故障注入这类硬实时任务。目标机上跑的是一套用C/C写的实时主循环周期固定通过共享内存把最新状态暴露给上层。中间是通信中间件负责实时目标机和上位机之间的数据交换。我们没有为每个台架自研协议而是统一走共享内存加TCP发布订阅。上位机里的数据订阅模块定期读取共享内存快照同时把控制字和参数写下去。这套设计的好处是实时目标机关机时上位机也能独立测试界面逻辑联调时的干扰项少了很多。再往上是服务层用Python实现测试序列解析、日志记录、数据库写入、报表生成。测试序列直接保存为文本文件YAML或JSON不再依赖某个商业软件的私有工程格式这让版本管理、代码评审、序列复用都变成了常规软件工程操作。最上层是Qt界面负责实时波形、数据表格、手动操作面板、报警事件展示。界面层不碰任何硬件细节只和服务层通过接口通信。这样换硬件、换通信协议、换数据记录格式界面层基本不用动。这套架构做完之后回头看真正的核心工作量不在代码而在“边界定义”和“接口约定”。只要接口定得清楚每一层都可以独立替换、独立测试这才是自主可控最有价值的体现。3. LabVIEW应用迁移从G语言到文本工程的实操3.1 前面板到PyQt事件循环、单例和画面刷新LabVIEW的Graphic语言里最常见的三个结构是While循环、事件结构、Shift Register移位寄存器这三个概念其实在文本语言里都有对应的东西。While循环对应Python里的while True循环事件结构对应Qt的信号槽机制Shift Register对应函数闭包里保存状态的变量。真正需要花心思的是LabVIEW里的“单例模式”。很多LabVIEW工程师习惯用一个全局VI保存配置参数、共享句柄迁移到Python里如果不管三七二十一全部用全局变量程序规模一大就崩。我推荐的做法是用模块级单例定义一个配置类实例化一次放在模块里导入模块即可共享。这样既保留了全局访问的方便又把数据封装在类方法后面后续加锁、加校验都有地方放比散落的全局变量好维护得多。界面刷新也是一个容易踩坑的点。LabVIEW的前面板控件由UI线程统一刷新不太需要担心线程安全。到PyQt里子线程一旦直接去setText控件轻则闪烁重则崩溃。我们项目里立的规矩是业务线程只向外发信号signal所有界面改动统一由主线程的槽函数处理。实测下来多通道高速刷新下的画面稳定性、交互手感都比原来的LabVIEW实现要好。波形图配色这个细节值得一提。NI默认的橙色/白色波形在深色背景下辨识度高但移植到PyQtGraph后直接搬配色反而刺眼。我们用过NI风格配色做过一版长时间盯屏幕容易疲劳后来改成背景灰白、波形分色通道1红色、通道2蓝色、报警信号黄色配合图例和游标工具现场调试体验反而更舒服。配色看起来是审美问题实际上是长时间值守人员的眼睛疲劳问题千万别轻视。3.2 VISA、串口和CRC16通信层的替换细节LabVIEW里做仪器通信最常用的是VISA。VISA本质上是一套标准的资源管理接口同样的SCPI指令通过VISA发出去换不同厂商的仪器都能用。迁移到Python后pyvisa把NI-VISA后端和访问过程封装成了Pythonic的API代码量比G语言少一半都不止。更大的价值在于文本代码很容易做单元测试不用真的接仪器也能用Mock对象模拟仪器返回这在回归测试里非常好用。不过我们最终还是把大部分仪器通信换成了底层SCPI直连。原因是产线环境要尽可能减少对外部运行时和后端组件的依赖。用socket直接连仪器纯TCP/IP仪器很常见或者用pyvisa-sim做离线测试部署时干净利落不需要额外装VISA Runtime。串口通信是另一个高频场景。LabVIEW的VISA串口配置相对是傻瓜式但很多人栽在“读取超时”和“返回不定长”上。迁移到Python后我们完整实现了一版串口解析框架串口配置集中放在yaml文件里按场景切换波特率读取线程把字节流塞进一个缓冲区解析器按帧头做滑动窗口分包。这样比当初在LabVIEW里用VISA直接读一版更稳因为文本语言的链表结构、缓冲区分包写起来直观得多。CRC16校验在这里必须专门说一下。很多仪表和工业设备走Modbus RTU报文最后是CRC16低字节在前。我们迁移时最早按网上的代码直接调库结果小端大端没注意挂在协议测试上半天。验算函数必须固定用同一套字节顺序去算发送方把CRC低字节放在前接收方也要先读低字节再进校验。把这段逻辑固化成一个工具函数并写上说明注释整个团队都可以安全复用。顺便提一句后续扩展设备协议时大端小端转换工具函数比到处手动拼比特要靠谱得多。3.3 多工位、数据记录和数据库工程化改造LabVIEW多工位测试最常见的做法是复制整个VI然后改工位号当时看着简单后续维护却非常痛苦——改动一个参数要同步所有副本。迁移到Python后我们彻底换了一套思路一个被测对象实例就是一个工位每个工位跑在独立线程或独立进程里公共配置从一份文件加载测试结果写同一个数据库。新增工位不再需要复制工程只需要在配置文件里加一组工位参数程序的启动器自动拉起对应实例。这套方式上线后现场新增台架的效率提升了不止一倍。数据记录这块LabVIEW日志常见做法是写TXT或CSV一些工程师会做“每天自动创建一个TXT文件”的功能。我们用Python的logging模块加RotatingFileHandler做了更灵活的记录方案按大小和日期双触发切换文件日志格式统一异常栈和运行数据可以写到同一个文件方便事后定位。对于结构化测试数据主流方案是往数据库写配合Parquet或HDF5做离线归档。LabVIEW连MySQL需要装数据库驱动迁移后直接在Python里用的pymysql/SQLAlchemy还顺手把数据版本、工位编号、序列编号加进了表结构报表查询时的便利性比原来的CSV大目录高一个量级。单例模式、队列、线程池这套东西在LabVIEW里因为没有明确的线程模型很多工程师其实写得不深。到Python后我的建议是尽量少开裸线程用concurrent.futures的线程池/进程池管理并发任务要传数据就统一用queue.Queue。这既避免了数据竞争也让程序再复杂都有一个清晰的执行边界。多工位大规模并发时如果各工位之间确实要隔离资源进程隔离比线程隔离更省心毕竟Python里有GIL密集计算场景下多线程并不总是并行。4. VeriStand和dSPACE场景的替代路径4.1 实时层和IO层怎么替VeriStand和dSPACE最核心的能力是把Simulink模型、IO、故障注入放进一个实时闭环里。想替代这一层必须先把两件事想清楚模型怎么进实时系统IO怎么被实时调度。模型这块当前行业里最好的破局点是FMI/FMU标准。导出FMU模型后任何支持FMI 2.0的运行环境都可以加载它。我们自己写了一个轻量FMU加载器配合PREEMPT_RT上的固定周期调度实现了模型步进、输入输出映射、参数在线修改。Simulink里开发好的控制逻辑通过FMI导出后不需要绑在某个专有实时目标上可以在我们的实时环境里跑。这一块的验证我们花了很长时间但一旦跑通模型层面的“锁死”就不存在了。IO调度方面自研代码需要解决的是一件事保证每个控制周期内完成对所有通道的读写。我们的做法是把IO操作抽象成一组接口实时主循环在每个固定周期按顺序调用。无论是PCIe板卡直接寄存器读写、EtherCAT总线的周期性帧交换还是和上位机之间的共享内存交换都走同样的接口。这样上层逻辑完全不知道底层用了什么板卡换硬件只改一个适配层。故障注入能力也是HIL系统的必备项。我们用独立通道的电压/电流输出配合继电器矩阵实现在实时任务里加入故障注入状态机可以通过上位机指令实时注入短路、断路、信号漂移等故障。这套功能的逻辑很简单难的是时序确定性同样由实时主循环统一调度保证注入动作发生在精确的控制周期内。4.2 测试序列引擎从私有格式到pytest框架AutomationDesk和VeriStand Test Sequence都是图形化的测试序列编辑器功能很完善步骤循环、条件判断、参数集调用、步骤失败后的行为配置。但私有格式带来的问题是序列文件没法diff、没法代码评审、没法通过脚本批量生成。我们最终用pytest做测试序列引擎每一条测试用例就是一个Python函数YAML文件保存参数和边界值。pytest带来的工程化能力是原本的图形化序列编辑器很难比的。fixture机制天然解决了“环境准备、上电、采样、下电、清理”这类前后置步骤参数化parametrize可以把同一套逻辑应用到几十组输入条件下失败重试、超时控制、日志采集都有现成插件Allure报告插件又补上了dSPACE那份图形化报告的文件感。团队里新来的工程师第一次看pytest代码就敢改测试用例这在原来面对AutomationDesk那种复杂的步骤树时几乎不可能。序列的一致性也得到很大提升。原来同一个测试用例在不同台架上可能因为参数复制漏了某个值而产生差异现在参数全部集中在yaml里用git管理commit历史即变更依据。4.3 在线监测、数据记录与报告dSPACE的ControlDesk在在线监测上体验很好启动后就能拖几个仪表盘实时看变量。迁移后的方案我们用Qt制图控件加信号订阅实现同等能力实时目标机通过共享内存发布变量上位机的订阅线程刷新波形和数字表。通信负载很低几路波形加数十个变量完全无压力。关键是变量列表做成配置文件新增观察变量不用重新编译重启加载配置即可。数据记录这块原来多数靠台架电脑上的CSV文件。迁移后我们在服务层加了一个采集模块按测试阶段把数据直接写入TSDB类数据库同时保留原始高頻数据到HDF5文件。这样现场在界面上可以按时间段、工位、产品批次查历史曲线不用再到一堆CSV目录里大海捞针。报表生成用openpyxl直接写Excel格式、温度、限值、判定结论、波形缩略图全部自动填好。在线监测和记录模块的稳定性关键在于“边界”要清晰采集端不丢点、不卡界面界面端不要过度刷新导致CPU飙高。我们后来把波形刷新帧率限制在20-30fps数据采样依然是尽可能高的原始频率画面上看到的波形是降采样后的视图需要精确值时用游标读取原始数据文件。5. 迁移遇到的高频问题与排查记录5.1 部署打包的坑从Runtime依赖到绿色发布LabVIEW程序发布时最让人头疼的就是Runtime Engine和各种驱动依赖。版本对不上、路径不对、装了新版反而不识别旧程序这些问题网上一搜一大把。迁移到Python后部署逻辑变得相对清爽但并不等于没有坑。第一个坑是Python环境干净性。这方面我们踩过很多次Anaconda全家桶装上去后程序在开发机上运行正常到现场却报库冲突。后来生产环境统一用虚拟环境加直接打包成单目录exe或者容器化彻底避免导入路径污染。部署包做出来以后现场电脑不再需要预装开发环境也不会出现LabVIEW运行时8.5和2023版本混装的尴尬局面。第二个坑是Win7兼容性。现在很多产线电脑还在Win7PyQt在Win7上的兼容性要看版本选择。我们测试后把Qt版本锁定在较早期的系列同时避免使用新版API里仅支持新系统的那部分功能。如果完全不支持Win7我们就把运行环境做成免安装绿色版通过批处理脚本设置环境变量一样能工作。关键是这件事必须在选型阶段就明确等到界面写了一半才发现系统不支持返工成本极高。5.2 通信可靠性问题实录串口通信迁移过程中遇到过几个典型怪问题。第一件是读取丢字节。分析下来是收数据线程在处理一段数据的同时新数据到达把缓冲区覆盖了。解决办法很简单收数据线程只负责把原始字节写进一个带锁的队列专门开一个解析线程按协议提取完整帧处理逻辑放到解析线程外。这个模型和LabVIEW里“生产者消费者”模式如出一辙只是文本语言里更容易看出线程边界。第二件是超时设置不当导致程序假死。SCPI指令下发后仪器响应时间在不同命令之间差很多有的指令几百毫秒有的要几秒。如果全局统一设置超时就会出现要么频繁报超时、要么卡住等下一条指令。我们的做法是按指令类型维护一个超时表并且在下发指令前开启看门狗超过基础时间后先查仪器状态再判定是否真的报错。第三件是帧边界识别错误。很多串口设备协议帧头是0xA5 0x5A这类特征字数据负载里也可能出现相同字节。没有统一处理时解析器偶尔错乱。我们后来把预处理逻辑固定成“按帧头搜索、按长度截取、按CRC验算”算法不通过就丢掉这一帧再重新找帧头。这套逻辑移植之前我专门跑过一个覆盖随机数据错乱的模拟用例试了上万帧才放心上线。5.3 波形显示、性能与数据竞争问题波形显示卡顿是迁移后的一个明显痛点。最初用原生Qt控件绘制多通道曲线数据量大时CPU占用直接拉满。换成PyQtGraph后性能肉眼可见地改善。但真正的大头还不是绘图本身而是刷新策略。如果每收到一个数据点都全量重绘一次哪怕用PyQtGraph也会卡。我们后来按固定刷新间隔30毫秒从循环队列中取增量数据重绘再配合只显示可视范围内的数据现场多人同时操作也没有再出现过掉帧。数据竞争问题在多工位并发后集中爆发。多个线程同时往同一个列表写测试结果偶尔会出现结果串位或丢失。定位方式也很直接写一个小脚本反复起多个线程并发写入用结果集合的一致性来判断是否有竞态。修法是给公共数据区统一加锁同时关键路径只允许主线程碰界面。这套规矩在代码评审时作为硬性要求后续几乎没有再犯过类似错误。6. 一点私货替换的真正门槛不在代码回到标题那句“再见了VeriStand / dSPACE / LabVIEW”。很多同行听到自主可控第一反应是公司要花很多钱、团队要学很多新东西。我的真实感受恰恰相反钱和代码都是可以计量的投入真正困难的是打破“工具决定思路”的惯性。LabVIEW里的图形化连线确实降低了入门门槛但也让很多工程师习惯了“不被版本管理”“不被单测覆盖”的写代码方式。迁移到文本工程之后团队被迫把测试步骤、协议解析、数据格式当成工程资产来治理这套转变比技术栈替换带来的长期价值更高。我们后来招聘新人时说得很直接优先看能不能独立把一个串口协议解析清楚、能不能把一个定时任务写出可测试的代码而不是看他点LabVIEW面板有多熟练。如果你也在评估这条路线我建议先从一条相对独立的台架开始把采集、界面、记录、报表全链路做通再逐步扩展到HIL和复杂实时场景。过程中尽量保存各层接口的文档和契约保证每一层都可以单独替换。等到你手里那一套系统任何时候都能独立升级、独立维护不再因为某个商业工具的版本策略而被迫加班时你就会明白自主可控这四个字对工程师来说究竟意味着什么。最后再分享一个小技巧迁移期间不要急着删掉老工具。我们让新旧两套系统在同一个台架上并行跑了两个月每条测试记录都交叉比对过结果之后再切产线。这个并行期看起来是双倍工作量实际上帮我们消化了大量隐蔽的兼容性问题强烈推荐给所有打算迈出这一步的团队。
返回列表