3. Clark变换与Park变换:从三相到两相的坐标魔法

坐标变换,说白了就是换个角度看电机。你想想看,三相电机里三个绕组互相差120°,控制起来多麻烦。要是能把它变成两相,甚至变成直流电机那样控制,是不是就简单多了?

Clark变换和Park变换就是干这个的。我刚开始做电机控制时,总觉得这些公式就是数学游戏。直到有一次调试一个高速主轴电机,三相电流波形乱成一团,怎么调PI参数都不行。后来静下心把坐标变换捋了一遍,才发现是Clark变换里一个符号搞反了。从那以后,我再也不敢小看这两步变换了。

3.1 为什么需要坐标变换?

三相电机的数学模型,在三相静止坐标系(ABC坐标系)下是这样的:

  • 三个绕组互相耦合,电感矩阵不是对角阵
  • 磁链方程里有很多互感项
  • 转矩表达式复杂,包含转子位置角

说白了,就是耦合太严重,你动A相,B相和C相也跟着受影响。控制起来就像同时拉三根绳子,很难精准发力。

坐标变换的目的就是解耦。先通过Clark变换,把三相变成两相;再通过Park变换,把静止的两相变成旋转的两相。最终,交流电机看起来就像直流电机一样好控制。

核心思想:变换前后,磁动势(MMF)保持不变。也就是说,不管你在哪个坐标系下看,电机产生的磁场效果是一样的。这是所有坐标变换的物理基础。

3.2 Clark变换:三相静止 → 两相静止

Clark变换,也叫3s/2s变换。它把ABC三相坐标系,映射到αβ两相静止坐标系。α轴和A轴重合,β轴超前α轴90°。

公式推导其实不复杂。核心原则是:变换前后,总磁动势不变。

设三相电流为 iA、iB、iC,两相电流为 iα、iβ。根据磁动势等效:

N₂ · i_α = N₃ · (i_A - 1/2 · i_B - 1/2 · i_C)
N₂ · i_β = N₃ · (0 + √3/2 · i_B - √3/2 · i_C)

其中N₂是两相绕组匝数,N₃是三相绕组匝数。匝数比取决于你选的是等幅值变换还是等功率变换。

等幅值变换:变换后电流幅值不变,匝数比 N₃/N₂ = 2/3。

等功率变换:变换前后功率不变,匝数比 N₃/N₂ = √(2/3)。

我个人习惯用等幅值变换。为什么?因为调试时看电流波形更直观,幅值没变,示波器上直接能看出问题。等功率变换在理论推导时更干净,但工程上我推荐等幅值。

最终Clark变换矩阵(等幅值):

[ i_α ]   [ 1      -1/2    -1/2   ] [ i_A ]
[ i_β ] = [ 0      √3/2   -√3/2  ] [ i_B ]
                                  [ i_C ]

注意,这里没有零序分量。如果三相平衡,i_A + i_B + i_C = 0,那么公式还可以简化。

工程小技巧:实际代码里,我一般先算 i_α = i_A,再算 i_β = (i_B - i_C) / √3。少算一次乘法,省一个时钟周期。在低成本MCU上,这点优化很实在。

3.3 Park变换:两相静止 → 两相旋转

Clark变换完了,我们有了iα和iβ。但它们还是交流量,随着转子转动而正弦变化。要把它变成直流量,就需要Park变换。

Park变换,也叫2s/2r变换。它把αβ静止坐标系,旋转到dq旋转坐标系。d轴和转子磁极对齐,q轴超前d轴90°。

公式推导同样基于磁动势等效。设转子位置角为θ(d轴与α轴的夹角):

i_d = i_α · cosθ + i_β · sinθ
i_q = -i_α · sinθ + i_β · cosθ

写成矩阵形式:

[ i_d ]   [ cosθ   sinθ ] [ i_α ]
[ i_q ] = [ -sinθ  cosθ ] [ i_β ]

你看,这就是一个旋转坐标变换。θ从哪里来?从编码器或霍尔传感器来。所以Park变换的质量,直接取决于角度测量的精度。

我记得有一次做无传感器FOC,角度估计有5°的误差,结果q轴电流里一直有100Hz的纹波,怎么都滤不掉。后来发现是角度观测器的收敛速度没调好。嗯,这里要注意:角度误差会直接映射到dq电流的纹波上。

3.4 逆变换:从旋转回到静止,从静止回到三相

控制算法算出了想要的Vd和Vq,但最终要加到三相绕组上。所以需要逆变换。

逆Park变换(2r/2s):

V_α = V_d · cosθ - V_q · sinθ
V_β = V_d · sinθ + V_q · cosθ

