SVPWM
Space Vector PWM
空间矢量脉宽调制 · 新工程师完整教程
// 01 · 动机

为什么不用普通的 SPWM

🎯
一句话理解SVPWM的目标

给电机施加一个任意方向、任意幅值的旋转电压矢量,同时把直流母线电压用到极致

在普通SPWM中,三路独立的正弦波各自调制,互相不知道对方的状态。而电机实际需要的是一个旋转的合成电压矢量——SVPWM正是从这个整体视角出发设计的。

😐 SPWM

  • 三路独立调制
  • 直流利用率:50%
  • 谐波稍高
  • 实现简单

✅ SVPWM

  • 以矢量整体考量
  • 直流利用率:57.7%
  • 谐波更低
  • 数字实现友好
🔦
比喻:手电筒打光

想象你要用手电筒在墙上打出一个指向任意方向的光斑。
SPWM:三个手电筒分别独立摆动,光斑是三者叠加的意外结果。
SVPWM:你明确知道要把光斑打到哪里,然后计算三个手电筒分别开多长时间来精确合成。

// 02 · 基础

三相逆变器有多少种开关状态

三相逆变器有三个桥臂,每个桥臂上管(S_up)和下管(S_down)互补导通(不能同时开,防止直通)。所以每个桥臂只有0或1两种状态,三个桥臂共有 2³ = 8种组合。

+ Vdc P N Sa↑ Sa↓ A Sb↑ Sb↓ B Sc↑ Sc↓ C M
PHASE A
A相
1
上管导通
PHASE B
B相
1
上管导通
PHASE C
C相
0
下管导通
当前矢量: V4 (100) — 非零矢量
矢量Sa Sb Sc类型含义
V₀0 0 0零矢量三相全下管,输出为零
V₁1 0 0有效矢量指向0°
V₂1 1 0有效矢量指向60°
V₃0 1 0有效矢量指向120°
V₄0 1 1有效矢量指向180°
V₅0 0 1有效矢量指向240°
V₆1 0 1有效矢量指向300°
V₇1 1 1零矢量三相全上管,输出为零
// 03 · 核心概念

六边形与空间矢量图

把8个开关状态对应的电压矢量画到二维平面(αβ坐标系)上,会得到一个正六边形。6个非零矢量均匀分布,把平面分成6个扇区

🕰️
比喻:时钟的时针

6个有效矢量就像时钟的6个方向(12点、2点、4点、6点、8点、10点)。 你想要时针指向1点30分,但只能用12点和2点的组合——靠近哪个方向就让它多作用一段时间,这就是时间平均合成的思路。

扇区: I
T₁: 0.00·Ts
T₂: 0.00·Ts
T₀: 0.00·Ts

旋转调节角度,观察:参考矢量(白色箭头)如何被相邻两个基矢量(彩色箭头)分解,以及零矢量时间如何随着幅值变化。

// 04 · 数学

Clark变换与时间计算

1

Clarke变换:三相 → αβ坐标

将三相电压(120°互差)投影到两轴正交坐标系,去掉冗余维度。

2

判断扇区:Vref在哪个扇区?

根据αβ分量,用位运算快速确定扇区号(1~6)。

3

计算作用时间:T₁, T₂, T₀

利用正弦定理,算出相邻两个基矢量各需作用多少时间。

4

生成比较值:写入定时器寄存器

按七段式对称排列,计算三个通道的计数器比较值。

Step 1:Clarke 变换

// 等功率变换(幅值×√(2/3)) = √(2/3) × [Va0.5×Vb0.5×Vc] = √(2/3) × [ (√3/2)×Vb − (√3/2)×Vc] // 工程中常用简化幅值不变形式: = Va = (Va + 2×Vb) / √3

Step 2:扇区判断(位运算法)

// 定义三个辅助量 U1 = U2 = −/2 + (√3/2)× U3 = −/2 − (√3/2)× // 用符号位编码 A = (U1 > 0) ? 1 : 0 B = (U2 > 0) ? 1 : 0 C = (U3 > 0) ? 1 : 0 N = 4×C + 2×B + A // N → 扇区 对照表: // N=3→I, N=1→II, N=5→III // N=4→IV, N=6→V, N=2→VI

Step 3:作用时间计算(以扇区I为例)

// 设 k = √3 × Ts / Vdc // 扇区I中,相邻矢量为 V1(100) 和 V2(110) T1 = k × ( (√3/2)×/2 ) ← V1方向分量 T2 = k × ← V2方向分量 T0 = Ts − T1 − T2 ← 零矢量时间 // 若 T1+T2 > Ts(过调制),需归一化: if (T1+T2 > Ts): T1 = T1×Ts/(T1+T2); T2 = T2×Ts/(T1+T2)

其他扇区的公式通过坐标旋转得到,结构完全一样,只是 Vα、Vβ 的系数正负不同。实现时通常统一用查表或 if-else 处理各扇区。

// 05 · 七段式

PWM 波形的对称排列

知道了 T1, T2, T0 之后,还需要决定这一个 PWM 周期内开关管的具体开关顺序。标准做法是七段式(Symmetric 7-segment)

