控制系统建模仿真(六):非线性控制系统的建模与仿真

前言

在《控制系统计算机辅助设计》书中,第六章 是 Simulink 的深度应用区。为了让大家彻底学会,我将这一章拆解为 MATLAB 编程篇 和 Simulink 实战教程篇。

如果说 MATLAB 是编写数学公式的"演草纸",那么 Simulink 就是搭建工业设备的"实验室"。在这一章,你将学会如何直接用"模块"和"导线"去模拟真实的物理系统。我们将重点解决:如何处理现实中常见的非线性环节 ,以及如何让 MATLAB 自动操纵 Simulink 进行大规模仿真。


这部分函数是连接"文字编程"和"图形建模"的桥梁。

1. sim() ------ 脚本自动化仿真

  • 功能:在 M 文件里直接启动 Simulink 模型并获取数据。

  • 输入 :model_name (模型名), options (仿真参数对象)。

  • 返回值 :SimOut 对象(包含时间、状态、输出)。

  • 代码示例 :

    matlab 复制代码
    % 1. 设置仿真配置
    opt = simset('Solver','ode45','FixedStep',0.01);
    % 2. 运行模型 (假设模型文件名为 MyModel.slx)
    simOut = sim('MyModel', [0 10], opt); 
    % 3. 提取数据
    t = simOut.get('tout'); 
    y = simOut.get('yout');
    plot(t, y); title('从脚本调用的仿真结果');

2. set_param() ------ 动态修改模块参数

  • 功能:在仿真运行前或循环中,用代码修改某个模块的数值。

  • 用法 :set_param('模型名/模块名', '属性名', '新值')

  • 代码示例 :

    matlab 复制代码
    % 将模型中名为 'Gain1' 的增益模块的值改为 15
    set_param('MyModel/Gain1', 'Gain', '15');

3. linmod() ------ 模型线性化提取

  • 功能 :将复杂的非线性 Simulink 框图转化为线性状态空间矩阵 A,B,C,DA, B, C, DA,B,C,D。

  • 代码示例 :

    matlab 复制代码
    [A, B, C, D] = linmod('MyModel');
    G = ss(A, B, C, D); % 转化为第五章学过的状态空间对象

这是针对非线性特性的手把手详细教程。

1. 常见非线性模块详解 (Library: Discontinuities)

需要熟练掌握以下四个"拦路虎"模块:

模块名称 图标特征 功能讲解与用处
Saturation (饱和) 阶梯状折线 功能 :限制信号上下限。用处:模拟电机驱动电压限制(如 ±12V)。
Dead Zone (死区) 中间平坦的线 功能 :输入在范围内输出为0。用处:模拟控制阀的摩擦力或不敏感区。
Relay (继电器) 开关符号 功能 :具有滞环(Hysteresis)的开关。用处:模拟恒温器(开启和关闭温度不同)。
Backlash (间隙) 平行四边形 功能 :输入反向时输出不立即反应。用处:模拟机械齿轮的啮合间隙。

2. 详细建模步骤:搭建一个"带限幅的伺服系统"

目标:模拟一个二阶系统,其控制器输出不能超过 ±0.5。

  1. 打开 Simulink :在命令行输入 simulink,点击 "Blank Model"。

  2. 放置受控对象:

    • 在库浏览器搜索 Transfer Fcn,拖入画布。
    • 双击它,设置 Numerator 为 [10],Denominator 为 [1 2 10]。

  3. 加入限幅器:

    • 在库中找到 Saturation 模块,放在传递函数前面。
      * 双击设置:Upper limit: 0.5, Lower limit: -0.5。(默认设置)
  4. 建立反馈环:

    • 拖入 Sum(求和)模块,双击将符号改为 |+-。

    • 拖入 Step(阶跃信号)作为输入。

    • 拖入 Scope(示波器)接在最末端。

    • 连线:Step -> Sum(+) -> Saturation -> Transfer Fcn -> Scope。再从 Transfer Fcn 输出连回 Sum(-)。

  5. 配置解算器 (Solver):

    • 按 Ctrl+E 打开设置。
    • Stop time 设为 10。
    • Type 选 Variable-step,Solver 选 ode45(这是最通用的)。
  6. 运行 :点击顶部的绿色 Run 按钮。双击 Scope 观察:你会发现波形在达到 0.5 左右时变平缓了,这就是饱和特性。


