☰
PMSM双闭环控制从SVPWM到ADRC的完整调试实战
2026/10/19 2:40:47 网站建设 项目流程

先说个我自己的真实经历。有一段时间我在调一台PMSM驱动器的速度控制,给到3000rpm的阶跃指令,电机会先啸叫一声,然后电流波形上明显带着锯齿状毛刺。当时第一反应是PI参数不够,把速度环Kp压低、Ki抬高来回试了十几组,问题一点没改善。后来发现竟然是SVPWM扇区判断里用错了坐标系的方向,导致电压矢量在某个扇区内整体偏移了30度,电流自然好不了。这让我意识到,做双闭环控制这件事,瓶颈往往不在“控制算法本身”,而在从坐标变换、SVPWM到采样链路这一整条物理通路是否真的严丝合缝。这篇文章就把我从头到尾走通这条链路的过程记录下来,覆盖PMSM双闭环的骨架设计、SVPWM实现细节、电流环速度环PI参数的计算方法,以及最后换用ADRC时那种“参数不细调也能压住扰动”的暴力美学。

适合什么人看呢?如果你刚把FOC跑起来,但电流波形总是不干净,速度环动态响应也不行;或者你已经在用PI,但对ADRC只有概念层面的了解,不知道从哪开始改代码;又或者你被各种PI调参口诀搞得晕头转向,想从原理上搞明白Kp、Ki到底怎么算——这篇应该能帮你在思路上少走很多弯路。

1. 想清楚PMSM在“反抗”什么:双闭环骨架背后的物理直觉

很多入门教程一上来就摆出PMSM的d-q轴电压方程、磁链方程、转矩方程,公式堆了满屏,但调试时最容易忽略的恰恰是这些方程背后的物理含义。

1.1 坐标变换:把三相交变问题变成两轴直流问题

PMSM的定子绕组是三相空间上相差120度的交流绕组,转子是永磁体。你在abc三相坐标系里看,反电动势是正弦变化的,电感磁链也随着转子位置变化,控制器面对的是一堆时变系数。直接在这上面做控制,每个采样周期都要处理正弦余弦耦合,而且电流环带宽做不高。

Clark变换把三相静止坐标系映射到两相静止αβ坐标系,去掉了冗余的零序分量;Park变换再把αβ坐标系旋转到与转子磁场同步的d-q旋转坐标系。这一步做完,原本随电角度变化的正弦量变成了直流量:d轴对应励磁分量,q轴对应转矩分量,电流环只需要处理两个常数-ish的RL回路。物理直觉上的等价关系是这样的:

  • d轴电流控制的是磁场强弱,PMSM转子是永磁体,d轴电流既不能增加主磁通,只会带来额外的铜耗和铁耗,所以表贴式PMSM常用id=0控制;
  • q轴电流直接决定电磁转矩,转矩Te = 1.5 * p * (ψf * iq + (Ld-Lq)idiq),在id=0时简化为Te = 1.5 * p * ψf * iq,变成一台“直流电机”。

有了这个变换,你在示波器上看到的再也不是三个正弦波,而是两个随工况缓慢变化的直流分量。调试时也直接了很多,i_d是否被控制在0附近,i_q是否跟指令一致,一眼就能看出电流环有没有好好工作。

1.2 双闭环为什么必须“电流内层、速度外层”

双闭环的结构图看上去很简单:速度环外面给定转速,转速误差经速度调节器输出q轴电流指令,电流环再跟踪这个指令,最终输出d-q轴电压。但内外环的带宽分配是有严格讲究的。

电流环处理的是电气时间常数,一般就是毫秒甚至亚毫秒级别;速度环面对的是机械时间常数,通常是几十毫秒级别。电流环必须快得多,才能把反电动势、负载变化这些扰动在还没传达到速度环之前就消化掉。如果电流环带宽不够或相位裕度太小,速度环一旦加大增益就容易引起电流指令振荡,甚至两条反馈回路一起共振——我在调试中见到的“振铃”很多时候根本不是机械问题,而是电流环响应太慢导致的。

工程上我习惯把电流环周期定在100us(10kHz),速度环周期1ms(1kHz),电流环带宽设计在800~1200Hz左右,速度环带宽则压在电流环带宽的1/10到1/5,也就是80~200Hz之间。这组数据不是拍脑袋,而是保证内外环之间有足够的频带间隔,避免环路交互带来的稳定性问题。

