2. 电机模型与坐标变换:Clark变换、Park变换、逆变换的数学推导与物理意义
做无传感器FOC,绕不开坐标变换。
说实话,我刚入行那会儿,看着Clark和Park这两个名字,心里直打鼓。觉得这就是一堆数学公式,跟实际电机控制八竿子打不着。后来被现实狠狠教育了一顿——有一次调试一个风机项目,电流波形乱七八糟,怎么调PI参数都没用。折腾了两天,最后发现是Clark变换的系数用错了。
嗯,从那以后,我再也不敢小看这些变换了。
2.1 为什么需要坐标变换?
你想想看,三相电机里,电流是随时间变化的正弦波。三个绕组,ABC三相,互相差120度。你要控制这么一个交流系统,直接上PID?不是不行,但效果很差。因为参考值本身就是变化的,你追都追不上。
坐标变换的核心思想,说白了就是:把交流量变成直流量。
Clark变换把三相静止坐标系(ABC)变成两相静止坐标系(αβ)。Park变换再把αβ坐标系旋转起来,变成两相旋转坐标系(dq)。在dq坐标系下,电流就是直流分量了。这时候你用PI控制器,稳得很。
核心逻辑:
三相交流 → 两相交流(Clark) → 两相直流(Park)
控制直流,比控制交流容易太多。
2.2 Clark变换(三相→两相静止)
Clark变换的物理意义很直观:把三个互相依赖的变量,变成两个独立的变量。
三相电流满足 iA + iB + iC = 0,所以实际上只有两个自由度。Clark变换就是把这个冗余的三维系统,投影到一个二维平面上。
2.2.1 等幅值变换
我个人习惯用等幅值变换。为什么?因为变换后的αβ电流幅值,跟原来三相电流的幅值一样。调试的时候看着舒服。
数学表达式:
iα = iA
iβ = (iA + 2*iB) / √3
写成矩阵形式:
[ iα ] [ 1 -1/2 -1/2 ] [ iA ]
[ iβ ] = [ 0 √3/2 -√3/2 ] [ iB ]
[ iC ]
我的经验: 实际代码里,我一般先算 iα = iA,再算 iβ = (iA + 2*iB) / 1.732。注意1.732是√3的近似值。如果你用浮点运算,直接除就行。如果是定点MCU,建议预先算好系数。
2.2.2 等功率变换
还有一种叫等功率变换。它多了一个系数 √(2/3)。
[ iα ] [ √(2/3) -1/√6 -1/√6 ] [ iA ]
[ iβ ] = [ 0 1/√2 -1/√2 ] [ iB ]
[ iC ]
等功率变换的好处是:变换前后功率不变。但幅值变了。我个人不太喜欢,因为调试时幅值对不上,心里不踏实。不过在一些高精度场合,等功率变换是必须的。
注意: 两种变换的逆变换系数不同。千万别混用。我曾经见过一个项目,Clark用等幅值,逆Clark用等功率,结果电流波形直接炸了。
2.3 Park变换(两相静止→两相旋转)
Park变换才是FOC的精髓。
它的物理意义:把坐标系转起来,让交流变直流。
你想想看,αβ坐标系是静止的,电机转子在转,所以αβ电流是正弦波。但如果你把坐标系跟着转子一起转,那电流看起来就是静止的。
数学表达式:
id = iα * cos(θ) + iβ * sin(θ)
iq = -iα * sin(θ) + iβ * cos(θ)
其中θ是转子电角度。
关键理解:
- id(直轴电流): 产生磁场的电流。控制id就是控制磁通。
- iq(交轴电流): 产生转矩的电流。控制iq就是控制力矩。
在表贴式永磁同步电机(SPMSM)中,我们通常让id=0,只控制iq。这样效率最高。
2.4 逆变换
控制完了,得把dq电压变回去,才能给SVPWM用。
2.4.1 逆Park变换
iα = id * cos(θ) - iq * sin(θ)
iβ = id * sin(θ) + iq * cos(θ)
其实就是Park变换的逆运算。把矩阵转置一下就行。
2.4.2 逆Clark变换
等幅值逆Clark:
iA = iα
iB = -iα/2 + iβ * √3/2
iC = -iα/2 - iβ * √3/2
等功率逆Clark:
iA = √(2/3) * iα
iB = -iα/√6 + iβ/√2
iC = -iα/√6 - iβ/√2
避坑指南: 我曾经在逆Clark变换里把iB和iC的符号搞反了。结果电机转起来嗡嗡响,电流波形像锯齿。查了两天,最后发现是公式抄错了。所以建议你每次写完变换代码,先用Matlab或者Python验证一下。
2.5 代码实现示例(C语言)
下面是我常用的代码片段。以等幅值变换为例:
// 结构体定义
typedef struct {
float alpha;
float beta;
} Clarke_t;
typedef struct {
float d;
float q;
} Park_t;
// Clark变换
Clarke_t Clark_Transform(float ia, float ib, float ic) {
Clarke_t out;
out.alpha = ia;
out.beta = (ia + 2.0f * ib) / 1.7320508f; // 1/√3
return out;
}
// Park变换
Park_t Park_Transform(float alpha, float beta, float theta) {
Park_t out;
float sin_theta = sinf(theta);
float cos_theta = cosf(theta);
out.d = alpha * cos_theta + beta * sin_theta;
out.q = -alpha * sin_theta + beta * cos_theta;
return out;
}
// 逆Park变换
Clarke_t Inv_Park_Transform(float d, float q, float theta) {
Clarke_t out;
float sin_theta = sinf(theta);
float cos_theta = cosf(theta);
out.alpha = d * cos_theta - q * sin_theta;
out.beta = d * sin_theta + q * cos_theta;
return out;
}
// 逆Clark变换(等幅值)
void Inv_Clarke_Transform(float alpha, float beta, float *ia, float *ib, float *ic) {
*ia = alpha;
*ib = -0.5f * alpha + 0.8660254f * beta; // √3/2
*ic = -0.5f * alpha - 0.8660254f * beta;
}
性能提示: 在低端MCU上,sin/cos计算很慢。建议用查表法或者CORDIC算法。我一般用256点的正弦表,精度够用,速度也快。
2.6 物理意义总结
| 变换 | 输入 | 输出 | 物理意义 |
|---|---|---|---|
| Clark | iA, iB, iC | iα, iβ | 三相→两相,去掉冗余 |
| Park | iα, iβ, θ | id, iq | 静止→旋转,交流变直流 |
| 逆Park | Vd, Vq, θ | Vα, Vβ | 旋转→静止,给SVPWM用 |
| 逆Clark | Vα, Vβ | VA, VB, VC | 两相→三相,生成PWM |
嗯,到这里,坐标变换的核心内容就讲完了。你可能会问:这些公式看起来简单,为什么实际做起来总出问题?
原因往往不在公式本身,而在细节:
- 角度θ的获取: 无传感器FOC里,θ是估算出来的,有误差。这个误差会直接影响Park变换的效果。
- 采样时序: 电流采样和角度采样必须同步。差一个PWM周期,结果就完全不对了。
- 数值精度: 定点MCU上,注意溢出和精度损失。我习惯把所有量归一化到Q15或者Q24格式。
这些坑,后面章节会一个一个填。今天先把变换本身吃透,后面就好办了。