4. Simulink建模基础:常用模块库介绍、信号线操作、子系统创建、模型配置参数设置

好,咱们进入第四讲。说实话,这一章是真正开始「动手」的关键一步。很多初学者觉得Simulink就是拖拖拽拽,没什么技术含量。嗯,我以前也这么想,直到有一次在项目里因为一个信号线没连对,导致生成的代码跑飞了整整两天……从那以后,我再也不敢小看这些基础操作了。

今天咱们就踏踏实实把Simulink建模的四个基本功讲透:常用模块库、信号线操作、子系统创建、模型配置参数。你想想看,这四个东西就像盖房子的砖、水泥、房间和施工图纸,缺一不可。

4.1 常用模块库介绍

打开Simulink库浏览器(Ctrl+Shift+L),你会看到一大堆模块。别慌,我帮你梳理一下电机控制里最常用的几类。

4.1.1 连续与离散模块

电机控制本质上是离散系统,所以我们主要用离散模块。我个人习惯把Discrete库里的这几个模块放在快捷工具栏:

  • Unit Delay:单位延迟,相当于Z⁻¹。我在做电流环时经常用它来模拟一拍延迟。
  • Discrete PID Controller:离散PID,注意要设置好采样时间,别和连续PID搞混了。
  • Discrete Integrator:离散积分器,做速度环或者位置环时必用。

重要提醒:电机控制中,所有离散模块的采样时间必须保持一致。我曾经见过一个模型,PID的采样时间是1e-4,而积分器是1e-5,结果仿真结果完全不对,查了三天才发现。

4.1.2 数学运算模块

这些模块在信号处理中很常用:

  • Gain:增益模块,做标幺化或者系数调整时用。注意数据类型,默认是double,如果要用定点数记得改。
  • Sum:求和模块,做误差计算。我习惯把输入端口数设为3,方便以后扩展。
  • Product:乘法模块,做Park变换或者Clarke变换时少不了它。
  • Saturation:限幅模块,保护你的输出不会超出物理范围。

4.1.3 信号路由模块

这个库我特别喜欢,因为它能让模型变得整洁:

  • Mux / Demux:合并/拆分信号。注意,Mux出来的信号是虚拟信号,不是向量,别搞混了。
  • Bus Creator / Bus Selector:总线操作。做复杂系统时,我强烈建议用总线,而不是满天飞信号线。
  • Goto / From:信号跳转。适合跨层级传递信号,但别滥用,否则模型可读性会变差。

4.2 信号线操作

信号线是Simulink模型的「血管」。操作得好,模型清晰流畅;操作不好,就是一团乱麻。

4.2.1 画线与分支

最基本的操作:

  • 画线:鼠标左键从输出端口拖到输入端口。
  • 分支:在已有信号线上右键拖动,或者按住Ctrl拖动。
  • 折线:画线时按住Shift,可以画出直角折线。

我的小技巧:画线时尽量保持横平竖直,别斜着拉。斜线虽然也能连,但看起来很不专业,而且容易误触。我在评审别人模型时,第一眼就看信号线是否整齐——这能反映一个人的工程素养。

4.2.2 信号线标注

给信号线起名字是个好习惯。双击信号线,输入名称即可。我个人建议:

  • 电流信号:Ia, Ib, Ic
  • 电压信号:Vdc, Valpha, Vbeta
  • 角度信号:Theta, Omega

命名规范一点,生成代码时变量名也会更清晰。我曾经接手过一个项目,信号线全是Signal1, Signal2……那感觉,就像看一本没有目录的书。

4.2.3 信号线数据类型

右键点击信号线,选择Display > Signal Dimensions可以查看维度。选择Display > Port Data Types可以查看数据类型。

注意:数据类型不匹配是常见的错误来源。比如一个double信号连到了uint16的输入端口,仿真时会报错。我建议在模型配置里开启Underspecified initialization detection,能帮你提前发现这类问题。

4.3 子系统创建

子系统就像函数,把相关功能封装起来,让模型更模块化。电机控制中,我通常会把电流环、速度环、坐标变换分别做成子系统。

4.3.1 创建子系统的方法

有两种常用方式:

  1. 先选后封装:选中要封装的模块,右键选择Create Subsystem。快捷键是Ctrl+G。
  2. 先建后填:从库中拖入Subsystem模块,双击进去再添加内容。

我个人更喜欢第一种方式,因为Simulink会自动帮你创建输入输出端口,省事。

4.3.2 子系统端口管理

双击子系统进入内部,你会看到In1Out1模块。右键点击它们可以修改端口名称和顺序。

这里有个坑:端口名称要和信号线名称对应。比如你有一个输入叫Current_Ref,那端口名称最好也改成Current_Ref,这样生成代码时变量名才直观。

4.3.3 原子子系统与触发子系统

在电机控制中,我们经常用到两种特殊子系统:

  • Atomic Subsystem:原子子系统,保证内部逻辑在一个任务中执行。右键子系统 -> Block Parameters -> 勾选Treat as atomic unit
  • Triggered Subsystem:触发子系统,只在触发信号到来时执行。适合做中断服务程序。

实战经验:我在做永磁同步电机控制时,把电流环放在一个原子子系统里,采样时间设为100μs。速度环放在另一个子系统里,采样时间设为1ms。这样既保证了实时性,又降低了CPU负载。

4.4 模型配置参数设置

模型配置参数,说白了就是告诉Simulink「你想怎么跑这个模型」。这个设置直接影响仿真精度和代码生成质量。

4.4.1 求解器设置

打开Model Settings(Ctrl+E),在Solver选项卡里:

  • Type:选Fixed-step。电机控制必须用固定步长,否则代码生成会出问题。
  • Solver:选discrete (no continuous states)。因为我们用的是离散模型,不需要连续求解器。
  • Fixed-step size:设为你的采样时间,比如1e-4

警告:千万别选Variable-step!虽然仿真时看起来没问题,但生成代码时会报错。我见过有人仿真跑得好好的,一生成代码就报错,查了半天发现是求解器类型没改。

4.4.2 代码生成设置

Code Generation选项卡里:

  • System target file:选ert.tlc(Embedded Real-Time)。这是专门为嵌入式系统准备的。
  • Language:选C
  • Generate code only:勾选这个,只生成代码,不编译。

还有一个重要的设置:Interface选项卡里的Hardware Implementation。这里要设置你的目标芯片类型,比如ARM Cortex-M4或者TI C2000。设置不对,生成的代码可能无法在目标板上运行。

4.4.3 数据导入/导出设置

Data Import/Export选项卡里:

  • Time:勾选,保存仿真时间。
  • Output:勾选,保存输出信号。
  • Final states:勾选,保存最终状态,方便下次仿真继续。

我个人习惯把Limit data points设为一个较大的值,比如100000,防止数据被截断。

4.5 实战小练习

光说不练假把式。我建议你动手做一个小练习:

  1. 新建一个模型,拖入一个Sine Wave模块和一个Scope模块。
  2. 把信号线命名为Sine_Output
  3. 把这两个模块封装成一个子系统,命名为Signal_Generator
  4. 设置求解器为固定步长1e-4。
  5. 运行仿真,观察波形。

这个练习虽然简单,但涵盖了今天讲的所有知识点。做完之后,你对Simulink建模的基本功就掌握了。

最后说一句:建模就像写代码,整洁和规范比花哨更重要。我见过太多人把模型画得跟蜘蛛网一样,结果自己都看不懂。记住,好的模型是「自文档化」的——别人一看就明白你在做什么。

下一讲,咱们会深入讲状态机建模,那是做复杂逻辑控制的核心。到时候见!