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

验证方法与判定标准

运行程序后,观察以下三点判定变换是否正确:

  1. 幅值保持:合成矢量 \(\sqrt{I_\alpha^2 + I_\beta^2}\) 应等于原三相电流幅值(本例为2.0A),误差小于1e-4;
  2. 相位正确:\(I_\alpha = 1.732\),\(I_\beta = 1.0\)(即幅值2A、相位30°对应的αβ分量),与理论计算一致;
  3. 两种形式等价:完整变换与简化变换的输出差异应小于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\)。