做电机控制仿真这行当久了,会发现一个规律:PID虽然经典,但碰上负载突变、参数摄动这类情况,调来调去总有点力不从心。尤其做永磁同步电机(PMSM)调速系统的时候,PI参数刚在一台电机上整定好,换一台电机或者工况一变,又得重新试。后来我把控制器换成自抗扰控制(ADRC),很多问题迎刃而解。这篇文章就把我搭建基于ADRC的PMSM仿真模型的过程、踩过的坑、参数整定的经验,完整写出来。不管是正在做毕业设计,还是做伺服驱动项目选型,这套Simulink仿真方案都值得参考,它能把“扰动估计+补偿”这套思路直接落到能跑通的模型上。
1. 为什么PMSM控制选择ADRC:从“对抗误差”到“对抗扰动”的思路转变
1.1 传统PID在PMSM控制里的固有短板
在聊ADRC之前,先把传统PID放在PMSM双闭环控制里的问题说透。PMSM的数学模型本身就是一个强耦合、非线性的系统,d轴和q轴之间存在交叉耦合项,反电动势还跟转速成正比。传统矢量控制用PI调节器,本质上是在“对抗误差”——误差大了就加大比例,持续存在就靠积分去消除。
这个思路在工程上很成熟,但有两个绕不开的痛点。
第一个痛点是积分饱和。转速环PI控制器在电机启动或者负载突加的时候,积分项很容易积累过头,导致转速超调大、恢复时间长。我见过不少同学把积分限幅调到最大值,结果电机一启动就猛冲,接着振荡好几拍才稳定下来。第二个痛点是参数鲁棒性差。PI参数是按某一组电机参数(电感、磁链、转动惯量)整定的,一旦电机温度升高导致磁链变化,或者带载转动惯量变大,实际系统的动态特性就变了,原本那组PI参数就不再是最优的。
I-PD结构的控制器能缓解超调问题,但本质上还是依赖精确的数学模型去“预测”系统行为。而ADRC的核心思想完全不同:它不纠结于误差有多大,而是把系统模型不确定性和外部负载扰动统一成一个“总扰动”项,用扩张状态观测器(ESO)把它实时估出来,然后在前馈通道里把这个估计值主动抵消掉。说白了,PID是在被扰动打了一拳之后才被动反应,ADRC是提前把这一拳的力度看穿并架住。
1.2 ADRC的三个核心部件和工程语言解释
ADRC由跟踪微分器TD、扩张状态观测器ESO、非线性状态误差反馈NLSEF三部分组成。用一句大白话说它们的职责:
- TD:先把你要的速度目标做个“平滑处理”,别让阶跃信号直接砸进系统,同时给出过渡过程的微分信号。
- ESO:系统的眼睛和侦察兵,实时估计当前转速和那个看不见的“总扰动”。
- NLSEF:拿着TD给的理想轨迹、ESO给的实测状态,做误差反馈,再加上ESO估计的扰动补偿值,形成最终控制量。
把这三部分放在PMSM转速环里具体解释一下。TD那边,我给定一个目标转速1000rpm,TD不会让控制器立刻去追1000rpm这个阶跃目标,而是生成一条平滑的过渡曲线,这样从根本上避免了超调——不是靠减小增益压出来的,而是目标本身就变平滑了。ESO则是把“负载转矩变化”、“摩擦变动”、“参数辨识误差”这些乱七八糟的东西统统归结成一项总扰动f(x,t),用一个扩张状态去观测它,再在控制律里减去这个观测值。NLSEF则是一个非线性组合,通常用fal函数实现,小误差大增益、大误差小增益,兼顾响应速度和稳态精度。
这三个部分配合起来,对PMSM来说意义很大:因为PMSM的模型里,dq轴电流耦合项电感变化、磁链温度漂移、负载突变,全都可以当作总扰动的一部分被ESO吃进去并补偿掉。这样控制器设计就不再依赖精确的电机动静态模型,鲁棒性上了一个台阶。
1.3 ADRC和PI控制在仿真阶段的直观对比
我用Simulink做过一个对比:同样一台PMSM,给定转速从500rpm阶跃到1000rpm,并在0.5秒时突加2倍额定负载。
PI控制下,转速先冲高到1080rpm,大约0.6秒才稳下来;换成ADRC之后,转速最大超调被压在20rpm以内,恢复时间缩短到0.2秒左右。更明显的是突加负载的瞬间,PI要塌下去大约80rpm,ADRC则只有不到20rpm的波动。
这个对比不是偶然。ADRC把“负载突变”当成总扰动的一部分,ESO在几百微秒内就能把它观测出来并前馈补偿掉;PI只能靠积分项慢慢把静差消掉。做仿真模型的时候,这两者的差异在示波器上看一眼就非常直观,也很适合放进论文或者汇报PPT里作为亮点。
2. 搭建前的准备:PMSM数学模型和ADRC离散化设计
纸上谈兵到此为止,真要在Simulink里搭模型,第一步得先把PMSM的数学模型在头脑里理清楚。有人喜欢直接用Simulink库里的PMSM模块,但我更推荐先自己搭一遍数学方程,一方面能深入理解电机运行机理,另一方面ESO的设计需要知道模型的结构形式,特别是控制增益b0的取值,跟电机参数直接挂钩。
2.1 PMSM在dq旋转坐标系下的数学模型
标准表贴式PMSM(SPMSM)在dq坐标系下,电压方程和转矩方程如下:
电压方程:
- ud = Rs * id + Ld * did/dt - ωe * Lq * iq
- uq = Rs * iq + Lq * diq/dt + ωe * (Ld * id + ψf)
其中Rs是定子电阻,Ld和Lq是dq轴电感,ωe是电角速度,ψf是永磁体磁链。对表贴式电机,Ld=Lq=L。
转矩方程: Te = 1.5 * p * ψf * iq
机械运动方程: J * dωm/dt = Te - TL - B * ωm
其中p是极对数,J是转动惯量,TL是负载转矩,B是阻尼系数。
做id=0矢量控制时,d轴电流给定为0,此时转矩只跟iq成正比。也就是说,PMSM的速度控制问题,在外环看来就变成了一个一阶被控对象:控制量是iq,输出是转速ωm,中间夹着电流环的跟踪延迟和机械积分环节。ADRC的ESO设计,本质上就是针对这个一阶系统的总扰动估计问题。
2.2 ADRC各环节的离散化公式和Simulink实现选择
ADRC在Simulink里实现有两种路径:一种是用现成的第三方ADRC库,另一种是自己用S-Function或者MATLAB Function写离散化算法。我强烈建议自己写,因为现成库封装得太黑盒,参数出了问题你完全不知道是哪个环节在作怪。自己写就几行代码,调试起来明明白白。
转速环ADRC的离散化设计,常用的是一阶ADRC。下面给出核心公式。
跟踪微分器TD(安排过渡过程): x1(k+1) = x1(k) + h * x2(k) x2(k+1) = x2(k) + h * fhan(x1(k) - v_ref, x2(k), r, h0)
其中v_ref是给定转速,r是跟踪速度因子,控制过渡过程快慢,h0是滤波因子,fhan是最速控制综合函数,它的表达式比较长,网上可以搜到标准形式,这里不展开,核心作用是既保证快速又避免超调。
扩张状态观测器ESO: e = z1(k) - y(k) z1(k+1) = z1(k) + h * (z2(k) - β1 * e) z2(k+1) = z2(k) + h * (z3(k) - β2 * fal(e, α1, δ) + b0 * u(k)) z3(k+1) = z3(k) - h * β3 * fal(e, α2, δ)
其中z1观测转速,z2观测转速变化率,z3观测总扰动,u是控制量iq给定,b0是控制增益。β1、β2、β3是观测器增益,α1、α2是fal函数的幂次,δ是线性区间宽度。
非线性状态误差反馈NLSEF: e1 = x1(k) - z1(k) e2 = x2(k) - z2(k) u0 = kp * fal(e1, α1, δ) + kd * fal(e2, α2, δ) u(k) = u0 - z3(k) / b0
这里的核心逻辑是:u0是非线性PD形式的反馈控制量,然后减去ESO估计的总扰动除以b0,这个补偿项把系统拉回纯积分串联型结构,让NLSEF面对的是一个“干净的”积分对象。
在Simulink里实现时,把上面这些公式写在一个MATLAB Function或者S-Function里面,输入是目标转速、实际转速,输出是q轴电流给定。采样周期h一定要和模型的固定步长一致,否则离散化误差会重到让你怀疑算法是不是写错了。
2.3 控制增益b0的物理含义和取值方法
ADRC里有个参数b0,很多初学者不理解它到底怎么取。b0是控制量的增益估计值,代表控制量对系统状态的直接影响程度。在转速环里,b0的物理量纲是“控制量iq变化引起的转速加速度的增益”,大致估算公式:
b0 ≈ 1.5 * p * ψf / J
注意这里不考虑电流环的延迟。如果电流环动态足够快(带宽是速度环的5-10倍),直接按这个公式估算就行;如果电流环比较慢,要适当把b0调小,因为电流跟踪延迟会让实际等效增益下降。
我在做仿真的时候,把J=0.001kg·m²,p=4,ψf=0.2Wb代入,算出来b0大约等于1200。ESO性能对b0的误差有一定的容忍度,一般估算偏差在±30%以内,ESO都能通过z3把这个增益误差当作扰动的一部分估计并补偿掉。这一点正是ADRC的强大之处——它不要求模型精确,只要求b0的数量级大致正确。
3. Simulink仿真模型搭建:从整体架构到核心模块详解
整个PMSM矢量控制系统的Simulink模型,自底向上分为五层:电机本体层、逆变器与SVPWM层、坐标变换层、电流环层、转速环ADRC层。下面拆开讲每一层的搭建要点。
3.1 整体模型架构和信号流设计
打开Simulink,新建一个模型,设置为定步长,步长我习惯取1e-5秒(10微秒)。这个步长对SVPWM调制频率(通常10kHz-20kHz)来说足够,还能保证数值稳定性。
模型层级的信号流这样走:
- 给定转速v_ref时序信号进入ADRC转速环控制器,输出q轴电流给定iq_ref。
- iq_ref和id_ref(恒为0)分别和实际反馈电流id_fb、iq_fb做差,送入两个电流环PI调节器,输出d轴和q轴电压给定ud_ref、uq_ref。
- ud_ref、uq_ref经过反Park变换(需要转子位置角θe),得到αβ坐标系下的电压uα、uβ。
- uα、uβ送入SVPWM模块,输出六路PWM信号驱动三相逆变器。
- 三相逆变器输出电压加载到PMSM定子绕组上,电机输出三相电流ia、ib、ic和机械转速、转子位置。
- 三相电流经过Clark变换和Park变换,得到同步旋转坐标系下的id_fb、iq_fb,反馈给电流环和ADRC。
这个结构是最标准的id=0矢量控制框架。ADRC代替了传统速度环PI,其他部分保持不变。
3.2 电机本体建模:推荐用数学方程模块自己搭
我建议用Simulink标准库里的“PMSM”模块也行,但更推荐自己搭dq模型。自己搭的好处是可以随时改参数、暴露中间变量、插入故障注入口,调试效率高很多。
搭建方法:用一个MATLAB Function实现PMSM的dq电流微分方程和机械方程,输入是ud、uq、负载转矩TL,输出是id、iq、转速ωm、转子位置θe。
内部逻辑大致是:
did/dt = (ud - Rsid + ωeLiq) / L diq/dt = (uq - Rsiq - ωe*(Lid + ψf)) / L Te = 1.5pψfiq dωm/dt = (Te - TL - Bωm) / J dθe/dt = pωm
写MATLAB Function的时候注意,状态变量要用persistent变量保存,配合定步长求解器做离散积分。也可以用连续积分模块,但我更习惯在函数内部用欧拉法做积分,这样和ADRC的离散化风格统一。
3.3 SVPWM模块的实现细节
SVPWM是矢量控制系统里的关键环节。我推荐用基于“参考电压矢量合成”的标准七段式SVPWM,实现步骤:
- 根据uα、uβ判断参考电压所在扇区。
- 计算两个相邻基本电压矢量的作用时间T1、T2。
- 根据扇区确定A相、B相、C相的开关切换时刻。
- 生成周期为PWM周期的三角载波比较值,输出六路PWM。
具体公式不在这里全列,网上现成的SVPWM计算函数很多。我提几个容易出错的地方:
扇区判断要严谨,用uα、uβ的符号和大小关系判断,别用atan2算角度再查表,浮点运算量大还容易在边界出问题。
T1、T2超过PWM周期一半时要限幅,否则逆变器会过调制,波形失真。
死区时间要在Simulink里用“Transport Delay”或者门极逻辑模拟,死区设置过小会导致桥臂直通,过大则电流波形畸变加剧。仿真里我一般加2微秒死区,刚好能看出死区效应又不至于太夸张。
3.4 电流环PI和ADRC转速环的接口匹配
电流环PI参数按经典工程设计方法整定:电流环带宽取2000rad/s左右,PI参数按“零极点对消”原则计算,Kp = Lωc,Ki = Rsωc。这样配对理由很直接:电流环的传递函数是一个一阶惯性环节,用PI的零点把被控对象的极点对消掉,剩下的闭环就是一阶低通。
转速环ADRC的输出是iq_ref,输入是v_ref和转速反馈。这里有一个轻量级的限制问题:iq_ref必须经过限幅处理,防止电流过大烧毁逆变器和电机。在ADRC结构里,限幅可以放在NLSEF输出之后、控制量施加之前。要注意限幅别把ESO的扰动补偿量也砍了,否则补偿效果会大打折扣。所以实现上我把u0和扰动补偿分开处理:
iq_ref_saturated = saturate(u0) - z3/b0
这样即使u0饱和,ESO的扰动补偿仍然全量生效。不过实际测试下来,如果把扰动补偿放外面,在重载启动工况下补偿项很大会让限幅失效,所以更稳妥的做法是:iq_ref_raw = u0 - z3/b0,然后整体限幅。代价是突变工况下补偿会被截断,但总比超流安全。
3.5 转子位置和速度测量的仿真模拟
实际系统里转子位置来自编码器,转速由位置微分或M/T法计算。仿真模型里可以直接用电机模型的真实θe、ωm,也可以为了贴近实际,在反馈通道上加一个一阶低通滤波器模拟测量延迟,甚至加一个量化模块模拟编码器分辨率。
我建议至少加一个低通滤波,带宽设1000rad/s左右,模拟实际测速环的滞后。不加的话,仿真模型会过于理想,ADRC参数整定得再好,搬到实物上也会因为反馈噪声、延迟而表现打折。
4. ADRC核心算法实现:参数设计方法和整定流程
4.1 经典的“带宽法”参数整定
ADRC参数确实比PI多,但整定路径是有章法的,核心方法就是“带宽法”。先看ESO部分的三个增益β1、β2、β3,它们跟观测器带宽ωo直接相关。当选好ωo之后,按如下规则配置:
β1 = 3ωo β2 = 3ωo² β3 = ωo³
这就是典型的“带宽配置法”,把ESO特征方程配置成——说起来就是让观测器跟踪速度由ωo决定,ωo越大,ESO跟踪和估计越快,但放大噪声越严重。工程经验上ωo取转速环闭环带宽ωc的3到5倍。
NLSEF部分的kp、kd则和控制器带宽ωc直接挂钩。对一阶ADRC,理想配置是:
kp = ωc² kd = 2*ωc
这也是和二阶系统标准形式对等出来的。不过NLSEF里的fal函数会让等效增益在小误差区域变大,所以实际整定时kp可以比公式值略小个10%到20%。
4.2 用极点配置理解ESO参数选择
我换个角度解释一下为什么β1、β2、β3这么配。把ESO的动态方程线性化,扰动的跟踪误差方程特征多项式是:
s³ + β1s² + β2s + β3 = 0
如果想让特征根都落在离原点ωo远的地方,那就令特征多项式等于(s+ωo)³,展开后就是:
s³ + 3ωos² + 3ωo²s + ωo³
所以β1=3ωo,β2=3ωo²,β3=ωo³。这个配置方法的好处:只有一个参数ωo要调,调观测器带宽就相当于同时调了三个参数,避免了手动瞎试。实践证明,用带宽法先把ESO调稳定,再单独调TD和NLSEF,比无头苍蝇一样乱调快得多。
4.3 极点配置原理应用
下面给一套实际能跑的ADRC转速环参数值。假设仿真电机参数:额定电压310V,额定电流4.5A,额定转速3000rpm,极对数4,定子电阻2.5Ω,dq电感8.5mH,磁链0.175Wb,转动惯量0.0008kg·m²,阻尼系数0.0001N·m·s。
b0估算:1.540.175/0.0008 = 1312.5,取整1300。
转速环控制器带宽ωc取100rad/s,观测器带宽ωo取500rad/s。那么:
kp = 10000,kd = 200 β1 = 1500,β2 = 750000,β3 = 125000000
TD部分,跟踪速度因子r取2000,滤波因子h0取0.001。fal函数的α1取0.5,α2取0.25,δ取0.01。
这套参数在仿真里表现:阶跃响应无明显超调,0.2秒内进入稳态,突加额定负载转速跌落30rpm以内,0.1秒内恢复。拿这套参数做基准,再根据自己电机的差异微调b0和ωc,通常几次就能收敛到满意效果。
4.4 仿真结果的分析维度
调好之后,从几个维度观察仿真结果是否健康:
第一个维度是ESO的观测精度。把z3(总扰动估计值)和实际的负载转矩折算值同时拉出来看,如果ESO正常工作,两条曲线应该基本重合。如果偏差大,要么ωo太低导致观测滞后太多,要么b0估得不准让补偿量失真。这个检查项特别重要,因为不管NLSEF调得多精致,只要ESO观察失真,整个ADRC性能就无从谈起。
第二个维度是控制量iq_ref的品质。看它是否平滑、是否频繁震荡、有没有长时间顶在限幅值上。如果iq_ref带高频毛刺,说明ESO把测量噪声放大得太厉害,适当调低ωo。如果iq_ref长时间饱和,说明加负载超出了电机的物理极限,或者TD安排的过渡时间太短,可以增加过渡时间。
第三个维度是转速波动的频谱,特别是稳态是否出现固定频率的周期振荡,这往往是ESO和NLSEF参数不匹配导致的极限环振荡。遇到这种情况,优先减小kp或增大δ值,让NLSEF的增益曲线更平坦,振荡通常能压下去。
5. Simulink仿真模型实施过程中的常见故障与排查
仿真模型搭好之后开始跑,几乎不可能一把过。我把调试过程中遇到频率最高的几类问题列出来,附带排查思路,方便各位直接对照处理。
5.1 模型发散、数据溢出:第一优先检查采样步长和代数环
仿真报错“Inputs to outputs are not properly connected”或者数值飞掉,十有八九是步长设置或者代数环的问题。定步长求解器如果步长大于PWM周期的四分之一,SVPWM的三角波比较就会出现严重混叠,电流波形乱成一团。步长一定要小于PWM周期的十分之一,用10kHz的开关频率,步长至少要1e-6到5e-6秒,我通常用1e-5秒配合15kHz开关频率,基本稳。
代数环问题则出现在你用了直接馈通的数据通路,比如电流反馈信号和PI输出之间没有经过任何状态。解决方法是把PWM比较值和电流反馈之间的通路加上Memory模块或Unit Delay,切断代数环。这是Simulink建模最常见的新手坑。
还有一种情况,ESO的β3取得太大导致数值刚性,步长又不够小,积分直接爆炸。遇到这种,把ωo调低一个数量级试试基本能稳住,或者把求解器换成ode15s先跑一次验证逻辑,再换回定步长。
5.2 ESO观测值发散但系统稳定:b0偏离真实值太多
我遇到过非常迷惑的情况:电机转速输出正常,但z3越跑越大,逐渐飘走。排查下来是b0设得严重偏大,ESO为了拟合实际响应,不得不估算出一个很大的负扰动来抵消控制量增益过高的问题。这种b0偏差超过真实值2倍以上,z3就会有缓慢漂移。
解决方法是把b0的估算公式重新算一遍,注意转动惯量J必须包含电机转子惯量和负载折算惯量的总和。如果负载通过减速器连接,折算惯量要乘以减速比的平方,很多人在这里算错,导致b0偏好几倍。
5.3 稳态转速存在固定误差:检查ESO的δ参数和fal函数线性区
转速环在稳态时如果始终差那么几十转不回来,常规PI会靠积分项把静差吃掉,但ADRC的NLSEF里fal函数在线性区间δ内等效增益是有限的,单纯靠比例型反馈不一定能把静差完全消除。
解决办法有三个方向:一是把δ调小,让fal函数在小误差区域的等效增益更高;二是把NLSEF里加一点误差积分项(但注意别破坏ADRC的抗扰性);三是检查ESO的z3是否真正补偿了负载转矩。实际排查下来,最常出现的问题是z3补偿方向反了——控制量u的补偿项前有个“减号”,你要是代码里写成加号,ESO不但不消扰动反而放大扰动,转速就会带上固定正偏差或者负偏差。
5.4 电流环响应慢导致转速环振荡:带宽匹配问题
ADRC把转速环设计得很快,但电流环带宽只要跟不上,整个系统的相位裕度就不够。症状是转速波形出现中频振荡,幅度逐渐加大,最后系统保护性停转。用带宽法设计时,电流环带宽至少要达到转速环ADRC带宽的5倍以上。也就是说转速环带宽100rad/s,电流环带宽至少要500rad/s。如果电流环PI整定得偏保守,转速环ADRC再激进也是白搭。
一个实用的检查方法:单独给电流环加一个阶跃,看iq的实际跟踪时间常数是否符合预期。如果电流环响应时间超過10ms,转速环带宽就别设太高,先loop shaping再谈算法先进性。
6. 仿真到实物移植的几个关键提醒
6.1 离散化采样周期的匹配
仿真里ADRC的采样周期h可以随便定,因为整个模型同步推进。但到实物MCU上,转速环和电流环的执行频率通常是不同的——电流环跑20kHz,转速环只能跑1-2kHz(受限于编码器分辨率和测速计算周期)。这时候ADRC在仿真里用的h要改成实际转速环执行周期。ESO的离散化系数β1、β2、β3跟h强相关,直接搬运仿真参数会导致观测器离散化后不稳定。
有个经验法则:离散化后的ESO稳定性要求ωo*h小于1。比如转速环执行周期0.0005秒,ωo就不能超过2000rad/s。仿真里可以轻松设到5000rad/s,到实物上就得降下来。
6.2 反馈信号噪声对ESO的影响
实物的转速反馈噪声远大于仿真里的理想信号。ESO的z3会把高频噪声放大传到控制量上,这是高频扰动通道,不可不防。仿真的最后阶段,一定在转速反馈通道上加上带限白噪声模块,看系统的噪声鲁棒性。如果噪声穿透过强,调低ωo是最直接手段,其次是加大TD的滤波因子h0。
我之前做过一个测试:不加噪声仿真非常完美,加了±1rpm的测量噪声后,iq_ref上出现了明显的高频抖振。把ωo从500rad/s降到300rad/s,抖振幅度降了一半以上,转速响应仅轻微变慢。这个权衡在工程上很值得。
6.3 控制周期延迟的数字实现问题
最后提一下控制延迟的问题。ADRC的ESO和控制律计算都需要时间,从采样到输出PWM更新天然存在一拍延迟。仿真模型里如果不模拟这个延迟,跑到实物上会发现相位裕度比仿真的差——差多少就看你的采样执行方式。
建议在仿真模型的ADRC输出和电流环给定之间加一个Unit Delay模块,模拟“当前周期采样、下个周期输出”的数字控制延迟。加上这一拍后如果ADRC还稳,实物基本稳;如果不稳,那就回头调参数,别到调实物的时候才发现问题。
这一节的内容是我反复折腾之后得出的教训,特别是ESO参数跨平台迁移这么点事,说大不大,但能把它处理好的工程师,基本都能把ADRC从Simulink顺利搬到DSP或者MCU上。