2、系统架构设计:基于dSPACE的HIL/SIL/MIL架构选型、硬件资源规划与软件分层

好,咱们进入第二章。系统架构设计,说白了就是给项目搭骨架。骨架搭歪了,后面填再多肉也白搭。我见过太多项目,前期架构没想清楚,到集成阶段才发现硬件资源不够用,或者MIL和HIL的模型根本没法复用——那叫一个痛苦。

这一章,我会结合我自己在几个量产项目里的经验,聊聊怎么选MIL/SIL/HIL架构,怎么规划DS1006、DS1202这些硬件,以及软件层怎么分才清爽。

2.1 MIL/SIL/HIL架构选型:别一上来就上HIL

很多刚接触dSPACE的工程师,容易犯一个毛病:觉得HIL最牛,直接上HIL。其实不是这样的。你想想看,一个控制算法还在改来改去的时候,你拿HIL去跑,那不是杀鸡用牛刀吗?

我个人习惯,按这个节奏来:

  • MIL(模型在环):算法开发初期用。说白了,就是Simulink里跑跑,看看控制逻辑对不对。这时候连代码都没生成呢。
  • SIL(软件在环):代码生成了,但跑在PC上。验证代码和模型是否一致。这一步我建议别省,很多数据类型不匹配的问题,SIL一跑就现原形。
  • HIL(硬件在环):代码烧到控制器里了,接上dSPACE的实时硬件。这时候才真正考验控制器和真实负载的交互。

我的经验之谈:我曾经在一个项目中,客户非要跳过SIL直接上HIL。结果呢?代码里有个uint16溢出,在MIL里根本看不出来,HIL上一跑,电机直接抖起来了。后来老老实实补了SIL测试,半天就定位了问题。所以,别图快,一步一个脚印。

选型时,你可以参考这个表格:

架构 适用阶段 实时性要求 硬件成本 我推荐的使用场景
MIL 算法开发 低(仅需Simulink) 控制策略验证、参数整定
SIL 代码生成后 低(PC即可) 代码一致性测试、回归测试
HIL 集成测试 硬实时 高(需dSPACE硬件) 故障注入、极限工况测试、标定

2.2 硬件资源规划:DS1006和DS1202怎么选?

硬件选型这块,我经常被问到:“DS1006和DS1202到底哪个好?” 其实没有绝对的好,只有合不合适。

DS1006 是dSPACE的老将了,多核PowerPC架构。我个人觉得它最大的优点是稳定。我在一个动力总成项目里,用DS1006跑了整整两年的HIL测试,没出过一次硬件故障。它的IO扩展性也强,适合那种通道数特别多的项目,比如整车控制器HIL。

DS1202 是后起之秀,基于Xilinx Zynq UltraScale+。说白了,它把FPGA和ARM揉在一起了。好处是什么?跑高速信号特别爽。比如电机控制里的PWM信号、旋变解码,用DS1202的FPGA来处理,延迟可以做到微秒级。我有个做电机HIL的朋友,换了DS1202之后,仿真精度直接上了一个台阶。

避坑指南:我曾经在一个项目中,用DS1006跑一个需要高速PWM输出的测试。结果发现CPU负载太高,PWM周期抖动超标。后来换成了DS1202,把PWM生成逻辑放到FPGA里,问题就解决了。所以,如果你的项目里有很多高速IO或者需要自定义协议,DS1202是更好的选择。

硬件资源规划时,我建议你考虑这几点:

  • CPU负载:别超过70%。留点余量给后续的测试用例扩展。
  • IO通道数:数清楚你需要的AI、AO、DI、DO、PWM、CAN、LIN、FlexRay通道。我习惯多预留20%的通道。
  • 实时性:步长要求是多少?1ms?100us?10us?这直接决定了你用DS1006还是DS1202。
  • 扩展性:未来会不会增加测试节点?如果会,建议选支持PHS总线的机箱,方便以后加板卡。

2.3 软件架构分层设计:让模型像乐高一样可拼插

软件架构这块,我踩过不少坑。早期我做项目,喜欢把所有的逻辑都写在一个巨大的Simulink模型里。结果呢?模型打开要5分钟,改一个参数要全局搜索,团队协作更是噩梦。

后来我学乖了,开始做分层设计。我的分层思路是这样的:

  1. 接口层:负责和硬件打交道。比如IO读取、CAN报文收发、PWM捕获。这一层只做信号转换,不做控制逻辑。
  2. 应用层:控制算法、状态机、诊断逻辑。这是核心,应该和硬件完全解耦。
  3. 调度层:管理任务的执行顺序和周期。比如10ms任务、100ms任务、事件触发任务。

这样做的好处很明显:接口层换了硬件,应用层不用动。我曾经在一个项目中,把HIL平台的IO板卡从DS2211换成了DS26555,只需要改接口层的模型,应用层一行代码没动。这就是分层设计的威力。

举个例子:假设你要做一个电池管理系统(BMS)的HIL测试。接口层负责采集电压、电流、温度信号,并转换成物理值。应用层负责SOC估算、均衡策略、故障诊断。调度层决定什么时候执行SOC估算(比如每100ms一次),什么时候执行故障诊断(比如事件触发)。这样,即使你换了不同的电池模型,或者换了不同的IO板卡,应用层的SOC算法依然可以复用。

嗯,这里要注意一点:分层不是越细越好。我见过有人分了七八层,结果信号传递的延迟比控制周期还长。一般来说,3到4层就足够了。

最后,分享一个我常用的模型组织方式:

ProjectRoot/
├── 00_Requirements/       # 需求文档
├── 01_Architecture/       # 架构设计
├── 02_InterfaceLayer/     # 接口层模型
│   ├── IO_Config.slx
│   └── CAN_Config.slx
├── 03_ApplicationLayer/   # 应用层模型
│   ├── ControlLogic.slx
│   └── Diagnostic.slx
├── 04_Scheduler/          # 调度层
│   └── TaskManager.slx
├── 05_TestCases/          # 测试用例
└── 06_Results/            # 测试结果

这样组织,不管是自己维护还是交接给同事,都一目了然。好了,这一章就到这里。下一章我们聊聊测试用例的设计,那又是一个大坑。