2、Clark变换与Park变换:三相坐标系到两相静止坐标系、两相静止到两相旋转坐标系的数学推导与代码实现
好,咱们今天聊聊FOC算法里最基础、也最核心的两个数学变换——Clark变换和Park变换。
说实话,我刚入行那会儿,看到这些矩阵公式就头大。心想:搞个电机控制,干嘛要这么折腾?后来在项目里被电流谐波折磨过几次,才真正明白——没有坐标变换,你根本没法对电机进行精确的力矩控制。
你想想看,三相电机的电流是三个正弦波,互相差120度。你直接去控制三个正弦波?那太复杂了。但如果我们换个坐标系去看,事情就简单多了。
2.1 为什么需要坐标变换?
先问个问题:直流电机为什么好控制?
因为直流电机的电枢磁场和励磁磁场天然就是正交的。你调电枢电流,只影响力矩;调励磁电流,只影响磁场。互不干扰,控制起来特别爽。
但交流电机呢?三相电流产生的旋转磁场,和转子磁场之间是耦合的。你调某一相电流,力矩和磁通都会变。这就是所谓的“强耦合、非线性”。
坐标变换的目的,说白了就是:把交流电机“伪装”成直流电机来控制。
Clark变换把三相变成两相,Park变换把静止的两相变成旋转的两相。最终,我们得到的就是一个和转子同步旋转的坐标系。在这个坐标系里,电流被分解成两个直流分量——d轴电流(励磁分量)和q轴电流(力矩分量)。
嗯,这样一来,控制就变成了调两个直流电压,跟直流电机一模一样。
核心思想: 坐标变换不是物理上的改变,而是观察角度的改变。就像你站在地上看旋转的风扇,和坐在风扇上看,看到的景象完全不同。
2.2 Clark变换:从三相到两相静止坐标系
Clark变换,也叫3s/2s变换。它的任务是把三相坐标系(a, b, c)上的电流,投影到两相静止坐标系(α, β)上。
数学上,假设三相电流是平衡的,即 ia + ib + ic = 0。那么变换公式就是:
iα = ia
iβ = (ia + 2*ib) / √3
等等,你可能会问:为什么这么简单?
其实完整的Clark变换矩阵是这样的:
[ iα ] [ 1 -1/2 -1/2 ] [ ia ]
[ iβ ] = [ 0 √3/2 -√3/2 ] [ ib ]
[ i0 ] [ 1/2 1/2 1/2 ] [ ic ]
第三行是零序分量。在三相三线制系统里,零序电流为0,所以可以简化成上面的形式。
我个人习惯用等幅值变换,也就是变换前后电流的幅值不变。还有一种叫等功率变换,系数不同,但原理一样。你在做项目时,一定要搞清楚你的库用的是哪种,不然算出来的角度和电流值会差一个系数。
避坑指南: 我曾经在一个项目里,直接复制了别人的Clark变换代码,结果电流环怎么调都调不好。查了两天才发现,对方用的是等功率变换,我用的传感器是等幅值标定的。系数差了√(2/3),整个控制都偏了。
2.3 Park变换:从两相静止到两相旋转坐标系
Clark变换做完,我们有了αβ轴上的两个正弦电流。但正弦信号还是不好控。怎么办?再转一次。
Park变换,也叫2s/2r变换。它把静止的αβ坐标系,旋转到和转子磁场同步的dq坐标系。
公式很简单:
id = iα * cos(θ) + iβ * sin(θ)
iq = -iα * sin(θ) + iβ * cos(θ)
这里的θ,就是转子电角度。从编码器或者霍尔传感器读到的位置信息,乘以极对数,就得到了θ。
你想想看,当θ和转子位置同步时,id和iq就变成了直流。id控制磁通,iq控制力矩。完美解耦。
这里有个关键点: θ的精度直接影响变换效果。如果θ有误差,id和iq之间就会串扰。你调iq的时候,id会跟着动,力矩控制就不准了。
注意: Park变换的逆变换(从dq回到αβ)同样重要。你在做电流环输出时,需要把dq轴上的电压指令,先反Park变换成αβ电压,再通过SVPWM生成三相占空比。这个流程是闭环的,一步都不能少。
2.4 代码实现:从公式到C语言
好了,理论讲完了,咱们看看代码怎么写。我习惯用浮点运算,方便调试。量产时可以考虑定点化,但原理一样。
// Clark变换:三相电流 -> 两相静止电流
void clark_transform(float ia, float ib, float ic,
float *i_alpha, float *i_beta) {
// 等幅值变换,假设三相平衡
*i_alpha = ia;
*i_beta = (ia + 2.0f * ib) * 0.577350269f; // 1/√3 ≈ 0.57735
}
// Park变换:两相静止 -> 两相旋转
void park_transform(float i_alpha, float i_beta, float theta,
float *i_d, float *i_q) {
float sin_theta = sinf(theta);
float cos_theta = cosf(theta);
*i_d = i_alpha * cos_theta + i_beta * sin_theta;
*i_q = -i_alpha * sin_theta + i_beta * cos_theta;
}
// 反Park变换:两相旋转 -> 两相静止
void inv_park_transform(float v_d, float v_q, float theta,
float *v_alpha, float *v_beta) {
float sin_theta = sinf(theta);
float cos_theta = cosf(theta);
*v_alpha = v_d * cos_theta - v_q * sin_theta;
*v_beta = v_d * sin_theta + v_q * cos_theta;
}
这段代码看起来简单,但有几个细节要注意:
- 三角函数计算: sinf/cosf在MCU上比较慢。我一般用查表法或者CORDIC算法。如果芯片有硬件三角函数加速器,记得用起来。
- 角度处理: θ的范围是0到2π。注意做模运算,防止溢出。我习惯用float,但如果你用定点数,要小心角度归一化的问题。
- 执行顺序: 先Clark,再Park。反变换时,先反Park,再反Clark(实际上反Clark就是直接算三相电压,通常和SVPWM合并了)。
2.5 实际项目中的常见问题
我在调试伺服驱动器时,遇到过几个典型问题,分享给你:
- 电流采样顺序搞反了: 三相电流采样有先后顺序,如果和PWM载波不同步,采到的值不是同一时刻的。Clark变换出来的αβ电流会有相位误差。我曾经因为这个,电流环带宽怎么都提不上去。
- 角度初始值不对: 电机上电时,转子位置是未知的。如果直接做Park变换,id和iq会乱跳。我一般先做一个开环强制定位,或者用高频注入法把转子位置找出来。
- 变换系数不匹配: 前面说了,等幅值和等功率变换的系数不同。如果你的电流采样、电压输出、和变换用的系数不一致,控制精度会受影响。
总结一下: Clark和Park变换,是FOC算法的数学基础。它们把复杂的三相交流控制,变成了简单的直流控制。代码实现不难,但细节决定成败。角度精度、采样时序、系数匹配,都是坑。踩过一次,你就记住了。
下一章,咱们聊聊SVPWM——怎么把dq轴电压指令,变成实实在在的三相占空比。那才是真正驱动电机转起来的关键一步。