矩阵形式:

[ V_α ]   [ cosθ  -sinθ ] [ V_d ]
[ V_β ] = [ sinθ   cosθ ] [ V_q ]

逆Clark变换(2s/3s):

等幅值变换下:

[ V_A ]   [ 1      0     ] [ V_α ]
[ V_B ] = [ -1/2   √3/2  ] [ V_β ]
[ V_C ]   [ -1/2  -√3/2  ]

注意,逆Clark变换的系数矩阵,就是Clark变换矩阵的转置(等幅值下)。这个性质很好记。

我曾经踩过的坑:逆Clark变换时,如果三相负载不平衡,零序分量会出来捣乱。这时候需要加一个零序补偿项。我有一版代码忘了加,结果电机在低速时振动特别大。排查了两天才找到原因。所以,如果你的电机有中性点引出,或者三相负载不对称,一定要把零序分量考虑进去。

3.5 坐标变换的完整流程

整个变换链路是这样的:

i_A, i_B, i_C  ——Clark变换——>  i_α, i_β  ——Park变换——>  i_d, i_q
                                                              ↓
                                                          PI控制器
                                                              ↓
V_d, V_q        ——逆Park变换——>  V_α, V_β  ——逆Clark变换——>  V_A, V_B, V_C
                                                              ↓
                                                          SVPWM调制

这个链路,就是FOC(磁场定向控制)的核心骨架。你把它吃透了,电机控制就算入门了。

关键点总结:

  • Clark变换:三相变两相,交流变交流
  • Park变换:静止变旋转,交流变直流
  • 逆Park变换:旋转变静止,直流变交流
  • 逆Clark变换:两相变三相,交流变交流
  • 所有变换的前提:磁动势等效

3.6 坐标系变换的SVG流程图

下面这张图,把整个坐标变换的脉络画清楚了。你可以对照着看,每一步的输入输出是什么。

坐标变换完整流程图 坐标变换完整流程 三相静止 ABC Clark 两相静止 αβ Park 两相旋转 dq PI 控制器 逆Park变换 逆Park 逆Clark变换 逆Clark 三相电压输出 SVPWM调制 θ 来自编码器/观测器 角度θ

3.7 工程实现中的几个要点

代码实现时,有几个细节我建议你注意:

要点 说明 我的建议
角度精度 Park变换依赖角度θ,误差会直接映射到dq电流 使用Q格式定点数,至少保留12位小数精度
三角函数计算 sin/cos计算耗时,尤其在没有FPU的MCU上 预存查找表(LUT),256点或512点足够
变换系数 等幅值 vs 等功率,系数不同 统一用一种,我推荐等幅值
零序分量 三相不平衡时需要考虑 加零序补偿,或硬件上保证三相平衡
溢出处理 定点数乘法可能溢出 用32位中间变量,最后截断到16位

代码片段参考:下面是一个C语言实现的Clark+Park变换,我用在STM32F103上跑过,单次变换大约2μs。

// 等幅值Clark变换
void clark_transform(float i_a, float i_b, float i_c, 
                     float *i_alpha, float *i_beta) {
    *i_alpha = i_a;
    *i_beta  = (i_b - i_c) * 0.57735f;  // 1/√3
}

// Park变换
void park_transform(float i_alpha, float i_beta, float theta,
                    float *i_d, float *i_q) {
    float sin_t = sinf(theta);
    float cos_t = cosf(theta);
    *i_d = i_alpha * cos_t + i_beta * sin_t;
    *i_q = -i_alpha * sin_t + i_beta * cos_t;
}

// 逆Park变换
void inv_park_transform(float v_d, float v_q, float theta,
                        float *v_alpha, float *v_beta) {
    float sin_t = sinf(theta);
    float cos_t = cosf(theta);
    *v_alpha = v_d * cos_t - v_q * sin_t;
    *v_beta  = v_d * sin_t + v_q * cos_t;
}

// 逆Clark变换(等幅值)
void inv_clark_transform(float v_alpha, float v_beta,
                         float *v_a, float *v_b, float *v_c) {
    *v_a = v_alpha;
    *v_b = -0.5f * v_alpha + 0.86603f * v_beta;  // √3/2
    *v_c = -0.5f * v_alpha - 0.86603f * v_beta;
}

这段代码看起来简单,但每个细节都值得推敲。比如那个0.57735f,就是1/√3的近似值。如果你用定点数,可以换成Q15格式的0x49E6。

好了,坐标变换就讲到这里。你把它吃透了,后面的SVPWM调制就水到渠成了。