第2章 SVPWM原理精讲:从空间电压矢量到七段式与五段式实现
好,咱们直接进入正题。SVPWM 这玩意儿,说白了就是让电机转得又稳又顺的核心技术。很多初学者一上来就被那些矢量、扇区、作用时间给绕晕了。别急,我带你一步步拆开看。
2.1 空间电压矢量:电机旋转的“指挥棒”
先问个问题:三相逆变器能输出什么?无非就是六个开关管,上管开下管关,或者反过来。六个开关组合,能产生 8 种基本状态。其中 6 种是非零电压矢量,2 种是零矢量(上下全开或全关)。
这 6 个非零矢量,在空间上刚好把 360° 电角度分成 6 个扇区。每个矢量的大小相等,方向相差 60°。你想想看,如果让电机转子跟着这些矢量走,它就能转起来。
我个人习惯把空间电压矢量想象成一个“旋转的指挥棒”。你给它一个指令,它就指向某个方向。但问题是,我们只有 6 个固定方向,怎么让电机平滑旋转?
答案就是:用相邻两个矢量去合成任意方向的矢量。这就是 SVPWM 的核心思想——伏秒平衡。
核心概念:空间电压矢量不是真实存在的电压,而是一种数学映射。它把三相静止坐标系下的电压,映射到两相旋转坐标系下,方便我们控制。
我在项目中遇到过一个问题:刚开始用 SVPWM 时,总觉得电机噪音大。后来发现是扇区判断的边界条件没处理好,导致矢量切换时出现了毛刺。嗯,这里要注意,边界条件一定要做死区处理。
2.2 扇区判断:快速定位你的矢量在哪
有了 6 个基本矢量,下一步就是判断当前要合成的矢量落在哪个扇区。怎么判断?用 Clark 变换后的 αβ 分量。
假设我们已经得到了 Uα 和 Uβ,那么扇区号 N 可以通过以下逻辑算出:
// 扇区判断伪代码
if (Uβ > 0) then A = 1 else A = 0
if (sqrt(3)*Uα - Uβ > 0) then B = 1 else B = 0
if (-sqrt(3)*Uα - Uβ > 0) then C = 1 else C = 0
N = A + 2*B + 4*C
这个 N 值从 1 到 6,对应 6 个扇区。我建议你把这个逻辑固化成一个查表函数,别每次实时算,能省不少 CPU 周期。
| N 值 | 扇区 | 对应基本矢量 |
|---|---|---|
| 1 | 扇区 II | V2 (60°-120°) |
| 2 | 扇区 VI | V6 (300°-360°) |
| 3 | 扇区 I | V1 (0°-60°) |
| 4 | 扇区 IV | V4 (180°-240°) |
| 5 | 扇区 III | V3 (120°-180°) |
| 6 | 扇区 V | V5 (240°-300°) |
小技巧:扇区判断的边界值可以用定点数处理,避免浮点运算。我一般把 sqrt(3) 近似为 1.732,然后左移 12 位做定点乘法,精度完全够用。
2.3 作用时间计算:伏秒平衡的数学表达
知道扇区后,就要算两个相邻矢量的作用时间了。假设当前扇区是 I,相邻矢量是 V1 和 V2,那么:
T1 = Ts * (Uα - Uβ / sqrt(3)) / Vdc
T2 = Ts * (2 * Uβ / sqrt(3)) / Vdc
T0 = Ts - T1 - T2
其中 Ts 是 PWM 周期,Vdc 是母线电压。T1 和 T2 分别是 V1 和 V2 的作用时间,T0 是零矢量的作用时间。
这里有个坑:如果 T1 + T2 > Ts,说明发生了过调制。我刚开始做的时候没处理这个,结果电机直接抖得像筛糠。后来加了个饱和处理,把 T1 和 T2 按比例缩放到 Ts 内,问题就解决了。
避坑指南:我曾经在过调制处理时,直接把 T1 和 T2 截断到 Ts,结果导致矢量方向偏移。正确的做法是按比例缩放:T1' = T1 * Ts / (T1 + T2),T2' = T2 * Ts / (T1 + T2)。
2.4 七段式 vs 五段式 SVPWM:效率与谐波的博弈
有了作用时间,接下来就是怎么安排开关序列。主流有两种方式:七段式和五段式。
七段式 SVPWM:每个 PWM 周期内,开关切换 7 次。序列是:零矢量 → V1 → V2 → 零矢量 → V2 → V1 → 零矢量。这种方式的优点是谐波小,电流波形好。缺点是开关损耗大。
五段式 SVPWM:每个 PWM 周期内,开关切换 5 次。序列是:V1 → V2 → 零矢量 → V2 → V1。它去掉了中间的一个零矢量,减少了开关次数。优点是开关损耗低,适合高频应用。缺点是谐波含量高一些。
| 对比项 | 七段式 | 五段式 |
|---|---|---|
| 开关次数/周期 | 7 次 | 5 次 |
| 开关损耗 | 高 | 低 |
| 谐波含量 | 低 | 高 |
| 电流波形 | 平滑 | 有毛刺 |
| 适用场景 | 低速、高精度 | 高速、高效率 |
我个人习惯在低速段用七段式,高速段切到五段式。这样既能保证低速时的电流质量,又能降低高速时的开关损耗。切换点一般设在额定转速的 70% 左右。
2.5 核心逻辑流程图
下面这张图把整个 SVPWM 的流程串起来了。从输入 Uα/Uβ 开始,到最终输出 PWM 波形,每一步都清晰可见。
2.6 代码实现要点
最后,给出一段七段式 SVPWM 的核心代码。这段代码我用了很多年,基本没出过问题。
// 七段式 SVPWM 核心实现
void svpwm_calc(float Ualpha, float Ubeta, uint16_t *pwm_compare) {
// 1. 扇区判断
uint8_t sector = get_sector(Ualpha, Ubeta);
// 2. 计算 T1, T2
float T1, T2, T0;
calc_time(Ualpha, Ubeta, sector, &T1, &T2);
T0 = TS - T1 - T2;
// 3. 过调制处理
if (T1 + T2 > TS) {
float scale = TS / (T1 + T2);
T1 *= scale;
T2 *= scale;
T0 = 0;
}
// 4. 生成七段式序列
float Ta = T0 / 4;
float Tb = Ta + T1 / 2;
float Tc = Tb + T2 / 2;
// 5. 根据扇区映射到三相
switch(sector) {
case 1:
pwm_compare[0] = (uint16_t)(Ta * PWM_PERIOD);
pwm_compare[1] = (uint16_t)(Tb * PWM_PERIOD);
pwm_compare[2] = (uint16_t)(Tc * PWM_PERIOD);
break;
// ... 其他扇区类似
}
}
经验之谈:代码里的 PWM_PERIOD 一定要和定时器的周期匹配。我习惯用 10kHz 的 PWM 频率,周期值设为 10000。这样 T0/4 这种计算不会出现小数溢出。
好了,SVPWM 的原理就讲到这里。你可能会问:七段式和五段式到底选哪个?我的建议是:先跑七段式,把电流环调稳了,再考虑切五段式降损耗。别一上来就追求极致效率,稳定才是第一位的。