2. 矢量控制原理:Clark变换、Park变换、逆变换的数学推导与代码实现
好,咱们直接进入正题。矢量控制,说白了就是要把电机里那些乱七八糟的电流,变成我们能轻松控制的直流分量。你想想看,电机里转的是三相交流电,又耦合又旋转,怎么控?
所以,数学家们想了个办法——坐标变换。把三相静止坐标系下的东西,先变到两相静止坐标系,再变到两相旋转坐标系。这样,交流量就变成了直流量,PID就能上去干了。
我个人习惯把这三步记成:Clark(克拉克)把三相变两相静止,Park(帕克)把两相静止变两相旋转。逆变换就是反过来走一遍。
2.1 Clark变换:从abc到αβ
Clark变换,也叫3s/2s变换。就是把三相静止的abc坐标系,映射到两相静止的αβ坐标系。
为什么要这么干?因为三相系统有冗余。你想想看,ia + ib + ic = 0,实际上只有两个自由度。去掉一个,计算量直接减三分之一。
数学上,Clark变换的公式长这样:
iα = ia
iβ = (ia + 2*ib) / √3
等等,有人会问:为什么不是iα = ia - 0.5*ib - 0.5*ic?
嗯,这里要注意。上面那个是等幅值变换的简化版,前提是三相平衡且中性点不接地。我当年刚入行时,在这个地方栽过跟头——直接用等功率变换的系数,结果算出来的转矩老是对不上。
关键点:等幅值变换 vs 等功率变换,系数差一个√(2/3)。做电流环用等幅值,做功率计算用等功率。别混用。
完整的等幅值Clark变换矩阵:
[iα] [ 1, -1/2, -1/2 ] [ia]
[iβ] = [ 0, √3/2, -√3/2 ] [ib]
[ic]
代码实现其实很简单,我一般这么写:
void clark_transform(float ia, float ib, float ic,
float *i_alpha, float *i_beta) {
// 等幅值变换,三相平衡时ic = -ia - ib
*i_alpha = ia;
*i_beta = (ia + 2.0f * ib) * 0.577350269f; // 1/√3
}
我在项目中遇到过一个问题:电流采样有偏置,导致Clark变换后αβ轴出现直流分量。后来加了高通滤波才解决。这个坑,你们做产品时大概率也会碰到。
2.2 Park变换:从αβ到dq
Clark变换完了,电流还是正弦波。要把它变成直流量,就得用Park变换。
Park变换的核心思想:让坐标系跟着转子转。转子转多快,坐标系就转多快。这样,原本旋转的电流矢量,在新的坐标系下就静止了。
公式很简单:
id = iα * cos(θ) + iβ * sin(θ)
iq = -iα * sin(θ) + iβ * cos(θ)
这里的θ是转子电角度,一般从编码器或者霍尔传感器读出来。
代码实现:
void park_transform(float i_alpha, float i_beta, float theta,
float *i_d, float *i_q) {
float sin_theta = sinf(theta);
float cos_theta = cosf(theta);
*i_d = i_alpha * cos_theta + i_beta * sin_theta;
*i_q = -i_alpha * sin_theta + i_beta * cos_theta;
}
小技巧:θ的计算要用浮点,但sin/cos计算很费时间。我建议用查表法或者CORDIC算法。在Cortex-M4上,用硬件FPU直接算sin也还行,但别在中断里频繁调用。
为什么id叫励磁电流,iq叫转矩电流?
因为id产生的磁场方向和转子磁场方向一致,只影响磁通;iq产生的磁场和转子磁场垂直,直接产生转矩。你想想看,这不就跟直流电机一模一样了吗?
2.3 逆Park变换:从dq回到αβ
电流环算出了想要的Vd和Vq,但SVPWM需要的是αβ坐标系下的电压。所以得逆变换回去。
逆Park变换就是Park变换的逆过程,把矩阵转置一下就行:
Vα = Vd * cos(θ) - Vq * sin(θ)
Vβ = Vd * sin(θ) + Vq * cos(θ)
代码:
void inv_park_transform(float v_d, float v_q, float theta,
float *v_alpha, float *v_beta) {
float sin_theta = sinf(theta);
float cos_theta = cosf(theta);
*v_alpha = v_d * cos_theta - v_q * sin_theta;
*v_beta = v_d * sin_theta + v_q * cos_theta;
}
警告:θ必须和Park变换时用的是同一个值!我曾经在调试时,因为角度更新不同步,导致电流波形畸变,电机嗡嗡响。查了两天才发现是角度差了半个周期。
2.4 逆Clark变换:从αβ回到abc
最后一步,把αβ电压变回三相电压,送给SVPWM模块。
逆Clark变换公式:
Va = Vα
Vb = (-Vα + √3 * Vβ) / 2
Vc = (-Vα - √3 * Vβ) / 2
代码:
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.8660254f * v_beta; // √3/2
*v_c = -0.5f * v_alpha - 0.8660254f * v_beta;
}
2.5 完整变换流程与避坑指南
整个矢量控制的变换链路是这样的:
- 采样:读三相电流ia, ib, ic
- Clark变换:ia, ib, ic → iα, iβ
- Park变换:iα, iβ, θ → id, iq
- 电流环PI控制:id_ref, iq_ref → Vd, Vq
- 逆Park变换:Vd, Vq, θ → Vα, Vβ
- 逆Clark变换:Vα, Vβ → Va, Vb, Vc
- SVPWM:生成PWM占空比
这个流程,每个控制周期跑一次。我一般用10kHz到20kHz的开关频率,也就是50μs到100μs跑完一圈。
避坑指南:
- 我曾经把Clark和Park的顺序搞反了,结果电流环根本稳不住。记住:先Clark后Park,先逆Park后逆Clark。
- 角度θ的单位是弧度,不是度。我见过有人传了角度值进去,结果变换出来的东西全是错的。
- 浮点运算注意精度。在定点DSP上,建议用Q格式。在带FPU的MCU上,直接用float就行。
最后说一句,这些变换公式看着简单,但真正用好需要理解背后的物理意义。别死记硬背,多画几个矢量图,多跑几次仿真,慢慢就熟了。
下一章,咱们聊聊SVPWM是怎么把Vα、Vβ变成六路PWM波的。那个更有意思。