ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

三相逆变器dq解耦控制与PI参数整定:Simulink仿真实践

三相逆变器dq解耦控制与PI参数整定:Simulink仿真实践

做三相逆变器仿真的时候,我最常见到的一种状态是这样的:在MATLAB/Simulink里搭建好双闭环,调PI参数时发现d轴电流好不容易调稳了,q轴电流又开始振荡;把i_d的给定从5A拉到10A,结果i_q波形跟着“抽”了一下,又慢慢恢复。很多人第一反应是PI参数没调好,于是继续调Kp、Ki,折腾几个晚上波形还是不对。其实问题大概率不在PI本身,而是d、q轴之间存在一条看不见的通道:耦合项。

这篇内容我打算围绕三相逆变器闭环控制、dq旋转坐标系下的解耦控制,以及基于MATLAB仿真的PI算法实现,把整个思路从头到尾复盘一遍。适合正在做电力电子仿真、刚接触逆变器控制、或者用Simulink做课程设计但被波形折磨过的人参考。内容里会有原理推导、Simulink搭建要点、参数整定思路,也会把我实际踩过的坑一并写出来。

1. 三相逆变器闭环控制的核心问题:为什么直接调PI经常不理想

1.1 先搞清楚闭环控制到底在解决什么问题

三相逆变器把直流电变成三相交流电,拓扑本身并不复杂:三个桥臂、六个开关管、后面接滤波电感和电容。纯开环的做法是给三个桥臂发固定占空比的SPWM波,输出端不加任何反馈。这种方式在负载变化不大的情况下勉强能用,但负载一跳、直流侧电压一波动,输出电压就直接跟着跑偏。

闭环控制的本质,就是实时测量输出量(电压或电流),把它跟给定值比较,用误差去驱动控制器调节占空比。三相逆变器的闭环控制里,最常用的是电压外环加电流内环的结构:外环稳住输出电压,内环让电感电流快速跟踪给定。这个结构看起来不复杂,但难点不在环路上,而在对象本身——三相交流量不好直接拿PI去控。

1.2 dq旋转坐标系下的耦合项是怎么冒出来的

这里要说清楚一个关键点:为什么三相电流用PI不好调控制器参数,而一到dq坐标系里就好调了。

三相逆变器经过电感接负载,在abc三相静止坐标系下,每相的电感电流方程是:

[ L\frac{di_a}{dt} = u_a - R i_a - e_a ]

写成三相形式后,三个相绕组的电流是相互牵制的,尤其是接星形负载时,三相电流相加为零,某相的电流变化会通过公共点影响另外两相。更麻烦的是,稳态时abc三相电流是50Hz的正弦波,PI控制器跟踪正弦给定本身存在稳态误差和创新性问题(PI对正弦指令的跟踪能力有限)。所以工程上都先把abc变换到静止αβ坐标系,再做Park变换,转到跟随转子(或虚拟转子)旋转的dq坐标系。

在dq坐标系下,三相工频正弦量变成了两个直流量:d轴对应有功分量,q轴对应无功分量。这时候用PI去控制直流量,理论上是没有稳态误差的。但问题来了——dq变换不是白给的,它把原本三相之间的耦合变成了两个轴之间的交叉耦合。

三相L滤波逆变器在dq旋转坐标系下的电压方程是:

[ L\frac{di_d}{dt} = u_d - R i_d - e_d + \omega L i_q ]

[ L\frac{di_q}{dt} = u_q - R i_q - e_q - \omega L i_d ]

注意看,d轴的电流动态方程里出现了 ( \omega L i_q ),q轴的方程里出现了 ( \omega L i_d ),这两个 ( \omega L ) 项就是耦合项。它的物理含义很直观:旋转坐标系跟随励磁频率转动,而电感电流在旋转坐标系里本来就存在一个由坐标旋转引起的“虚拟电动势”分量。用生活里的例子类比,就像坐在旋转的转盘上推一个球,你觉得自己在沿直线推,但球实际走的轨迹会受到转盘旋转的影响——( \omega L i_q ) 就是这么一股“靠旋转带出来的力”。

