4、SVPWM算法(上):空间矢量概念、扇区判断、基本矢量作用时间计算
各位同学,咱们今天来啃SVPWM这块硬骨头。
说实话,我刚入行那会儿,看到SVPWM的矢量图就头大。什么αβ坐标系、什么扇区判断,感觉像在看天书。后来在项目里被逼着调了好几次电机,才慢慢摸到门道。今天我把这些经验掰开了揉碎了讲给你听。
4.1 空间矢量的概念
先问个问题:为什么叫“空间矢量”?
你想想看,三相逆变器输出的是三个相电压——Ua、Ub、Uc。这三个电压在时间上是正弦波,但在空间上,它们其实可以合成一个旋转的矢量。这个矢量,就是空间电压矢量。
我习惯用一个比喻来理解:
- 三相电压就像三个壮汉,分别朝三个方向拉绳子
- 他们拉的方向相差120度
- 合力就是一个旋转的矢量
数学上,我们用Clark变换把三相电压映射到αβ坐标系:
Uα = Ua - 0.5*Ub - 0.5*Uc
Uβ = (√3/2)*(Ub - Uc)
这个(Uα, Uβ)就是空间电压矢量。它的幅值代表电压大小,角度代表方向。
关键点:SVPWM的本质,就是用八个基本电压矢量(六个非零矢量+两个零矢量),去合成任意方向、任意大小的目标电压矢量。
4.2 八个基本电压矢量
三相逆变器有六个开关管,上下桥臂互补导通。所以一共有2³=8种开关状态。
我列个表给你看:
| 开关状态 (Sa Sb Sc) | 矢量编号 | Uα | Uβ | 幅值 |
|---|---|---|---|---|
| 000 | V0 | 0 | 0 | 0 |
| 100 | V1 | 2/3 Vdc | 0 | 2/3 Vdc |
| 110 | V2 | 1/3 Vdc | √3/3 Vdc | 2/3 Vdc |
| 010 | V3 | -1/3 Vdc | √3/3 Vdc | 2/3 Vdc |
| 011 | V4 | -2/3 Vdc | 0 | 2/3 Vdc |
| 001 | V5 | -1/3 Vdc | -√3/3 Vdc | 2/3 Vdc |
| 101 | V6 | 1/3 Vdc | -√3/3 Vdc | 2/3 Vdc |
| 111 | V7 | 0 | 0 | 0 |
注意看,V0和V7都是零矢量,只是开关状态不同。非零矢量的幅值都是2/3 Vdc,方向依次相差60度。
我的经验:刚开始记这八个状态时,我总搞混。后来发现一个规律——把二进制数看成十进制,V1=1, V2=2, V3=3...这样就好记多了。另外,零矢量有两个,实际使用时要交替用,不然开关损耗会集中在某一相上。
4.3 扇区判断
有了目标矢量Uref,第一步就是判断它在哪个扇区。六个扇区,每个占60度。
判断方法有很多种。我最早用的是查表法——算角度,然后看落在哪个区间。但后来发现,用数学判断更高效,适合在DSP或MCU上跑。
具体做法是这样的:
- 先算三个中间变量:
B0 = Uβ
B1 = (√3/2)*Uα - 0.5*Uβ
B2 = -(√3/2)*Uα - 0.5*Uβ
- 然后定义三个符号位:
if (B0 > 0) then A = 1 else A = 0
if (B1 > 0) then B = 1 else B = 0
if (B2 > 0) then C = 1 else C = 0
- 扇区号 = A + 2*B + 4*C
嗯,这里要注意:算出来的扇区号是1到6,但顺序可能和你的矢量图编号不一致。我习惯在代码里加一个映射表,把计算出的扇区号映射到实际的扇区编号。
避坑指南:我曾经在项目里直接用计算出的扇区号去查表,结果电机转起来一顿一顿的。查了半天才发现,是扇区编号和矢量作用顺序没对应上。所以,一定要确认你的扇区编号规则和后续计算一致。
4.4 基本矢量作用时间计算
判断完扇区,接下来就是算时间了。说白了,就是用相邻的两个非零矢量和零矢量,去合成目标矢量。
假设目标矢量在扇区I,相邻矢量是V1和V2。那么:
T1 = (√3 * Ts / Vdc) * (Uα * sin(60° - θ) + Uβ * cos(60° - θ))
T2 = (√3 * Ts / Vdc) * (-Uα * sin(θ) + Uβ * cos(θ))
其中Ts是开关周期,θ是目标矢量在扇区内的角度。
实际工程中,我们一般不直接用三角函数,而是用查表或近似计算。更常见的做法是,用前面算的B0、B1、B2直接算时间:
// 扇区I
T1 = (√3 * Ts / Vdc) * B1
T2 = (√3 * Ts / Vdc) * B2
// 扇区II
T1 = (√3 * Ts / Vdc) * B2
T2 = (√3 * Ts / Vdc) * (-B0)
// 扇区III
T1 = (√3 * Ts / Vdc) * (-B0)
T2 = (√3 * Ts / Vdc) * (-B1)
// 扇区IV
T1 = (√3 * Ts / Vdc) * (-B1)
T2 = (√3 * Ts / Vdc) * (-B2)
// 扇区V
T1 = (√3 * Ts / Vdc) * (-B2)
T2 = (√3 * Ts / Vdc) * B0
// 扇区VI
T1 = (√3 * Ts / Vdc) * B0
T2 = (√3 * Ts / Vdc) * B1
你看,每个扇区只是B0、B1、B2的组合不同。这就是为什么我前面让你先算这三个中间变量——一劳永逸。
重要提醒:T1和T2算出来后,要检查是否超过Ts。如果T1+T2 > Ts,需要做等比例缩小处理:
if (T1 + T2 > Ts) {
T1 = T1 * Ts / (T1 + T2);
T2 = T2 * Ts / (T1 + T2);
}
这叫过调制处理,说白了就是当目标矢量太大时,把它拉回到六边形内。
4.5 零矢量的分配
T1和T2算完了,剩下的时间就是零矢量:T0 = Ts - T1 - T2。
零矢量有两个:V0和V7。怎么分配?
我个人的习惯是:
- 如果T0不大,就平均分给V0和V7
- 如果T0很大,可以适当偏向V0或V7,以减少开关次数
举个例子,在扇区I,开关顺序通常是:
V0(000) → V1(100) → V2(110) → V7(111) → V2(110) → V1(100) → V0(000)
这样每个周期只开关一次,开关损耗最小。
小技巧:实际调试时,我建议先用示波器看一相的输出波形。如果波形不对称,多半是零矢量分配有问题。另外,死区时间也要考虑进去,不然上下桥臂直通就烧管子了。
好了,这一节的内容就到这儿。空间矢量的概念、扇区判断、基本矢量作用时间计算,这三块是SVPWM的基石。下一节我们讲PWM波的生成和实际代码实现,到时候我会把完整的C代码贴出来。
记住,SVPWM的核心就八个字:矢量合成,时间分配。搞懂了这八个字,后面的东西就水到渠成了。