07SVPWM

空间电压矢量、扇区、T1/T2/T0

本模块主旨
把目标电压矢量按时间分给六边形里相邻两个基本矢量 + 零矢量;调色板只有 8 种颜色,靠"时间比例"调出任意色 + 多榨 15.5% 母线。

学完应能回答

查看完整 Walkthrough(8 步 + 4 误区)

总览
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αβ。

为什么要学

第一手操作
把右侧"电角度"从 0° 缓慢拖到 360°,看左侧六边形里的扇区高亮按 1→2→3→4→5→6 顺序切换。再把"调制比"拉到 0.95 看 T0 接近 0;拉过 1.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。

工程意义

STM32 移植指南

常见误区

  • 扇区边界 0°/360° 归一化错(atan2 返回 [−π, π],需要 +2π 后再除 60)。
  • T0 < 0 没钳位继续输出,duty 异常。
  • 三相 duty 没限到 [0.02, 0.98],PWM 比较器吃不到。
  • 七段式和五段式序列搞混。

调试方法

建议实验

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));
 */

下一步

随堂题

SVPWM 比 SPWM 在母线利用率上的优势大约是?
  1. 完全没差
  2. 15% 左右 (正确)
  3. 50%
  4. 一倍
提示:SPWM 线性区 m_max ≈ 1,对应输出电压 0.5·Udc 峰值。SVPWM m_max ≈ 1,对应 Udc/√3 峰值,多 √3/2 ≈ 1.155 倍 = 15.5%。
六边形顶点 V1 对应的上桥臂状态码是?
  1. 000
  2. 100 (正确)
  3. 110
  4. 111
提示:V1 = (100) = A 高、B 低、C 低。V2(110), V3(010), V4(011), V5(001), V6(101),V0(000)/V7(111) 是零矢量。
调制比 m > 1.0 时进入"过调制",硬件上会发生什么?
  1. 没影响
  2. 某些 PWM 周期 T0 < 0,被钳到 0,输出非线性 (正确)
  3. PWM 关断
  4. ADC 错
提示:T0 < 0 物理上不可能(零矢量没法负时间)。代码会钳到 0,让 T1+T2 = Ts,结果输出失真,增加电流谐波。
为什么 SVPWM 等价于 "SPWM + 注入三次谐波"?
  1. 偶然
  2. min-max 偏置注入正好是相电压的三次谐波,三相和为 0 不影响线电压 (正确)
  3. 历史原因
  4. 便于编程
提示:三次谐波在三相相同(同相),加进每相 duty 不改变线电压,但能让中性点电压"下沉",扩大可用相电压范围 → 利用率提升。
中心对齐 PWM + 注入 ADC 触发 + 七段式 SVPWM,采样点放在 PWM 中点的好处是?
  1. 硬件要求
  2. 中点是开关切换刚结束、电流稳定区,纹波最小 (正确)
  3. 减少代码量
  4. 无功消耗低
提示:中心对齐计数器达到 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 线性区)