3. S-Function 编写教程:用代码定义模块

当 Simulink 自带模块不够用时(比如你要写一个复杂的数学逻辑),就需要用到 S-Function。

操作步骤:

  1. 在画布中拖入 MATLAB S-Function 模块。
  2. 在命令行输入 edit sfuntmpl(这是 MATLAB 提供的标准模板)。
  3. 核心填空 :
    • 在 mdlInitializeSizes 里定义:sizes.NumContStates = 2; (假设系统是2阶)。
    • 在 mdlDerivatives 里写微分方程:sys = A*x + B*u;。
    • 在 mdlOutputs 里写输出:sys = C*x;。
  4. 保存为 my_logic.m,在模块属性里填入这个文件名。

第三部分:本章阶段性综合练习 (Milestone 2)

综合题目:非线性系统的稳定性对比

要求:

  1. 在 Simulink 中建立两个相同的二阶系统 G(s)=100s2+10s+100G(s) = \frac{100}{s^2+10s+100}G(s)=s2+10s+100100。
  2. 系统 A:纯线性闭环。
  3. 系统 B:在反馈回路上增加一个 Dead Zone (死区) 模块,范围设为 [-0.2, 0.2]。
  4. 编写一个 MATLAB 脚本,运行该仿真,并在一张图中对比两个 Scope 的输出数据。

参考 MATLAB 控制脚本:

matlab 复制代码
% 假设模型名为 'Nonlinear_Comp',包含两个 Outport 模块:Out1(线性), Out2(非线性)
set_param('Nonlinear_Comp', 'StopTime', '5');
simOut = sim('Nonlinear_Comp');

t = simOut.get('tout');
y_lin = simOut.get('yout').getElement(1).Values.Data; % 获取线性路数据
y_non = simOut.get('yout').getElement(2).Values.Data; % 获取带死区路数据

figure;
plot(t, y_lin, 'b', t, y_non, 'r--');
grid on;
legend('线性系统', '带死区系统');
title('死区非线性对系统响应的影响');

第六章 学习要点总结:

  1. Simulink 并不是只能点鼠标 :学会用 sim() 和 set_param() 操纵它,你才能做自动化的设计(如参数扫描)。
  2. 理解解算器 :如果波形出现奇怪的锯齿,记得去配置里调小 Max step size。
  3. 非线性是本质 :学会用 Saturation 和 Dead Zone 模拟真实的电机和阀门。
相关推荐
星夜离尘562 天前
MATLAB 工程实验:从相邻块均值手写重叠 Allan 偏差,数清有效项
算法·matlab·均值算法
风巽·剑染春水2 天前
【数据处理】Matlab 环境下安装 SPM 与 CAT 工具并进行脑核磁数据预处理
matlab·spm·cat·脑部核磁·t1w图像
机器学习之心2 天前
把 PINN 塞进群智能反演:一次可审计的结构损伤识别 MATLAB 复现
matlab
机器学习之心2 天前
基于CNN-BiLSTM的轴承剩余寿命预测,MATLAB代码
matlab·cnn·cnn-bilstm·轴承剩余寿命预测
苦瓜汤补钙3 天前
Matlab 2022b(中文)的使用教程——Win11
开发语言·matlab
星夜离尘563 天前
MATLAB 工程实验:滞回加持续时间报警,把 UNKNOWN 留在状态机里
开发语言·matlab
星夜离尘564 天前
MATLAB 只剩批次摘要怎么合并方差:用 n、mean、M2 保留批间差异
开发语言·matlab
爱喝热水的呀哈喽5 天前
HEJIAN RESEARCH
开发语言·matlab
星夜离尘565 天前
MATLAB阶跃响应怎么量:别把最后一个采样点当成稳态
开发语言·matlab
星夜离尘565 天前
MATLAB滑动RMS如何接报警:窗口未满和缺样不能当成正常
开发语言·matlab