4、模型构建基础:模块的添加、连接、信号线操作、子系统创建与封装(Mask)入门

Simulink 的建模过程本质上是在图形化画布上构建一个数据流与状态机混合的运算网络。无论是简单的传递函数仿真,还是复杂的多域物理系统,其底层操作都离不开三个核心动作:放置模块、连接信号线、组织子系统。本章将围绕这三个基础动作展开,并深入讲解子系统封装(Mask)这一提升模型复用性与可读性的关键技能。我们将从模块库的检索逻辑出发,逐步过渡到信号线的数据流语义,最后通过一个完整的PID控制器封装案例,串联起本章全部知识点。

Simulink 模型构建核心链路 1. 模块库检索 Simulink/Continuous Math Operations Sinks/Sources 搜索框 + 库浏览器 拖拽或双击添加 2. 模块操作 参数设置 (双击) 名称/方向/颜色 复制 (Ctrl+Drag) Ctrl+I 翻转 Ctrl+R 旋转 3. 信号线连接 端口到端口拖拽 分支线 (Ctrl+拖拽) 信号标签 (双击) 数据类型/维度检查 Goto/From 跨层连接 4. 子系统 选中→创建子系统 Ctrl+G 封装 Mask 编辑器 参数/图标/文档 封装后变单模块 信号线数据流语义(非物理连线) • 信号线方向决定数据流向,箭头指向接收端 • 信号线可携带标量、向量、矩阵及总线数据,维度需匹配 • 红色虚线表示数据类型错误或维度不匹配;黑色实线表示正常连接 Mask 封装四步法 ① 选中子系统 → ② 右键 Mask > Create Mask → ③ 添加参数(如 Kp, Ki, Kd)→ ④ 在子系统内部用 Mask 变量名替换常量 效果:双击封装模块弹出参数对话框,模型文件更简洁,参数可批量调优

上图展示了从模块库到封装子系统的完整操作链路。在实际工程中,这四个环节并非严格串行,而是不断迭代优化的过程。例如,工程师可能先搭建一个未封装的子系统用于快速验证算法,待功能稳定后再进行 Mask 封装,以便在团队中共享。下面我们将逐一拆解每个环节的操作细节与底层逻辑。

4.1 模块的添加与参数配置

核心原理:Simulink 的模块库(Library Browser)本质是一个分层组织的函数与系统集合。每个模块都封装了特定的数学运算、逻辑判断或信号源功能。模块的添加不仅仅是拖拽一个图标,更重要的是理解其端口语义(输入/输出个数、数据类型、维度)和采样时间(连续/离散/继承)。

操作流程:

  1. 打开库浏览器:在 MATLAB 命令行输入 simulink 或在 Simulink 起始页点击"库浏览器"图标。
  2. 检索模块:使用浏览器顶部的搜索框直接输入模块名(如 "Gain"、"PID Controller"),或按目录浏览:Simulink > Continuous(连续系统)、Simulink > Math Operations(数学运算)、Simulink > Sinks(输出显示)。
  3. 添加模块:双击库中的模块,或直接拖拽到模型画布。推荐使用双击添加,因为模块会自动放置在画布中心附近,便于后续连线。
  4. 参数配置:双击画布上的模块实例,打开参数对话框。例如,增益模块(Gain)需要设置增益值(K),传递函数模块(Transfer Fcn)需要设置分子分母系数向量。
经验提醒:对于常用模块(如 Gain、Sum、Scope),建议记住其快捷键。例如,在画布中直接输入 "gain" 后按回车,可快速添加增益模块。此外,使用 Ctrl+I 可翻转模块(左右镜像),Ctrl+R 可旋转90度,这在整理连线布局时非常高效。
模块类别典型模块关键参数常见用途
信号源Sine Wave, Step, Constant幅值、频率、相位、阶跃时间测试激励输入
连续系统Transfer Fcn, Integrator, PID Controller分子/分母系数、初值、PID增益线性动态系统建模
数学运算Gain, Sum, Product, Math Function增益值、符号列表、函数类型信号运算与标定
信号路由Mux, Demux, Goto, From, Bus Creator输入个数、信号名称信号合并、拆分与跨层传递
输出显示Scope, Display, To Workspace坐标轴数量、变量名、采样间隔结果可视化与数据导出

常见误区:初学者常混淆 Gain 模块与 Constant 模块。前者是乘法运算,输出等于输入乘以增益值;后者是常数信号源,输出始终为设定值。另一个误区是忽略模块的采样时间属性。在混合系统(连续+离散)中,若离散模块的采样时间与连续求解器不匹配,会导致仿真结果异常或报错。

4.2 信号线操作与数据流管理

核心原理:信号线(Signal Line)是 Simulink 模型中的"血管",它承载着数据流。与电路图中的物理导线不同,信号线传递的是数值矩阵,且具有方向性。信号线的颜色和线型能直观反映数据类型:黑色实线表示 double 类型,蓝色表示 int8/uint8 等整数类型,红色虚线表示数据类型错误或维度不匹配。

操作流程:

  • 基本连接:将鼠标移至输出端口(>符号),光标变为十字形,按住左键拖拽至目标输入端口(>符号)后松开。若端口兼容,连线变为黑色实线。
  • 信号分支:将信号线连接到多个模块时,在已有连线上按住 Ctrl 键,然后从连线上拖出新线。分支线共享同一信号源,但可分别连接不同模块。
  • 信号标签:双击任意一段信号线,输入名称(如 error_signal)。标签不仅用于注释,还可用于 Goto/From 模块的跨层引用。
  • 删除与重连:选中连线按 Delete 删除。若需改变连线路径,可按住 Shift 键拖动连线中间节点。
