4. Park变换:两相静止坐标系到两相旋转坐标系

上一章我们聊了Clark变换,把三相ABC变成了两相静止的αβ坐标系。但问题来了——αβ坐标系里的电流还是正弦波,控制器追着正弦波跑,永远有静差。怎么办?

Park变换就是来解决这个问题的。它把αβ坐标系再转一次,转到跟转子磁场同步旋转的dq坐标系里。转完之后,正弦波变成了直流分量。PID控制器看到直流信号,那叫一个舒服,静差直接归零。

我个人习惯把Park变换理解为“站在转子上看电流”。你站在地面看风扇叶片,它在转;你坐在叶片上看,它就是静止的。Park变换就是这个道理。

4.1 从静止到旋转:物理直觉

先建立直觉。αβ坐标系是静止的,α轴和β轴固定在定子上。dq坐标系是旋转的,d轴始终对准转子磁极方向,q轴超前d轴90°电角度。

为什么要对准转子?因为力矩的产生只跟q轴电流有关,磁链只跟d轴电流有关。把这两个解耦开,控制就变成了:

  • d轴电流:控制磁链(弱磁、增磁)
  • q轴电流:控制力矩(要快就大,要慢就小)

我在做第一个FOC项目时,没理解这个解耦的意义。结果力矩和磁链互相干扰,电机嗡嗡响,电流波形像锯齿。后来把Park变换的角度算准了,一切才正常。

4.2 Park变换公式推导

推导其实不复杂。我们从αβ坐标系出发,旋转一个角度θ,就到了dq坐标系。

设αβ坐标系下的电流为Iα和Iβ,旋转角度为θ(转子电角度)。那么dq坐标系下的电流Id和Iq为:

Park变换公式(正变换):

Id = Iα × cos(θ) + Iβ × sin(θ)
Iq = -Iα × sin(θ) + Iβ × cos(θ)

写成矩阵形式更清晰:

| Id |   |  cos(θ)  sin(θ) | | Iα |
|    | = |                  | |    |
| Iq |   | -sin(θ)  cos(θ) | | Iβ |

这个矩阵就是旋转矩阵。你想想看,它本质上就是把αβ坐标系逆时针旋转了θ角。

反过来,从dq回到αβ就是逆Park变换:

逆Park变换公式:

Iα = Id × cos(θ) - Iq × sin(θ)
Iβ = Id × sin(θ) + Iq × cos(θ)

矩阵形式:

| Iα |   |  cos(θ)  -sin(θ) | | Id |
|    | = |                   | |    |
| Iβ |   |  sin(θ)   cos(θ) | | Iq |

嗯,这里要注意:正变换和逆变换的矩阵是互为转置的,因为旋转矩阵是正交矩阵。这个性质在代码实现时可以用来做优化。

4.3 角度θ从哪来?

公式里的θ是转子电角度。怎么得到它?

传感器类型 获取方式 注意事项
霍尔传感器 查表得到粗略角度 分辨率低,需要插值
编码器(增量式) 脉冲计数 + 初始位置校准 上电需要找零位
编码器(绝对式) 直接读取角度值 精度高,成本也高
无传感器(观测器) 反电动势估算 低速时估算不准

我曾经在一个项目里用过增量式编码器,上电时没做零位校准,结果电机直接飞车。从那以后,我每次上电都会强制做一次角度对齐。

4.4 Park变换的代码实现

直接上代码。这是C语言的实现,适合嵌入式环境:

/**
 * @brief Park变换:αβ -> dq
 * @param Ialpha α轴电流
 * @param Ibeta  β轴电流
 * @param theta  转子电角度(弧度)
 * @param Id     d轴电流(输出)
 * @param Iq     q轴电流(输出)
 */
void Park_Transform(float Ialpha, float Ibeta, float theta,
                    float *Id, float *Iq)
{
    float sin_theta = sinf(theta);
    float cos_theta = cosf(theta);

    *Id = Ialpha * cos_theta + Ibeta * sin_theta;
    *Iq = -Ialpha * sin_theta + Ibeta * cos_theta;
}

/**
 * @brief 逆Park变换:dq -> αβ
 * @param Id     d轴电流
 * @param Iq     q轴电流
 * @param theta  转子电角度(弧度)
 * @param Ialpha α轴电流(输出)
 * @param Ibeta  β轴电流(输出)
 */
void InvPark_Transform(float Id, float Iq, float theta,
                       float *Ialpha, float *Ibeta)
{
    float sin_theta = sinf(theta);
    float cos_theta = cosf(theta);

    *Ialpha = Id * cos_theta - Iq * sin_theta;
    *Ibeta = Id * sin_theta + Iq * cos_theta;
}

性能优化建议:

  • 如果MCU没有硬件浮点单元(FPU),用查表法代替sinf/cosf
  • 查表精度:1024点/360°足够大多数应用
  • 角度归一化到[0, 2π)区间,避免角度累积误差

4.5 避坑指南:我踩过的三个坑

做Park变换看起来简单,但实际项目中容易出问题。我分享几个亲身经历:

  1. 角度符号搞反

    我曾经把正变换和逆变换的符号弄反了,结果电流环震荡,电机发热严重。检查了三天才发现是符号问题。记住:正变换是Id = Iα*cos + Iβ*sin,Iq = -Iα*sin + Iβ*cos。负号在Iq的Iα项上。

  2. 电角度 vs 机械角度

    θ是电角度,不是机械角度。对于4对极电机,电角度 = 机械角度 × 4。我见过有人直接用编码器的机械角度做Park变换,结果电流波形完全不对。

  3. 角度更新不及时

    Park变换的角度必须在每个PWM周期更新。如果角度滞后,dq轴会耦合,力矩控制就不准。我习惯在PWM中断里先更新角度,再做Park变换。

重要提醒:Park变换的精度直接决定FOC的控制质量。角度误差1°,力矩误差约1.7%。角度误差10°,力矩误差约17%。所以角度估算一定要准。

4.6 Park变换在FOC中的位置

为了让你更清楚Park变换在整个FOC流程中的位置,我画了一张图:

Park变换在FOC中的位置 FOC控制流程:Park变换的位置 三相电流采样 Clark变换 Park变换 αβ → dq PI控制器 Id_ref / Iq_ref 逆Park变换 dq → αβ SVPWM 电机 角度θ反馈

从图中可以看到,Park变换位于Clark变换之后、PI控制器之前。它的输入是αβ电流和转子角度θ,输出是dq电流。PI控制器在dq坐标系下工作,输出dq电压,再经过逆Park变换回到αβ坐标系,最后给SVPWM生成驱动信号。

这个流程我调试过无数次。最让我头疼的一次是角度反馈线断了,结果Park变换的角度一直是0,电机完全失控。所以我现在做项目,第一件事就是确认角度反馈是否正常。

4.7 小结

Park变换的核心就一句话:把静止的正弦波变成旋转的直流信号。公式不复杂,但角度精度和符号方向是命门。

做FOC控制,Park变换是绕不开的一步。理解了它,你就掌握了FOC的“旋转视角”。后面我们再聊PI控制器怎么调,那才是真正出效果的地方。