简介:面向初学者的倒立摆模糊控制Simulink仿真资料包,围绕非线性倒立摆系统的稳定控制展开,完整演示从模糊PID角度控制到位置与角度分段模糊控制的实现路径,适合学习模糊逻辑与MATLAB/Simulink建模的控制类专业学生和工程技术人员。压缩包共140个文件,约6.15MB,以mat数据文件、m脚本、mdl模型、fis模糊规则文件、avi仿真录像及docx实验报告为主,并配有png/jpg图片辅助查看曲线与结果。已有6455人学习下载。内容涵盖实验1-1的模糊PID控制器模型PID_pendulum.mdl,以及实验1-2的位置模糊控制器position_fuzzy.fis与pendulum_pre.mdl联合控制方案,模糊控制实验报告对设计思路和仿真结果做了详细说明。原始仿真.avi与改进仿真.avi可直观对比模糊控制前后的动态差异,GetPendulum.m和Animation.m脚本支持提取倒立摆动态数据并生成动画,便于复现实验和调整参数。整体结构清晰,特别适合通过具体案例快速上手模糊控制设计与Simulink仿真验证。
1. 倒立摆的模糊控制:不靠精确模型也能把摆杆稳住
被倒立摆支配过的控制专业学生,多半都经历过这个场景:老师说用状态空间法设计 LQR,推导了一页草稿纸,最后仿真里的摆杆还是像个醉汉一样左右打摆。而这个项目标题给出的路径完全反着来——倒立摆的模糊控制,基于 Simulink 仿真,适合初学者。模糊控制不依赖精确数学模型,而是把人的操作经验翻译成几条“角度偏大且还在加速倒,就用力顶回去”这类规则,就能稳定住摆杆。你要做的不过是三件事:搭一个能动的倒立摆模型、设计一张模糊规则表、在 Simulink 里把闭环接起来。这套方案适合正在学模糊控制、做课程设计、或者第一次碰 Simulink 仿真的人。但事先说清楚:它参数比 PID 少,却一点都不“傻瓜”,真正开始调仿真时,发散才是常态,撑过那一步后面就是平地。
2. 倒立摆动力学模型:从运动方程到 Simulink 可跑的积分器结构
2.1 为什么模糊控制不需要精确模型,但还是得先搭一个
模糊控制的设计过程确实可以完全绕开被控对象模型,因为规则表直接建立在“角度大、角速度快”这类语言变量上,不需要线性化状态矩阵 A 和 B,也不需要解 Riccati 方程。但做闭环仿真时,Simulink 里必须有一个被控对象的微分方程,否则控制器输出找不到落点。倒立摆适合做模糊控制入门,正是因为它非线性、自不稳定,姿态一偏就指数级发散,模糊控制要处理的恰恰是这种“一个线性模型描述不了全工况”的对象。
我见过不少初学者直接双击资源包里的封装子系统就开始仿真,跑通了也不知道里面是什么,一旦发散就无从下手。做这个方向,建议至少手动搭一遍动力学部分,哪怕后面换成资源包里现成的模型,你也能在信号线上看出哪一段是积分、哪一段是控制器。倒立摆的常见简化模型是忽略摩擦、把摆杆质量集中在质心,这样只涉及四个物理量:小车质量 M、摆杆质量 m、质心到转轴距离 l、重力加速度 g。
2.2 用 MATLAB Function 写 cart-pole 动力学:核心方程与参数
小车-摆杆系统的运动方程可以由拉格朗日方程推出。设 x 为小车水平位移,θ 为摆杆与竖直方向的夹角,F 为作用在小车上的水平控制力,则两个主方程是:
(M + m) x'' + m l θ'' cosθ - m l θ'² sinθ = F x'' cosθ + l θ'' = -g sinθ把 θ'' 从这两个方程里消掉,就能得到适合在积分器里直接使用的加速度表达式。下面这段 MATLAB Function 是常见做法,也是我建议初学者优先采用的方案:输入状态量,输出两个加速度,交给 Simulink 积分器积分成速度和位移。
function [x_dd, theta_dd] = cart_pole_dynamics(x, theta, x_d, theta_d, F, M, m, l, g) % 输入:x 小车位移,theta 摆杆角度,x_d 小车速度,theta_d 摆杆角速度,F 控制力 % 输出:x_dd 小车加速度,theta_dd 摆杆角加速度 % 单位:角度用弧度,力用牛顿,长度用米 % 分母项:当 theta 接近 ±90° 时分母会变小,这是模型自身的非线性特性 den = l * ((M + m) - m * cos(theta)^2); % 摆杆角加速度 theta_dd = -(F * cos(theta) + (M + m) * g * sin(theta) ... + m * l * theta_d^2 * sin(theta) * cos(theta)) / den; % 小车加速度,由第一个运动方程改写而来 x_dd = (F - m * l * theta_dd * cos(theta) + m * l * theta_d^2 * sin(theta)) / (M + m); end这段代码的逻辑不复杂:den 是消元后出现的分母项,它跟摆杆质量在小车方向上的投影有关;theta_dd 的分子里有重力项、控制力项和离心项,分别对应摆杆自然倾倒、小车推力带来的惯性力、以及摆杆转动时的离心效应。注意 theta 必须用弧度,如果你把角度值直接喂进来,sin 函数的输入会完全错乱,这是新手最容易忽略的一个单位陷阱。
参数按课程设计的常见配置取即可,不需要纠结精确值,因为模糊控制对参数不敏感:
| 参数 | 含义 | 常见取值 |
|---|---|---|
| M | 小车质量 | 1.0 kg |
| m | 摆杆质量 | 0.1 kg |
| l | 摆杆质心到转轴距离 | 0.5 m |
| g | 重力加速度 | 9.8 m/s² |
2.3 从方程到 Simulink:积分器、常量和连接顺序
有了加速度表达式,剩下的工作就是积分。倒立摆仿真模型的被控对象部分通常由两组积分器构成:theta_dd 积分成 theta_d,再积分成 theta;x_dd 积分成 x_d,再积分成 x。MATLAB Function 模块放在控制器输出和积分器之间,输入依次是 x、theta、x_d、theta_d、F,输出是 x_dd 和 theta_dd。
我一般先把参数写成独立脚本,这样仿真前不用在模型里敲数字,后面调参也方便。建模时增益模块和积分器初始值直接引用脚本里的变量名。
% set_params.m 倒立摆仿真初始化脚本 M = 1.0; % 小车质量, kg m = 0.1; % 摆杆质量, kg l = 0.5; % 摆杆质心到转轴距离, m g = 9.8; % 重力加速度, m/s^2 theta0 = 0.2; % 初始摆角, rad(约11.5度) x0 = 0; % 小车初始位移, m theta_d0 = 0; % 初始角速度, rad/s x_d0 = 0; % 初始速度, m/s % 量化因子:把物理量映射到模糊论域 [-3,3] Ke = 15; % 角度: 0.2 rad -> 3 Kec = 3; % 角速度: 1 rad/s -> 3 Ku = 6.67; % 控制力: 3 -> 20 N % 加载模糊规则文件,Simulink 通过工作区变量名访问它 fis = readfis('cart_pole.fis');这里面 Ke、Kec、Ku 是模糊控制器最重要的三个数。角度实际范围是 ±0.2 rad,映射到论域 ±3,所以 Ke 取 15;角速度一般不超过 ±1 rad/s,所以 Kec 取 3;输出力实际范围是 ±20 N,所以 Ku 取 6.67。先按这个量级跑通,再往大了或往小了调。
Simulink 里连接时注意两点:一是 MATLAB Function 模块的输入端口顺序必须跟你写的函数签名一致,我把 x 排最前是因为后面接示波器时习惯先看位移;二是 theta 积分器的初始条件一定在模块参数里设置为 theta0,如果保持默认的 0,摆杆一开始就是竖直的,模糊控制根本没有机会展示纠偏过程,仿真曲线也看不出控制效果。
3. 模糊控制器设计:输入输出、隶属度函数与规则表的制作
3.1 模糊控制器的输入输出怎么选:E 和 EC 的物理含义
倒立摆模糊控制最常见的结构是双输入单输出:输入取摆角角度 E 和角速度 EC,输出取小车控制力 U。E 告诉你“偏了多少”,EC 告诉你“正在往哪个方向偏、偏得多快”,有了这两条信息,就能像人一样判断该往哪边推、推多大力。位置 x 为什么不作为输入?因为第一层控制目标是姿态稳定,位置漂移属于外环问题,初学者的方案通常只做姿态环,把小车位置留到后续扩展,否则规则表维度一上去,设计难度立刻翻倍。
输入输出选定后,先要把物理量映射到一个统一论域。Fuzzy Logic Designer 里默认论域是 [-3, 3],但实际角度只有 ±0.2 rad,角速度只有 ±1 rad/s,直接喂给 FIS 会打到论域边缘,控制精度很差。所以 Simulink 里在信号进 FIS 之前要加增益模块做尺度变换,这就是 2.3 节里 Ke、Kec 的由来。输出端同理,FIS 输出的论域值是抽象力度,必须乘 Ku 换算成真实牛顿数,再经过限幅模块才送给被控对象。
3.2 用脚本创建 FIS:隶属度函数与参数设置
创建 FIS 有两种路径:老式做法是在 MATLAB 命令窗口输入 fuzzy 打开图形界面,手动添加输入输出、画隶属度函数、编辑规则表,最后导出 .fis 文件;新版本 MATLAB 更推荐用脚本方式,可重复性更好,改起来也快。
% 创建倒立摆模糊控制器 FIS fis = mamfis('Name', 'cart_pole_fis'); % 输入1:角度误差 E,论域 [-3,3],5个语言值 fis = addInput(fis, [-3 3], 'Name', 'E'); fis = addMF(fis, 'E', 'trimf', [-3 -3 -1.5], 'Name', 'NB'); fis = addMF(fis, 'E', 'trimf', [-3 -1.5 0], 'Name', 'NS'); fis = addMF(fis, 'E', 'trimf', [-1.5 0 1.5], 'Name', 'ZO'); fis = addMF(fis, 'E', 'trimf', [0 1.5 3], 'Name', 'PS'); fis = addMF(fis, 'E', 'trimf', [1.5 3 3], 'Name', 'PB'); % 输入2:角速度 EC,论域 [-3,3],5个语言值 fis = addInput(fis, [-3 3], 'Name', 'EC'); fis = addMF(fis, 'EC', 'trimf', [-3 -3 -1.5], 'Name', 'NB'); fis = addMF(fis, 'EC', 'trimf', [-3 -1.5 0], 'Name', 'NS'); fis = addMF(fis, 'EC', 'trimf', [-1.5 0 1.5], 'Name', 'ZO'); fis = addMF(fis, 'EC', 'trimf', [0 1.5 3], 'Name', 'PS'); fis = addMF(fis, 'EC', 'trimf', [1.5 3 3], 'Name', 'PB'); % 输出:控制力 U,论域 [-3,3],7个语言值 fis = addOutput(fis, [-3 3], 'Name', 'U'); fis = addMF(fis, 'U', 'trimf', [-3 -3 -2], 'Name', 'NB'); fis = addMF(fis, 'U', 'trimf', [-3 -2 -1], 'Name', 'NM'); fis = addMF(fis, 'U', 'trimf', [-2 -1 0], 'Name', 'NS'); fis = addMF(fis, 'U', 'trimf', [-1 0 1], 'Name', 'ZO'); fis = addMF(fis, 'U', 'trimf', [0 1 2], 'Name', 'PS'); fis = addMF(fis, 'U', 'trimf', [1 2 3], 'Name', 'PM'); fis = addMF(fis, 'U', 'trimf', [2 3 3], 'Name', 'PB'); % 规则表:25条规则,格式为 [E索引 EC索引 U索引 权重 连接方式] % 连接方式:1 表示 AND ruleList = [ 1 1 1 1 1; 1 2 1 1 1; 1 3 2 1 1; 1 4 3 1 1; 1 5 4 1 1; 2 1 1 1 1; 2 2 2 1 1; 2 3 3 1 1; 2 4 4 1 1; 2 5 5 1 1; 3 1 2 1 1; 3 2 3 1 1; 3 3 4 1 1; 3 4 5 1 1; 3 5 6 1 1; 4 1 3 1 1; 4 2 4 1 1; 4 3 5 1 1; 4 4 6 1 1; 4 5 7 1 1; 5 1 4 1 1; 5 2 5 1 1; 5 3 6 1 1; 5 4 7 1 1; 5 5 7 1 1]; fis = addRule(fis, ruleList); % 保存成 .fis 文件,方便统一下发给其他人 writeFIS(fis, 'cart_pole.fis');addMF 的参数格式是“底左、顶点、底右”三个横坐标,例如 [-3 -1.5 0] 表示一个三角形,顶点落在 -1.5,底边从 -3 延伸到 0。输入 E 的五个语言值均匀覆盖论域,相邻三角形在中间点交叉,这样任意输入值都会被两到三条规则同时触发,输出曲线更平滑。输出 U 用了七个语言值,比输入多两层,是为了在规则输出端能表达“稍微推一点”和“用力推”之间的中间力度。
3.3 5×5 模糊规则表的建立思路与实例
规则表可以按人的直觉直接写:摆杆向右倒(E 为正),而且倒的速度还在加快(EC 为正),那就用力向右推小车。注意不是向左推——向右推小车,小车向右加速,摆杆由于惯性会相对向左倾斜,正好把右倒的趋势抵消。这个方向关系是倒立摆控制里最容易搞反的一点,反了就是正反馈,仿真直接爆炸。
5×5 规则表如下,行是角度 E,列是角速度 EC,表内是对应输出 U 的语言值:
| E \ EC | NB | NS | ZO | PS | PB |
|---|---|---|---|---|---|
| NB | NB | NB | NM | NS | ZO |
| NS | NB | NM | NS | ZO | PS |
| ZO | NM | NS | ZO | PS | PM |
| PS | NS | ZO | PS | PM | PB |
| PB | ZO | PS | PM | PB | PB |
这张表有两个值得注意的地方。第一,主对角线方向是“同向加力”:角度和角速度同号时输出较强,异号时输出减弱甚至为零。比如 E 为 PB(向右倒)、EC 为 NB(正在回摆),输出是 ZO,说明这时候不需要再推,让摆杆自己摆回来。第二,边界处 NB 和 PB 区域有强饱和效果,也就是角度已经非常大时,无论角速度如何,输出都顶到最大力度,目的是尽快把摆杆拉回工作区。
3.4 在 Simulink 中挂载 FIS 及量化因子的作用
Simulink 里需要从 Fuzzy Logic Toolbox 库拖出 Fuzzy Logic Controller 块,双击后把 FIS Name 填成 fis,让它指向工作区变量。很多人在这里翻车:模型里填的是 'cart_pole.fis' 这个字符串,但那是文件名,不是变量名。正确做法是先运行 2.3 节的 set_params.m,让 fis 变量加载到工作区,再在块参数里填 fis。
信号顺序是:theta 和 theta_d 分别经过 Gain(Ke、Kec)进入 FIS 块,输出再经过 Gain(Ku)和 Saturation 限幅模块,最后接到被控对象的 F 输入端。Ke 把实际角度压缩到论域内,Kec 同理,Ku 把论域力度还原成物理力。三者一旦设置不当,症状差异很明显:Ke 太小响应慢,Ke 太大高频振荡;Kec 太大系统僵硬,Kec 太小回摆过冲;Ku 则是全局力度,太大发抖,太小根本拉不回来。
4. 在 Simulink 里搭闭环:从零连线到跑出稳定波形
4.1 闭环回路架构:被控对象、控制器与反馈路径
整体模型分成三块:被控对象(两组积分器加 MATLAB Function)、控制器(Ke/Kec 增益、FIS 块、Ku 增益、限幅)、观测输出(Scope 与 To Workspace 模块)。连接关系是:theta 和 theta_d 从积分器输出端引出,经过控制器后生成 F,F 进入 MATLAB Function 参与动力学计算,新算出的 x_dd 和 theta_dd 再积分回状态量,形成闭环。整个过程没有任何外部信号发生器参与,完全靠初值起动。
新建模型时,模块清单和参数可以参照下面这张表:
| 模块 | 库路径 | 关键设置 |
|---|---|---|
| MATLAB Function | Simulink / User-Defined Functions | 填入 cart_pole_dynamics 函数代码 |
| Integrator(两组) | Simulink / Continuous | 角度链第一个 Initial condition 填 theta0 |
| Gain(3 个) | Simulink / Math Operations | 分别填 Ke、Kec、Ku |
| Fuzzy Logic Controller | Fuzzy Logic Toolbox | FIS name 填 fis |
| Saturation | Simulink / NonLinear | Lower=-20,Upper=20 |
| Scope | Simulink / Sinks | 接 theta、x、F 三个信号 |
| To Workspace | Simulink / Sinks | 变量名 theta_out,方便后处理 |
MATLAB Function 模块默认只显示一个输入端口和一个输出端口,双击打开代码编辑器写上 2.2 节的函数后,端口会自动变成五个输入两个输出。此时手动连线容易接错,建议把信号线用标签标出来:输入端口从左到右对应 x、theta、x_d、theta_d、F,其中 F 来自控制器输出,其余四个来自积分器。
4.2 关键模块参数设置:积分器初始值、仿真停时与限幅
积分器初始值直接影响仿真的“开局难度”。theta 积分器的 Initial condition 填 theta0(0.2),另外三个积分器填 0。车初始位置为 0,摆杆从偏离竖直约 11.5° 的地方开始下落,这个幅度对模糊控制器来说既看得出控制过程,又不至于一上来就超出线性工作范围。如果想看控制器更强力的表现,可以改成 0.3,但超过 0.35 之后很多简单规则表会拉不回来,仿真表现为摆杆直接倒下、输出饱和。
仿真求解器默认的 ode45 通常够用,但需要注意一点:FIS 块本身是连续采样,如果你希望模拟真实数字控制器的采样周期,可以在 FIS 前加一个 Zero-Order Hold 模块,采样时间填 0.01 s。这会让控制量离散化,摆杆的稳定性会有所下降,但更接近实际嵌入式实现,属于进阶玩法。
Saturation 限幅必须加在 Ku 增益之后、被控对象之前,否则模糊控制器输出极端值时,MATLAB Function 会收到一个不切实际的巨大力度,积分步长会因此自适应缩小到极小,仿真慢得像蜗牛。限幅取 ±20 N 与 Ku 的设计值匹配,如果调大了 Ku,记得同步放宽限幅。
4.3 运行仿真:初始化脚本、观察曲线与调参流程
模型保存成 cart_pole_control.slx 后,运行顺序是先执行 set_params.m 把参数、量化因子、FIS 变量全部加载进工作区,再启动仿真。命令行方式如下:
% 命令行运行 set_params; sim('cart_pole_control.slx');仿真时间设 20 s 左右足够看到完整过程。正常情况下 theta 曲线应该在前 3 到 5 秒内收敛到 0 附近,之后在 ±0.05 rad 以内小幅波动,不再发散。如果 theta 像正弦波一样持续等幅振荡,说明参数接近临界稳定;如果振幅越来越大,说明参数方向反了或者模型搭建有误。
调参顺序我一般固定为“先 Ke,再 Ku,最后 Kec”,每次只动一个变量,不要同时改三个然后不知道是哪个起的作用。第一步把 Ke 从 15 往小调到 5,会发现摆杆响应变慢、恢复时间拉长;第二步把 Ku 从 6.67 往大调到 15,会发现过冲变大、振荡加剧;第三步把 Kec 从 3 往大调到 8,振荡会被压住一些,但太大会让摆杆像被冻住一样反应迟钝。最理想的一组参数是:稳态误差小、超调量在 20% 以内、控制力曲线不持续贴住限幅。
5. 初学者避坑:模糊控制倒立摆仿真最常见的 5 个翻车点
5.1 仿真直接发散:曲线一个积分步就飞到 1e10 级别
现象:点击 Run 后 Scope 里 theta 立刻出现 1e10 量级的数值,或者 MATLAB 报出 NaN、Inf,仿真直接崩掉。
原因:八成是控制方向接反了。倒立摆模糊控制的输出符号和角度定义有严格对应关系,向右倒(theta 为正)必须向右推小车(F 为正),如果 F 的符号接反,控制器一直在把摆杆往倒的方向推,就成了正反馈,系统自然瞬间发散。另外初始角度太大也会发散,模糊规则表的工作范围通常只有 ±0.2 rad 左右,你非要设成 0.6,超出规则有效覆盖区,控制器一直输出极限力度也救不回来。
解决:先把 theta0 改成 0.05 验证模型本身是否稳定,如果小角度还发散,那就是符号问题。最简单的排查方法是在 Ku 增益前面加一个 -1 增益模块试试,符号一翻,仿真立刻收敛,那就说明控制器方向反了,把 Ku 的符号改掉即可。
5.2 Fuzzy Logic Controller 提示找不到 FIS 变量
现象:双击 Fuzzy Logic Controller 块后模型图标变红,运行时弹错 “Error evaluating parameter 'fis' in ...”,或者提示变量不存在。
原因:块参数里填的 FIS 名称和工作区里的变量名对不上。最常见的是读者把 .fis 文件名当成变量名填了进去,比如填了 ’cart_pole.fis’ 而不是 fis。另一个常见原因是模型打开时 set_params.m 还没执行过,工作区是空的,变量自然不存在。
解决:先把块参数里的 FIS name 改成 fis;然后运行一次 set_params.m。如果还报错,在命令行单独执行一下 load 语句确认变量真的在:
fis = readfis('cart_pole.fis'); % 重新加载 whos fis % 检查是否存在于工作区5.3 摆杆一动不动:theta 保持初始值不变,控制输出恒为零
现象:Scope 里 theta 始终等于 theta0,F 曲线一直是一条 0 直线。
原因:信号线没接对。常见情况是 MATLAB Function 模块的输入端口顺序和函数签名不一致,把 theta 接到了 x 端,或者 theta_d 接到了 theta 端,导致控制器拿到的角度一直是 0,规则表输出 ZO,控制力永远为 0。还有一种情况是 F 信号没从控制器接出来,直接悬空,Simulink 会把悬空输入当 0 处理。
解决:打开 MATLAB Function 模块核对函数签名:第一个输入是 x,第二个是 theta,第三个是 x_d,第四个是 theta_d,第五个是 F。对照 2.2 节的代码和模型连线逐一检查。也可以在 MATLAB Function 里临时加一行 fprintf('F=%.3f\n', F); 看命令行有没有输出,F 始终为 0 就说明上游控制器有问题。
5.4 摆杆剧烈抖动:theta 在零附近高频振荡,像抽搐
现象:theta 最终没有发散,但一直以明显的高频小幅振荡,曲线毛刺很多,控制力 F 也在快速正负切换。
原因:最常见的是 Ku 过大或 Kec 过大,导致控制器在小误差区域输出增益太高,系统在一个极小范围里反复超调;其次是求解器步长问题,MATLAB Function 里的非线性表达式在角度接近 0 时动态极快,固定步长取得太大会引入数值误差。
解决:先把 Ku 减半,再把 Kec 减半,看振荡幅度是否下降。如果有效,说明是增益过高,逐步回调找一个临界值。如果减了增益没用,把求解器从变步长 ode45 改成固定步长 ode4,步长 1e-3,排除数值刚性问题。另外注意模型里不要形成代数环:MATLAB Function 的输入 F 如果直接来自它自己的输出,Simulink 会画出一条红色虚线回路,双击仿真信息窗口可以看到具体提示。
5.5 小车一直朝一个方向跑:theta 稳了,但 x 越来越大
现象:摆杆角度控制得很好,始终在零附近,但小车位置 x 一直单向增大,很快超出画面。
原因:这不是故障,是结构缺陷。当前的模糊控制器只有角度和角速度两个输入,它并不知道小车在哪里、在往哪跑。为了维持摆杆竖直,控制器会不断朝一个方向推小车,小车自然越走越远。这是单级倒立摆姿态控制的固有现象,不是你模型搭错了。
解决:如果只是做课程设计演示,接受这个现象,把仿真时间控制在 10 s 内,说明“完成了姿态稳定”即可。如果希望小车位置也稳住,需要扩展控制器设计:增加第三个输入 x 或小车速度 x_d,把位置反馈引入规则表,或者采用串级结构,外环 PD 控制位置、输出作为内环角度给定值。这个升级方向适合把仿真做完之后进一步深挖,属于这个项目标题之外的进阶内容。
6. 从仿真到实物:验证你的模糊控制到底可不可信
6.1 先骗过仿真:给模型加噪声、加延迟,再看稳不稳
很多人在干净模型上跑通之后就直接宣称“控制成功”,但真实物理系统里传感器带噪声、执行器有延迟,仿真里却什么都没有。验证模糊控制器是否真正可用,第一步是主动往模型里“掺沙子”:在 theta 反馈通道上加一个 Random Number 模块,噪声功率设 0.001;在 Ku 后面加一个 Transport Delay,延迟 20 ms;再把限幅换成带死区的 Saturation。如果这样改造之后系统还能收敛,这块控制器才有上实物的资格。
6.2 把 FIS 搬到硬件之前要做的三件事
一个是把 .fis 文件转成可执行的代码。新版 MATLAB 的 Fuzzy Logic Toolbox 支持用命令直接导出 C 语言结构的初始化函数,Simulink 模型也支持 C 代码生成,生成的代码可以移植到嵌入式控制器里。另一个是参数标定,量化因子 Ke、Kec、Ku 在实物上不能照搬仿真值,需要根据实际传感器量程重新换算。第三个是加输入滤波,实测角度信号里往往混有高频噪声,一阶低通滤波或滑动平均都能明显改善抖动。
我做过最蠢的一次是把仿真里调好的参数原封不动搬到小型实验台架上,结果摆杆一上电就开始振铃,整个台子像得了帕金森。问题出在仿真里我用的角度信号是理想值,实物上角度传感器有噪声,模糊规则里 ZO 区域内增益再被 Ku 放大,噪声直接变成了控制抖动。后来在角度反馈前加了截止频率 30 Hz 的一阶低通,并在规则表里把 ZO 区域改成输出死区,才压住。这个坑几乎是每个做倒立摆的人都要踩一遍的,记住一个原则:仿真参数是起点,不是终点。
做这个方向,建议不管你现在手里拿到的是哪个版本的资源包,都抽出半天时间把模型完全拆开重新搭一遍,重点放在规则表设计和信号方向检查上。你可能会发现,搭模型比调规则快,查方向比改参数要命。希望帮到你。
本文还有配套的精品资源,点击获取