坐标变换理论:Clark变换、Park变换与反变换
坐标变换,说白了就是换个角度看问题。
你想想看,电机里三相绕组通的是交流电,产生的磁场在空间里转。可我们做控制,最习惯的是处理直流信号——给多大电流,出多大转矩,简单直接。那能不能把交流电机控制得像直流电机一样爽?
能。靠的就是坐标变换。
这套理论不是我发明的,但我在项目里用了不下几十次。每次调试新板子,第一步就是验证坐标变换算得对不对。这一步错了,后面全是白搭。
为什么需要坐标变换?
三相电机有三相绕组,A、B、C。它们空间上差120°,电流时间上也差120°。你盯着三相电流看,三个正弦波,相位不同,幅值相同。想靠这三个量直接做转矩控制?麻烦。
但如果我们换个坐标系:
- αβ坐标系:把三相投影到两相正交轴上,静止不动。
- dq坐标系:让坐标系跟着转子转,这样交流量就变成了直流量。
这样一来,控制就变成了:调d轴电流(励磁分量),调q轴电流(转矩分量)。跟直流电机一模一样。
核心思想:坐标变换不改变物理本质,只改变数学描述。电机还是那个电机,但控制难度降了一个数量级。
Clark变换(3s/2s)
Clark变换,就是把三相静止坐标系(A、B、C)变换到两相静止坐标系(α、β)。
公式很简单:
iα = iA
iβ = (iA + 2*iB) / √3
等等,这里有个细节。上面这个是等幅值变换,我项目里最常用的。还有一种叫等功率变换,系数不一样。
| 变换类型 | α轴系数 | β轴系数 | 适用场景 |
|---|---|---|---|
| 等幅值变换 | 1 | 1/√3 | 电流环控制(我最常用) |
| 等功率变换 | √(2/3) | √(2/3) | 功率计算、效率分析 |
我的习惯:做电流环控制时用等幅值变换,因为电流限幅直观。做系统仿真或效率标定时用等功率变换。别混用,否则算出来的功率对不上。
Clark变换的物理意义是什么?就是把三相绕组的合成磁动势,等效成两相正交绕组产生的磁动势。说白了,三个线圈干的事,两个线圈也能干,只要电流算对了。
Park变换(2s/2r)
Clark变换完了,我们有了αβ坐标系下的电流。但αβ还是静止的,电流仍然是交流量。要把它变成直流量,就得让坐标系转起来。
Park变换,就是把两相静止坐标系(α、β)变换到两相旋转坐标系(d、q)。
公式:
id = iα * cosθ + iβ * sinθ
iq = -iα * sinθ + iβ * cosθ
这里的θ,就是转子位置角。一般来自编码器或霍尔传感器。
我在项目里踩过一个坑:角度对齐问题。编码器安装时有个零位偏移,如果这个偏移没校准,Park变换出来的dq电流就是错的。电机能转,但效率低、噪音大、还容易抖。
注意:Park变换依赖准确的角度信息。角度误差1°,转矩控制精度就下降约1.7%。角度误差超过30°,电机基本没法正常控制。
Park变换之后,id和iq就是直流量了。id控制励磁,iq控制转矩。你给一个阶跃指令,电流环就能稳稳地跟上去。这就是矢量控制的精髓。
反Park变换与反Clark变换
控制算法算出来的是dq坐标系下的电压指令。但最终要加到电机上的,是三相电压。所以得把dq变回去。
反Park变换(2r/2s):
uα = ud * cosθ - uq * sinθ
uβ = ud * sinθ + uq * cosθ
反Clark变换(2s/3s):
uA = uα
uB = -0.5 * uα + (√3/2) * uβ
uC = -0.5 * uα - (√3/2) * uβ
你看,反变换就是正变换的逆过程。数学上是对称的,实现起来也简单。
但有个细节:反Clark变换出来的三相电压,是相对于中性点的相电压。如果你用的是三相全桥驱动,还需要转换成线电压或者直接给SVPWM模块用。这个后面章节会细讲。
完整变换流程
整个坐标变换的链路是这样的:
这个流程,每个PWM周期跑一次。我一般放在ADC采样完成中断里,先读电流,然后做变换,再跑控制算法,最后反变换输出。整个链路要在几十微秒内完成。
代码实现要点
实际写代码时,我建议把坐标变换封装成独立的函数。这样调试方便,也容易移植。
// Clark变换(等幅值)
void clark_transform(float iA, float iB, float iC, float *iAlpha, float *iBeta) {
*iAlpha = iA;
*iBeta = (iA + 2.0f * iB) * 0.577350269f; // 1/√3
}
// Park变换
void park_transform(float iAlpha, float iBeta, float theta, float *id, float *iq) {
float cos_t = cosf(theta);
float sin_t = sinf(theta);
*id = iAlpha * cos_t + iBeta * sin_t;
*iq = -iAlpha * sin_t + iBeta * cos_t;
}
// 反Park变换
void inv_park_transform(float ud, float uq, float theta, float *uAlpha, float *uBeta) {
float cos_t = cosf(theta);
float sin_t = sinf(theta);
*uAlpha = ud * cos_t - uq * sin_t;
*uBeta = ud * sin_t + uq * cos_t;
}
// 反Clark变换
void inv_clark_transform(float uAlpha, float uBeta, float *uA, float *uB, float *uC) {
*uA = uAlpha;
*uB = -0.5f * uAlpha + 0.866025404f * uBeta; // √3/2
*uC = -0.5f * uAlpha - 0.866025404f * uBeta;
}
性能优化建议:三角函数用查表法或者CORDIC算法,别直接调math.h里的cosf/sinf,太慢了。我一般用512点或1024点的正弦表,精度够用,速度能快5倍以上。
常见问题与避坑
- 电流采样顺序:三相电流要同时采样,或者至少在一个PWM周期内完成。我用的是双采样模式,在PWM载波顶点和底点各采一次。
- 角度补偿:从采样到变换完成有延迟,角度需要做补偿。我一般根据当前转速估算角度增量,加到采样时刻的角度上。
- 数值精度:定点MCU上做变换,注意溢出。我习惯先把电流缩放到Q12或Q15格式,算完再缩放回来。
我曾经踩过的坑:有一次调试,电机低速时正常,高速时电流波形畸变。查了两天,发现是角度更新频率不够。PWM频率20kHz,但角度计算只做了1kHz。高速时角度跟不上,Park变换出来的dq电流全是纹波。后来把角度计算也放到PWM中断里,问题解决。
坐标变换,说难不难,说简单也不简单。关键是要理解它的物理意义,而不仅仅是背公式。你想想看,三个线圈转成一个线圈,再转成两个直流分量——这套思想,贯穿了整个电机控制领域。
嗯,这一章就到这里。把变换吃透了,后面的SVPWM、电流环、速度环,都会顺很多。