风险提示:当信号线出现红色虚线时,通常表示数据类型不匹配(如将 int8 信号连接到要求 double 输入的模块)或维度不一致(如将 3x1 向量连接到标量输入端口)。此时应使用 Data Type Conversion 模块进行类型转换,或使用 Selector 模块提取向量中的特定元素。切勿强行连接,否则仿真会立即报错。

案例拆解:假设我们需要将两个传感器信号(温度 T 和压力 P)合并为一个向量,并分别送入显示模块和计算模块。操作步骤如下:

  1. 添加两个 Constant 模块(分别设为 25 和 101.3)作为模拟传感器值。
  2. 添加一个 Mux 模块,双击设置输入个数为 2。
  3. 将两个 Constant 输出分别连接至 Mux 的两个输入端口。
  4. 从 Mux 输出端引出分支线:一条连接至 Scope 用于观察,另一条连接至 Gain 模块(增益设为 0.1)进行压力换算。
  5. 在 Mux 输出线上双击,输入标签 sensor_data。

此案例展示了信号线分支、合并与标签的典型用法。通过标签 sensor_data,我们可以在模型的其他位置使用 From 模块引用该信号,而无需绘制跨越整个模型的连线。

4.3 子系统创建与封装(Mask)入门

核心原理:子系统(Subsystem)是将一组相关模块封装为一个独立模块的机制,用于降低模型复杂度、提高可读性。而封装(Mask)则是在子系统基础上,为其创建自定义的参数对话框、图标和文档,使其行为类似于一个独立的、可配置的模块。封装的核心价值在于参数化复用:同一个子系统,通过不同的 Mask 参数,可以表现出不同的行为。

创建子系统的两种方法:

  • 自上而下:先添加一个 Subsystem 模块(位于 Simulink > Ports & Subsystems),然后双击进入其内部,自行添加输入输出端口(In1/Out1)和逻辑模块。
  • 自下而上(推荐):在画布中选中多个模块(按住鼠标框选或 Ctrl+点击),右键选择 Create Subsystem from Selection。Simulink 会自动将选中模块的输入输出端口映射为子系统的 In1/Out1 端口。

Mask 封装操作流程:

  1. 选中已创建的子系统,右键选择 Mask > Create Mask。
  2. 在 Mask 编辑器中,切换到 Parameters 标签页,点击"Edit"添加参数。例如,添加一个名为 Kp 的编辑框(Prompt 为 "比例增益"),类型选择 edit。
  3. 切换到 Icon 标签页,在绘图命令中输入 disp('PID') 或使用 port_label 函数标注端口名称。
  4. 切换到 Documentation 标签页,填写封装模块的描述文本,便于他人理解。
  5. 点击 OK 完成封装。此时双击该模块,将弹出自定义的参数对话框,而非直接进入子系统内部。
关键技巧:在子系统内部,双击任意常量模块(如 Gain),将其数值设置为 Kp(即 Mask 参数名)。这样,当用户在封装模块对话框中输入 Kp=2.5 时,子系统内部的增益模块会自动更新为 2.5。这是实现参数化复用的核心机制。

案例拆解:PID 控制器封装

假设我们需要一个可调参数的 PID 控制器,用于多个不同被控对象的仿真。若直接使用 Simulink 自带的 PID Controller 模块,虽然参数可调,但无法自定义图标和文档。我们通过封装实现一个"教学版 PID":

步骤操作内容关键参数/命令
1. 搭建内部结构创建子系统,内部包含 Gain(P)、Gain(I)、Gain(D)、Sum、Integrator、Derivative 模块P 增益设为 Kp,I 增益设为 Ki,D 增益设为 Kd
2. 创建 Mask右键子系统 → Mask > Create Mask添加三个编辑框参数:Kp, Ki, Kd
3. 设置图标在 Icon 页输入 disp('PID') 和 port_label('input',1,'e')、port_label('output',1,'u')显示 PID 文本及端口标签
4. 填写文档在 Documentation 页输入描述:"教学用 PID 控制器,支持 P/I/D 参数独立调节"—
5. 测试封装双击封装模块,输入 Kp=1.2, Ki=0.5, Kd=0.1,点击 OK观察子系统内部 Gain 模块数值是否更新

复盘与经验:封装过程中最常见的错误是参数名拼写不一致。例如,Mask 参数名为 Kp,但子系统内部 Gain 模块写成了 kp,这会导致参数无法传递。此外,封装后的模块在模型文件中只显示为一个图标,这大大减少了顶层模型的连线数量。但要注意,过度封装会隐藏内部细节,不利于团队协作调试。建议在模型开发初期保持子系统内部可见,待功能冻结后再进行封装。

风险提示:当封装参数用于多个模块时,若参数类型不匹配(如将字符串赋给数值增益),仿真会报错。建议在 Mask 编辑器的 Parameters 页中,为每个参数设置合适的 Type(如 edit 表示文本输入,popup 表示下拉选择),并在 Evaluate 选项中勾选"评估",确保输入值被正确解析为数值或表达式。