很多人在MATLAB仿真里遇到i_d阶跃,i_q跟着波动,进而影响整个电流波形,根因就是这个耦合项,而不是PI参数不匹配。

1.3 耦合在实际波形上长什么样

仿真的表现很直观:给i_d给定一个阶跃,比如从5A升到10A,另一边i_q的给定保持不变。此时因为d轴电流突变,经过Park变换的实际电流里,q轴电流也被拉偏,PI控制器会去纠正这个偏差,于是i_q波形就会出现一个尖峰后回落的过程。尖峰的大小和恢复时间,跟电感值、PI参数都有关系。电感越大,( \omega L ) 越大,耦合的冲击越明显。

更糟糕的情况是带负载突变。负载一变化,e_d、e_q分量跟着变,两个轴都会被迫动态调整,耦合项的存在会让两个轴互相“拖后腿”。这个时候你去单独调某个轴的PI参数,往往越调越乱,因为两个轴的干扰不是独立的。

所以在设计闭环控制器之前,必须先回答一个问题:是让PI自己去硬扛这个耦合,还是主动写一个解耦环节,把耦合项抵消掉?答案是后者。

2. 控制架构设计:电压外环、电流内环与PI算法的分工逻辑

2.1 双闭环为什么是主流结构

三相逆变器的闭环控制方案里,单电流环也能做,但工程上几乎没人这么用,因为逆变器最终要给负载提供一个稳定的电压,而电流环只能控制电流,没法直接保证负载端电压不塌。电压外环加电流内环的结构,本质上是把“电压稳不稳”和“电流快不快”两件事分开处理。

内环电流环的带宽做高,电流能快速跟踪给定,同时起到限流作用;外环电压环的带宽做低,避免两个环之间产生频率耦合。这个“内快外慢”的原则,在Simulink仿真里很好体现:给电压外环输出的电流给定一个慢变化的包络,电流内环要能几乎无延后地跟住它。如果两个环的带宽没拉开,仿真波形会出现低频振荡,就是外环跟内环在互相争夺主导权。

2.2 为什么dq坐标系下PI就够了

做控制的人应该都知道PI的局限:它对付阶跃给定很好,对付正弦给定就有稳态误差。三相逆变器的电压电流是正弦量,如果直接在abc坐标系上做PI控制,跟踪效果不好。所以Park变换的真正价值,是让PI去控直流量。

这个逻辑在仿真里的体现是:abc三相电流转换成dq电流之后,i_d、i_q在稳态时是平的直线,这时候PI的积分项可以慢慢把误差“磨”干净。在Simulink里你可以在Scope里同时观察abc电流和dq电流,看稳态时dq波形是否为平直直线,这是判断闭环控制是否“真的建好了”的第一个直观标志。

需要补充一点:这里PI的积分项不能省。有些同学为了追求响应快,把Ki调得很小甚至去掉积分,结果dq电流稳态存在静差。这是积分项的职责所在,不能偷懒。

2.3 PI参数整定:从带宽法到仿真试凑

PI参数是绕不开的话题。在dq坐标系下,因为对象已经被解耦(或近似解耦),两个轴的电流环对象可以看作一阶惯性加纯滞后:

[ G(s) = \frac{1}{Ls + R} ]

用带宽法设计时,令PI控制器的零点 ( K_i/K_p = R/L ) 与被控对象极点对消,电流环闭环传递函数近似为一阶惯性环节 ( 1/(\tau s + 1) )。带宽 ( \omega_c = 1/\tau ),Kp可以直接给 ( L/\tau ),Ki给 ( R/\tau )。这个思路比单纯试凑靠谱得多。