2. SVPWM最容易翻车的三个位置:扇区判断、矢量时间与死区补偿

SVPWM的原理在很多教材里是“六个有效矢量加两个零矢量,按伏秒平衡合成任意电压矢量”,听起来很干净,但落到代码里,翻车的地方几乎都在细节上。

2.1 相邻矢量合成与扇区判断的等价条件

逆变器三相桥臂一共有8种开关状态,其中6个非零矢量把αβ平面分成6个60度扇区,剩下两个零矢量。要输出任意方向和大小的电压矢量,最直接的办法就是找到它落在哪个扇区,然后用该扇区相邻的两个非零矢量按时间比例合成,零矢量填充剩余时间。

扇区判断常见的两种做法:一种是用Uα、Uβ直接做几何判断;另一种是用三相电压UA、UB、UC做比较。我踩过坑的是:几何判断时,角度换了一种约定,导致整个扇区编号偏一格。矢量落在扇区I,代码却按扇区II的相邻矢量去合成,电压矢量的方向偏了60度,电机能转,但电流波形明显变形、转矩脉动大,而且启动时噪声比正常情况大很多。

一个不会出错的等价判断条件可以写成:

// Ualpha、Ubeta为Park逆变换输出的两相静止坐标电压 // 用一个通用方法计算扇区号 int sector; float v1 = Ubeta; float v2 = -0.5f * Ubeta + 0.866f * Ualpha; // sqrt(3)/2 ≈ 0.866 float v3 = -0.5f * Ubeta - 0.866f * Ualpha; if (v1 > 0) sector = 1; else sector = 0; if (v2 > 0) sector += 2; if (v3 > 0) sector += 4; switch (sector) { case 3: sector = 1; break; case 1: sector = 2; break; case 5: sector = 3; break; case 4: sector = 4; break; case 6: sector = 5; break; case 2: sector = 6; break; }

这段代码里的v1、v2、v3本质上是把Uα、Uβ又投影回三个互差120度的轴上,然后按符号组合出扇区,比起直接求角度再查表,少了一次反正切运算,也不会遇到角度边界值问题。实测定点MCU上跑,精度完全够。

2.2 七段式SVPWM的生成顺序与作用时间计算

确定扇区后,需要算出两个相邻矢量的作用时间T1、T2。以扇区I为例,电压矢量由100矢量(V1)和110矢量(V2)合成,伏秒平衡得到:

  • T1与Ubeta正相关;
  • T2与Ualpha和Ubeta的组合相关;
  • 剩余时间由零矢量填充,T0 = Ts - T1 - T2。

完整的工程代码里通常会直接列一个查表式的时间计算,下面是其中一个扇区对应的核心逻辑:

float T1, T2, T0; float Ts = 1.0f / PWM_FREQ; // PWM周期,单位秒 // 以扇区I为例: // V1作用时间正比于Ubeta // V2作用时间正比于 (sqrt(3)*Ualpha - Ubeta) / 2 float Vdc = bus_voltage; // 母线电压,单位V T1 = (Ubeta * Ts) / Vdc; T2 = ((0.866f * Ualpha - 0.5f * Ubeta) * Ts) / Vdc; // 过调制限幅:T1+T2超出Ts时等比例压缩 float sum = T1 + T2; if (sum > Ts) { T1 = T1 / sum * Ts; T2 = T2 / sum * Ts; } T0 = Ts - T1 - T2;

七段式输出的核心思想是:在一个PWM周期里,让每个桥臂的开关次数尽量平均,从而降低开关频率带来的谐波。采用131-132这样的开关序列,也就是从零矢量000开始,依次经过V1、V2,再到111,再对称回来,每个周期内每相只开关一次。这样做的好处是中心对齐的PWM波形谐波含量低,电流纹波也相对小。实际生成时,把T0均分为四份,T1、T2各两份,得到一个对称序列。虽然听起来繁琐,但在代码里就是三个比较寄存器的赋值,并不难。

2.3 死区、管压降和母线利用率:工程细节决定波形好坏

这一小节要说的是“仿真里跑得好好的,上机就完蛋”的三个元凶。

第一是死区时间。上下桥臂不能同时导通,否则母线直通短路,必须插入死区。死区时间通常取0.5~2us,但死区会造成实际的电压矢量和指令值之间的偏差,电流过零附近尤其明显,表现出来就是低速轻载时电流波形过零畸变、转矩脉动,q轴电流上有明显的6倍频脉动。简单有效的补偿思路是:根据三相电流方向,在占空比上叠加一个死区补偿量;电流方向判断不准时,宁可不补偿,也不要补反。

