刚接手这个项目时,我第一反应是怀疑:一台250kW燃料电池机车,控制核心为什么要用LabVIEW?按我的惯性思维,这种轨道交通装备级别的控制,要么PLC,要么C++,LabVIEW总感觉是实验室里做数据采集的东西。等我把整车逻辑跑通、现场联调完,才意识到LabVIEW在这个场景里的价值不在于“能不能控制”,而在于它能把复杂的并发任务组织得让工程师看得懂、改得动、调得快。
所谓250kW燃料电池机车,说白了就是靠燃料电池发电驱动牵引电机的轨道交通车辆。车上除了整套氢燃料电池发电系统,还有动力电池、DC/DC变换器、牵引变流器、牵引电机、制动电阻,以及一堆水泵、空压机、阀件和传感器。LabVIEW在这个项目里干了整车控制加监控的活:发功率指令、管电堆启停和吹扫、看氢系统状态、跟BMS和变流器通信,同时把几百个参数实时呈现给操作员。
这篇文章想把从架构设计到现场调试的完整过程梳理一遍,重点放在LabVIEW控制方案怎么落地、CAN通信怎么处理、功率跟随怎么整定、故障保护怎么分级。适合正在做LabVIEW控制类项目、或者准备碰燃料电池和混合动力系统的工程师参考。这里面的经验和坑,比教科书上写的实在得多。
1. 整车控制架构:LabVIEW要管哪些事
1.1 为什么是LabVIEW而不是PLC或C++
先说结论:LabVIEW不是万能的,但在这个项目里它是最合适的“策略层”工具。
整车控制分两层:底层是安全回路和硬线互锁,这一层我用的是继电器和PLC;上层是功率管理、状态切机、故障诊断和通信组带,这一层就是LabVIEW的地盘。为什么这么分?因为燃料电池机车的控制对象太多太散,而且大部分子系统都是“黑盒”,燃料电池控制器、BMS、牵引变流器各自带着自己的逻辑,整车控制器要做的是在一个大循环里把它们的指令和数据揉到一起。
LabVIEW的优势在这里非常明显。第一,数据流编程天然适合并发场景,CAN接收线程、发送线程、UI刷新、故障监控可以并行跑,不用像文本语言那样手动管理线程、锁和信号量;第二,UI和逻辑在一套环境里,调试时拖几个控件就能把内部状态可视化,做功率跟随调试时我直接把母线电压曲线和电堆电流曲线放同一个Graph里看,效率极高;第三,LabVIEW对NI硬件的支持是原生的,如果控制目标直接部署到CompactRIO或PXI上,实时性还能上一个台阶。
当然,PLC和C++也各有位置。纯逻辑的硬安全交给PLC,因为PLC的扫描周期确定、故障行为可预期;底层算法比如牵引变流器里面的FOC矢量控制,那必然是DSP或者FPGA的事。LabVIEW的位置是“大脑皮层”,做决策和协调,不碰最终执行器的高速控制。这个边界在一开始就必须划清楚,否则后面会混乱。
| 方案 | 优点 | 缺点 | 这个项目里的定位 |
|---|---|---|---|
| PLC | 稳定可靠、适合硬安全逻辑 | 复杂策略和数据处理麻烦、可视化能力弱 | 安全回路、硬线互锁 |
| C++ | 性能强、可移植性好 | 开发周期长、调试并发问题痛苦 | 变流器内部算法、底层驱动 |
| LabVIEW | 图形化并发、开发调试快、HMI集成 | 需要正版授权、对第三方硬件依赖驱动 | 整车控制策略、监控、故障诊断 |
1.2 整车控制拓扑:三级分层
整个控制架构我设计成三层,原则是“上层只管策略,下层只管执行”。
第一层是人机指令层,包括司机控制器、按钮、触摸屏和仪表显示。驾驶员的牵引手柄推到一个位置,产生一个百分比的牵引指令,这个指令不走模拟量直接去拉电流,而是先进入整车控制器。
第二层是整车控制层,也就是LabVIEW运行的工控机或者PXI系统。它干的事情包括:解析驾驶指令、查牵引特性曲线算出需求功率、决定燃料电池输出多少、动力电池补多少、给牵引变流器发转矩指令,同时管理整车的状态机、故障等级和通信链路。这一层是项目的核心,后面所有内容都围绕它展开。
第三层是子系统执行层。燃料电池系统有自己的控制器FCCU,通过CAN接收功率指令,内部自己去管氢气压力、空气流量和电堆温度;DC/DC变换器接收电流指令,把电堆的低压大电流变换到直流母线电压;BMS负责动力电池的SOC和绝缘检测;牵引变流器接收转矩/转速指令,内部完成电机控制;辅机系统的水泵、空压机、风扇则通过Modbus RTU通信去控制。
这三级之间的通信链路主要靠CAN总线和Modbus。手头有条件的话,建议把整车CAN、子系统CAN、调试CAN用网关分开,避免调试时一个节点干扰全车。我们前期图省事整了一条CAN,结果某个子系统频繁掉线,排查了一个星期,后来分网才解决。
注意:分层不是物理上把设备拆开,而是逻辑边界要清晰。每个子系统都是黑盒,整车控制器只跟它的通信接口打交道,绝不能跨层直接控制某个接触器或继电器,否则出了事故责任界面都说不清。
1.3 安全回路:软件永远替代不了硬线
这一点我必须放到最前面强调:LabVIEW再聪明,也不能替代硬线安全回路。
燃料电池机车上有几个致命风险:氢气泄漏、绝缘失效、过温、急停。这些信号必须通过硬线直接接到安全继电器回路,一旦触发,不管软件在干什么,主接触器直接断开、氢瓶电磁阀直接关闭。LabVIEW只做一件事:通过数字量输入模块读取安全回路的干接点状态,回路断开就立刻进故障流程,记录时间戳并显示报警。
我见过一些团队为了省成本,把急停信号只接到PLC里,依赖PLC程序去断电。在这种高压大功率的场合,这是绝对不能接受的设计。软件运行有可能卡死,LabVIEW进程有可能崩溃,Windows有可能蓝屏,但硬线回路不会。安全设计的原则很简单:最坏情况下即使所有控制器都失效,车上还有一套独立的硬线能切断能量。
如果安全PLC用的是西门子的S7-1200或者S7-200 SMART,LabVIEW和它通信可以直接用OPC UA,也可以用开源的Snap7库直连读状态。我在后期调试时就让LabVIEW周期读取安全PLC里急停回路的反馈位,一旦发现反馈与指令不一致,立刻判定为安全回路故障。
2. 燃料电池机车控制逻辑与HMI设计
2.1 整车状态机:从自检到吹扫下电
把整车控制逻辑建模成状态机,是我在这个项目里做得最正确的决定之一。燃料电池机车不像普通电动车,一脚电门下去就完事,它有一套非常长的上电和断电流程,每一步都有先后顺序和确认条件。如果不用状态机,而是一堆布尔量散落在各个VI里,调试的时候你会疯掉。
我用LabVIEW做了这几个主状态:PowerOn、Standby、Ready、Run、Fault、Shutdown。每个状态内部还有细分步骤,比如PowerOn里包含绝缘检测、氢检、冷却启动等子步骤。状态转换不是随便跳的,每个转换条件都要满足上一状态的所有条件加上触发事件。
| 当前状态 | 触发事件 | 执行动作 | 目标状态 |
|---|---|---|---|
| PowerOn | 自检全部通过 | 记录就绪、允许上电 | Standby |
| Standby | 收到启动指令 | 启动氢回路、开始电堆准备 | Ready |
| Ready | 收到牵引指令 | 使能DC/DC、发功率指令 | Run |
| 任意 | 故障等级≥2 | 降功率或停机、召唤处理 | Fault |
| Run | 收到停机指令 | 降载、吹扫、泄压 | Shutdown |
在代码实现上,状态变量用LabVIEW的枚举控件保存,外面套一个条件结构,每个条件分支里再放子状态机。所有状态跳转都记录到一个事件日志数组里,带时间戳。后期复现问题的时候,把事件日志导出来一看,就能知道故障发生前五分钟系统到底经历了什么。这个习惯帮我省了大量排查时间。
2.2 燃料电池系统的启动和停机流程
燃料电池系统是整个机车上控制时序最长、条件最多的部分。上电流程大概是这样:先让冷却水泵转起来建立循环,同时做绝缘检测和氢气泄漏检测;确认没泄漏以后,打开氢瓶主阀和电堆进气阀,等氢气压力稳定;然后启动空压机建立空气供给;最后才让DC/DC使能,电堆开始加载发电。
每一步都有超时时间。比如绝缘检测15秒没完成,直接返回失败;氢气压力30秒内没达到设定值,也要回滚到安全状态。回滚的意思是一步步还原,先关氢阀,再泄压,然后延时停水泵,不是简单把程序跳回待机就完事。
停机流程比启动流程更考验细节。电堆不能带着功率直接切断,得先把负载降到最小,然后让DC/DC功率降到零,接着做吹扫——用氢气或氮气把电堆阳极残留的水吹掉,防止停堆后水淹和低温冻结。吹扫时间取决于电堆温度和上次运行时长,程序里我留了可配置的参数,实测下来冬天吹扫时间必须比夏天长至少一倍,否则再次启动时电压拉不上去。
2.3 关键监控参数与操作界面布局
250kW燃料电池机车的监控参数非常多,满打满算几百个点。如果UI全铺出来,操作员根本看不过来。我的原则是:一屏显示关键信息,二屏显示细节曲线,三屏留给故障和事件。
主屏放最关键的十几个参数:母线电压、母线电流、电堆功率、电堆电压、电堆电流、DC/DC效率、动力电池SOC、氢瓶压力、氢气泄漏浓度、冷却液温度、空压机转速、牵引电机转矩和转速。这些参数用大字号数字控件显示,颜色根据正常/告警/严重自动变化。
| 参数 | 正常范围 | 告警阈值 | 严重阈值 | 处理方式 |
|---|---|---|---|---|
| 母线电压 | 700~800V | 超过840V或低于650V | 超过860V或低于550V | 降功率/断接触器 |
| 电堆功率 | 0~250kW | 超过260kW | 超过280kW | 限制电流/停机 |
| 氢气泄漏浓度 | 0~200ppm | 超过500ppm | 超过1000ppm | 降功率/停机+断开氢阀 |
| 冷却液温度 | 40~75℃ | 超过80℃ | 超过85℃ | 降功率/停机 |
| 动力电池SOC | 30%~90% | 低于20%或高于95% | 低于10%或高于98% | 限制充放电 |
UI布局我建议用Tab控件分页,不要把所有东西堆在一个界面。实时趋势图一定要有,调试功率跟随的时候,我同时看母线电压、电堆电流、需求功率和实际功率四条曲线,参数好坏一眼就能看出来。报警显示单独占一块区域,最新的排在最上面,并且每条报警要带状态机的状态信息,否则光看报警文字判断不了当时整车处于什么状态。
3. CAN通信链路搭建与报文处理
3.1 CAN硬件选型与驱动匹配
CAN总线是这套系统的数据主动脉。燃料电池控制器、BMS、牵引变流器基本上都有标准CAN接口,个别辅机走Modbus RTU。选CAN硬件的时候,我考虑过NI的XNET系列,性能确实好,而且LabVIEW原生支持,实时目标上还能直接FPGA级收发,但是价格一下就上去了,而且这个项目没有到需要微秒级同步的程度。
最后我用的是周立功的USBCAN-II,成本不高,驱动在LabVIEW里调用dll就行。网上有现成的周立功CAN通信-LabVIEW示例,但要注意几个问题:第一,周立功的驱动接口是32位dll,LabVIEW也要用32位版本,否则调用会报错;第二,不同批次设备的设备号不同,初始化时设备号、CAN通道号要能配置;第三,驱动安装后最好用自带测试工具先确认硬件工作正常,再进LabVIEW,免得软件层面排查半天结果设备根本没识别到。
如果项目预算充足,或者打算把控制器部署到CompactRIO/PXI上做实时控制,强烈建议直接用NI XNET。XNET在RT目标上有独立的内核线程,收发时间戳精度能到纳秒级,对通信故障分析帮助很大。但普通工控机加Windows,USB-CAN加队列足以应付这个项目的数据量。
3.2 通信协议表:命根子
写LabVIEW程序之前,先把CAN协议表整理出来。协议表是整车通信的命根子,没有它,后期调试一定乱套。
我把每个子系统的报文做成一张Excel表,内容包含:报文ID、发送周期、数据长度、字节定义、数据类型、因子、偏移量、取值范围。举个例子,发给DC/DC的电流指令报文:
| 报文ID | 周期 | 字节 | 信号名称 | 因子 | 偏移 | 范围 |
|---|---|---|---|---|---|---|
| 0x0CF11E00 | 20ms | Byte0-1 | 目标电流指令 | 0.1A/bit | 0 | 0~500A |
| 0x0CF11E00 | 20ms | Byte2 | 控制模式 | 1 | 0 | 0~2 |
| 0x0CF11E00 | 20ms | Byte3 | 使能状态 | 1 | 0 | 0或1 |
这里最容易被坑的是字节序。很多控制器默认使用Intel格式(小端),低位在前,但也有设备用Motorola格式(大端)。解析的时候如果字节序搞反了,读出来的电流值可能差了几十倍。协议表里必须标注清楚,LabVIEW解析VI里也要按协议统一处理,最好做一个集中的解析库,所有设备都用同一套函数,不要在每个VI里写复制粘贴的解析代码。
3.3 LabVIEW收发程序框架
LabVIEW本身的图形化代码没法直接在文章里贴出来,但整个程序的框架可以说清楚。CAN接收用生产者消费者模式:USB-CAN的回调或定时读取作为生产者,把原始帧推入队列;消费者循环从队列取出每一帧,按照协议表解析,更新到一个全局数据簇或者功能全局变量中。
// 生产者:CAN接收循环 while (run) { ret = CAN_Receive(device, channel, &frame, timeout); if (ret == success) { Queue_Push(receiveQueue, frame); } } // 消费者:CAN解析循环 while (run) { frame = Queue_Pop(receiveQueue); if (frame.id == 0x0CF11E00) { current = (frame.data[0] | (frame.data[1] << 8)) * 0.1; mode = frame.data[2]; enable = frame.data[3]; UpdateSharedData("DC_DC", current, mode, enable); } }CAN发送同样是一个独立循环。周期报文用定时循环控制,20ms的报文就用“等待下一个整数倍毫秒”的节点,确保发送周期稳定。直接调用Wait(ms)会有累积漂移,20ms的报文跑半小时可能就变成30ms了,这对功率控制来说是不可接受的。发送内容不要直接写在发送循环里,而是从控制逻辑循环中通过队列或局部变量取最新值,保证每个周期发出去的都是最新数据。
3.4 实时性与通信超时处理
Windows不是实时系统,用USB-CAN做控制有几个固有风险:USB枚举不稳定、驱动缓冲可能溢出、系统调度存在不确定性。解决办法是在软件层面做防护。
第一,每条周期报文必须带时间戳。我定义了一个“最近收到时间”的全局变量,接收解析循环每次更新。另外有一个监控循环,每100ms检查一遍所有周期报文的上次接收时间,如果超过正常周期三倍还没收到,就判定通信超时。比如20ms周期的报文,超过60ms没收到就报警,超过200ms没收到就降功率或者进入故障状态。
第二,接收循环的消费者处理速度必须够快。USB-CAN接收缓冲区一旦溢出,前面的报文会被硬件直接丢弃,现象就是某个信号偶尔跳变或者长时间不更新。当时我们遇到过一次,排查到最后发现是UI刷新占用了大量CPU,消费者循环被挤到几百毫秒才处理一次。后来把UI刷新降到10Hz,并且把CAN解析循环的优先级调高,问题立刻消失。
第三,如果要把控制逻辑部署到NI RT目标上,建议用RT FIFO替代队列,用定时循环配合wire和local variable,实时性会可靠很多。上位机加Windows的方案适合调试和监控,不适合作为最终量产的整车控制器。
4. 功率跟随控制与安全保护策略
4.1 250kW功率链路的关键参数计算
控制算法不是凭空写的,先要把功率链路的参数算清楚。一套250kW燃料电池系统,电堆输出的电压通常不高,250~450V左右,因为电堆单体电压低、串联数量也有限。额定功率250kW在450V端电压下,电流大约是:
I = P / U = 250000W / 450V ≈ 556A
这个556A决定了电堆侧电缆、接触器、熔断器和铜排的规格,整套东西都要按至少600A去选。电堆出来的电一般要经过DC/DC变换器升压到750V直流母线,这样升压后母线上的电流大约就是:
I = 250000W / 750V ≈ 333A
母线侧的电缆和接触器按400A选就行,跟电堆侧差了一个等级,设计的时候别搞混。牵引峰值功率如果按500kW算,燃料电池输出250kW,剩下250kW就由动力电池来补。电池的放电倍率和容量也是按这个峰值功率去匹配的。
氢气消耗量也可以算一笔账。燃料电池发电效率一般按50%估算,氢气的低热值约33.3kWh/kg。要产生250kW电功率,对应的氢气化学能输入就是500kW:
每小时耗氢量 = 500kW / 33.3kWh/kg ≈ 15kg/h
这个数值直接影响到氢瓶容量、管路直径和整个续航计算。控制程序里我也会显示实时氢耗,便于观察燃料电池效率是否正常。
4.2 功率跟随控制与PID整定
燃料电池机车的功率控制目标是这样的:驾驶员推手柄,整车控制器根据牵引曲线算出当前需要的总功率,然后分配——燃料电池给出稳态功率,动力电池补动态缺口,制动时能量回馈到电池或制动电阻。
我这里用的是级联PID结构。外环控制直流母线电压,目标是维持750V,外环PID的输出作为内环电堆电流指令。内环控制电堆实际输出电流,内环输出给DC/DC变换器的目标电流。为什么不用单环直接用功率指令控制DC/DC?因为燃料电池动态响应慢,不能直接跟需求功率变化,必须通过母线电压间接控制,让动力电池承担动态部分,否则电堆很容易被拉出氧饥饿。
PID参数整定顺序是先内环后外环。先把内环的P调好,让它跟随阶跃指令没有大的超调,再加一点积分消除稳态误差;然后调外环,外环的作用是让母线电压稳住,P不能太大,否则母线电压来回震荡。经验上外环的比例系数从0.2左右开始试,积分时间常数10秒左右;内环比例系数从0.5左右开始试。这只是这个项目的参考值,具体参数取决于通信周期和系统惯性。
除了PID,功率变化率限制必须单独做。燃料电池的加载速度一般有限制,我设了10kW/s的爬坡率上限。直接用PID输出去驱动DC/DC,如果PID响应太快或者需求功率跳变太大,电堆功率可能瞬间拉高,空气系统跟不上就会欠气,最坏情况会导致电堆局部反极,那损失就大了。程序里我在PID输出后面加了一个rate limiter,同时把PID输出的变化率限制写进DC/DC的指令里,双保险。
注意:PID的积分项在通信故障时一定要冻结或者清零。我们调试时发现,CAN通信偶发丢帧会让直流母线电压反馈短暂卡在旧值,积分项持续累加,等通信恢复后母线电压过冲接近20V。后来加了“通信故障时冻结PID输出”的逻辑才稳住。
4.3 故障分级与安全保护策略
整车故障不能只有“报错”和“停机”两档,必须分级处理。我把它分成三级:
| 等级 | 处理方式 | 典型触发条件 |
|---|---|---|
| Level 1 | 记录报警,仅提示操作员 | 雾气泄漏检测低阈值、某个温度传感器轻微偏高、SOC偏低 |
| Level 2 | 降功率运行,限制电堆输出到50% | 冷却液温度偏高、氢气泄漏达到中阈值、空压机效率偏低 |
| Level 3 | 紧急停机,断开主接触器和氢阀 | 氢气泄漏高阈值、绝缘故障、急停触发、母线过压/欠压 |
LabVIEW程序里要做一个全局故障状态簇,包含每个故障源的上次触发时间、当前等级、锁存状态。每个控制循环里最先做故障扫描,得出当前整车允许的最高运行等级,然后决定状态机应该待在Run还是跳到Fault。故障复位不能简单自动清零,重要故障需要锁存,必须操作员确认信号恢复正常后手动复位,防止故障反复跳动导致接触器频繁吸合断开。
安全保护还有一个原则:软件只发起“请求”,最终执行靠硬线。LabVIEW检测到Level 3故障,能做的是把主接触器指令置为断开、把氢阀指令置为关闭,并且把这个状态通过硬线输出反馈给安全PLC,由安全PLC确认实际执行。执行结果要反馈回来,如果LabVIEW发了断开指令但接触器反馈还在闭合状态,必须判定为安全执行失败,触发整车急停硬线。
5. 现场调试踩坑实录与排查方法
5.1 LabVIEW安装部署与驱动兼容的坑
项目刚开始的时候,光环境就折腾了快两天。LabVIEW安装报错是最常见的问题,原因无非几种:安装路径带了中文或者特殊字符,杀毒软件拦截了驱动组件,许可证没有激活,或者旧版本残留。我的建议是装LabVIEW时老老实实走默认路径,不要自作主张改到D盘自定义目录,很多第三方驱动和NI组件默认找的是C盘相对路径。
还有一个非常隐蔽的坑:LabVIEW位数的选择。周立功USBCAN-II的驱动包是32位dll,虽然它也有64位版本,但很多第三方驱动更新滞后。我一开始装了LabVIEW 64位,调用CAN dll一直失败,后来改用32位版本一次就通了。如果项目里要用第三方硬件驱动,先确认驱动支持多少位,再决定LabVIEW装多少位。
部署的时候也踩过坑。直接在开发机上跑没有问题,但用Application Builder打包后到现场工控机上装,提示缺各种运行时组件。后来我打包的时候把“安装NI运行时引擎”选项选上,并且把第三方dll一起打包到exe目录,才解决了问题。现场如果只有Ubuntu主机,LabVIEW也有Linux版本,但第三方USB-CAN驱动不一定有Linux版,立项前就要确认好,否则跨平台就是给自己挖坑。
5.2 CAN通信与功率震荡的现场排查
联调阶段遇到最多的问题是CAN通信“看起来正常但数据不对”。数据不对大概率出在字节序、因子和偏移上。比如一个电流信号因子是0.1A/bit,如果按1A/bit去解析,实际500A的电流会显示成5000,第一反应以为是传感器坏了,其实是解析问题。排查的时候先用CAN测试工具抓原始帧,手算一遍字节值,跟协议表核对,再回看LabVIEW解析结果,一步就能定位。
丢帧问题也要重点说。USB-CAN接了之后,如果长时间跑,某些报文会偶发缺失。原因通常是接收缓冲区溢出或者消费者循环处理不过来。我当时的解决方法是:把UI刷新频率降下来,消费者循环里只做解析和共享变量更新,不做任何文件写入;文件记录放到单独的更低优先级循环里。另外一个很实用的技巧是给每帧报文加计数器,接收方检查计数器是否连续,不连续就知道丢了多少帧,这对定位问题帮助极大。
功率震荡问题调试了好几次。现象是机车怠速时母线电压上下波动,幅度到20V左右,虽然不至于跳闸,但听着变流器声音都觉得不舒服。先怀疑PID参数,把外环P调小效果不明显;后来发现是CAN发送循环和功率控制循环的周期没对齐,功率指令时快时慢。把发送循环改成20ms严格定时,再给PID输出加软件滤波,震荡就消失了。回头想想,这种问题不一定是算法本身错了,而是执行周期抖动把系统带得振荡。
5.3 常见问题速查表
| 现象 | 可能原因 | 排查思路 | 解决建议 |
|---|---|---|---|
| LabVIEW安装报错 | 路径含中文、杀软拦截、旧版本残留 | 查看详细日志、关闭杀软 | 用默认安装路径,清理残留 |
| 调用CAN驱动失败 | LabVIEW位数与驱动dll不匹配 | 确认LabVIEW是32还是64位 | 换用匹配位数的LabVIEW |
| CAN报文收到但值不对 | 字节序错误、因子偏移错误 | 抓原始帧手算核对协议表 | 统一解析库,标注字节序 |
| 周期报文偶发丢失 | 接收缓冲区溢出、处理不及时 | 检查计数器连续性、CPU占用 | 队列消费、降UI刷新、提高优先级 |
| 母线电压震荡 | PID参数不当、指令周期抖动 | 看曲线、检查发送周期 | 加滤波、严格定时、冻结积分 |
| 功率指令发了但电堆没反应 | DC/DC使能位没置位、CAN超时被保护 | 检查使能逻辑、通信状态 | 确保使能顺序正确、超时逻辑合理 |
最后再说几句
工程上做LabVIEW控制,最怕的不是不会用控件,而是逻辑混乱。我见过一些项目把启停逻辑散在十几个VI里,改一个条件要翻半天框图。我的个人习惯是:状态机全局只有一个,通信解析集中在一个公共库里,所有关键参数做成配置文件,不写死在程序里。前期多花一点时间把架构理清,后面调试能省一半时间。
这趟250kW燃料电池机车项目下来,最大的收获不是LabVIEW技巧,而是明白了哪些事必须用硬线兜底,哪些事可以放给软件去优化。LabVIEW负责聪明,安全回路负责可靠,两者配合才能让这套系统既智能又安全。如果你也在做类似的LabVIEW控制项目,建议开工前先把状态机图和CAN协议表画清楚,再动手拖框图。这是我踩了无数次坑之后最想跟你说的一句话。