4、Park变换:两相静止到两相旋转坐标系的变换原理与数学推导

好,咱们接着聊。上一节我们把Clark变换讲透了,从三相静止ABC变到了两相静止αβ坐标系。但问题来了——αβ坐标系下的电流还是正弦波,对吧?

正弦波意味着什么?意味着你没法直接用PI控制器去跟踪。PI控制器对直流信号有很好的稳态精度,但对交流信号,尤其是频率变化的交流信号,效果就很差。这就是为什么我们需要Park变换。

4.1 为什么要从静止到旋转?

说白了,Park变换就是把αβ坐标系下的正弦波,变成dq坐标系下的直流量。

你想想看,电机转子在旋转,定子绕组产生的磁场也在旋转。如果我们能把自己的视角「坐」到转子上,跟着它一起转,那看到的电流会是什么样?

对,就是直流!

我个人习惯把Park变换理解为「视角转换」。就像你站在路边看一辆行驶的汽车,车轮上的一个点在做圆周运动;但如果你坐在车里看同一个点,它就是静止的。Park变换做的就是这件事——把观察坐标系从静止的定子,搬到旋转的转子上。

核心思想:Park变换将两相静止坐标系(αβ)下的交流量,变换到两相旋转坐标系(dq)下的直流量,从而可以用简单的PI控制器实现无静差控制。

4.2 数学推导:从几何到公式

好,我们来看数学。假设αβ坐标系下的电流为:

iα = Im * cos(θ)
iβ = Im * sin(θ)

其中θ = ωt + φ0,是电流矢量的空间角度。

现在,我们想要一个旋转坐标系,它的d轴与转子磁极方向对齐,旋转角速度为ωe(电角速度)。设d轴与α轴的夹角为θe = ωe·t。

那么,从αβ到dq的变换,本质上就是一个坐标旋转。我画个图你就明白了:

        β轴
         ↑
         |   / 电流矢量
         |  /
         | /   θ
         |/______→ α轴
         |
        (静止坐标系)

        q轴
         ↑
         |   / 电流矢量
         |  /
         | /   θ-θe
         |/______→ d轴
         |
        (旋转坐标系,d轴与转子对齐)

从几何上看,dq坐标系下的电流分量,就是电流矢量在d轴和q轴上的投影。而d轴与α轴的夹角是θe,所以:

id = iα * cos(θe) + iβ * sin(θe)
iq = -iα * sin(θe) + iβ * cos(θe)

写成矩阵形式就是:

[ id ]   [ cos(θe)  sin(θe) ] [ iα ]
[ iq ] = [ -sin(θe) cos(θe) ] [ iβ ]

这就是Park变换的数学表达式。简单吧?就是一个旋转矩阵。

我的经验:在实际代码中,我建议把cos(θe)和sin(θe)提前算好,不要每次变换都重新计算。因为θe是随时间变化的,但cos和sin的计算开销比较大。我一般会在每个PWM周期开始时,先查表或调用一次三角函数,然后把结果存起来供后续使用。

4.3 逆Park变换:从dq回到αβ

有正变换就有逆变换。在FOC中,电流环的输出是dq坐标系下的电压指令(ud, uq),但最终要加到电机上的必须是三相电压。所以我们需要先把ud, uq变回αβ坐标系,再通过SVPWM生成PWM波。

逆变换的矩阵就是正变换矩阵的转置(因为旋转矩阵是正交矩阵):

[ uα ]   [ cos(θe)  -sin(θe) ] [ ud ]
[ uβ ] = [ sin(θe)   cos(θe) ] [ uq ]

嗯,这里要注意符号。正变换和逆变换的符号刚好相反。我刚开始做的时候经常搞混,后来养成了一个习惯:每次写完变换函数,先用单位矩阵测试一下——输入[1, 0]经过正变换再逆变换,应该回到[1, 0]。

避坑指南:我曾经在一个项目中,因为正逆变换的符号搞反了,导致电机转起来后电流波形全是毛刺,还以为是传感器噪声。查了两天才发现是Park变换的符号问题。所以,写完变换函数一定要做自检!

4.4 代码实现:C语言版

下面是我常用的Park变换实现。注意,我用了浮点运算,但在资源受限的MCU上,你可以考虑用Q格式定点数。

typedef struct {
    float id;   // d轴电流
    float iq;   // q轴电流
} dq_t;

typedef struct {
    float alpha;  // α轴电流
    float beta;   // β轴电流
} ab_t;

// Park变换:αβ -> dq
// theta_el: 电角度(弧度)
dq_t park_transform(ab_t ab, float theta_el) {
    dq_t result;
    float cos_theta = cosf(theta_el);
    float sin_theta = sinf(theta_el);
    
    result.id = ab.alpha * cos_theta + ab.beta * sin_theta;
    result.iq = -ab.alpha * sin_theta + ab.beta * cos_theta;
    
    return result;
}

// 逆Park变换:dq -> αβ
ab_t inv_park_transform(dq_t dq, float theta_el) {
    ab_t result;
    float cos_theta = cosf(theta_el);
    float sin_theta = sinf(theta_el);
    
    result.alpha = dq.id * cos_theta - dq.iq * sin_theta;
    result.beta = dq.id * sin_theta + dq.iq * cos_theta;
    
    return result;
}

性能优化建议:如果你的MCU没有硬件浮点单元(FPU),建议用查表法代替cosf/sinf。我一般用256点的正弦表,精度足够。另外,θe通常由编码器或霍尔传感器提供,记得把机械角度乘以极对数得到电角度。

4.5 物理意义:d轴和q轴分别控制什么?

搞清楚了数学,我们聊聊物理意义。在dq坐标系下:

  • d轴(直轴):与转子磁极方向对齐。d轴电流id主要产生磁通,影响电机的磁场强度。在表贴式永磁同步电机(SPMSM)中,通常控制id=0,因为永磁体已经提供了励磁。
  • q轴(交轴):与d轴垂直。q轴电流iq产生转矩。说白了,你想要的力矩大小,主要靠iq来控制。

这就是为什么FOC的核心是「id=0控制」——让所有电流都用来产生转矩,不浪费在励磁上。当然,在弱磁控制时,我们会故意让id为负值,来削弱永磁磁场,从而让电机跑得更快。

物理含义 控制目标
d轴 励磁分量(产生磁通) 通常控制为0(SPMSM)
q轴 转矩分量(产生力矩) 根据速度环输出调节

4.6 常见问题与调试技巧

最后,分享几个我在项目中踩过的坑:

  1. 电角度对齐问题:Park变换需要知道转子位置。如果编码器安装有偏差,或者初始角度没校准,dq轴就会偏。表现为:id和iq都有交流分量,电机效率低。解决办法是做一次「角度自校准」——给一个固定的d轴电压,看电机转到的位置。
  2. 三角函数计算延迟:如果θe更新不及时,变换出来的dq分量会有误差。我建议在中断服务函数中先更新θe,再调用Park变换,确保角度和电流采样是同步的。
  3. 数值稳定性:在低速时,θe变化慢,问题不大。但在高速时(比如几万转),θe变化很快,要注意浮点运算的精度。我遇到过因为角度累积误差导致dq轴漂移的情况,后来改用双精度浮点解决了。

好了,Park变换就讲到这里。下一节我们会把Clark变换和Park变换串起来,看看完整的坐标变换链路是什么样的。到时候我会给出一个完整的FOC电流环代码框架。