3. 电压前馈解耦:d-q轴电压方程与交叉耦合项补偿
做FOC的人,迟早都会碰到一个问题——d轴和q轴明明是两个独立的控制通道,怎么调来调去总觉得它们在互相拉扯?
这种现象,说白了就是交叉耦合在作怪。我刚开始做电机控制那会儿,也在这上面栽过跟头。当时调一个高速电机,d轴电流一上去,q轴电流就往下掉,PID怎么整都整不好。后来才明白,不是PID不行,是耦合项没处理。
3.1 d-q轴电压方程回顾
先看基础。永磁同步电机在同步旋转坐标系下的电压方程长这样:
Vd = Rs·Id + Ld·(dId/dt) - ωe·Lq·Iq
Vq = Rs·Iq + Lq·(dIq/dt) + ωe·(Ld·Id + ψf)
这里面,-ωe·Lq·Iq 和 +ωe·(Ld·Id + ψf) 就是交叉耦合项。它们把d轴和q轴绑在了一起。
你想想看,当电机转速ωe升高时,耦合项的幅值也跟着变大。低速时还好说,到了高速弱磁区间,耦合项可能比电阻压降还大好几倍。这时候如果不去管它,两个轴的控制就会互相干扰。
核心理解:交叉耦合的本质是反电动势和磁链在d-q轴之间的能量交换。它不是故障,是物理规律。我们要做的不是消除它,而是补偿它。
3.2 耦合项对控制性能的影响
耦合带来的问题,我归纳成三点:
- 动态响应变慢——调d轴时q轴跟着抖,两个环路互相等待
- 稳态精度下降——耦合项相当于一个随转速变化的扰动,PI控制器很难完全抑制
- 参数敏感度增加——电感Ld、Lq不准时,耦合补偿效果打折扣
我在一个项目里遇到过这样的情况:电机转速到3000rpm以上时,q轴电流纹波突然变大,怎么调PI参数都没用。后来用示波器抓了d-q轴电压波形才发现,是耦合项在作祟。补偿加上去之后,纹波直接降了一半。
3.3 前馈解耦原理
前馈解耦的思路其实很直接——既然知道耦合项长什么样,那就主动把它算出来,加到控制输出里抵消掉。
具体做法是:
- 从电流环PI控制器输出Vd_pi、Vq_pi
- 根据当前转速ωe和电流Iq、Id,算出耦合补偿量
- 把补偿量加到PI输出上,得到最终的Vd_ref、Vq_ref
公式表达就是:
Vd_ref = Vd_pi - ωe·Lq·Iq
Vq_ref = Vq_pi + ωe·(Ld·Id + ψf)
嗯,这里要注意——补偿量的符号和电压方程里的耦合项符号是相反的。目的就是让它们互相抵消。
个人习惯:我一般把前馈补偿放在PI控制器之后、SVPWM之前。这样PI控制器只负责处理误差,前馈负责处理已知的耦合扰动,分工明确。
3.4 数字实现中的注意事项
把上面的公式写成代码,看起来很简单。但实际做起来有几个坑:
| 注意事项 | 说明 | 我的建议 |
|---|---|---|
| 时序对齐 | 补偿用的电流值必须是当前周期的采样值 | 用上一周期的电流做补偿,会有相位滞后 |
| 电感参数误差 | Ld、Lq会随电流变化 | 建议做查表补偿,或者在线辨识 |
| 转速信号质量 | ωe噪声会直接引入补偿量 | 对转速做低通滤波,截止频率别太低 |
| 饱和处理 | 补偿后电压可能超过母线限制 | 先限幅再输出,或者做抗饱和处理 |
我曾经在一个项目里吃过亏——转速信号没滤波,结果补偿量里全是高频噪声,电流环反而更不稳定了。后来加了个截止频率200Hz的一阶低通,问题就解决了。
3.5 前馈解耦与PI控制器的配合
加上前馈之后,PI控制器的参数可以怎么调?
我的经验是:
- 比例增益Kp可以适当降低——因为前馈已经处理了大部分扰动,PI不用那么激进
- 积分增益Ki基本不变——积分还是负责消除稳态误差
- 带宽可以推高——解耦后两个轴独立了,电流环带宽可以比不解耦时高20%~30%
避坑指南:不要以为加上前馈就万事大吉。如果电感参数偏差超过30%,前馈补偿反而会引入新的扰动。我曾经遇到过标称电感值和实际值差了40%的情况,补偿后电流环直接振荡了。所以,参数不准时,宁可补偿系数打八折,也别硬上。
3.6 弱磁区间的特殊处理
进入弱磁区间后,d轴电流Id变成负值,而且幅值越来越大。这时候耦合项ωe·(Ld·Id + ψf)会变小,甚至变负。
这意味着什么?
在弱磁区,q轴的反电动势被d轴的去磁效应抵消了一部分。如果还用恒定的ψf做前馈,补偿量会偏大。我建议的做法是:
- 实时计算
ψf + Ld·Id作为等效磁链 - 用这个等效磁链做q轴前馈补偿
- d轴前馈补偿中的Lq·Iq项不变
这样在弱磁区也能保持解耦效果。
3.7 前馈解耦的整体流程
下面这张图展示了前馈解耦在FOC中的位置和信号流向:
从图上可以看到,前馈补偿计算需要三个输入:转速ωe、反馈电流Id和Iq。补偿结果分别叠加到d轴和q轴的PI输出上,形成最终的电压参考值。
3.8 代码实现示例
下面是一个简化的前馈解耦实现,我用C语言写的,适合嵌入到中断服务函数里:
typedef struct {
float Ld; // d轴电感 (H)
float Lq; // q轴电感 (H)
float psi_f; // 永磁体磁链 (Wb)
float vd_ff; // d轴前馈补偿量
float vq_ff; // q轴前馈补偿量
} FeedForward_t;
void FeedForward_Calc(FeedForward_t *ff, float Id, float Iq, float omega_e) {
// d轴前馈:-ωe·Lq·Iq
ff->vd_ff = -omega_e * ff->Lq * Iq;
// q轴前馈:+ωe·(Ld·Id + ψf)
ff->vq_ff = omega_e * (ff->Ld * Id + ff->psi_f);
}
void CurrentLoop_WithFF(float Id_ref, float Iq_ref, float Id_fb, float Iq_fb, float omega_e) {
float vd_pi, vq_pi;
float vd_ref, vq_ref;
// 1. PI控制器计算(省略内部实现)
vd_pi = PI_Controller(&pi_d, Id_ref - Id_fb);
vq_pi = PI_Controller(&pi_q, Iq_ref - Iq_fb);
// 2. 前馈补偿计算
FeedForward_Calc(&ff, Id_fb, Iq_fb, omega_e);
// 3. 叠加补偿量
vd_ref = vd_pi + ff.vd_ff;
vq_ref = vq_pi + ff.vq_ff;
// 4. 限幅处理
Voltage_Limit(&vd_ref, &vq_ref, Vdc);
// 5. 输出到SVPWM
SVPWM_SetVoltage(vd_ref, vq_ref);
}
一个小技巧:如果电感参数不太准,可以在前馈补偿前加一个可调系数Kff。调试时从0.8开始,慢慢往上加,直到电流环响应最好为止。我一般用0.9~1.0之间的值。