3. MIL验证环境搭建

MIL(Model-in-the-Loop)验证的第一步不是“跑仿真”,而是把工程环境搭对。电机控制器模型一旦涉及FOC电流环、SVPWM、位置/速度采样和故障保护,模型规模会迅速膨胀。如果工程结构混乱、求解器与采样周期不匹配、信号记录随意,后续SIL阶段几乎无法复用。本节围绕一个可落地的MIL工程骨架展开,给出目录组织、模型配置、求解器选择、信号记录与数据字典、版本管理五个关键环节的具体做法。

一、工程目录结构:让模型、参数、脚本、数据各归其位

推荐采用“单一工程根目录 + 分层子目录”的方式,避免把 .slx、.m、.mat、.xlsx 全部堆在同一层。一个可直接使用的结构如下:

MCU_MIL_Project/
├─ models/                 % 模型文件
│   ├─ mcu_top.slx         % 顶层模型(含控制器与被控对象)
│   ├─ ctrl_foc.slx        % 控制器子系统(可独立测试)
│   └─ plant_pmsm.slx      % 电机+逆变器被控对象
├─ params/                 % 参数脚本与数据字典
│   ├─ mcu_params.m        % 电机、逆变器、控制参数
│   └─ MCU_DD.sldd         % Simulink Data Dictionary
├─ scripts/                % 自动化脚本
│   ├─ init_project.m      % 工程初始化
│   └─ run_mil_test.m      % 批量仿真入口
├─ data/                   % 输入激励与记录数据
│   ├─ testcases/          % 工况定义
│   └─ logs/               % 仿真输出
└─ docs/                   % 需求、接口、测试说明

顶层模型 mcu_top.slx 只做信号连接和接口定义,不写具体算法;控制器与被控对象分别封装为引用模型(Model Reference),这样在SIL阶段可以把控制器替换为C代码生成的S-Function,而被控对象保持不变。参数脚本 mcu_params.m 只负责赋值,不参与计算逻辑,便于版本对比。

二、模型配置参数:把“仿真正确性”固化到配置里

模型配置参数决定了仿真是否可信。对电机控制器MIL,重点检查以下几项:

  • 求解器类型:选择“定步长(Fixed-step)”,因为后续要生成嵌入式代码,变步长无法直接映射到实际控制器任务。
  • 固定步长:与控制器实际中断周期一致。例如电流环10 kHz,则步长设为 1e-4 s;若速度环1 kHz,可在模型内用Rate Transition或独立采样保持实现。
  • 求解器:定步长下推荐 ode4(Runge-Kutta)或 ode1(Euler)。ode4精度更高,适合含连续被控对象的场景;若被控对象已离散化,ode1即可。
  • 任务模式:单任务时所有模块继承同一采样时间;多速率时需显式设置各子系统采样时间,并检查Rate Transition模块是否插入正确。
  • 代码生成兼容性:勾选“仅生成代码”相关检查项,避免使用不支持代码生成的模块(如连续传递函数、部分查表模块)。
建议把上述配置保存为 mcu_mil_config.m,在 init_project.m 中通过 set_param 统一设置,避免每次手动改配置导致仿真结果不一致。

三、求解器选择:定步长与采样周期的匹配关系

求解器选择的核心是“仿真步长 ≤ 控制器最小采样周期”,且尽量取整数倍关系。以某永磁同步电机FOC为例:电流环采样周期 Ts_i = 100 μs,速度环 Ts_s = 1 ms,PWM开关频率 f_sw = 10 kHz。若仿真步长取 Ts = 100 μs,则电流环每个周期执行一次,速度环每10个周期执行一次,PWM每周期更新一次,三者关系清晰。

若步长取 50 μs,虽然精度更高,但仿真时间翻倍,且与实际控制器任务周期不一致,容易掩盖多速率调度问题。因此MIL阶段建议直接采用与目标控制器一致的最小采样周期作为固定步长。对于含连续被控对象的场景,可在被控对象内部用 ode4 以更小步长积分,但控制器侧仍保持 100 μs 离散执行。

MIL工程结构与信号流示意 工程目录 models/ params/ scripts/ data/ docs/ MCU_DD.sldd mcu_top.slx 控制器 ctrl_foc 电流环 100 μs / 速度环 1 ms 被控对象 plant_pmsm PMSM + 逆变器 + 负载 信号记录与数据字典 To Workspace / Dataset / sldd 模型配置与求解器 定步长 Fixed-step Ts = 1e-4 s 求解器 ode4 / ode1 与代码生成兼容 多速率任务调度 Rate Transition 检查 版本管理 Git + .slx 二进制管理 参数脚本统一初始化 → 模型引用分层 → 定步长求解 → 信号记录到 Dataset → 数据字典集中管理

四、信号记录与数据字典:让每次仿真可追溯

MIL验证需要观察电流、转速、转矩、母线电压、故障标志等信号。推荐使用“信号记录(Signal Logging)+ Dataset”方式,而不是把每个信号都手动连到 To Workspace。具体做法:在顶层模型选中需要记录的信号线,右键 → Properties → 勾选“Log signal data”;在配置参数中设置 Signal logging 名称,例如 logsout。仿真结束后,logsout 是一个 Simulink.SimulationData.Dataset,可用 logsout.get('Ia') 按名称提取。

数据字典 MCU_DD.sldd 用于集中管理参数和信号对象。把 mcu_params.m 中的变量迁移到数据字典,并设置 Simulink.Parameter 的 StorageClass(如 ExportedGlobal 或 Model default),这样在SIL代码生成时参数能正确映射为C变量。数据字典还支持版本对比,便于追踪参数变更。

不要用 eval 或 assignin('base', ...) 在脚本中动态创建参数,这会导致数据字典与脚本不一致,SIL阶段容易出现“参数找不到”或“值被覆盖”的问题。

五、版本管理基础:模型文件与脚本的协同

Simulink 的 .slx 是二进制压缩包,Git 无法逐行对比。推荐策略:

  • 模型文件使用 Git LFS 管理,避免仓库膨胀;
  • 参数脚本、初始化脚本、测试脚本用普通 Git 管理,可逐行 diff;
  • 数据字典 .sldd 同样用 LFS,但关键参数变更需在提交信息中写明;
  • 每次提交前运行 init_project.m 和 run_mil_test.m,确保模型可加载、仿真可运行;
  • 为每个MIL测试用例建立独立分支或标签,例如 mil/current-loop-step,便于回溯。

一个实用的提交前检查清单如下:

检查项判断依据
模型能否无警告加载load_system('mcu_top') 无报错
参数是否全部来自数据字典Model Explorer 中无未定义变量
求解器与步长是否一致配置参数中 Fixed-step = 1e-4
信号记录是否开启logsout 包含 Ia、Ib、Ic、Speed、Torque
仿真是否可复现同一提交两次运行结果一致