我一般在Simulink里的做法是这样:先按 ( \omega_c = 1000~2000 rad/s ) 计算一组初始Kp、Ki,跑仿真看阶跃响应,再根据超调量和调节时间微调。调整的原则很简单:

  • 超调大、振荡:适当减小Kp,或者微增Ki;
  • 响应慢、跟踪滞后:增大Kp;
  • 稳态出现小抖动:检查Ki是否过大造成积分过冲。

2.4 限幅、积分饱和与保护环节:仿真里也绝不能省

Simulink仿真跟真实系统一个重要的区别:真实系统有物理约束,仿真模型如果不加限幅,PI输出可以飞到天上去,反正数学上不管。这会导致一个问题——你仿真调出来的PI参数,波形很漂亮,但放到实际系统里根本没法用。

电流内环的PI输出最终要转成调制波,而调制波的幅值受限于直流侧电压和调制方式。如果PI输出超过可调制范围,实际系统里的占空比会饱和,相当于控制量被截断。这个时候PI如果还在继续积分,就会出现积分饱和:给定突变时,控制器迟迟不响应,直到积分退出来。

所以在Simulink里,PI控制器之后、调制模块之前,必须加一个限幅环节。限幅范围根据调制比来定,SPWM大约限制在直流母线电压的一半范围内。对于积分饱和的处理,可以选择带抗积分饱和功能的PID模块(Simulink里有内置Anti-windup选项),也可以用外部限幅加条件积分。要做到这一步不算难,但很多人第一次仿真时根本不加,导致阶跃响应波形很怪,然后又花大量时间去调参数。我建议从一开始就加上,免得后面返工。

3. 解耦控制的完整实现:前馈补偿的全部细节

3.1 解耦控制的本质是什么

前面对耦合现象已经做了解释,现在说说怎么消除它。核心思路不复杂:既然d轴方程里有一个 ( \omega L i_q ) 项在干扰,q轴方程里有一个 ( \omega L i_d ) 项在干扰,那就在控制器输出里主动生成一个相反的补偿量,把干扰抵消掉。

举个例子,你要推动一个靠左轮和右轮分别驱动的机器人沿直线前进。由于机械结构的原因,左轮右轮之间存在交叉干扰:给左轮加力,右轮也会被带着动一点。解耦控制的做法是:算出这个交叉干扰有多大,然后给右轮额外加一个反向的补偿力,让右轮“感觉不到”左轮的驱动。逆变器的dq轴耦合就是这样一对“传感器信号互相干扰”的控制通道。

具体到控制上,常用的方法是前馈解耦。标准的电流环控制方程写成:

[ u_d^* = \left(K_p + \frac{K_i}{s}\right)(i_d^* - i_d) + e_d - \omega L i_q ]

[ u_q^* = \left(K_p + \frac{K_i}{s}\right)(i_q^* - i_q) + e_q + \omega L i_d ]

注意这里的符号:d轴方程里本来有 ( +\omega L i_q ),所以补偿量是 ( -\omega L i_q );q轴方程里本来有 ( -\omega L i_d ),所以补偿量是 ( +\omega L i_d )。如果符号搞反了,耦合不但没抵消,反而会变成正反馈放大,波形会更糟。这是搭建仿真时最容易出错的细节之一。

3.2 推导一遍,确保符号不会搞错

为了确保符号正确,我把推导过程写一遍。上面的电压方程:

[ L\frac{di_d}{dt} + R i_d = u_d - e_d + \omega L i_q ]

如果我们希望设计一个控制器,让 ( i_d ) 的动态只由误差驱动,而不受 ( i_q ) 影响,那么可以把 ( +\omega L i_q ) 这一项当作“已知扰动”,从控制量 ( u_d ) 里主动减去它:

[ u_d = v_d - \omega L i_q + e_d ]

这里 ( v_d ) 是PI控制器根据误差生成的中间控制量,( -\omega L i_q + e_d ) 是前馈项。把 ( u_d ) 代回电压方程,得到:

[ L\frac{di_d}{dt} + R i_d = v_d ]

