ARTICLE DETAIL

资讯详情

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

Veristand Custom Device开发实战:HIL数据流控制模块设计与实现

Veristand Custom Device开发实战:HIL数据流控制模块设计与实现 1. 为什么要在Veristand里自己写Custom Device如果你已经在用Veristand做HIL测试大概率遇到过这种尴尬模型跑起来了IO板卡也通了但数据流就是不听使唤。比如你想在某个转速阈值触发时把一路CAN信号切换到另一路模拟量输出或者想把采集到的原始数据先做一层滤波再喂给模型——Veristand自带的通道映射和激励编辑器做不了这种带逻辑的实时处理。这时候有两条路一是把逻辑塞进Simulink模型里二是写一个Custom Device。前者的问题是模型编译一次动辄十几分钟改一行逻辑就要重新生成代码迭代效率极低后者用LabVIEW写编译快、部署灵活而且能直接操作硬件IO实时性也有保障。我这次接到的需求就是一个典型的HIL数据流控制模块在Veristand环境下通过Custom Device实现多路模拟量采集、阈值判断、通道切换和故障注入功能。关键词里的Veristand、Custom Device、HIL、LabVIEW这几个词基本框定了技术栈——用LabVIEW开发Custom Device跑在Veristand的实时引擎上服务于硬件在环测试。这篇文章适合两类人看一类是刚接触Veristand Custom Device、想知道从零怎么搭的另一类是用过但踩过坑、想搞清楚数据流到底怎么在Custom Device里流转的。我会把整个开发过程拆开讲包括为什么这么设计、哪些地方容易翻车、以及实测下来比较稳的做法。2. 动手之前先把Custom Device的骨架搞清楚2.1 Custom Device在Veristand里的角色定位Veristand的架构可以粗略理解成三层上层是Host界面负责配置和监控中间是实时引擎跑在RT目标机上底层是各种设备驱动和模型。Custom Device是插在实时引擎里的一个组件它和Veristand的交互通过一套固定的接口——也就是Custom Device API。这套API的核心是几个必须实现的VIInitialize、Start、Stop、Finalize以及可选的Read from HW和Write to HW。Veristand在启动时会调用Initialize来初始化设备运行时按循环周期调用读写VI停止时调用Stop和Finalize做清理。理解这一点很关键Custom Device不是独立运行的程序它是被Veristand主循环调度的。你的代码不能在里面写死循环也不能阻塞太久否则会拖垮整个实时系统的时序。2.2 三种Custom Device模板怎么选LabVIEW里创建Custom Device项目时Veristand提供了几个模板Basic、Inline Hardware、Inline Model。我一开始图省事选了Basic结果发现它默认把读写放在异步循环里延迟不稳定。后来换成Inline Hardware模板读写VI直接挂在Veristand的主定时循环上周期抖动从原来的几百微秒降到了几十微秒以内。选模板的判断标准很简单模板类型适用场景实时性开发复杂度Basic低速数据记录、非实时任务低低Inline Hardware硬件IO控制、闭环测试高中Inline Model需要嵌入模型代码高高我这个项目涉及阈值触发和通道切换对时序敏感所以Inline Hardware是唯一合理的选择。如果你只是做数据日志Basic也能凑合但别指望它能稳定跑在1kHz以上。2.3 项目文件结构里容易忽略的细节创建完项目后LabVIEW会生成一堆文件其中这几个必须搞清楚Custom Device Definition XML定义设备的通道、属性、页面布局。Veristand读这个文件来生成配置界面。Initialization VI解析XML配置初始化内部数据结构。Main VI包含读写循环是数据流的核心。RT Driver VI编译后部署到RT目标机的入口。我踩过的一个坑是改了XML里的通道定义后忘记在Initialization VI里同步更新解析逻辑结果Veristand界面上能看到通道但运行时数据全是零。XML和代码必须同步改这是铁律。3. 数据流控制模块的核心逻辑怎么落地3.1 从硬件采集到模型输入的完整链路这个模块的数据流大致是这样的模拟量板卡采集原始电压信号 → Custom Device读取原始值 → 做工程单位转换和滤波 → 判断是否超过阈值 → 根据判断结果决定输出通道的取值 → 写回Veristand通道供模型使用。在LabVIEW里这条链路对应的是Read from HWVI里的一个顺序结构。注意不要用条件结构把整个链路包起来因为Veristand每个周期都会调用这个VI条件结构会导致某些周期不执行读取数据出现断点。正确的做法是读取永远执行判断和切换逻辑放在读取之后用选择函数Select而不是条件结构来处理分支。这样每个周期都有完整的数据流只是输出值不同。3.2 阈值判断与通道切换的实现方式阈值判断本身很简单一个比较函数就够了。但通道切换有个细节切换瞬间如果直接跳变会给下游模型一个阶跃激励可能引发振荡。我的做法是加一个斜率限制让输出在N个周期内线性过渡到目标值。具体实现用移位寄存器保存上一个周期的输出值每个周期计算目标值与当前值的差乘以一个系数比如0.1累加到当前值上。这样切换过程平滑实测对模型的冲击小了很多。这里有个参数需要算假设Veristand循环周期是1ms你希望切换在50ms内完成那系数就是1/500.02。系数越小过渡越慢但太慢会影响测试效率。我一般取0.05到0.1之间兼顾平滑性和响应速度。3.3 故障注入功能的实现与边界条件故障注入是这个模块的另一个核心功能模拟传感器断线、信号超量程、信号漂移等异常情况。实现方式是在正常数据流上叠加一个故障值或者直接替换成预设的故障值。但这里有个边界条件容易忽略故障注入的优先级。如果同时触发了多个故障条件哪个生效我的处理是定义一个优先级数组高优先级的故障覆盖低优先级的。比如断线故障优先级最高一旦触发直接输出断线值忽略其他故障。另外故障注入的使能和禁用必须和Veristand的界面联动。我在XML里定义了一个布尔属性FaultEnableInitialization VI里读取这个属性Main VI里根据它的值决定是否执行故障逻辑。这样操作人员可以在Host界面上实时开关故障注入不用重新部署。4. 编译部署环节的坑与排查过程4.1 编译报错“VI不兼容RT目标”的根因第一次编译时LabVIEW报了一堆错说某些VI不支持RT目标。排查后发现两个原因一是用了RT不支持的函数比如某些字符串处理和文件IO函数二是调用了第三方DLL但没把DLL部署到RT目标机上。RT目标的LabVIEW是精简版很多Host上能用的函数在RT上不存在。解决办法是所有在RT上运行的VI只能用RT支持的函数集。具体哪些支持可以查LabVIEW帮助里的“RT Module支持的VI列表”。我后来把字符串处理全部改成字节数组操作问题就解决了。第三方DLL的问题更隐蔽编译能过但部署后运行时报错“找不到DLL”。需要在Custom Device的配置里指定DLL路径并确保DLL文件被复制到RT目标机的对应目录。这个目录通常是/ni-rt/system/下面。4.2 部署后数据不更新的排查链路部署成功后Veristand界面上通道值一直是零但RT目标机的CPU占用率很高说明代码在跑只是数据没出来。排查步骤先在Main VI里加一个计数器每个周期加一把这个计数器写到某个通道上。结果计数器在动说明Main VI确实在执行。再检查读取VI的返回值发现读取函数返回了错误码。查手册错误码含义是“通道未配置”。回到XML检查通道定义发现读取通道的Direction属性写成了Output应该是Input。改过来重新编译部署数据正常了。这个问题的教训是XML里的通道方向必须和实际数据流方向一致。Input是Veristand从硬件读Output是Veristand往硬件写。写反了不会报配置错误但运行时读取会失败。4.3 实时性不达标时的优化方向数据通了之后测了一下循环周期抖动发现偶尔会跳到2ms以上设定是1ms。对于HIL测试来说这种抖动可能导致模型求解不稳定。优化从三个方向入手减少VI调用层级把一些子VI直接展开到主VI里减少调用开销。LabVIEW的子VI调用在RT上是有成本的层级越深开销越大。预分配数组和内存RT上动态内存分配是大忌。所有数组在Initialization阶段就分配好固定大小运行时不改变维度。关闭调试信息LabVIEW默认会在VI里保留调试信息这会增加内存占用和执行开销。在RT目标上部署前把VI的调试选项关掉。优化后抖动降到了200微秒以内满足要求。5. 和Veristand系统集成的几个关键配置5.1 通道映射与别名管理Custom Device定义好通道后需要在Veristand的System Definition里把这些通道映射到具体的硬件IO或模型端口。这里建议给每个通道起一个有意义的别名比如AI_Throttle_Position而不是AI0。后期维护时看到别名就知道信号含义不用翻手册。别名在XML里通过Alias标签定义Veristand会自动在映射界面里显示。注意别名不能重复也不能包含特殊字符否则Veristand会报错。5.2 属性页面的自定义与参数传递Custom Device的配置界面是通过XML定义的属性页面。我定义了几个关键参数采样率、阈值上限、阈值下限、切换斜率系数、故障使能。这些参数在Initialization VI里从XML读取然后传递给Main VI。这里有个技巧参数读取要用默认值兜底。如果XML里没配置某个参数Initialization VI应该给一个合理的默认值而不是报错退出。这样即使操作人员漏配了某项系统也能跑起来只是用默认行为。5.3 多设备实例的命名冲突问题如果同一个Custom Device在System Definition里被实例化了多次比如两个相同的IO模块每个实例的通道名必须唯一。Veristand会自动加前缀区分但如果你在代码里硬编码了通道名就会冲突。我的做法是所有通道名在Initialization VI里动态生成基于实例名称加后缀。这样无论实例化多少次通道名都不会重复。6. 实测中值得记录的几个经验点6.1 用Veristand自带工具做在线调试Veristand提供了一个Custom Device调试工具可以在Host上实时查看Custom Device的内部变量。用法是在Main VI里把需要观察的变量写到指定的调试通道上然后在Veristand的Debug页面里添加这些通道。这个工具在排查数据流问题时非常有用。比如我之前遇到一个滤波系数不生效的问题通过调试通道看到系数在Initialization阶段被正确读取但在Main VI里被意外覆盖了。没有这个工具光靠猜很难定位。6.2 版本兼容性LabVIEW和Veristand的匹配LabVIEW和Veristand的版本必须匹配否则Custom Device编译会失败。比如Veristand 2020对应LabVIEW 2020Veristand 2021对应LabVIEW 2021。跨版本编译基本都会报错。另外Custom Device API的版本也要注意。Veristand 2019之后的API有较大变化老版本的Custom Device代码不能直接迁移。如果是从旧项目升级建议重新创建项目把逻辑代码复制过去而不是直接打开旧项目编译。6.3 文档化XML注释和VI说明Custom Device项目后期维护时最怕的就是看不懂。我的习惯是在XML里给每个通道和属性加注释在LabVIEW的VI属性里写清楚功能说明和修改记录。特别是XMLVeristand的配置界面不会显示注释但后续开发人员看XML时注释能省很多时间。比如!-- 阈值上限单位伏特范围0-10V --这样的注释比任何文档都直接。7. 这套方案还能怎么扩展这个数据流控制模块目前只做了模拟量通道的阈值判断和切换但框架是通用的。后续可以扩展的方向有几个一是加入CAN信号的处理。Veristand本身有CAN接口Custom Device可以通过CAN API读取报文解析后参与逻辑判断。这样就能实现基于CAN信号的故障注入。二是加入数据记录功能。在Main VI里把关键数据写入TDMS文件跑完测试后可以直接用DIAdem分析。注意RT上的文件写入要用缓冲不能每个周期都写磁盘否则会拖垮实时性。三是把逻辑参数化。目前阈值和斜率系数是配置项但判断逻辑本身是硬编码的。如果做成可配置的状态机就能在不重新编译的情况下改变控制策略。这需要把逻辑抽象成配置表在Initialization阶段解析。我在实际项目里做过类似的扩展把状态机配置放在XML里操作人员通过Veristand界面就能修改状态跳转条件。灵活性提升很大但调试复杂度也上去了适合逻辑变化频繁的场景。最后分享一个小技巧Custom Device开发时先在Host上跑通逻辑再部署到RT。Host上可以用探针和断点调试效率比在RT上高得多。等逻辑稳定了再处理RT兼容性问题。这样能把大部分bug在Host阶段就消灭掉减少RT上的反复部署。
返回列表