第二是管压降和开通关断延时。IGBT或MOSFET的导通压降、开关延时在每个扇区都会引入一个小的平均电压误差,高速大电流工况下可能可以忽略,但低速低压时这些误差可能盖过实际指令电压,导致低速性能急剧恶化。做低速带载的场合,建议做一次简单的电压误差补偿,把每相导通压降作为固定偏置修正掉。

第三是母线电压利用率。SVPWM线性调制范围比SPWM高出约15%,最大相电压峰值能达到Vdc/sqrt(3)。但如果你用不好过调制,或者限幅做成了简单的“削顶”,电压矢量幅值超过六边形内切圆后被截断,电流波形就会变成缺少顶部弧度的台阶状,谐波立刻变差。我在代码里习惯用等比例压缩法做限幅,保留矢量方向、只缩幅值,这样在弱磁区之外都能尽量保持正弦性。

3. 电流环和速度环的PI,别靠试:内模法与带宽倍数一次定下来

很多工程师调PI还在用“先Kp后Ki,调完再回来”的土办法。运气好能调出来,运气不好就是今天调好明天换台电机又炸。实际上电流环和速度环的对象模型都很简单,足够用解析方法把初值算出来,剩下需要手动调的只是很小一个范围。

3.1 电流环PI:从RL模型直接推出Kp/Ki

在d-q旋转坐标系下,电流环的被控对象近似为一阶RL回路:L * di/dt = u - R*i - e,其中e是反电动势和交叉耦合项。电流环PI控制器只要带宽足够高,反电动势可以看作慢扰动,交给积分项处理。忽略耦合项后,对象就是典型的365体育官网 Ls + R。

用内模控制或零极点对消法,可以直接得到PI参数:

  • Kp = L * ωc
  • Ki = R * ωc

其中ωc是期望的电流环闭环带宽(rad/s)。这套公式的本质是让PI的零点刚好抵消对象的极点,回路传函变成一阶惯性环节,闭环带宽正好是ωc。举个例子:某台电机定子电感Ls = 0.4mH,定子电阻Rs = 0.12Ω,希望电流环带宽800Hz,也就是ωc = 2π×800 ≈ 5027 rad/s,那么:

  • Kp = 0.0004 × 5027 ≈ 2.01
  • Ki = 0.12 × 5027 ≈ 603

如果控制周期是10kHz,离散化时把Ki乘上采样周期Ts,得到积分系数Ki_d = Ki × 0.0001 ≈ 0.0603。注意这里的坐标系问题:你控制的是d轴和q轴两套独立的PI,但实际对象中存在d-q轴耦合项(ωLqiq和ωLdid),转速高时耦合电压不可忽略。工程上一般先用PI的积分项硬抗,带宽够高时问题不大;若高速性能不好,再加解耦前馈。

3.2 速度环PI:机械对象的积分特性与带宽搭配

速度环的被控对象是电机转子的机械方程:J * dω/dt = Te - TL - B*ω,写成传递函数是对象在积分环节后面串了一个一阶惯性。理论上有两种思路:用PI去对消机械时间常数,或者用更保守的整定方法。

我的习惯是,先把电流环带宽固定好,再把速度环带宽设为电流环带宽的1/10左右。假设电流环闭环后等效成一阶惯性环节,其时间常数为1/ωc,速度环设计就可以在“电流环等效对象”之上进行。这时PI参数同样可以从对象参数推导:先估算转动惯量J和阻尼系数B。如果没有转动惯量数据,就做一次空载阶跃实验,记录转速上升斜率,反推J = Te / (dω/dt)。有了J,速度环PI初值可以按:

  • Kp_speed ≈ J * ωs(ωs为速度环期望带宽)
  • Ki_speed ≈ Kp_speed / τm(τm为机械时间常数,J/B)

为方便理解,给一组典型值:某小型PMSM转子惯量J = 3.5e-5 kg·m²,阻尼B很小近似0.001,电流环带宽1000Hz,速度环带宽取100Hz,ωs = 628 rad/s,则Kp_speed ≈ 3.5e-5 × 628 ≈ 0.022。注意这套初值只是给了你一个可靠的起点,最终要根据阶跃响应的超调量和振荡情况微调。调试速度环时一个很实用的原则:先确保电流环无超调,再提速度环增益;速度环出现低频振荡,加Ki或者降Kp;速度环出现高频噪声,多半是转速反馈没有滤波。

