4、SVPWM原理与实现:空间矢量调制原理、扇区判断、作用时间计算、七段式SVPWM、五段式SVPWM、死区时间插入
好,咱们接着聊。前面我们把Clark变换和Park变换搞定了,电流环也调通了。但有个关键问题一直没解决:你算出来的Vα和Vβ,怎么变成逆变器六个开关管的导通信号?
答案就是SVPWM——空间矢量脉宽调制。说实话,我刚入行那会儿,觉得SVPWM特别神秘,什么六边形、什么扇区,听着就头大。后来自己手写了一遍代码,才发现核心逻辑其实很清晰。今天我就带你把它彻底拆开。
4.1 空间矢量调制原理
先想一个问题:三相逆变器只有六个开关管,上管导通下管就关断,所以一共就8种开关状态。其中6个是有效矢量,2个是零矢量(全上管通或全下管通)。
这6个有效矢量,在复平面上画出来,就是一个正六边形。每个矢量长度都是2/3 * Vdc,相邻间隔60度。
核心思想:你想要的任意电压矢量,都可以用相邻的两个有效矢量和零矢量,通过时间加权来合成。这就是“伏秒平衡”原理。
我习惯用一个比喻:你想去一个不在正东正北方向的地方,那就先往东走一段,再往北走一段,最终就能到达。SVPWM也是这个道理。
4.2 扇区判断
拿到Vα和Vβ之后,第一件事就是判断它在哪个扇区。说白了,就是看这个矢量落在六边形的哪一块里。
我常用的方法是:定义三个中间变量:
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β )
然后根据扇区查表:
| 扇区 | T1 | T2 |
|---|---|---|
| I | -Z | X |
| II | Z | Y |
| III | X | -Y |
| IV | -X | Z |
| V | -Y | -Z |
| VI | Y | -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分配给三相的比较寄存器:
| 扇区 | CMPA | CMPB | CMPC |
|---|---|---|---|
| I | Tb | Ta | Tc |
| II | Ta | Tb | Tc |
| III | Ta | Tc | Tb |
| IV | Tc | Tb | Ta |
| V | Tc | Ta | Tb |
| VI | Tb | Tc | Ta |
你看,其实就是把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的核心内容就这些。从扇区判断到时间计算,再到波形生成和死区插入,每一步都有它的物理意义。你写代码的时候,建议先在仿真环境里把波形跑出来,确认马鞍波形状对了,再往硬件上下。这样能省不少调试时间。