你看,( i_q ) 这一项就消失了,d轴电流的动态变成了一个单纯的一阶对象,由 ( v_d ) 直接控制。这就是解耦的全部含义——不是改变物理对象,而是在控制量里做文章,让系统对外表现得像没有交叉耦合一样。

3.3 Simulink模块搭建:从头到尾怎么连

说完了原理,下面把Simulink模型里各个环节的搭建细节列一下。整体信号流是这样的:

  1. 三相电源给直流侧供电(直流侧可用固定电压源代替,省去整流桥部分,简化仿真);
  2. 逆变器输出接滤波电感和电阻负载(或阻感负载);
  3. 电流传感器测三相电感电流i_a、i_b、i_c;
  4. abc三相电流 → Clarke变换(abc→αβ) → Park变换(αβ→dq),得到i_d、i_q;
  5. i_d、i_q分别跟给定值比较,误差进两个PI控制器;
  6. PI输出加上前馈解耦补偿量:( -\omega L i_q + e_d ) 和 ( +\omega L i_d + e_q );
  7. 得到u_d^、u_q^,再经过反Park变换(dq→αβ)得到两相静止坐标系下的调制信号;
  8. 调制信号经SPWM(三相调制波与三角载波比较)得到六路驱动脉冲,送给逆变器的六个开关管。

这里面几个Simulink模块要用对:

  • 坐标变换可以用内置的Clarke变换和Park变换模块(Simulink/Simscape里有现成的),也可以自己写MATLAB Function。我的建议是先用内置模块跑通,再考虑用代码替换,先用最简单的方案把逻辑验证清楚;
  • 前馈解耦项的 ( \omega L ) 中,( \omega ) 是基波角频率(50Hz对应314 rad/s),L是滤波电感值。这个值在仿真里是常量,可以用Gain模块算好,不需要实时计算;如果要做成通用模型,也可以从PLL(锁相环)测得的角频率动态取值——不过三相逆变器独立带负载的仿真里,频率由调制波频率决定,直接用固定值即可;
  • e_d、e_q是负载电压的dq分量。带阻感负载时,e_d、e_q是负载电压经过Park变换后的值。如果是独立带负载的逆变器,这个值其实可以从负载端电压量测得到;如果是并网逆变器,e_d、e_q就是电网电压的dq分量,必须量测。

3.4 解耦之后PI设计为什么变简单了

解耦的最大收益,是PI参数可以分轴独立整定了。没有解耦的时候,d轴PI的调整会通过耦合项影响q轴的响应,你调一个轴等于同时调两个轴,参数寻优空间被拖得很辛苦。解耦之后,d轴和q轴的传递函数都变成了:

[ G(s) = \frac{1}{Ls + R} ]

这是两个完全相同的对象,所以d、q两个轴的PI参数完全一样,理论上可以“一套参数,两个轴通用”。在Simulink里你会看到:i_d闭环阶跃响应波形的调节时间和超调量,跟i_q闭环阶跃响应几乎一模一样,这就是解耦做对了的表现。

4. 仿真模型搭建中的核心参数选择与结果判读方法

4.1 仿真参数怎么定

一做仿真就卡在参数上的人非常多。我直接给一组可以跑通的基准参数,后面自己想调整也知道往哪个方向改。

参数取值说明
直流母线电压400V直接用直流电压源代替整流输出
滤波电感5mHL越大,电流纹波越小,但动态响应变慢
等效电阻0.1Ω电感绕组及线路电阻
滤波电容20μF对LC滤波型逆变器,需根据截止频率调整
负载10Ω阻感负载(电感10mH)模拟实际阻感性负荷
基波频率50Hz调制波频率
三角载波频率10kHz开关频率越高,谐波越小,但仿真计算量增大
采样周期100μs对应10kHz采样,与开关频率同频
电流环PIKp=可变,Ki=可变按带宽法估算后试凑
电压环PI带宽设为电流环的1/10~1/5保证时间尺度分离

