07SVPWM
空间电压矢量、扇区、T1/T2/T0
本模块主旨
把目标电压矢量按时间分给六边形里相邻两个基本矢量 + 零矢量;调色板只有 8 种颜色,靠"时间比例"调出任意色 + 多榨 15.5% 母线。学完应能回答
- 能列举 8 种开关状态及其对应矢量(V0/V7 零矢量,V1-V6 六个非零矢量及其上桥臂二进制码)
- 能口算 atan2(Uβ, Uα) → 扇区号,知道 [-π, π] → [0, 2π] 归一化的边界陷阱
- 能解释 SVPWM 比 SPWM 多 15.5% 利用率的原因(min-max 偏置 = 三次谐波注入 = 零序不影响线电压)
- 能识别过调制(m > 1.0)的现象、硬件后果与两种处置(圆内限幅 / 六步切换)
- 知道为什么"七段式"对称序列是嵌入式实现的事实标准 + 它如何天然让 ADC 采样落在电流纹波谷
- 会配 STM32 TIM1 BDTR / DTG 设死区,懂 duty 必须钳到 [0.02, 0.98] 给自举电容充电
总览
SVPWM = "把目标电压矢量按时间分给 6 个扇区两侧的有效矢量 + 零矢量"。代码里就是判扇区 → 算 T1/T2/T0 → 算 duty 三步。零基础速入
类比
SVPWM 像调色——你想要"任意方向的电压矢量",但调色板上只有 8 种基本色(V0-V7 = 8 种开关状态)。SVPWM 在每个 PWM 周期里**按时间比例混合**最近的两种基本色 + 一种"白色"(零矢量),让平均下来等于你想要的颜色。核心概念
把 αβ 平面六边形划成 6 个扇区,每个扇区用相邻两个有效矢量 V_k、V_{k+1} 加零矢量 V0/V7 按时间 T1、T2、T0 加权合成目标 Uαβ。为什么要学
- SVPWM 比 SPWM 多 15% 母线利用率,电机能转更高速度;电动车、伺服基本都用 SVPWM。
- 六个扇区 + 8 种开关状态是逆变器与电机之间的"语法"——读懂代码、读懂硬件波形都靠它。
- 过调制(m > 1.0)和扇区误判是常见 bug,看六边形图是最直观的诊断方式。
第一手操作
把右侧"电角度"从 0° 缓慢拖到 360°,看左侧六边形里的扇区高亮按 1→2→3→4→5→6 顺序切换。再把"调制比"拉到 0.95 看 T0 接近 0;拉过 1.0 进入饱和(红色徽标)。学习目标
- 理解六个有效矢量、两个零矢量和六个扇区的关系
- 掌握 T1/T2/T0 与占空比 dutyA/B/C 计算
- 区分 SVPWM 与 SPWM 母线利用率的差距和原因
核心概念
- SVPWM 不是给三相正弦,而是 PWM 周期内组合相邻两个有效矢量和零矢量让"平均电压"等于目标矢量。
- 目标落在哪个 60° 扇区,就用该扇区两侧基本矢量;扇区由 atan2(Uβ, Uα) 决定。
- V0(000)/V7(111) 是零矢量,让"中点电压"为 0;插入它们以补足周期。
公式
扇区判断
sector = floor(atan2(Uβ, Uα) / 60°) + 1
把 [0, 2π) 角度均分 6 段,每段 60°。归一化时注意正负。
T1, T2 计算(扇区 N,0 ≤ θ-N·60° ≤ 60°)
T1 = m·sin((N·60° - θ + 60°))·Ts\nT2 = m·sin(θ - (N-1)·60°)·Ts\nT0 = Ts - T1 - T2
m 是调制比,Ts 是 PWM 周期。T0 < 0 → 进入过调制需要钳位。
调制比
m = √3·|Uref| / Udc
m = 1 是 SVPWM 线性区上限(比 SPWM 的 m=1 高 √3/2 ≈ 1.155 倍利用率)。
三相占空比
Tcm = (Ts + T1 - T2)/2 等(按扇区分)\nduty = Tc / Ts
中心对齐 PWM 中常用"七段式"序列:000 → 100 → 110 → 111 → 110 → 100 → 000,对应三相 duty。
工程意义
- SVPWM 比 SPWM 利用率高 √3/2 ≈ 15.5%——同样母线电压能转更快,省母线电容。
- SVPWM 等价于 SPWM + 三次谐波注入;嵌入式实现常用"min-max"算法(duty = sinusoidal - (max+min)/2)只需一次 sin/cos 累加。
- 过调制处理:m > 1 时按比例缩短 T1/T2 让 T0 ≥ 0,或者切到六步运行。
STM32 移植指南
- 计算出 dutyA/B/C ∈ [0, 1] 后写 TIMx->CCR = (uint16_t)(duty × ARR)。
- 中心对齐 PWM + ADC 注入序列,采样点放在 PWM 中点(电流纹波最小)。
- min-max 实现一行:duty_a = (Vα·k1 + offset);offset = -(max(va,vb,vc)+min(va,vb,vc))/2。
常见误区
- 扇区边界 0°/360° 归一化错(atan2 返回 [−π, π],需要 +2π 后再除 60)。
- T0 < 0 没钳位继续输出,duty 异常。
- 三相 duty 没限到 [0.02, 0.98],PWM 比较器吃不到。
- 七段式和五段式序列搞混。
调试方法
- 旋转 Uα/Uβ 一周,检查扇区按 1→2→3→4→5→6→1 顺序切换。
- 低调制比(m < 0.5)时三相 duty 应是平滑正弦+1.5 次谐波样的"鞍形波"。
- 示波器抓 PWM_A 和 PWM_B 上桥臂,相差应有相位关系而不是同步。
建议实验
- 加载"SVPWM 扇区切换"预设,缓慢调电角度看 6 个扇区依次高亮。
- 加载"过调制"预设(m > 1),看红色饱和警告。
- 比较母线利用率指标:SVPWM 71.1% vs SPWM 82.1% 在不同 m 下的差。
STM32 C 代码骨架
/* ============================================
* svpwm.h — SVPWM 算法(min-max 实现,单次 PWM 中断 < 1μs)
* 适配 STM32 高级定时器,输出范围 [0, 1] 直接喂 CCR
* ============================================ */
#define ONE_OVER_SQRT3 0.57735026919f
typedef struct {
float duty_a; // 三相上桥臂占空比 [0, 1]
float duty_b;
float duty_c;
uint8_t sector; // 1-6
uint8_t saturated; // 1 = 进入过调制
} svpwm_t;
/* 输入 αβ 电压指令(V),母线电压 Udc(V),返回三相 duty */
svpwm_t svpwm_calc(float v_alpha, float v_beta, float udc) {
svpwm_t r = { 0 };
/* 1. min-max 算法核心:等价于 SPWM + 三次谐波注入
* Va_ref = Vα
* Vb_ref = -0.5·Vα + (√3/2)·Vβ
* Vc_ref = -0.5·Vα - (√3/2)·Vβ
*/
const float SQRT3_2 = 0.8660254038f;
float va = v_alpha;
float vb = -0.5f * v_alpha + SQRT3_2 * v_beta;
float vc = -0.5f * v_alpha - SQRT3_2 * v_beta;
/* 2. 找出 max / min,注入 -(max+min)/2 */
float vmax = va > vb ? (va > vc ? va : vc) : (vb > vc ? vb : vc);
float vmin = va < vb ? (va < vc ? va : vc) : (vb < vc ? vb : vc);
float offset = -0.5f * (vmax + vmin);
/* 3. 归一化到 [0, 1] 占空比 */
float scale = 1.0f / udc;
r.duty_a = 0.5f + (va + offset) * scale;
r.duty_b = 0.5f + (vb + offset) * scale;
r.duty_c = 0.5f + (vc + offset) * scale;
/* 4. 限幅 */
if (r.duty_a < 0.0f) { r.duty_a = 0.0f; r.saturated = 1; }
if (r.duty_a > 1.0f) { r.duty_a = 1.0f; r.saturated = 1; }
if (r.duty_b < 0.0f) { r.duty_b = 0.0f; r.saturated = 1; }
if (r.duty_b > 1.0f) { r.duty_b = 1.0f; r.saturated = 1; }
if (r.duty_c < 0.0f) { r.duty_c = 0.0f; r.saturated = 1; }
if (r.duty_c > 1.0f) { r.duty_c = 1.0f; r.saturated = 1; }
/* 5. 顺手算扇区 (诊断/可视化用) */
float angle = atan2f(v_beta, v_alpha);
if (angle < 0) angle += 2.0f * M_PI;
r.sector = (uint8_t)(angle * (3.0f / M_PI)) + 1;
if (r.sector > 6) r.sector = 6;
return r;
}
/* 用法(FOC 中断尾部):
* svpwm_t s = svpwm_calc(v_alpha, v_beta, g_state.udc);
* TIM1->CCR1 = (uint16_t)(s.duty_a * (TIM1->ARR + 1));
* TIM1->CCR2 = (uint16_t)(s.duty_b * (TIM1->ARR + 1));
* TIM1->CCR3 = (uint16_t)(s.duty_c * (TIM1->ARR + 1));
*/下一步
- 进入逆变器模块,看 duty 如何变成相电压和线电压(含死区损失)。
随堂题
SVPWM 比 SPWM 在母线利用率上的优势大约是?
- 完全没差
- 15% 左右 (正确)
- 50%
- 一倍
提示:SPWM 线性区 m_max ≈ 1,对应输出电压 0.5·Udc 峰值。SVPWM m_max ≈ 1,对应 Udc/√3 峰值,多 √3/2 ≈ 1.155 倍 = 15.5%。
六边形顶点 V1 对应的上桥臂状态码是?
- 000
- 100 (正确)
- 110
- 111
提示:V1 = (100) = A 高、B 低、C 低。V2(110), V3(010), V4(011), V5(001), V6(101),V0(000)/V7(111) 是零矢量。
调制比 m > 1.0 时进入"过调制",硬件上会发生什么?
- 没影响
- 某些 PWM 周期 T0 < 0,被钳到 0,输出非线性 (正确)
- PWM 关断
- ADC 错
提示:T0 < 0 物理上不可能(零矢量没法负时间)。代码会钳到 0,让 T1+T2 = Ts,结果输出失真,增加电流谐波。
为什么 SVPWM 等价于 "SPWM + 注入三次谐波"?
- 偶然
- min-max 偏置注入正好是相电压的三次谐波,三相和为 0 不影响线电压 (正确)
- 历史原因
- 便于编程
提示:三次谐波在三相相同(同相),加进每相 duty 不改变线电压,但能让中性点电压"下沉",扩大可用相电压范围 → 利用率提升。
中心对齐 PWM + 注入 ADC 触发 + 七段式 SVPWM,采样点放在 PWM 中点的好处是?
- 硬件要求
- 中点是开关切换刚结束、电流稳定区,纹波最小 (正确)
- 减少代码量
- 无功消耗低
提示:中心对齐计数器达到 ARR 时触发 ADC 注入,此时所有桥臂处于稳定状态(同一组开关组合),电流纹波最小。
相关公式索引
SVPWM 调制比
m = √3 |Uref| / Udc
SVPWM min-max 零序注入
voff = −(vmax + vmin)/2; duty = 0.5 + (v + voff)/Udc
弱磁基速
ω_base = V_max / ψf; V_max = Udc/√3 (SVPWM 线性区)