4. 实现Clark变换
任务目标
本案例实现BLDC FOC控制中的Clark变换,将霍尔传感器或采样电阻测得的三相电流 \(I_a, I_b, I_c\) 转换为两相静止坐标系下的 \(I_\alpha, I_\beta\),并通过给定输入验证变换结果的正确性。
变换原理与公式
Clark变换采用等幅值约束(非等功率),变换矩阵为:
\[ \begin{bmatrix} I_\alpha \\ I_\beta \end{bmatrix} = \frac{2}{3} \begin{bmatrix} 1 & -\frac{1}{2} & -\frac{1}{2} \\ 0 & \frac{\sqrt{3}}{2} & -\frac{\sqrt{3}}{2} \end{bmatrix} \begin{bmatrix} I_a \\ I_b \\ I_c \end{bmatrix} \]
对于无中线连接的电机绕组,满足 \(I_a + I_b + I_c = 0\),因此实际工程中常省略 \(I_c\) 采样,利用 \(I_c = -I_a - I_b\) 简化计算。本案例同时给出完整矩阵形式和省略 \(I_c\) 的简化形式,二者在平衡系统下等价。
关键完整代码
#include <stdio.h>
#include <math.h>
#define SQRT3_2 0.8660254037844386f // √3/2
// 完整Clark变换(三电流输入)
void clark_transform_full(float Ia, float Ib, float Ic, float *Ialpha, float *Ibeta) {
*Ialpha = (2.0f/3.0f) * (Ia - 0.5f*Ib - 0.5f*Ic);
*Ibeta = (2.0f/3.0f) * (SQRT3_2*Ib - SQRT3_2*Ic);
}
// 简化Clark变换(利用Ia+Ib+Ic=0,省略Ic采样)
void clark_transform_simple(float Ia, float Ib, float *Ialpha, float *Ibeta) {
float Ic = -Ia - Ib;
*Ialpha = Ia; // 代入Ic后化简结果
*Ibeta = (1.0f/SQRT3_2) * (Ia + 2.0f*Ib) * 0.5f; // 等价于(Ia+2Ib)/√3
// 更直观写法:*Ibeta = (Ia + 2.0f*Ib) / 1.7320508f;
}
int main() {
// 测试用例:三相平衡电流,幅值2A,相位30°
float Ia = 2.0f * cosf(30.0f * M_PI / 180.0f); // ≈1.732
float Ib = 2.0f * cosf(150.0f * M_PI / 180.0f); // ≈-1.732
float Ic = 2.0f * cosf(270.0f * M_PI / 180.0f); // ≈0.0
float a1, b1, a2, b2;
clark_transform_full(Ia, Ib, Ic, &a1, &b1);
clark_transform_simple(Ia, Ib, &a2, &b2);
printf("输入: Ia=%.4f, Ib=%.4f, Ic=%.4f\n", Ia, Ib, Ic);
printf("完整变换: Iα=%.4f, Iβ=%.4f\n", a1, b1);
printf("简化变换: Iα=%.4f, Iβ=%.4f\n", a2, b2);
// 验证:等幅值变换下,|Iαβ|应等于原电流幅值2A
float magnitude = sqrtf(a1*a1 + b1*b1);
printf("合成矢量幅值: %.4f (期望2.0)\n", magnitude);
// 验证简化与完整结果一致
float diff_a = fabsf(a1 - a2);
float diff_b = fabsf(b1 - b2);
printf("简化与完整差异: Δα=%.6f, Δβ=%.6f\n", diff_a, diff_b);
return 0;
}
编译与运行
gcc -o clark_test clark_test.c -lm
./clark_test
验证方法与判定标准
运行程序后,观察以下三点判定变换是否正确:
- 幅值保持:合成矢量 \(\sqrt{I_\alpha^2 + I_\beta^2}\) 应等于原三相电流幅值(本例为2.0A),误差小于1e-4;
- 相位正确:\(I_\alpha = 1.732\),\(I_\beta = 1.0\)(即幅值2A、相位30°对应的αβ分量),与理论计算一致;
- 两种形式等价:完整变换与简化变换的输出差异应小于1e-5,证明在平衡系统下省略 \(I_c\) 采样是可行的。
预期输出
输入: Ia=1.7321, Ib=-1.7321, Ic=0.0000
完整变换: Iα=1.7321, Iβ=1.0000
简化变换: Iα=1.7321, Iβ=1.0000
合成矢量幅值: 2.0000 (期望2.0)
简化与完整差异: Δα=0.000000, Δβ=0.000000
常见问题
- 若用于STM32等定点MCU:将float改为q15格式,并将 \(\sqrt{3}/2\) 预先计算为定点常量,避免运行时浮点开销;
- 电流采样方向:确保 \(I_a, I_b\) 的符号与电机绕组方向一致,否则变换后矢量相位会偏移180°;
- 非平衡系统:若三相电流不满足 \(I_a+I_b+I_c=0\)(如存在共模电流),必须使用完整变换并单独采样 \(I_c\)。