4、SVPWM原理与实现:空间矢量调制原理、扇区判断、作用时间计算、七段式SVPWM、五段式SVPWM、死区时间插入

好,咱们接着聊。前面我们把Clark变换和Park变换搞定了,电流环也调通了。但有个关键问题一直没解决:你算出来的,怎么变成逆变器六个开关管的导通信号?

答案就是SVPWM——空间矢量脉宽调制。说实话,我刚入行那会儿,觉得SVPWM特别神秘,什么六边形、什么扇区,听着就头大。后来自己手写了一遍代码,才发现核心逻辑其实很清晰。今天我就带你把它彻底拆开。

4.1 空间矢量调制原理

先想一个问题:三相逆变器只有六个开关管,上管导通下管就关断,所以一共就8种开关状态。其中6个是有效矢量,2个是零矢量(全上管通或全下管通)。

这6个有效矢量,在复平面上画出来,就是一个正六边形。每个矢量长度都是2/3 * Vdc,相邻间隔60度。

核心思想:你想要的任意电压矢量,都可以用相邻的两个有效矢量和零矢量,通过时间加权来合成。这就是“伏秒平衡”原理。

我习惯用一个比喻:你想去一个不在正东正北方向的地方,那就先往东走一段,再往北走一段,最终就能到达。SVPWM也是这个道理。

SVPWM 核心知识体系 SVPWM 实现流程 ① 扇区判断 ② 作用时间计算 ③ 切换点计算 Uα、Uβ 符号判断 T1、T2、T0 计算 Ta、Tb、Tc 赋值 ④ 七段式 / 五段式 PWM 输出

4.2 扇区判断

拿到之后,第一件事就是判断它在哪个扇区。说白了,就是看这个矢量落在六边形的哪一块里。

我常用的方法是:定义三个中间变量:

B1 = Vβ
B2 = (√3/2)*Vα - (1/2)*Vβ
B3 = -(√3/2)*Vα - (1/2)*Vβ

然后根据这三个值的正负,就能唯一确定扇区:

N = 4*sign(B3) + 2*sign(B2) + sign(B1)

其中sign(x)在x>0时返回1,否则返回0。N值1~6对应扇区I~VI。

我的小技巧:实际代码里,我一般直接用查表法。把N值映射到扇区号,比每次if-else判断快得多。在STM32上测过,能省几十个时钟周期。

4.3 作用时间计算

扇区定下来之后,就该算两个相邻矢量的作用时间了。这里有个通用公式,我直接给你:

X = (√3 * Ts / Vdc) * Vβ
Y = (√3 * Ts / Vdc) * ( (√3/2)*Vα + (1/2)*Vβ )
Z = (√3 * Ts / Vdc) * ( -(√3/2)*Vα + (1/2)*Vβ )

然后根据扇区查表:

扇区T1T2
I-ZX
IIZY
IIIX-Y
IV-XZ
V-Y-Z
VIY-X

零矢量时间:T0 = Ts - T1 - T2。如果T1+T2 > Ts,需要做等比例缩小处理——这叫过调制,我后面会专门讲。

注意:我曾经在过调制处理上栽过跟头。当时没做限幅,结果T0算出来是负数,PWM波形直接乱套,电机嗡嗡响。后来加了一行限幅代码才解决。所以一定要检查T0是否大于0。

4.4 七段式SVPWM

七段式,顾名思义,一个PWM周期里分成7段。它的特点是:每次切换只改变一个开关管的状态,谐波小,是工业上最常用的方式。

先算三个比较值:

Ta = (Ts - T1 - T2) / 4
Tb = Ta + T1/2
Tc = Tb + T2/2

然后根据扇区,把Ta、Tb、Tc分配给三相的比较寄存器:

扇区CMPACMPBCMPC
ITbTaTc
IITaTbTc
IIITaTcTb
IVTcTbTa
VTcTaTb
VITbTcTa

你看,其实就是把Ta、Tb、Tc按不同顺序塞进去。波形出来就是中间高两边低的马鞍形——这正是SVPWM比SPWM母线利用率高的原因。

4.5 五段式SVPWM

五段式,也叫不连续调制。它每个周期只插入一次零矢量,开关次数比七段式少1/3。开关损耗能降低约30%。

我做过一个对比实验:同样10kHz开关频率,七段式下MOS管温升是45℃,五段式只有32℃。如果你的系统对效率要求高,或者散热条件差,五段式是个好选择。

五段式的实现也很简单:把零矢量时间全部放在开头或结尾。比如:

// 五段式(零矢量集中在前半段)
Ta = 0
Tb = T1/2
Tc = T1/2 + T2/2

但代价是谐波会大一些。嗯,这就是典型的“效率vs质量”的取舍。

4.6 死区时间插入

最后说一个特别重要但容易被忽略的点——死区时间。

你想想看,同一桥臂的上下管,如果同时导通,那就是短路。所以必须在切换时,先关断一个,等一小段时间,再开通另一个。这个等待时间就是死区。

我一般这样处理:

// 伪代码示例
void insert_deadtime(uint32_t *cmp_register, uint32_t deadtime_ticks) {
    // 上管比较值不变
    uint32_t cmp_high = *cmp_register;
    // 下管比较值减去死区
    uint32_t cmp_low = *cmp_register - deadtime_ticks;
    // 分别写入上下管比较寄存器
    write_high_cmp(cmp_high);
    write_low_cmp(cmp_low);
}

避坑指南:死区时间不是越大越好。我见过有人设了5μs死区,结果电机在低速时电流波形明显畸变,转矩脉动大得吓人。一般建议:IGBT设2~3μs,MOSFET设0.5~1μs。具体看你的开关器件datasheet。

另外,死区会导致电压损失,影响低速性能。如果要求高,可以用死区补偿算法——这个我们后面章节再细聊。

好了,SVPWM的核心内容就这些。从扇区判断到时间计算,再到波形生成和死区插入,每一步都有它的物理意义。你写代码的时候,建议先在仿真环境里把波形跑出来,确认马鞍波形状对了,再往硬件上下。这样能省不少调试时间。


专注资料整理