ADRC永磁同步电机Simulink仿真模型搭建与抗扰控制实践
1. 项目概述为什么选ADRC做永磁同步电机仿真搞电机控制的人谁没被PID支配过几年从大学实验室到产线调试PID确实是万金油结构简单、参数直观、工程经验丰富。可一旦碰到永磁同步电机这种强耦合、非线性、参数时变的被控对象PID那三板斧就开始露怯了——负载突变时转速波动大参数摄动时动态性能明显退化更别提Simulink里仿真跑得欢、上了台架就翻车的经典尴尬。这也是我当初决定把ADRC自抗扰控制引入PMSM仿真模型的核心动机。这个模型解决的是这样一个问题在不改变电机本体数学模型的前提下用ADRC替代传统的PID速度环通过扩张状态观测器ESO实时估计系统内部扰动和外部负载扰动并在控制律中进行主动补偿从而提升系统的抗扰能力和鲁棒性。说人话就是——负载突然加上去转速掉得少、回得快电机参数因为温度变化漂移了系统还跟没事人一样。项目本身非常值得做。一方面ADRC是当前工业控制领域最有希望大规模替代PID的候选方案之一其理论体系完整、工程实现路径清晰另一方面Simulink仿真平台给了我们一个低成本、零风险验证算法效果的绝佳环境。无论你是学生做毕业设计还是工程师搞技术预研这套仿真模型都能让你在半天之内建立起对ADRC从理论到实践的全链路认知。我在实际搭建过程中踩了不少坑这篇文章把每一步的来龙去脉都写清楚看完你也能从零搭出一套能跑的ADRCPMSM仿真模型。1.1 标题拆解ADRC和PMSM各自是什么永磁同步电机简称PMSM是当前工业伺服、电动汽车、机器人领域最主流的电机类型。它的转子装有永磁体不需要励磁电流所以效率高、功率密度大。但它的数学模型是一个典型的非线性强耦合系统——d轴和q轴之间存在交叉耦合项反电动势与转速成正比转矩与电流之间存在非线性的乘积关系。这些特性决定了它不像直流电机那样一个PI环就能怡然自得。自抗扰控制ADRC的核心思想最早由韩京清研究员在上世纪90年代提出。它把系统的未建模动态和外部扰动统一看成总扰动然后通过扩张状态观测器把这个总扰动实时估计出来再在控制输入中减去这个估计值实现对扰动的主动补偿。这套思想的精妙之处在于它不依赖被控对象的精确数学模型——你是几阶系统、非线性有多强ESO都能给你兜住。这两个东西放到一起碰撞出的火花非常有意思。PMSM数学模型越复杂、扰动越不确定ADRC发挥的空间就越大。如果被控对象本身是理想线性的那ADRC相对PID的优势并不明显甚至PID已经足够了。但PMSM恰恰不是它内部有交叉耦合、外部有负载突变还有参数漂移天然就是ADRC的试验田。1.2 为什么不用PID改用ADRC一场控制理念的对比既然PID用了这么多年为什么还要折腾ADRC我个人的体会是PID是基于误差消除误差但它有一个天然短板——没有办法区分误差是因为外部扰动造成的还是因为控制器本身没干好造成的。整个反馈系统就像一个被动挨打的拳手被打了一拳才做出反应反应完了可能又被补了一拳。ADRC的逻辑完全不同。ESO的数学本质是一个扩张了状态维度的观测器。在原系统状态的基础上把那个说不清道不明的总扰动也当成一个状态来估计。也就是说它不仅能测到转速掉了还能同时估计出是负载转矩增加了还是磁链衰减了还是逆变器非线性导致的等效扰动。然后控制器不再等转速掉下去再慢慢调——而是在扰动刚出现的瞬间就把补偿量叠加到控制输入上提前把坑填平。这个差异在仿真里体现得很直观。给系统加一个阶跃负载PID控制的转速会先掉下去再慢慢爬回来回落的深度和恢复时间与PID参数直接相关ADRC控制的转速几乎只有一点点瞬态凹坑然后迅速恢复到给定值——那个凹坑的大小直接取决于ESO的跟踪速度。这个仿真模型跑通了之后你会实实在在地感受到什么叫主动抗扰。2. ADRC控制器的结构拆解ADRC不是一个单一的控制算法而是一个控制框架。我在模型里实现的是最经典的二阶ADRC——二阶系统模型速度环作为被控对象。它由三个核心部件组成跟踪微分器TD、扩张状态观测器ESO和非线性状态误差反馈NLSEF。这三个部件各司其职但缺一个整体性能都会打折。2.1 跟踪微分器TD给速度信号安排一条平滑路径TD解决的是快速性与超调的矛盾。传统的PID一阶低通滤波也能滤掉转速测量中的噪声但滤波会带来相位滞后滞后的信号反馈回来会让系统觉得我还没到目标呢继续使劲输出结果就是超调。TD的思路是安排一个过渡过程给一个阶跃速度给定TD输出一条平滑的、有最大加速度限制的轨迹让实际转速沿着这条轨迹平滑到达目标。TD的离散形式我在Simulink里是这样实现的function [x1, x2] td_update(x1, x2, v, r, h0) % x1: 过渡信号, x2: 过渡信号导数 % v: 给定值, r: 跟踪速度因子, h0: 滤波因子 f fhan(x1 - v, x2, r, h0); x1 x1 h0 * x2; x2 x2 h0 * f; end function f fhan(x1, x2, r, h) % 最速控制综合函数ADRC中TD的核心 d r * h; d0 d * h; y x1 h * x2; a0 sqrt(d^2 8 * r * abs(y)); if abs(y) d0 a x2 y / h; else a x2 0.5 * (a0 - d) * sign(y); end if abs(a) d f -r * a / d; else f -r * sign(a); end end这段代码里的fhan函数是韩京清提出的最速控制综合函数。我最初在搭模型的时候一度很困惑为什么不直接用一阶惯性环节代替TD后来仿真对比发现TD的过渡过程能让系统在阶跃给定下几乎无超调地达到目标转速而一阶惯性环节则会因为相位滞后产生可观的超调量。TD的跟踪速度因子r直接决定过渡过程快慢——r越大过渡过程越短但对噪声越敏感r太小转速响应会变得拖沓。这个参数和PID里的比例增益有点像需要根据实际系统特性权衡。2.2 扩张状态观测器ESO整个ADRC的灵魂如果说TD是前馈整形那ESO就是整个ADRC最核心的部分。它解决的是状态感知问题——在只知道被控对象输入输出信息的前提下同时估计出系统状态和总扰动。二阶系统的扩张状态观测器可以写成这样的形式对于系统x1_dot x2, x2_dot f(x1, x2, w, t) b0 * u其中f就是那个总扰动包含内部未建模动态和外部扰动w。扩张状态x3 f则ESO可以设计为e z1 - yz1_dot z2 - beta1 * ez2_dot z3 - beta2 * fal(e, 0.5, delta) b0 * uz3_dot -beta3 * fal(e, 0.25, delta)这里的fal函数是一个非线性函数表达式为function f fal(e, alpha, delta) if abs(e) delta f e / delta^(1 - alpha); else f sign(e) * abs(e)^alpha; end end直观理解就是小误差时放大线性段大误差时饱和非线性段从而保证观测器在小误差时快速收敛在大误差时不过度超调。我在搭建这个模块时用了一个小技巧把beta参数从带宽法出发设定。ESO的观测带宽w0决定了ESO的收敛速度三个增益的初值可以取为beta1 3w0, beta2 3w0^2, beta3 w0^3。这样整定参数时只需要关注w0一个数就行。当然实际仿真中这些增益还要微调因为非线性函数的存在使得带宽法估算值只是一个好的出发点。2.3 非线性状态误差反馈NLSEF与扰动补偿NLSEF的作用是把TD给出的过渡信号与系统实际状态之间的误差结合ESO的扰动估计组合成最终的控制律。传统PID是对误差做比例、积分、微分的线性组合而NLSEF用非线性组合误差——小误差用高增益大误差用低增益从数学形式上更符合小偏差精细调节、大偏差快速逼近的工程直觉。控制律的形式一般是u0 kp * fal(e1, alpha1, delta) kd * fal(e2, alpha2, delta)然后最终控制输入u (u0 - z3) / b0其中z3是ESO估计的总扰动b0是控制增益估计值。这个b0的分母项正是扰动补偿的关键——ESO估计出多大扰动控制输入就反向减去多大分量。如果b0的估计不准确补偿就会产生偏差b0偏大补偿过冲b0偏小补偿不足。这里有一个非常关键的Simulink实现细节控制律的输出是转速环的给定转矩电流iq_ref由于PMSM的电磁转矩与q轴电流近似成正比在id0控制策略下所以ADRC速度环的输出直接串联到电流环的输入端。这个等效链路的增益是1.5p磁链与电机参数相关在整定b0时需要把这个增益折算进去否则ESO的扰动估计会失真。我一开始偷懒直接取b01结果ESO的观测效果看着还行但整体系统的抗扰性能明显不如预期排查了半天才发现是这个增益折算的问题。3. Simulink模型整体架构设计搭建ADRCPMSM仿真模型架构设计决定成败。如果一上来就闷头拖模块后面改起来会非常痛苦。我的建议是先在纸上把信号流图画清楚——从速度给定到转速反馈中间经过哪些环节每个环节的输入输出是什么然后再说Simulink里怎么搭。3.1 模型整体拓扑双闭环还是三环伺服系统最常见的拓扑是位置环、速度环、电流环三环结构。这个仿真模型我做的是速度电流双闭环位置环留了接口但没闭环——因为ADRC的速度环是核心位置环如果要加也只是在速度环外面串一个比例控制器思路完全一致。双闭环结构如下外环速度环ADRC控制器输入是给定转速与反馈转速的误差关系经过TD和ESO状态输出是q轴电流给定iq_ref内环电流环两个PI控制器分别控制d轴电流和q轴电流。d轴电流给定为0id0控制q轴电流给定来自速度环输出我遇到不少人在仿真时把速度环和电流环都用ADRC认为用ADRC越多越高级。其实没必要。电流环的动态比速度环快得多电流环的被控对象定子绕组相对而言更接近线性模型PI控制完全够用还省了ADRC参数整定的麻烦。速度环是真正面临负载扰动和参数摄动的环节把ADRC放在这里性价比最高。3.2 坐标变换与PMSM数学模型的Simulink实现PMSM在Simulink里有两种建模方式直接用Simscape Electrical里的永磁同步电机模型或者用数学公式自己搭dq坐标系下的电机模型。我做模型时用的是数学公式方式——好处是每一个物理量都看得见摸得着方便调试和排查问题。dq坐标系下的电压方程为ud Rsid Lddid/dt - omega_eLqiquq Rsiq Lqdiq/dt omega_e*(Ld*id psi_f)电磁转矩方程Te 1.5p(psi_f*iq (Ld - Lq)idiq)对于表贴式PMSMLd Lq转矩方程退化为Te 1.5ppsi_f*iq非常清爽。我用的电机参数如下参数数值单位极对数 p4-定子电阻 Rs2.875Ωd轴电感 Ld8.5mHq轴电感 Lq8.5mH永磁体磁链 psi_f0.175Wb转动惯量 J0.001kg·m²阻尼系数 B0.0001N·m·s/rad坐标变换模块实现Park变换和Clark变换。Clark把三相abc坐标系变到静止两相αβPark把αβ变到旋转dq。这两个变换在Simulink里可以用Fcn模块直接写表达式也可以用封装好的子系统。我个人的习惯是单独建一个坐标变换子模块里面用Fcn写公式这样改动电机参数时不用动变换模块。3.3 离散化与采样时间设置的工程考量仿真模型的采样时间设置是很多人忽略但影响很大的细节。ADRC本身是一个连续算法但实际工程中一定是在DSP或MCU里离散化运行的所以我在模型里做了离散化处理——速度环ADRC的采样时间设为0.1ms对应10kHz控制频率电流环的采样时间设为0.01ms100kHz。为什么速度环要慢一拍因为电流环需要更快的带宽来保证电流跟随速度环的带宽相对较低。如果两个环都用0.01ms采样仿真速度会变慢而且对ADRC来说没必要——ESO的带宽不需要做那么高。我在实际跑仿真时发现ESO的观测带宽w0设定在300rad/s左右就足够应对大多数工况了对应的采样时间0.1ms完全够用。离散化方式上ESO和TD我用的是前向欧拉法一阶实现简单、计算量小在采样时间足够短的时候精度完全够用。如果你追求更高精度可以用RK4但仿真步长固定为0.01ms时欧拉法和RK4的差别肉眼几乎看不出来——完全没必要为了这种自以为是的精度拖慢仿真速度。4. 建模实操从零搭建仿真模型下面进入重头戏——具体怎么搭。我会按从底层到顶层的顺序一步步讲解每一步要建什么模块、参数怎么填、有哪些坑都写清楚。整个模型我建议分成三个大子系统PMSM本体子系统、坐标变换与逆变器子系统、ADRC控制器子系统。4.1 第一步搭建PMSM本体与逆变器模块PMSM本体用电压方程和转矩方程搭。输入是ud和uq输出是电流id、iq和机械转速。在Simulink里我的做法是建一个子系统内部用积分模块Integrator表示电流动态。dq轴电流的微分方程写成ud Rs*id Ld*did/dt - omega_e*Lq*iq的形式那么did/dt (ud - Rs*id omega_e*Lq*iq)/Ld从这个公式直接连积分器。机械方程同理转速的积分基于运动方程J*dω/dt Te - B*ω - TL所以转速积分器的输入是(Te - B*ω - TL)/J。电角速度omega_e ω * p直接乘一个增益模块。逆变器的建模我做了简化——没有用IGBT导通损耗那种细节模型而是用一个饱和限幅模块模拟逆变器输出电压极限。直流母线电压假设为300V那么三相线电压有效值要经过SVPWM限制简化后就是ud和uq的幅值限幅在±150V左右。提示初次跑仿真时如果发现id和iq发散到几千甚至几万基本可以确定是限幅没加或者电机参数填错了。我踩过这个坑——忘记加限幅仿真结果直接变成一条直线根本看不出控制效果。4.2 第二步ADRC控制器C-MEX S-Function实现ADRC控制器我用的是S-Function方式实现而不是一堆Simulink基本模块堆砌。原因很简单S-Function的代码逻辑清晰参数调整只需要改一个变量数组而且方便后续移植到嵌入式代码里。另一个方案是Matlab Function模块也可以但代码组织不如S-Function规整。S-Function的框架如下function adrc_sfun(block) % 输入: 速度给定ref, 速度反馈w % 输出: 电流给定iq_ref setup(block); end function setup(block) block.NumInputPorts 2; block.NumOutputPorts 1; block.SetPreCompPortInfoToDynamic; block.InputPort(1).Dimensions 1; block.InputPort(2).Dimensions 1; block.OutputPort(1).Dimensions 1; block.SampleTimes [0.0001 0]; % 0.1ms离散采样 block.RegDialogs ... {b0, Parameters for ADRC, b0}; % 参数: [b0, r, h0, w0, kp, kd] block.SetAccelRunOn true; block.SimStateCompliance DefaultSimState; block.NumContStates 0; block.NumDworks 4; block.Dwork(1).Name z1; block.Dwork(1).Dimensions 1; % ... 其他dwork定义省略 end更简洁的方式是用Level-2 MATLAB S-Function把状态更新打包。我在实际的模型里是这样实现核心更新逻辑的function OutputUpdate(block) % 读取输入 ref block.InputPort(1).Data; w block.InputPort(2).Data; % 读取状态 z1 block.Dwork(1).Data; z2 block.Dwork(2).Data; z3 block.Dwork(3).Data; x1 block.Dwork(4).Data; % TD状态 x2 block.Dwork(5).Data; % TD [x1, x2] td_update(x1, x2, ref, r, h0); % ESO e z1 - w; z1 z1 h * (z2 - beta1 * e); z2 z2 h * (z3 - beta2 * fal(e, 0.5, delta) b0 * u_prev); z3 z3 h * (-beta3 * fal(e, 0.25, delta)); % NLSEF e1 x1 - z1; e2 x2 - z2; u0 kp * fal(e1, 0.5, delta) kd * fal(e2, 0.5, delta); u (u0 - z3) / b0; % 输出并保存上一次u block.OutputPort(1).Data u; block.Dwork(6).Data u; % u_prev end这个代码框架基本就是ADRC的全貌。你可能注意到ESO的更新方程里用了上一次的控制输入u_prev这是离散化的自然结果——当前时刻的ESO输出用上一时刻的控制输入来计算因为当前时刻的控制输入还没算出来呢。在连续域里没有这个问题但离散仿真里必须这样处理否则会出现代数环报警。4.3 第三步电流环PI控制器搭建与限幅设置电流环两个PI控制器结构一样只是参数不同。d轴PI控制id到0q轴PI控制iq到给定。PI参数我用的是零极点对消法整定PI的零点对消电机电时间常数的极点即Ti Lq/Rs或Ld/Rs比例增益Kp取电流环带宽wc乘以电感Lq。举个例子q轴Lq 8.5mH, Rs 2.875Ω, 电时间常数Tq Lq/Rs ≈ 2.96ms取电流环带宽wc 3000rad/sKi Kp / TiKp wc * Lq 3000 * 0.0085 25.5Ti 0.00296所以Ki 25.5 / 0.00296 ≈ 8615这样算出来的参数可以直接用但跑仿真时要注意如果出现电流震荡多半是带宽取太高了把wc降到2000rad/s试试。电流环的输出限幅也要注意我设的限幅是±20A——超过这个值在仿真里会看到iq_ref被削顶。这个仿真模型最复杂的地方其实是ADRC参数的协调。单独调ESO和NLSEF都没问题但两者放在一起需要多次迭代。下面是我调试时用的参数表只针对上文电机参数ADRC参数数值说明b023.5控制增益折算转矩常数1.5*p*psi_fr1000TD的跟踪速度因子越大过渡越快h00.001滤波因子抑制噪声w0300ESO观测带宽rad/skp8NLSEF比例增益kd1.2NLSEF微分增益这套参数能让系统在额定转速下启动无超调并且在2Nm负载突变时转速跌落小于20rpm、恢复时间约0.05s。如果你想抄作业直接用这套参数跑保准能出基本正确的波形。5. 仿真验证与结果分析模型搭出来只是第一步最关键的环节是验证ADRC到底比PID强在哪里。我的建议是设计三组对照实验启动响应测试、负载突变测试、参数摄动鲁棒性测试。这三组实验做完ADRC和PID的差异就一目了然了。5.1 启动响应测试阶跃给定对比给定1000rpm阶跃转速指令。PID组的响应曲线大概是这样转速快速上升到达额定值附近后有一个约15%~20%的超调然后经过约0.1s的振荡收敛。ADRC组的曲线则不同——转速沿着TD规划的平滑路径上升几乎无超调地到达给定转速但上升时间会比PID慢一点大约0.15s左右。这个对比结果很典型。PID的快是牺牲了超调换来的ADRC的稳是通过主动规划过渡过程实现的。如果你把PID参数往小调压低超调它的响应会变得很慢反而比ADRC更慢。也就是说ADRC在同超调量下响应更快这个维度上通常能赢。5.2 负载突变测试抗扰能力直观对比在t0.5s的时刻突加2Nm负载观察转速动态。PID组的转速跌落大约60~80rpm恢复时间约0.3sADRC组的转速跌落大约20rpm左右恢复时间约0.05s。差距非常直观。原理上也不难理解PID要等转速出现偏差后才通过积分环节慢慢把偏差拉回属于事后补偿ADRC的ESO在负载突加的瞬间就感知到了转矩的变化立即在控制量中叠加补偿属于事前抵消。我为了验证ESO确实观测到了扰动在Scope里特意把z3总扰动估计值的波形调出来看——负载加上后z3的数值在极短时间内跳变到大约2Nm换算成转矩附近而PID控制器里根本没有这个环节。5.3 参数摄动鲁棒性测试真实工程价值仿真做完了很多人会想参数实物模型和仿真不一样怎么办 这正好是ADRC的优势所在——让电机参数在仿真中途突变看看谁扛得住。我把Lq从8.5mH突变为13mH模拟磁路饱和转动惯量J从0.001增大到0.002。PID组在参数突变后转速波形出现了明显振荡甚至需要重新整定参数才能恢复性能ADRC组的波形变化几乎看不出来ESO自动把参数摄动当成内部扰动给补偿掉了。这就是ADRC在工程中最值钱的地方——你不知道的、测不了的、算不准的那些因素ESO都会替你打包处理。如果把同样的算法移植到实物台架上意味着你可以少花很多时间在为不同工况分别整定参数上。6. 常见问题与调试心得这一节是血泪经验总结。我在搭建和调试这套模型的过程中遇到的各种问题梳理成速查表大概率你也会碰到。6.1 仿真直接发散先排除最蠢的错误最典型的发散原因是ESO参数beta值设置过大或b0设置错误。可以按下面的排查顺序来先把b0设成0控制器就没有扰动补偿了看系统是否能稳定。如果此时还不稳定问题不在ADRC而在电流环或电机模型本身。然后把b0恢复逐步增加ESO带宽w0。如果从w050开始不收敛、到300时发散检查是否离散化步长太大——把仿真步长从0.01ms改到0.001ms对比一下。还有一种情况是限幅缺失。逆变器饱和限幅没有加控制器输出几百A的电流给电机模型电机转速直接飞了。6.2 ESO观测结果抖动严重fal函数delta参数的问题ESO的z3波形抖动最常见的原因是fal函数里的delta参数设得太小。delta决定了线性区间的大小delta越小非线性段越强但对噪声越敏感。在Simulink的数值仿真环境中计算误差不可避免如果delta0.0001观测器会一直在极小的误差区域来回震荡导致z3抖动。解决办法很简单——把delta改为0.01甚至0.05z3的波形会平滑很多。不要担心delta改大后ESO性能下降仿真里的噪声水平通常远低于实物在仿真中追求极致精度但牺牲稳定性的做法没有意义。6.3 b0到底该取多少控制增益的物理折算这是ADRC入门最容易卡住的地方。ESO的原理要求我们知道b0的精确值但很多资料直接告诉你b0是个大概值就完事了实际操作起来很困惑。我的经验是这样针对PMSM速度环速度环的输入是iq_refA输出是转速rad/s。一阶近似的传递关系是dω/dt (1.5*p*ψ_f / J) * iq_ref。所以b0 ≈ 1.5*p*ψ_f / J。代入参数1.5 * 4 * 0.175 / 0.001 1050。但实际模型还有电流环动态在环路里电流环的延迟会降低等效增益所以仿真中我发现b0取800~1200之间都能跑但取值偏离太多时ESO的估计会偏。注意b0的物理意义就是控制输入到状态微分的增益。你可以通过开环仿真精确测定——给一个阶跃iq_ref测量转速的加速度两者一比就是b0。这个方法比纯理论计算靠谱得多。6.4 电流环与ADRC速度环的耦合问题跑仿真时另一个常见现象是速度环输出iq_ref已经很大了但电流环就是跟踪不上。原因在于电流环的带宽不够或者限幅太小。电流环PI带宽至少要达到速度环ESO带宽的3~5倍否则内环的动态响应会成为整个系统的瓶颈。如果电流环带宽上不去可以检查电流环PI参数是不是按零极点对消法设置的。很多教程里直接给Kp10, Ki100之类的经验值但对不同参数电机来说完全不适用。按前面提到的公式算出来的参数虽然可能不是最优但至少方向正确。7. 扩展方向与后续演进这个模型跑通之后可以沿着几个方向继续深入。第一位置环ADRC。在当前双闭环基础上把位置环设为外环一样可以用TD安排位置过渡过程。位置环的ADRC设计思路完全一致只是被控对象变成了一阶积分环节状态维度减少到一阶对应的ESO也降为二阶。第二无传感器控制。把速度环的反馈从直接测量改为基于反电动势的滑模观测器估计ADRC的ESO会自动把估计误差当成扰动的一部分处理掉——这也是ADRC的一个隐藏加成它对上游传感器的不精确有一定的容忍度。第三参数自适应。固定参数的ADRC已经能扛参数摄动了但如果磁链或电感变化范围极大可以对b0做在线辨识修正让ESO的估计精度进一步改善。我个人最推荐第一和第三个方向。位置环ADRC在工业伺服里有直接应用价值参数自适应则是把ADRC推向工程化的重要一步。如果你打算做毕业设计或者技术储备往这三个方向任何一个延伸都比停留在仿真层面更有说服力。最后再分享一个小技巧调试ADRC时一定要把ESO的z1、z2、z3三个信号引出到Scope和实际转速、电流波形对照着看。z1应该实时跟住转速反馈z2是转速的导数z3平滑不抖动就说明观测器工作正常。很多人调试时只关注最终的转速波形ESO内部出问题都不知道走了不少弯路。先确认ESO观测准确再去调NLSEF这条调试路径是最省时间的。