2. 坐标变换理论:Clark变换、Park变换及其逆变换的数学推导与物理意义
好,咱们进入FOC算法里最核心的数学基础——坐标变换。说实话,很多初学者一看到矩阵、三角函数就头大,觉得这东西太抽象。我当年刚接触FOC时也是这个感觉,心想:好好的三相电流,干嘛非要转来转去?
嗯,等你真正理解了物理意义,就会发现这些变换其实非常优雅。它们把复杂的交流电机控制,变成了类似直流电机的控制方式。说白了,就是让控制变得简单、直观。
2.1 为什么要做坐标变换?
先问个问题:三相交流电机里,定子电流是三个正弦波,相位差120度。你想想看,要控制这样一个系统,直接对三相电流做PID调节,能行吗?
理论上可以,但非常麻烦。因为三相电流是耦合的、时变的。你调A相,B相和C相也跟着变。我在做第一个FOC项目时,就试图直接控制三相电流,结果调了整整两周,系统还是抖得厉害。
坐标变换的目的,就是把这三个时变的正弦量,变成两个直流量。一个控制磁通,一个控制转矩。这不就跟直流电机一样了吗?
核心思想: 三相静止坐标系(ABC)→ 两相静止坐标系(αβ)→ 两相旋转坐标系(dq)
最终在dq坐标系下,电流变成了直流量,可以用简单的PI控制器精确控制。
3.2 Clark变换:从ABC到αβ
Clark变换,也叫3s/2s变换。就是把三相静止坐标系,映射到两相静止坐标系。说白了,就是降维。
数学上,我们假设三相电流是平衡的:
i_a + i_b + i_c = 0
那么Clark变换的公式是:
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_0] [ 1/2 1/2 1/2 ] [i_c]
注意这个i_0,它是零序分量。在三相三线制系统里,i_0 = 0,可以忽略。
我的经验: 实际代码实现时,我习惯用等幅值变换,而不是等功率变换。等幅值变换的好处是,变换后的αβ电流幅值跟原来三相电流的幅值一样,调试时直观很多。等功率变换虽然数学上更严谨,但幅值会变,容易搞混。
Clark逆变换呢?就是从αβ回到ABC:
[i_a] [ 1 0 1 ] [i_α]
[i_b] = [ -1/2 √3/2 1 ] [i_β]
[i_c] [ -1/2 -√3/2 1 ] [i_0]
嗯,这里要注意,逆变换矩阵就是正变换矩阵的逆矩阵。如果你用了等幅值变换,逆变换的系数要对应调整。
2.3 Park变换:从αβ到dq
Clark变换之后,我们得到了两个正交的正弦波i_α和i_β。它们还是时变的。怎么办?再转一次,转到跟转子同步旋转的坐标系里。
这就是Park变换,也叫2s/2r变换。
公式很简单:
i_d = i_α * cos(θ) + i_β * sin(θ)
i_q = -i_α * sin(θ) + i_β * cos(θ)
其中θ是转子电角度,也就是转子磁场的位置。
物理意义是什么?
- i_d(直轴电流): 产生磁场的电流分量。控制它,就是控制电机的励磁。
- i_q(交轴电流): 产生转矩的电流分量。控制它,就是控制电机的力矩。
你看,经过Park变换后,i_d和i_q变成了直流量。这时候用PI控制器去控制它们,就非常容易了。
避坑指南: 我曾经在项目里犯过一个低级错误——Park变换的角度θ用错了。当时用的是编码器的机械角度,忘了乘以极对数。结果电机转起来完全失控,嗡嗡响。后来查了整整一天才发现,θ必须是电角度,不是机械角度。切记!
Park逆变换,就是从dq回到αβ:
i_α = i_d * cos(θ) - i_q * sin(θ)
i_β = i_d * sin(θ) + i_q * cos(θ)
这个逆变换在FOC里非常重要。因为控制器输出的是dq电压,但最终要加到电机上的必须是三相电压。所以要先Park逆变换到αβ,再Clark逆变换到ABC。
2.4 完整的变换流程
咱们把整个流程串起来,看看FOC里坐标变换是怎么走的:
- 采样: 采集三相电流i_a、i_b、i_c(通常只采两相,第三相通过平衡条件算出)
- Clark变换: i_a、i_b、i_c → i_α、i_β
- Park变换: i_α、i_β → i_d、i_q(需要转子角度θ)
- PI控制: 对i_d和i_q分别做PI调节,得到V_d、V_q
- Park逆变换: V_d、V_q → V_α、V_β
- Clark逆变换: V_α、V_β → V_a、V_b、V_c
- SVPWM: 根据三相电压生成PWM波,驱动逆变器
你看,整个流程里,坐标变换出现了两次正变换、两次逆变换。每一步都环环相扣。
2.5 代码实现示例
下面是我在实际项目中用过的C代码片段,做了简化,但核心逻辑不变:
// Clark变换:ABC -> αβ
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_a + 2.0f * i_b) * 0.57735f; // 1/√3 ≈ 0.57735
}
// Park变换:αβ -> dq
void park_transform(float i_alpha, float i_beta, float theta,
float *i_d, float *i_q) {
float cos_theta = cosf(theta);
float sin_theta = sinf(theta);
*i_d = i_alpha * cos_theta + i_beta * sin_theta;
*i_q = -i_alpha * sin_theta + i_beta * cos_theta;
}
// Park逆变换:dq -> αβ
void inv_park_transform(float v_d, float v_q, float theta,
float *v_alpha, float *v_beta) {
float cos_theta = cosf(theta);
float sin_theta = sinf(theta);
*v_alpha = v_d * cos_theta - v_q * sin_theta;
*v_beta = v_d * sin_theta + v_q * cos_theta;
}
// Clark逆变换:αβ -> ABC
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 ≈ 0.86603
*v_c = -0.5f * v_alpha - 0.86603f * v_beta;
}
个人建议: 在嵌入式平台上,三角函数计算比较耗时。我一般会建一个查找表,或者用CORDIC算法来算sin/cos。如果MCU有硬件浮点单元,那就直接用math.h里的函数,精度更高。
2.6 物理意义再理解
最后,咱们从物理角度再捋一遍:
| 坐标系 | 物理含义 | 信号特点 |
|---|---|---|
| ABC(三相静止) | 实际的电机三相绕组 | 三个正弦波,相位差120° |
| αβ(两相静止) | 等效的正交两相绕组 | 两个正交的正弦波 |
| dq(两相旋转) | 跟转子同步旋转的坐标系 | 两个直流量 |
说白了,Clark变换是把三个绕组简化成两个正交绕组。Park变换是把这两个静止的正交绕组,投影到旋转的坐标系里。这样,原本旋转的磁场,在dq坐标系下看起来就是静止的。
我记得有一次给团队新人讲这个,他问了一句:「那如果转子不转呢?」
好问题!如果转子不转,θ不变,Park变换就退化成一次固定的旋转。这时候i_d和i_q还是交流量,但频率很低。实际上,FOC在零速时也能输出力矩,靠的就是这个变换。
嗯,坐标变换就讲到这里。下一节咱们聊SVPWM,看看怎么把dq电压变成实实在在的PWM波。