Clark变换与Park变换:坐标变换的数学基础

各位同学,今天我们来聊聊坐标变换。说实话,我刚接触SVPWM那会儿,觉得Clark和Park这两个变换就是一堆数学公式,枯燥得很。直到我在一个电机驱动项目里,死活调不出正弦波电流,最后发现是坐标变换的符号搞反了——嗯,从那以后我再也不敢小看这两步了。

你想想看,电机里跑的是三相交流电,可我们做控制的芯片只能处理两路直流信号。怎么把三相变成两相?怎么把静止的坐标系转到旋转的坐标系?这就是Clark和Park要干的事。

一句话总结:Clark变换把三相静止坐标系(abc)变到两相静止坐标系(αβ);Park变换再把两相静止坐标系(αβ)变到两相旋转坐标系(dq)。

2.1 为什么需要坐标变换?

三相电机有三根线,电流分别是ia、ib、ic。这三路信号是耦合的,而且随时间正弦变化。你让MCU直接去控制三个正弦波?太麻烦了。

我个人的习惯是:先把它们解耦。Clark变换就是干这个的——把三个互相差120°的矢量,投影到两个互相垂直的轴上。这样一来,三个变量变成了两个变量,而且这两个轴是正交的,控制起来方便多了。

但Clark变换后的αβ轴还是静止的,电流依然是正弦波。想要做闭环控制,最好让电流变成直流量。这时候Park变换上场,把αβ坐标系旋转起来,跟电机转子同步旋转。旋转之后,d轴和q轴上的电流就变成了直流。

我的经验:坐标变换的本质就是「换一个角度看问题」。三相看是旋转磁场,两相静止看是正弦波,两相旋转看就是直流。角度不同,控制难度天差地别。

2.2 Clark变换:从abc到αβ

Clark变换也叫3s/2s变换(三相静止到两相静止)。数学上,它把三相电流投影到αβ轴上。

标准公式是这样的:

iα = i_a
iβ = (i_a + 2*i_b) / √3

等等,这个公式看着有点奇怪?其实这是等幅值变换的简化版本。完整的矩阵形式是这样的:

[ iα ]   [ 1      -1/2      -1/2   ] [ i_a ]
[ iβ ] = [ 0      √3/2     -√3/2  ] [ i_b ]
                                   [ i_c ]

注意,这里有个系数问题。我遇到过不少新手在这里栽跟头——等幅值变换和等功率变换的系数不一样。等幅值变换前面乘的是2/3,等功率变换乘的是√(2/3)。

变换类型 系数 特点
等幅值变换 2/3 变换前后电流幅值不变,方便观测
等功率变换 √(2/3) 变换前后功率不变,理论分析常用

避坑指南:我曾经在一个项目里用了等功率变换的系数,但后续的PI参数是按等幅值变换调的,结果电流环怎么都稳不住。后来花了整整两天才找到这个bug。建议你在项目初期就统一好变换类型,并在代码注释里写清楚。

2.3 Park变换:从αβ到dq

Clark变换之后,我们有了iα和iβ。但它们还是正弦波。想要变成直流,就得让坐标系跟着转子转。

Park变换的公式:

i_d = iα * cos(θ) + iβ * sin(θ)
i_q = -iα * sin(θ) + iβ * cos(θ)

这里的θ是转子电角度,由编码器或观测器提供。说白了,就是把αβ轴上的矢量,旋转到与转子磁场对齐的方向上。

d轴对齐转子磁场方向,q轴垂直于d轴。d轴电流控制励磁,q轴电流控制转矩。这就是FOC(磁场定向控制)的核心思想。

关键点:Park变换的输入是αβ轴上的正弦波,输出是dq轴上的直流量。直流量用PI控制器处理,比正弦波容易得多。这就是为什么FOC能实现高精度的转矩控制。

2.4 坐标变换的完整流程

在实际的SVPWM实现中,坐标变换的流程是这样的:

  1. ADC采样得到三相电流ia、ib、ic
  2. Clark变换得到iα、iβ
  3. Park变换得到id、iq
  4. PI控制器处理id、iq,得到Vd、Vq
  5. 反Park变换得到Vα、Vβ
  6. SVPWM根据Vα、Vβ计算占空比

你看,Clark和Park各出现一次,正变换和反变换各一次。这个流程在电机控制里是标配,我做了这么多年项目,几乎每个FOC代码里都是这个结构。

下面这张图展示了整个坐标变换的脉络:

坐标变换流程框架图 三相静止 i_a, i_b, i_c Clark 两相静止 i_α, i_β Park 两相旋转 i_d, i_q PI控制 V_d, V_q 反Park V_α, V_β SVPWM 占空比输出 关键说明 • 正变换:abc→αβ→dq • 反变换:dq→αβ→SVPWM • θ由编码器/观测器提供 • 变换系数需统一 • 符号决定旋转方向

2.5 代码实现要点

在实际的嵌入式代码里,Clark和Park变换通常写成函数。我习惯用浮点运算,但如果你用的是低成本MCU,可以考虑定点化。

下面是一个简单的C语言实现:

// Clark变换:abc -> αβ
void clark_transform(float i_a, float i_b, float i_c, 
                     float *i_alpha, float *i_beta) {
    // 等幅值变换,系数2/3
    *i_alpha = (2.0f/3.0f) * (i_a - 0.5f * i_b - 0.5f * i_c);
    *i_beta  = (2.0f/3.0f) * (0.866025f * i_b - 0.866025f * i_c);
}

// Park变换:αβ -> dq
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;
}

我的建议:sin和cos计算比较耗时,如果MCU没有硬件三角函数单元,建议用查表法或者CORDIC算法。我在一个STM32F103的项目里,用256点的正弦表,精度完全够用。

2.6 常见问题与避坑

  • 符号搞反:Park变换里i_q的公式有个负号,很多人漏掉。我吃过这个亏,电机转起来嗡嗡响,电流波形乱七八糟。
  • 角度对齐:θ必须是电角度,不是机械角度。极对数要乘上去。
  • 系数不一致:正变换和反变换的系数要匹配。等幅值变换的反变换系数是1,等功率变换的反变换系数是√(2/3)。
  • 浮点精度:低端MCU用float就够了,double反而慢。如果要做定点化,注意Q格式的选择。

我曾经踩过的坑:有一次我把Clark变换的系数写成了1/3而不是2/3,结果电流环的增益全偏了。调试了三天,最后用示波器对比αβ轴的波形才发现幅值不对。从那以后,我每次写完坐标变换,都会先用Matlab或者Python验证一下波形。