3、扇区判断与作用时间计算:SVPWM的核心算法

说实话,很多初学者一上来就被SVPWM的扇区判断和时间计算给唬住了。什么Clarke变换、Park变换、扇区编号、作用时间……看着公式一堆,心里就发怵。

但我想告诉你的是——这东西没那么玄乎。说白了,SVPWM的核心就两件事:判断参考电压矢量在哪个扇区,然后算出相邻两个基本矢量的作用时间。搞懂了这两步,整个SVPWM的骨架就搭起来了。

我当年刚接触伺服驱动时,也在这块卡了很久。后来发现,只要把空间矢量图画出来,再配合几个简单的逻辑判断,一切就都清晰了。嗯,咱们今天就把它彻底讲透。

3.1 扇区判断:三步定位法

先说说扇区判断。参考电压矢量 \( V_{ref} \) 在 \(\alpha\beta\) 坐标系下旋转,它落在哪个扇区,我们就用哪两个相邻的基本矢量去合成它。

怎么判断?我习惯用三变量符号法,简单又可靠。

首先,定义三个中间变量:

B1 = Vβ
B2 = (√3/2) * Vα - (1/2) * Vβ
B3 = -(√3/2) * Vα - (1/2) * Vβ

然后,根据这三个变量的符号,得到一个扇区编号 N:

N = sign(B1) + 2 * sign(B2) + 4 * sign(B3)

其中 sign(x) 在 x>0 时取 1,x<0 时取 0。

最后,查表就能得到扇区号:

N 值 1 2 3 4 5 6
扇区号 II VI I IV III V
我的小技巧: 实际写代码时,我一般直接用 N 值做索引,省去查表这一步。比如定义一个数组 sector_map[6] = {2, 6, 1, 4, 3, 5},直接映射。这样既快又不容易出错。

3.2 作用时间计算:从几何到代数

扇区判断完了,接下来就是算时间。这个其实是个伏秒平衡的问题——用相邻两个基本矢量和零矢量,在时间上平均出参考电压矢量。

以扇区 I 为例,参考矢量 \( V_{ref} \) 由 \( V_4(100) \) 和 \( V_6(110) \) 合成。设作用时间分别为 \( T_4 \) 和 \( T_6 \),PWM 周期为 \( T_s \),零矢量作用时间为 \( T_0 \)。

根据伏秒平衡:

V_ref * T_s = V_4 * T_4 + V_6 * T_6 + V_0 * T_0

在 \(\alpha\beta\) 坐标系下展开,解方程得到:

T_4 = (√3 * T_s / V_dc) * ( (√3/2) * Vα - (1/2) * Vβ )
T_6 = (√3 * T_s / V_dc) * Vβ

其他扇区也是类似的思路,只是符号和顺序不同。我整理了一个通用公式,可以直接套用:

扇区 T_x(第一个矢量) T_y(第二个矢量)
I T_4 = K * ( (√3/2) * Vα - 0.5 * Vβ ) T_6 = K * Vβ
II T_6 = K * ( (√3/2) * Vα + 0.5 * Vβ ) T_2 = K * ( - (√3/2) * Vα + 0.5 * Vβ )
III T_2 = K * Vβ T_3 = K * ( - (√3/2) * Vα - 0.5 * Vβ )
IV T_3 = K * ( - (√3/2) * Vα + 0.5 * Vβ ) T_1 = K * ( -Vβ )
V T_1 = K * ( - (√3/2) * Vα - 0.5 * Vβ ) T_5 = K * ( (√3/2) * Vα - 0.5 * Vβ )
VI T_5 = K * ( -Vβ ) T_4 = K * ( (√3/2) * Vα + 0.5 * Vβ )

其中 \( K = \sqrt{3} \cdot T_s / V_{dc} \)。

注意: 算出来的 T_x 和 T_y 可能超过 T_s。这时候需要做过调制处理。我一般这样处理:如果 T_x + T_y > T_s,就按比例缩小:
T_x' = T_x * T_s / (T_x + T_y)
T_y' = T_y * T_s / (T_x + T_y)
T_0 = 0
这样虽然会损失一点电压利用率,但能保证系统稳定运行。

3.3 七段式与五段式:两种调制策略

时间算出来了,怎么安排开关顺序?这里有两种主流策略:七段式和五段式。

