3. 电流环软件架构:Clark变换与Park变换的代码实现,旋转坐标系下的PI调节
好,咱们进入电流环的核心了。前面两章把硬件和采样讲完,这一章就是真正让电流“转”起来的关键——坐标变换和旋转坐标系下的PI调节。
说白了,FOC的精髓就是把三相交流电机的控制,变成像控制直流电机一样简单。怎么做到的?就是靠Clark和Park这两把“手术刀”。
3.1 从三相到两相:Clark变换
电机里有三根线,电流分别是Iu、Iv、Iw。这三兄弟是交流的,相位差120度,直接控制很麻烦。Clark变换的任务就是:把这三个静止的坐标系,投影到两个互相垂直的静止坐标系上——也就是α轴和β轴。
公式其实很简单:
Iα = Iu
Iβ = (Iu + 2*Iv) / √3
嗯,这里有个小细节。实际代码里我们一般用标幺值,而且会做等幅值变换。我个人习惯用Q15格式来做,避免浮点运算拖慢中断。
关键点:Clark变换本身不改变信号的频率,只是把三相投影到两相。变换后的Iα和Iβ仍然是正弦波。
来看一段我实际项目里用过的代码:
// Clark变换,输入三相电流,输出Iα、Iβ
void clark_transform(q15_t Iu, q15_t Iv, q15_t Iw, q15_t *Ialpha, q15_t *Ibeta)
{
*Ialpha = Iu; // Iα = Iu
// Iβ = (Iu + 2*Iv) / √3
// 这里用Q15格式,1/√3 ≈ 0.57735,对应Q15值为18919
q15_t temp = Iu + (Iv << 1); // Iu + 2*Iv
*Ibeta = (q15_t)(((q31_t)temp * 18919) >> 15);
}
我的经验:采样三相电流时,理论上Iu+Iv+Iw=0。但实际ADC采样有误差,我一般只采两相,第三相用公式算出来。这样能省一个ADC通道,还能避免累加误差。
3.2 跟着转子转:Park变换
Clark变换完,我们有了Iα和Iβ。但它们还是正弦波,没法直接做PI控制——因为PI调节器对交流信号的跟踪效果很差,会有静差。
Park变换就是来解决这个问题的。它把静止的αβ坐标系,旋转到跟转子磁场同步的dq坐标系。说白了,就是让坐标系跟着转子一起转。
公式:
Id = Iα * cos(θ) + Iβ * sin(θ)
Iq = -Iα * sin(θ) + Iβ * cos(θ)
这里的θ就是转子电角度,由编码器或霍尔传感器提供。
变换之后,Id和Iq就变成了直流量。Id控制励磁分量,Iq控制转矩分量。这时候再用PI调节器,效果就非常好了。
注意:Park变换依赖转子位置θ。如果θ不准,变换出来的Id、Iq就会有耦合。我曾经在一个项目里遇到过编码器安装偏差,导致电机高速时转矩波动。后来加了角度补偿才解决。
代码实现:
// Park变换,输入Iα、Iβ和电角度θ,输出Id、Iq
void park_transform(q15_t Ialpha, q15_t Ibeta, q15_t sin_theta, q15_t cos_theta,
q15_t *Id, q15_t *Iq)
{
// Id = Iα*cosθ + Iβ*sinθ
*Id = (q15_t)(((q31_t)Ialpha * cos_theta + (q31_t)Ibeta * sin_theta) >> 15);
// Iq = -Iα*sinθ + Iβ*cosθ
*Iq = (q15_t)(((q31_t)(-Ialpha) * sin_theta + (q31_t)Ibeta * cos_theta) >> 15);
}
3.3 旋转坐标系下的PI调节
好了,现在我们有Id和Iq了。它们都是直流量,目标值分别是Id_ref和Iq_ref。Id_ref通常设为零(表贴式电机),Iq_ref由速度环输出给定。
PI调节器的形式大家都熟悉:
输出 = Kp * 误差 + Ki * 积分项
但在旋转坐标系下,有个坑要注意——反电动势耦合。电机高速旋转时,d轴和q轴之间会互相影响。如果不做解耦,PI调起来会很痛苦。
我一般会在PI输出后加一个解耦项:
Vd = Vd_pi - ω * Lq * Iq
Vq = Vq_pi + ω * Ld * Id + ω * ψf
其中ω是电角速度,Ld、Lq是电感,ψf是永磁体磁链。
实战建议:刚开始调参时,先别加解耦。把Kp和Ki调稳了,再逐步加入解耦项。这样出问题了容易定位。
PI代码示例:
// 增量式PI调节器,带积分限幅
typedef struct {
q15_t Kp;
q15_t Ki;
q15_t integral;
q15_t integral_max; // 积分限幅
} PI_Controller;
q15_t pi_run(PI_Controller *pi, q15_t error)
{
q15_t output;
// 比例项
q15_t p_term = (q15_t)(((q31_t)error * pi->Kp) >> 15);
// 积分项
pi->integral += (q15_t)(((q31_t)error * pi->Ki) >> 15);
// 积分限幅
if(pi->integral > pi->integral_max)
pi->integral = pi->integral_max;
else if(pi->integral < -pi->integral_max)
pi->integral = -pi->integral_max;
output = p_term + pi->integral;
return output;
}
3.4 整体流程与SVG框架图
把上面这些串起来,电流环的完整流程就是:采样 → Clark → Park → PI调节 → 反Park → SVPWM。下面这张图帮你理清脉络:
3.5 调参顺序与避坑指南
电流环调参,我建议按这个顺序来:
- 先调Id环:给一个阶跃指令,观察Id的响应。Kp先给一个保守值,Ki从零开始慢慢加。
- 再调Iq环:同样方法,但注意Iq环受反电动势影响更大,高速时可能不稳定。
- 加解耦:两个环都调稳了,再把解耦项加进去。你会发现高速性能明显改善。
我曾经踩过的坑:有一次在调试高速电机时,Iq环突然震荡。查了半天,发现是角度采样延迟太大。Park变换用的θ滞后了实际位置,导致Id和Iq耦合。后来我把角度采样放在中断最前面,问题就解决了。
还有一个常见问题:积分饱和。电机启动时,误差很大,积分项会迅速积累。等误差变小后,积分项需要很长时间才能退出来,导致超调。我的做法是加积分限幅,并且启动时把积分清零。
| 参数 | 作用 | 调大影响 | 调小影响 |
|---|---|---|---|
| Kp | 比例增益,决定响应速度 | 响应快,但可能震荡 | 响应慢,稳态误差大 |
| Ki | 积分增益,消除稳态误差 | 消除静差快,但易超调 | 静差消除慢 |
| 积分限幅 | 防止积分饱和 | 限幅大,抗饱和弱 | 限幅小,可能达不到目标 |
我的习惯:先用仿真工具(比如Simulink)把PI参数粗调一遍,再下到硬件里微调。这样能省很多时间。另外,记得把电流环的中断频率设高一点,我一般用10kHz以上,这样PI调节才能跟上电流的变化。
好了,这一章的内容就到这。Clark变换、Park变换、旋转坐标系下的PI调节,这三板斧是电流环的基石。代码我给你了,流程图也画了,剩下的就是动手调。记住,理论再漂亮,不如实际跑一次来得实在。