参数内部关系的两个要点:

  • 滤波电感和电容的谐振频率要远离基波频率,同时要在开关频率以下有足够的衰减。( f_{LC} = 1/(2\pi \sqrt{LC}) ) 这个公式可以用来估算。比如L=5mH、C=20μF时,谐振频率大约是503Hz,跟50Hz基波之间隔了10倍频,跟10kHz开关频率也很远,这样不会在基波附近产生谐振放大;
  • 采样周期跟开关周期一般取同频,逆变器PWM在每个开关周期更新一次占空比,仿真步长要小于采样周期,否则PWM波形跟采样数据对不上,电流波形会莫名变毛糙。我习惯把仿真步长固定为10μs,即采样周期的1/10。

4.2 说清楚实验设计:怎么判断解耦有没有真的起作用

判断解耦是否有效,不能只看稳态波形,因为解耦前和解耦后的稳态波形几乎一样,都在给定的直流量附近。关键要看动态过程,具体的实验方法是:

  1. 先把前馈解耦项设为0,跑一组i_d给定阶跃实验:i_d从5A阶跃到10A,i_q给定保持不变;
  2. 记录i_q的波动峰峰值和恢复时间;
  3. 再启用前馈解耦项,做完全相同的阶跃实验;
  4. 对比两次实验i_q的波形。

仿真结果中,没有解耦时,i_q会出现明显的瞬态尖峰,幅度可能达到1~2A,恢复到稳态的时间在几毫秒到十几毫秒不等;加了前馈解耦之后,i_q应该几乎不动,或者只有由PI参数动态限速造成的极小的波动。如果前馈项符号正确且参数精确,i_q的响应幅度能下降一个数量级。

4.3 波形判读的时间尺度和观察方法

很多初学者喜欢看着整个仿真时间段的波形,从0一直到0.5s全看,结果波形密密麻麻,根本看不清动态过程。我的做法是分段观察:

  • 0~0.02s(一个基波周期):看启动过程、初始冲击电流;
  • 0.02~0.1s:看电流环阶跃响应的动态过程,设置Scope的时间窗口在0.5ms左右,可以看清PI的响应细节;
  • 0.1s~0.2s:看稳态波形质量,此时应关注三相电流的THD,而不是瞬时波形。

在判断THD时,可以用Simulink的“Powergui”中的FFT分析工具,选中电流波形做FFT,看基波幅值和高次谐波含量。这个指标很重要:解耦控制解决的是动态耦合问题,谐波含量反映的是调制方式和滤波器设计是否合理,两者不要混为一谈。不然你花三天优化谐波,结果动态耦合问题还在,方向就偏了。

4.4 SPWM和SVPWM:调制方式要不要换

标题里只提到逆变器闭环和解耦PI,没有直接点名调制方式,但仿真里绕不开。SPWM(正弦脉宽调制)是基础方案,三个调制波和三角载波比较,逻辑简单,Simulink里用几个比较器和逻辑模块就能做。SVPWM(空间矢量脉宽调制)利用逆变器8种开关状态合成期望电压矢量,直流电压利用率比SPWM高约15%,谐波也略好一些,但实现复杂一些。

我的建议是:如果目标是研究闭环控制和解耦PI算法,第一步先用SPWM,把控制的逻辑验证通了再说。解耦控制本身跟调制方式不冲突——解耦在控制环路里,调制在PWM生成环节——所以你先把控制环路调对了,再把SPWM换成SVPWM,结果不会差太多,但调试工作量少很多。

5. 建模过程中最容易踩的坑:角度、离散化、抗饱和

5.1 Park变换的角度对齐问题

这是Simulink里特别隐蔽的一个坑。Park变换需要依据旋转角度 ( \theta ),而这个 ( \theta ) 在独立逆变器仿真里,应该是由调制波的相位来确定的。有些同学直接从三相电压源模块的相位里取角度,结果坐标变换基准和调制基准不一致,导致dq轴电流都带高频振荡,解耦完全失效。

