简介:这是一份基于Simulink的单自由度轴向磁悬浮轴承控制模型,适合从事磁悬浮控制、电力电子或自动控制方向的学生与工程师,用于快速搭建磁悬浮仿真环境、研究悬浮控制算法。压缩包共2个文件,分别为主Simulink模型(.mdl)和Matlab建模脚本(.m),前者包含传感器信号处理、控制器与电磁力计算等模块结构,后者基于磁路法生成系统数学模型,整体仅12KB,轻量易用。已有408人学习下载,常用于课程设计、毕业设计或预研验证。借助该资源,用户可直观理解磁悬浮系统的建模与仿真流程,并基于模型修改参数,为PID、滑模等不同控制策略的仿真对比提供实践基础。
1. 悬浮控制模型在 Simulink 里先要处理的正反馈刚度
解压一个磁轴承仿真包,最常见的劝退场景不是模型打不开,而是 Scope 里位移通道在 0.2 秒内直接冲到底板。很多 Simulink 模型不收敛,并不是 PID 给得太激进,而是磁轴承被控对象的运动方程里天然带一个正反馈项:转子偏离中心后,吸气隙更近的那一侧电磁吸力会自动增大,形成“越偏、拉力越大”的循环。对机械系统来说,这个等效刚度是负的,所以工程里叫它磁轴承负刚度。做悬浮控制模型时,第一原则不是急着拉 PID,而是先把电磁力线性化成两个系数:一个反映控制电流能产生多大的力,另一个反映位置偏移会产生多大的正反馈力。下面按这个顺序,把磁轴承模型从物理方程讲到可仿真的 Simulink 闭环。
2. 磁轴承差动磁力线性化:把 ki 和 kx 算出来再进 Simulink
2.1 单磁极电磁吸力与差动电磁铁的工作点
磁轴承每个自由度通常不是用单个电磁铁,而是用一对面对面安装的差动电磁铁。单个磁极的电磁吸力可以写成:
F = C * i^2 / g^2
其中i是线圈电流,g是气隙,C = mu0 * A * N^2 / 4,由磁极面积A和线圈匝数N决定。仿真空心铁芯模型时直接用这个表达式没有问题,但直接做控制系统会遇到两个麻烦:电流平方项让输入和输出不是线性关系,气隙平方项让位置刚度随工作点剧烈变化。所以实际工程中会先给电磁铁加一个偏置电流i0,让转子稳定在额定气隙g0附近,再用控制电流ic在两侧做差动调节。
偏置电流的作用有两面性。一方面,它让电流-力曲线在零点附近近似线性,否则i=0附近控制器几乎没有增益;另一方面,偏置电流也同时带来了“越偏越吸”的正反馈梯度。很多简化模型只保留电流刚度而丢掉位置刚度,闭合之后仿真看起来稳定,换到真实磁轴承上却完全压不住转子,问题就出在这里。
2.2 把差动合力展开成 ki 和 kx 两个刚度
设转子向右偏移量为x,控制电流ic定义成让左侧磁极电流增大、右侧磁极电流减小。于是向右的合力可以写成:
F = C*(i0-ic)^2/(g0-x)^2 - C*(i0+ic)^2/(g0+x)^2
在x/g0远小于 1、ic/i0也远小于 1 的条件下保留一阶项,差动合力可以线性化成:
m * x'' = kx * x + ki * ic
其中:
kx = 4 * C * i0^2 / g0^3,单位 N/m,表示位移力梯度ki = 4 * C * i0 / g0^2,单位 N/A,表示电流刚度
这里kx出现在运动方程右侧且符号为正,说明它是正反馈项。写成机械弹簧形式就是m*x'' + k_mech*x = ...,其中k_mech = -kx,所以才叫负刚度。ki的符号取决于控制电流定义和电磁铁接线方向,如果仿真里发现方向反了,把ki取负即可,不需要改模型结构。
2.3 算例:一组能支撑仿真的刚度与状态矩阵
下面的 MATLAB 脚本给出一组典型磁轴承单自由度参数,并直接生成开环被控对象的状态空间模型。参数不需要追求和某个实物完全一致,关键是量级要对:转子质量几十千克以下,位移刚度通常在 10^5 N/m 左右,电流刚度在 10^2 N/A 左右。
% 磁轴承单自由度参数 m = 10; % 等效质量,kg mu0 = 4*pi*1e-7; % 真空磁导率 A = 4e-4; % 单磁极有效磁极面积,m^2 N = 100; % 线圈匝数 C = mu0 * A * N^2 / 4; % 电磁力系数 g0 = 3e-4; % 额定气隙,m i0 = 2; % 偏置电流,A kx = 4 * C * i0^2 / g0^3; % 位移力梯度,N/m ki = 4 * C * i0 / g0^2; % 电流刚度,N/A A_mat = [0 1; kx/m 0]; B_mat = [0; ki/m]; C_mat = [1 0]; D_mat = 0; sys_p = ss(A_mat, B_mat, C_mat, D_mat); % SISO 被控对象 eig(A_mat) % 查看是否有一个右半平面根脚本里A_mat的第二行完全由kx/m决定。算出来eig(A_mat)会是一对实根,一个为正,一个为负,这就是开环不稳定的直接证据。后面在 Simulink 里用 State-Space 模块时,可以直接把A_mat、B_mat这些矩阵填进去,不用再重复搭积分器和增益。
| 符号 | 物理含义 | 单位 | 示例值 |
|---|---|---|---|
| m | 单自由度等效质量 | kg | 10 |
| C | 电磁力系数 | N·m²/A² | 1.26e-6 |
| g0 | 额定气隙 | m | 3e-4 |
| i0 | 偏置电流 | A | 2 |
| kx | 位移力梯度 | N/m | 7.45e5 |
| ki | 电流刚度 | N/A | 111.7 |
3. Simulink 悬浮控制模型搭建:State-Space 被控对象、电流环与 PID 接线
3.1 用 State-Space 模块把 ki、kx 装进模型
搭建 Simulink 模型时,我一般不会用两个 Gain 和两个 Integrator 手工搭状态方程,而是直接拖一个 State-Space 模块。双击模块,把上一章脚本里算好的A_mat、B_mat、C_mat、D_mat填进去。这样后续用 Simulink Control Design 做线性化、算传递函数、整定 PID 都会非常顺,因为线性化工具能直接识别状态空间模块。
需要注意State-Space模块的输入是控制电流ic,不是最终 PWM 占空比或功放电压。如果你把电流环也放进 Simulink,那么电流环输出接 Plant,位置环 PID 输出接电流环给定。开环模型可以先用一个 Step 加在 Plant 输入端,看位移是不是按指数发散方向走:如果正向阶跃导致正向位移快速增长,说明kx/m的作用方向正确。
下面是打开已有闭环模型并设置参数的示例脚本。模型名mag_bearing_close是手动搭好的结构,接线顺序是“参考 0 -> 差值 -> 位置环 PID -> 饱和 -> 电流环 PI -> 电流饱和 -> Plant -> 位移反馈”。
% 把上一章算好的参数写进闭环模型 set_param('mag_bearing_close/Position PID', ... 'P','20000', 'I','5000', 'D','35'); set_param('mag_bearing_close/Current PI', ... 'P','5', 'I','500'); set_param('mag_bearing_close/Plant', ... 'x0','[1e-5; 0]'); % 给 0.01mm 初偏,观察回中 sim('mag_bearing_close', 0.2);set_param的好处是参数以字符串形式写进模块,后续做批量扫描时,只需要把数字换成工作区变量,例如'P','PID_P',然后循环改PID_P即可。模型里Plant的初始状态不能设成全零,否则仿真只会在平衡点附近无事发生;给一个很小的 10 微米初偏,能很快看出闭环是否真的把转子拉回中心。
3.2 电流环和功率放大器:不是用一个 Gain 糊弄过去
磁轴承控制系统如果只看位置环,很容易把电流环简化成1/(T_i*s+1)的一阶惯性。但这样做有一个隐藏风险:电流环带宽如果低于被控对象开环不稳定的特征频率,位置环实际控制的是一个“拖着慢尾巴”的惯性对象,仿真很容易出现 200 Hz 到 500 Hz 的高频振荡。
对于 5 mH 电感、2 欧姆电阻的线圈,从电压到电流的传递函数是1/(0.005*s+2),时间常数 2.5 ms。如果电流环 PI 给得太慢,闭环电流环带宽可能只有一两百 rad/s,而上一章算出的开环正根已经接近 273 rad/s,这就不满足最小带宽要求。仿真的意义就是把这个问题提前暴露。
推荐的做法是至少保留一个电流环 PI 和一个饱和模块,并单独测一下电流环阶跃响应。电流环 PI 可以先给P=5、I=500,让电流环带宽落在 1 kHz 以上。位置环再去处理机械刚度和阻尼,不要让位置环同时去补电流环的滞后。
3.3 位置环 PID 和负刚度抵消
位置环的 PID 三个参数在磁轴承里有很明确的分工:比例项产生与位移成比例的电磁力,用于抵消kx*x正反馈;微分项提供等效阻尼,压住刚体模态;积分项解决不对称偏载和传感器零漂,保证稳态悬浮在中心位置。
接线时把参考位移设成 0,位置反馈从 State-Space 模块的输出端接回差值点。如果用的是真实传感器,反馈端还要加 20 kHz 到 40 kHz 的低通滤波,但仿真里可以先不加。PID 模块记得开启微分滤波,N默认取 1000 或更小,否则在求解器步长变化剧烈时,微分项会把传感器噪声放大成抖动。位置环输出经过一个 ±10 的饱和再加到电流环,防止启动时 PID 给一个几十安培的电流指令。
3.4 一组能跑起来的仿真参数
按照上面的模型结构,可以使用下面这组初始参数跑通第一次仿真:
| 模块 | 参数 | 初值 |
|---|---|---|
| 位置环 PID | P=20000, I=5000, D=35, N=1000 | 抗饱和 back-calculation,增益 0.3 |
| 位置环输出饱和 | 上下限 | ±10 |
| 电流环 PI | P=5, I=500 | 输出限幅 ±10 |
| Plant 初始状态 | x0 | [1e-5; 0] |
| 求解器 | ode45,最大步长 | 1e-4 s |
| 仿真时间 | StopTime | 0.2 s |
位置环D=35对应的阻尼系数是ki*D,约 3900 N·s/m,对 10 kg 质量来说是过阻尼方向偏临界阻尼,先跑一次看有没有超调。如果位移回中太慢,加大 P;如果回中前出现明显振荡,加大 D,再拉大积分增益 I。仿真时间 0.2 秒足够看到至少一次完整的回中过程。
4. 磁悬浮控制模型仿真发散排查:pidtune、求解器与抗饱和
4.1 用 pidtune 先拿一组稳定 PID
手工给 PID 参数容易在负刚度模型上踩坑,因为开环有右半平面极点,比例增益给小了根本稳不住。更好的做法是直接利用线性对象sys_p,用闭环带宽作为设计目标来整定。目标带宽必须明显高于开环正根,这里正根约 273 rad/s,所以先试 400 rad/s。
% 用线性被控对象 sys_p 整定位置环 PID opts = pidtuneOptions('PhaseMargin', 45); [Cpos, info] = pidtune(sys_p, pid(20000, 5000, 35), 400); % 把整定结果写回模型 set_param('mag_bearing_close/Position PID', ... 'P', num2str(Cpos.Kp), ... 'I', num2str(Cpos.Ki), ... 'D', num2str(Cpos.Kd));pidtune对不稳定的被控对象也能生成稳定控制器,但它返回的是连续域 PID,且默认带一阶微分滤波参数Tf。如果算出来的滤波时间常数接近 1e-4 秒以下,说明目标带宽给得偏高,可以把 400 降到 350 或 300。info结构里能看到闭环极点和稳定标志,不要只看Cpos。
4.2 用 margin 和根轨迹确认正根被拉回左半平面
Simulink 模型跑出看起来不错的回中曲线后,还需要确认稳定性裕度。把整定后的 PID 和被控对象串起来画 Bode 图:
L = sys_p * Cpos; margin(L);margin会显示开环穿越频率和相位裕度。磁轴承位置环的相位裕度最好保持在 30 度以上,穿越频率落在 200 rad/s 到 500 rad/s 区间。低于 200 rad/s 说明控制器反应偏慢,难以克服负刚度;高于 500 rad/s 则容易把高频噪声带进电流环,实际硬件很难跟踪。如果相位裕度不够,优先减小 PID 的积分项,必要时降低目标带宽,而不是一味加大 D。
4.3 发散、饱和、采样时间不一致
仿真发散的原因需要分类排查,不要一上来就怀疑求解器。
| 现象 | 常见原因 | 检查点 |
|---|---|---|
| 位移直线冲向限位 | 控制方向反了或比例增益太小 | 把ki取负,逐步加大 P |
| 5 kHz 以上高频抖动 | 微分项噪声放大或电流环太慢 | 加微分滤波 N,提高电流环带宽 |
| 波形稳定但偏差很大 | 积分增益不够或传感器零漂偏置 | 加大 I,加入参考前馈 |
| 数值出现 NaN | 气隙被算到 0 或负值 | 检查位移初值和饱和限幅 |
有一点容易被忽略:位置环 PID 模块里的N如果不设置,默认值在高频时也会引入零点,仿真会把这个零点当成真实微分放大。很多模型从 MATLAB 旧版本迁移过来后突然高频振荡,就是因为 PID 模块的微分滤波参数变了。
4.4 抗积分饱和
磁轴承启动时位置误差很大,位置环 PID 输出会很快顶到饱和。如果 PID 没有开抗饱和,积分项会继续往上累计,等位移回到中心时,积分输出还挂在最大值附近,转子会冲过中心再被拉回来,形成一次低频大幅摆动。事实上有时候“发散”只是积分饱和后的一次过冲。
在 Simulink 的 PID Controller 模块里,把 Anti-windup method 设为 back-calculation,Anti-windup gain可以先给 0.3。电流环 PI 同样要设输出饱和,很多模型只在位置环出口设了饱和,结果电流环积分器自己先饱和了,问题依旧。两个环路都要限幅,并且限幅值要匹配实际功放输出能力。
5. 用 linearize 把磁轴承 Simulink 模型闭环整定做成批量工作流
5.1 从非线性模型拿到线性化对象
仿真能稳定运行之后,不要只靠 Scope 波形判断性能。更好的做法是在模型中用 Simulink Control Design 的线性化输入输出点,把整个闭环在平衡工作点处线性化,然后读闭环阶跃响应和 Bode 图。这样可以客观地看出闭环带宽、相位裕度和负刚度抵消效果,而不是靠肉眼数超调量。
% 在位置环输入处打断线性化回路,在 Plant 输出处取位移 io = [linio('mag_bearing_close/Position PID', 1, 'input'), ... linio('mag_bearing_close/Plant', 1, 'output')]; sys_lin = linearize('mag_bearing_close', io); step(sys_lin); bode(sys_lin);linio里的模型路径要和实际 Simulink 模块名一致。线性化会在当前工作点自动求偏导,不需要手动给状态初值。这一步比直接跑sim快得多,也更适合做参数扫描:每次改完 PID,重新linearize一次,就能看到闭环带宽往哪个方向移动。
5.2 用工作区变量把 PID 参数和批量扫描串起来
最后一个实用技巧是把所有 PID 参数写成工作区变量,而不是在模块对话框里写死数字。这样后续批量扫描只改变量循环,不需要反复打开 Simulink 界面。
% 先在工作区定义参数 PID_P = 20000; PID_I = 5000; PID_D = 35; % 模型里 PID 模块参数写成 'PID_P'、'PID_I'、'PID_D' set_param('mag_bearing_close/Position PID', ... 'P','PID_P', 'I','PID_I', 'D','PID_D'); % 批量扫描比例增益 P_list = [10000 20000 40000]; for k = 1:length(P_list) PID_P = P_list(k); simOut(k) = sim('mag_bearing_close', 'StopTime', '0.2'); end模型里 PID 模块的 P 参数直接填字符串PID_P,Simulink 在仿真开始时会自动从工作区取值。这样批量扫描的结果都在simOut变量里,可以一次性绘制不同比例增益下的位移曲线。如果后续要上硬件,还可以把同一组 PID 参数通过set_param写进 Embedded Coder 生成代码前使用的模型,配合外部模式先在真实功放上做一次小幅摆锤测试,确认电流环方向后,再让转子闭环悬浮。整个过程从线性化到代码生成共用一份参数,避免在 UI 和脚本之间来回抄数字。
本文还有配套的精品资源,点击获取