4. ADRC的“暴力美学”:ESO如何把未知统统吃掉

“暴力美学”这个说法,我在用ADRC之前一直觉得是夸张,直到我自己在调试现场把负载突变时转速的跌落压下去,才意识到这个“暴力”真的有它的道理。

4.1 为什么调试现场会想放弃PI

PI在理想的一阶或二阶对象面前表现很好,但PMSM速度环的真实对象里有模型误差、转动惯量变化、负载突变、摩擦非线性、电流环等效延时。这些不确定性到了PI这里,全部要靠积分器一点一点地攒误差去补偿。积分器攒够了,稳态精度不错,但动态响应慢;积分器没攒够,负载突变瞬间转速跌落很大,恢复时间被拉长。

ADRC的思路不一样:它不试图精确建模,而是把系统内部的未建模动态和外部的负载扰动,统统合并成一个“总扰动”,然后用扩张状态观测器(ESO)把这个总扰动实时估计出来,并在控制量里直接减掉。换句话说,PI是让误差慢慢归零,ADRC是看见了扰动就当场把它抵消。这个“当场抵消”的冲动感,就是暴力美学的第一层含义。

4.2 线性扩张状态观测器的离散实现

以速度环为例,把电流环闭环后的对象近似为:

dω/dt = b0 * iq_ref + f(ω, TL, ...)

其中f是总扰动,b0是控制增益估计。这里的b0不需要准确,别差一个数量级就行。取状态变量x1 = ω,x2 = f,那么扩张状态观测器的连续形式是:

  • ẑ1 = z2 + b0u + l1(ω - z1)
  • ẑ2 = l2*(ω - z1)

其中z1估计转速,z2估计总扰动。参数l1、l2根据观测器带宽ωo确定:l1 = 2*ωo,l2 = ωo²。这样写的好处是只需要调一个ωo,而不是调两个PI参数。离散化时用最简单的欧拉法在速度环周期Ts里迭代:

// LADRC速度环,Ts为速度环周期 // omega_ref为给定转速,omega为反馈转速,b0为控制增益估计 float z1, z2; // z1: 转速估计, z2: 总扰动估计 float e = z1 - omega; z1 += (z2 + b0 * iq_ref - 2 * wo * e) * Ts; z2 += ( -wo * wo * e ) * Ts; // 控制律:带宽为wc的PD控制器 + 扰动前馈补偿 float iq_out = (wc * wc * (omega_ref - z1) - z2) / b0;

这个实现里其实只有三个参数:观测器带宽ωo、控制器带宽ωc、控制增益b0。ωc决定跟踪速度,ωo决定扰动估计能力,b0只是一个粗略的控制增益。整定过程可以直接按“带宽法”:先定ωc,满足速度响应要求;再让ωo = 3~5倍ωc;b0按电机参数粗估,调试时微调。

4.3 三个参数怎么暴力而克制地调

粗暴版本是这样的:ωc给到100~200rad/s,ωo给到500~1000rad/s,b0按J估算后直接上电。如果转速反馈噪声大,先把ωo降下来,再看阶跃响应要不要调高ωc。这套流程比调PI直观得多,基本不需要来回折腾Kp和Ki的组合。

不过我也要说清楚“暴力”的边界在哪。ADRC的观测器本质上是一个高频增益环节,ωo越高,观测噪声放大越明显。转速采样上有量化噪声或者编码器零位误差时,ωo拉太高会让q轴电流包含明显的高频毛刺。如果出现这种情况,不要硬扛,把ωo降到转速噪声可以被接受的范围,同时通过ωc把期望的动态性能拉回来。实践证明,只要转速反馈本身不是特别烂,LADRC的鲁棒性足够覆盖参数失配。

还有一点值得专门提:b0给错了会发生什么?b0偏小,补偿力度不足,扰动抑制变弱,但系统通常还能稳定;b0偏大,补偿过猛,转速会表现出高频振铃。排查这种问题不要靠感觉,直接看iq指令波形,如果iq指令在负载突变瞬间有一个明显过头的大尖峰,再把b0适当调小。

5. 联调实录:三次关键修正,从畸变电流到稳如磐石的转速

