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 实际项目中的常见问题

我在调试伺服驱动器时,遇到过几个典型问题,分享给你:

  1. 电流采样顺序搞反了: 三相电流采样有先后顺序,如果和PWM载波不同步,采到的值不是同一时刻的。Clark变换出来的αβ电流会有相位误差。我曾经因为这个,电流环带宽怎么都提不上去。
  2. 角度初始值不对: 电机上电时,转子位置是未知的。如果直接做Park变换,id和iq会乱跳。我一般先做一个开环强制定位,或者用高频注入法把转子位置找出来。
  3. 变换系数不匹配: 前面说了,等幅值和等功率变换的系数不同。如果你的电流采样、电压输出、和变换用的系数不一致,控制精度会受影响。

总结一下: Clark和Park变换,是FOC算法的数学基础。它们把复杂的三相交流控制,变成了简单的直流控制。代码实现不难,但细节决定成败。角度精度、采样时序、系数匹配,都是坑。踩过一次,你就记住了。

下一章,咱们聊聊SVPWM——怎么把dq轴电压指令,变成实实在在的三相占空比。那才是真正驱动电机转起来的关键一步。