🎵
比喻:三明治结构

七段 = 前半段(V₀ → V_x → V_{x+1} → V₇)+ 后半段(镜像对称)
结果:每个周期内每相只发生2次开关动作,而且波形关于中点对称,谐波最低。

扇区I(Sa=1先拉高)为例,七段排列如下:

Tcma: 0.0%
Tcmb: 0.0%
Tcmc: 0.0%

三个比较值(Tcma, Tcmb, Tcmc)直接写入定时器的捕获比较寄存器即可,DSP/MCU内部的上下计数器会自动产生对称PWM。

// 扇区I 比较值(以计数器周期归一化) Tcma = T0/4 Tcmb = T0/4 + T1/2 Tcmc = T0/4 + T1/2 + T2/2 // 不同扇区的A/B/C分配不同,查表确定
// 06 · 实现

完整 C代码 实现

以下是可直接用于 DSP(TMS320F28xxx)或 STM32 的 SVPWM C 函数,注释详尽:

/* ============================================================ * svpwm.c · SVPWM 空间矢量调制 * 输入: Valpha, Vbeta (αβ坐标系电压,已归一化到 Vdc) * 输出: Tcma, Tcmb, Tcmc (定时器比较值,归一化到 0~1) * ===========================================================*/ #include <math.h> #define SQRT3 1.732050808f #define SQRT3_2 0.866025404f #define ONE_OVER_SQRT3 0.577350269f typedef struct { float Tcma, Tcmb, Tcmc; // 三相比较值 [0,1] int sector; // 当前扇区 1~6 } SVPWM_Out; SVPWM_Out SVPWM_Calc(float Va, float Vb) { SVPWM_Out out; float T1, T2, T0; float X, Y, Z; // --- Step 1: 计算三个辅助量 --- float U1 = Vb; float U2 = -Vb * 0.5f + SQRT3_2 * Va; float U3 = -Vb * 0.5f - SQRT3_2 * Va; // --- Step 2: 扇区判断(位运算) --- int A = (U1 > 0) ? 1 : 0; int B = (U2 > 0) ? 1 : 0; int C = (U3 > 0) ? 1 : 0; int N = 4*C + 2*B + A; int sector_map[] = {0,2,6,1,4,3,5,0}; out.sector = sector_map[N]; // --- Step 3: 计算 X, Y, Z(通用时间基) --- X = SQRT3 * Vb; Y = SQRT3_2 * Va + Vb * 0.5f; // 即 (√3/2·Vα + Vβ/2) Z = -SQRT3_2 * Va + Vb * 0.5f; // --- Step 4: 按扇区分配 T1, T2 --- switch (out.sector) { case 1: T1= Y; T2= X; break; case 2: T1= -Z; T2= -Y; break; case 3: T1= Z; T2= X; break; // 注:此处有符号约定 case 4: T1= -X; T2= -Z; break; case 5: T1= X; T2= Y; break; case 6: T1= -Y; T2= -X; break; default: T1=T2=0; } // --- Step 5: 过调制限幅 --- if (T1 + T2 > 1.0f) { float k = 1.0f / (T1 + T2); T1 *= k; T2 *= k; } T0 = (1.0f - T1 - T2) * 0.5f; // V0 和 V7 各占一半 // --- Step 6: 七段式比较值 --- float Ta=0, Tb=0, Tc=0; switch (out.sector) { case 1: Ta=T0; Tb=T0+T1; Tc=T0+T1+T2; break; case 2: Ta=T0+T2; Tb=T0; Tc=T0+T1+T2; break; case 3: Ta=T0+T1+T2; Tb=T0; Tc=T0+T1; break; case 4: Ta=T0+T1+T2; Tb=T0+T1; Tc=T0; break; case 5: Ta=T0+T1; Tb=T0+T1+T2; Tc=T0; break; case 6: Ta=T0; Tb=T0+T1+T2; Tc=T0+T1; break; } out.Tcma = 0.5f - Ta; // 转换为对称中心格式 out.Tcmb = 0.5f - Tb; out.Tcmc = 0.5f - Tc; return out; }
⚠️
新工程师常见坑
// 07 · 小结

一张图理解整个流程

┌─────────────────────────────────────────────────────────┐ │ SVPWM 完整数据流 │ └─────────────────────────────────────────────────────────┘ 电流环/速度环 ↓ Vd, Vq (旋转坐标系) ↓ Park逆变换 Vα, Vβ (静止坐标系) ↓ 扇区判断 Sector (1~6) ↓ 时间计算 T1, T2, T0 ↓ 七段式排列 Tcma, Tcmb, Tcmc ↓ 写入定时器 PWM 三路互补信号 → 驱动IC → IGBT/MOSFET → 电机
概念关键点常见问题
开关状态8个(含2个零矢量)混淆 V0 和 V7 的区别
扇区判断用位运算,速度快忘记处理 N=0 异常
时间计算T1+T2 ≤ Ts过调制不做归一化
七段式每相 2 次开关/周期比较值方向搞反
直流利用率1/√3 ≈ 57.7%——