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) 矢量编号 幅值
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上跑。

具体做法是这样的:

  1. 先算三个中间变量:
B0 = Uβ
B1 = (√3/2)*Uα - 0.5*Uβ
B2 = -(√3/2)*Uα - 0.5*Uβ
  1. 然后定义三个符号位:
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
  1. 扇区号 = 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的核心就八个字:矢量合成,时间分配。搞懂了这八个字,后面的东西就水到渠成了。