正确的做法是:如果用的是三相调制波 ( \sin(\omega t) )、( \sin(\omega t - 120°) )、( \sin(\omega t + 120°) ),那么Park变换角度 ( \theta = \omega t ),直接用Ramp模块生成 ( \omega t ) 再取cos、sin即可。如果加了PLL锁相环,就要通到锁到哪一相的相位,确保Park变换的角度基准跟控制目标一致。角度差只要差个 ( \pi/6 ) 或 ( \pi/3 ),dq轴的解耦就没法正常工作,波形全是乱的。

5.2 离散化与采样保持导致的振荡

Simulink里可以跑连续系统,但真实控制器是离散的。如果你直接用连续PI控制器模块,仿真波形很好,但换到离散PI之后,波形开始出现小幅振荡——这不是PI参数的问题,而是数字控制的固有延迟。

数字控制在每个采样周期读一次电流,算一次PI输出,下个周期才更新PWM占空比,这中间有一拍延迟。这一拍延迟在高带宽情况下会让系统相位裕度下降。处理办法有两个方向:一是电流环带宽不要设计得太高,留出足够的相位裕度;二是把采样和PWM更新统一在同一时刻,采用中心对齐PWM时,在计数器的峰点或谷点采样,保证采样值不含开关纹波,同时让延迟尽可能小。

5.3 求解器与PWM生成环节的设置

Simulink里PWM调制是高频开关过程,跟低频控制环路的动态尺度差了好几个数量级。如果用的是变步长求解器(默认的ode45),仿真时间很长时,PWM开关的每个边沿都会触发小步长,总步数会爆炸,仿真跑起来特别慢。

我在实际中的做法是:

  • 用固定步长求解器(如ode3或ode4),步长设为开关周期的1/20左右,即10kHz开关频率下设5μs步长;
  • 仿真时间不用太长,看稳态波形時0.1s就够,看阶跃响应時0.05s即可。存着数据多跑几次,比一次跑个5秒然后卡死要好得多。

如果用了Simscape Electrical(原SimPowerSystems)里的IGBT/二极管模块,开关过程的仿真步长要求会更严,必要时可以适当降低开关频率到5kHz,先把控制逻辑跑通,再提高频率看精细波形。

5.4 积分饱和:一个容易被仿真掩盖的坑

前面已经提过积分饱和。这里补充一个具体的Simulink验证方法:把电流给定从0突然拉到30A,这超过了电流环PI输出限幅允许达到的最大电流能力,此时如果你不加抗积分饱和,PI输出会冲到限幅值,然后积分项持续累积,最终波形上会是一段“死区”——电流下降缓慢,甚至出现超调后才回落。

如果你用的是Simulink标准PID Controller模块,把“Anti-windup method”从none改成“back-calculation”,并给一个合适的Back-calculation gain(一般取Kp的2~4倍),就能看到响应过程明显改善。我实际试过,同样的参数,加上抗饱和之后,超调量能从20%降到5%以下,恢复时间缩短接近一半。这一步在单纯连续仿真里容易被忽略,但放到硬件上就是烧管子的问题,仿真阶段必须养成规避它的习惯。

做整套仿真下来,最大的体会是解耦控制本身并不复杂,它难在把每一个细节都对齐:坐标变换角度对没对、前馈项符号对不对、PI参数是否超出物理限幅、离散化延迟有没有留足裕量。只要这些地方不出错,MATLAB仿真得到的结果会是干净利落的。调PI这件事,也从“玄学”变成了“按带宽算参数,按阶跃响应微调”的确定性过程。后面如果想把模型往更实用的方向扩展,可以把固定阻感负载换成整流型负载,看解耦控制在非线性负载下的表现,或者把L滤波换成LCL滤波,那又会牵扯到谐振抑制和阻尼设计,跟解耦PI配合起来又是一套新的玩法。但地基还是这些:坐标变换、电流闭环、前馈解耦,把这套基本功练扎实了,其他都是上层建筑。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进