3. Simulink 子系统与模型层次划分
从扁平模型到层次化模型
一个可维护的 MBD 模型,通常不是把所有模块平铺在一张画布上,而是按“职责边界”拆成若干子系统。重构的核心判断标准只有一条:每个子系统对外只暴露必要的输入/输出端口,内部实现可以独立替换而不影响其他部分。
下面以一个“电机转速闭环控制”扁平模型为例。原始模型包含:转速指令 SpeedRef、转速反馈 SpeedFbk、误差计算、PI 控制器、限幅、被控对象(电机+负载)、以及一个用于监视的示波器。所有模块都在同一层,信号线交叉严重。
职责划分与端口定义
按功能职责,将扁平模型拆为三个子系统,并明确各自的边界:
| 子系统 | 职责 | 输入端口 | 输出端口 |
|---|---|---|---|
Ctrl_Core | 误差计算 + PI 控制 + 输出限幅 | SpeedRef、SpeedFbk | uCmd |
Plant_Model | 电机一阶惯性 + 负载扰动 | uCmd、LoadTq | SpeedFbk |
Monitor | 记录指令、反馈、控制量 | SpeedRef、SpeedFbk、uCmd | —(仅记录) |
拆分后,顶层模型只保留三个子系统块和它们之间的信号连线,不再出现任何增益、积分器或限幅模块。这样做的直接收益是:修改 PI 参数只需进入 Ctrl_Core,替换电机模型只需进入 Plant_Model,两者互不干扰。
层次化结构示意
重构操作要点
- 框选与创建子系统:在 Simulink 中框选误差计算、PI、限幅三个模块,右键选择
Create Subsystem from Selection,重命名为Ctrl_Core。 - 整理端口:进入
Ctrl_Core,确认输入端口为SpeedRef和SpeedFbk,输出端口为uCmd。删除内部多余的信号标签,只保留端口名称。 - 同样处理被控对象:将电机惯性环节和负载叠加封装为
Plant_Model,输入uCmd、LoadTq,输出SpeedFbk。 - 建立监视子系统:将示波器替换为
To Workspace模块,封装为Monitor,输入为三路信号,不产生输出端口。 - 顶层连线:在顶层只连接三个子系统之间的信号,确保没有悬空端口。使用
Signal Label标注关键信号名。
验证方法:重构完成后,运行仿真,检查
Monitor 记录的数据与重构前一致。若 SpeedFbk 波形出现异常,优先检查 Plant_Model 的输入端口是否误接了 SpeedRef,以及反馈路径是否在子系统外部正确闭合。
常见错误:创建子系统时,Simulink 会自动生成
In1、Out1 端口。务必手动重命名为有意义的信号名,否则后续接口追溯和代码生成都会出现混乱。另外,子系统内部不要保留未使用的输入端口,否则会触发编译警告。
重构前后对比
| 对比项 | 扁平模型 | 层次化模型 |
|---|---|---|
| 顶层模块数量 | 约 12 个 | 3 个子系统 + 2 个输入源 |
| 信号线交叉 | 严重,难以追踪 | 清晰,仅 4 条主连线 |
| 修改 PI 参数 | 需在大量模块中定位 | 直接进入 Ctrl_Core |
| 替换电机模型 | 影响顶层连线 | 仅修改 Plant_Model 内部 |
| 代码生成粒度 | 整体生成,难以复用 | 可按子系统独立生成 |