第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 波形,每一步都清晰可见。

SVPWM 核心逻辑流程图 SVPWM 核心逻辑流程图 输入 Uα, Uβ 扇区判断 计算 T1, T2, T0 过调制判断与处理 七段式 / 五段式选择 输出 PWM 波形 注意 过调制时需按比例 缩放 T1 和 T2 选择依据 低速:七段式 高速:五段式

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 的原理就讲到这里。你可能会问:七段式和五段式到底选哪个?我的建议是:先跑七段式,把电流环调稳了,再考虑切五段式降损耗。别一上来就追求极致效率,稳定才是第一位的。