前4章把每个模块的原理和实现原则拆完了,这一章我按真实排错的顺序,记录一下把整套系统从“能转”调到“好使”的过程中遇到的三次关键修正。

5.1 第一刀:扇区判断反了,相电流出现直流偏置

现象是电机能转、转速能闭环,但三相电流波形不对称,某一相电流明显带直流偏置,电机噪声偏大。当时我先查采样偏置、电流调零,都正常;后来把所有电压指令设成固定幅值和固定角度,开环看相电流,才发现电压矢量对不上。

定位思路很简单:给一个固定的Uα = 0.1V、Uβ = 0V的电压指令,理论上电压矢量应该严格指向α轴方向,此时A相电流应最大、B相C相基本对称分流。但实际波形显示的是A、B相电流都有成分且不对称,那几乎可以断定是扇区判断的映射关系错了。逐项检查后发现,扇区编号与矢量顺序之间少了一步映射,相当于整个扇区平移到相邻位置。修正映射后,开环电流波形立刻变为对称正弦,闭环后直轴电流也不再出现2次波动。

5.2 第二刀:死区补偿解决低速轻载的过零畸变

第二轮问题是低速轻载工况下,q轴电流出现明显6倍频脉动,波形在过零处出现台阶状畸变。这个6倍频特征非常典型:SVPWM产生的电压误差跟三相电流方向有关,方向每换一次就产生一次突变,一个电周期里三相电流各过零两次,正好6次。

我用的是开环电压前馈叠加补偿:锁定三相电流方向,在输出PWM占空比上叠加补偿量。补偿量的来源很简单,就是死区时间乘上开关频率再除以母线电压。比如死区2us、PWM频率10kHz、母线电压24V,那补偿占空比约0.0002×10000/24 ≈ 0.083,也就是每相在每个周期人为加宽或收窄约8.3%的占空比。这个补偿量不算小,效果也立竿见影:低速轻载下q轴电流的6倍频脉动从约0.15A压到了0.05A以内,声音也干净了很多。

5.3 第三刀:LADRC带宽拉上去之后的振荡与b0修正

最后把速度环从PI换成LADRC。第一次上电我把ωc设成80rad/s、ωo设为400rad/s,b0按转动惯量估了一个值,空载阶跃响应很好。但加到50%额定负载突变时,转速跌落虽然比PI控制小了一半,却在恢复过程中出现了一小段高频振铃。我把ωo从400降到300后振铃消失,但负载突变恢复时间又变长了一些。后来对照iq指令波形,发现负载突变瞬间q轴电流尖峰明显偏大,判断是b0偏大导致补偿过冲。把b0调小约20%后,振铃和恢复时间同时得到改善。

这次经历让我确认了一个观点:ADRC参数只有两三个,确实比PI好调,但要出好性能,也得在示波器上看波形,而不只是看仿真里的响应曲线。任何控制算法,到了硬件现场,最终都是要跟真实噪声、真实延时效应的博弈。

6. 最后分享一点我自己的调试体会

整套系统从SVPWM一路做到ADRC之后,我最大的体会就是:不要一开始就把希望寄托在“高级算法”上。SVPWM的扇区映射、死区补偿、电流环采样对齐这些基础工作没做扎实,换ADRC也只是把底层的烂波形包装成一个更漂亮的转速曲线。反过来,底层调制和电流环扎实了,哪怕PI参数粗一点,系统也已经能稳定跑起来,ADRC是在这个稳定的底子上给你额外的鲁棒性和动态表现。

参数整定上再多说一句,我后来给入门的朋友讲的时候都会强调:电流环的内模法算参数,和速度环的带宽搭配法,比盲目试凑靠谱得多,但也别拿着公式算出来的参数当最终值。现场环境里的母线电压波动、温度变化、电缆电感都会让对象参数偏离理论值,所以学会“看波形微调”才是一辈子受用的功。波形看什么呢?一是看三相电流是否对称正弦、过零处有无畸变,二是看q轴电流有没有多余的纹波和尖峰,三是看转速阶跃时的超调量和恢复时间。

如果你也想往下深入,建议在LADRC跑顺之后,试着把观测器估计出来的扰动信号接到上位机里录下来,你会发现负载突变时的扰动波形基本跟转矩变化趋势一致,那一刻才算真正理解了ADRC所谓的“暴力”是怎么回事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询