七段式是我用得最多的。它在每个 PWM 周期内,开关状态按对称的方式切换。以扇区 I 为例,顺序是:

000 → 100 → 110 → 111 → 110 → 100 → 000

这样每个周期有 7 段,谐波特性好,电流纹波小。但开关次数多,损耗大一点。

五段式则省掉了零矢量 111,只保留 000,顺序变成:

000 → 100 → 110 → 100 → 000

开关次数少了 1/3,损耗降低,但谐波会大一些。

策略 开关次数 谐波特性 适用场景
七段式 多 好 对电流质量要求高的场合
五段式 少 一般 对效率要求高的场合
我的经验: 在伺服驱动中,我一般用七段式。因为伺服对电流纹波和转矩脉动比较敏感,多花点开关损耗换更好的性能,值得。但在一些大功率、低开关频率的场合,五段式会更合适。

3.4 整体流程:一张图说清楚

说了这么多,咱们用一张流程图把整个 SVPWM 的核心逻辑串起来。从参考电压输入,到扇区判断、时间计算、过调制处理,再到生成 PWM 占空比,一步到位。

SVPWM 核心算法流程图 输入 Vα, Vβ, Ts, Vdc 计算 B1, B2, B3 → 扇区 N 查表计算 Tx, Ty Tx + Ty > Ts ? 是 否 比例缩小 Tx, Ty T0 = Ts - Tx - Ty 生成 PWM 占空比 说明:过调制时 T0=0,电压利用率最高可达 1.1547 倍

3.5 代码实现:从理论到实践

理论讲完了,咱们看看代码怎么写。下面是一个完整的 SVPWM 核心函数,我把它写成了 C 语言风格,方便你移植到 DSP 或 MCU 上。

void svpwm_calc(float V_alpha, float V_beta, float Ts, float Vdc,
                float *Ta, float *Tb, float *Tc) {
    float B1, B2, B3;
    int N, sector;
    float Tx, Ty, T0;
    float K = 1.732f * Ts / Vdc;  // √3 ≈ 1.732

    // 1. 计算中间变量
    B1 = V_beta;
    B2 = 0.866f * V_alpha - 0.5f * V_beta;   // √3/2 ≈ 0.866
    B3 = -0.866f * V_alpha - 0.5f * V_beta;

    // 2. 扇区判断
    N = (B1 > 0) + 2 * (B2 > 0) + 4 * (B3 > 0);
    int sector_map[6] = {2, 6, 1, 4, 3, 5};
    sector = sector_map[N - 1];

    // 3. 计算作用时间
    switch(sector) {
        case 1:
            Tx = K * (0.866f * V_alpha - 0.5f * V_beta);
            Ty = K * V_beta;
            break;
        case 2:
            Tx = K * (0.866f * V_alpha + 0.5f * V_beta);
            Ty = K * (-0.866f * V_alpha + 0.5f * V_beta);
            break;
        // ... 其他扇区类似
    }

    // 4. 过调制处理
    if (Tx + Ty > Ts) {
        float scale = Ts / (Tx + Ty);
        Tx *= scale;
        Ty *= scale;
        T0 = 0;
    } else {
        T0 = Ts - Tx - Ty;
    }

    // 5. 生成三相占空比(七段式,扇区I为例)
    float T1 = T0 / 4;          // 000
    float T2 = T1 + Tx / 2;     // 100
    float T3 = T2 + Ty / 2;     // 110
    // 根据扇区映射到 Ta, Tb, Tc
    // ...
}
避坑指南: 我曾经在过调制处理上栽过跟头。当时没做比例缩小,直接截断 Tx 和 Ty,结果电流波形出现了明显的削顶失真。后来改成比例缩小,波形就平滑多了。记住:过调制时一定要保持 Tx 和 Ty 的比例不变。

3.6 小结

扇区判断和作用时间计算,是 SVPWM 的心脏。你只要记住:

  • 扇区判断:用三个中间变量的符号,三步定位到扇区
  • 时间计算:根据伏秒平衡,查表得到 Tx 和 Ty
  • 过调制处理:超时按比例缩小,别直接截断
  • 调制策略:七段式谐波好,五段式损耗低,按需选择

把这些搞明白了,SVPWM 的骨架你就搭起来了。剩下的就是根据实际硬件去调参数、做优化。嗯,这部分咱们后面再细聊。