4、SVPWM算法实现:扇区判断、矢量作用时间计算、占空比更新、过调制处理

SVPWM,说白了就是让电机转得又稳又顺的核心算法。很多初学者觉得它很神秘,其实拆开来看,就是四个步骤:扇区判断 → 时间计算 → 占空比更新 → 过调制处理。每一步都有坑,我踩过的坑不少,今天一次性给你讲透。

核心思路: 把三相电压指令,转换成六个功率管开关的占空比,让合成电压矢量沿着圆形轨迹旋转。

4.1 扇区判断——先搞清楚电压矢量落在哪

拿到 Vα 和 Vβ 之后,第一件事就是判断合成矢量在哪个扇区。为什么?因为不同扇区里,相邻两个基本矢量的组合不一样。

我习惯用 三值判断法,简单又高效。先算三个中间变量:

// 三个参考量
B1 = Vβ
B2 = (√3/2)*Vα - (1/2)*Vβ
B3 = -(√3/2)*Vα - (1/2)*Vβ

// 扇区号计算
N = 4*sign(B1) + 2*sign(B2) + 1*sign(B3)

这里的 sign() 是符号函数,大于0返回1,否则返回0。算出来的 N 值在 1~6 之间,直接对应扇区编号。我在项目里用过查表法,也用过 if-else 链,最后还是觉得这个位运算方法最稳——没有分支预测惩罚,执行时间固定。

N 值 扇区 基本矢量
1 扇区 II V2(010), V6(110)
2 扇区 VI V5(001), V1(100)
3 扇区 I V4(011), V6(110)
4 扇区 IV V1(100), V3(010)
5 扇区 III V3(010), V2(110)
6 扇区 V V5(001), V4(011)
我的小技巧: 调试时把 N 值和扇区号打印出来,用手转动电机转子,看扇区切换是否连续。如果出现跳变,大概率是 Vα/Vβ 符号反了。

4.2 矢量作用时间计算——T1 和 T2 怎么算

知道扇区之后,就要算两个相邻基本矢量的作用时间 T1 和 T2。公式其实是从 伏秒平衡原理 推出来的:

// 以扇区 I 为例
T1 = (√3 * Ts / Vdc) * ( (√3/2)*Vα - (1/2)*Vβ )
T2 = (√3 * Ts / Vdc) * Vβ

每个扇区的公式不一样,但可以统一用三个通用变量 X、Y、Z 来算:

X = (√3 * Ts / Vdc) * Vβ
Y = (√3 * Ts / Vdc) * ( (√3/2)*Vα + (1/2)*Vβ )
Z = (√3 * Ts / Vdc) * ( -(√3/2)*Vα + (1/2)*Vβ )

// 根据扇区查表
switch(N) {
    case 1: T1 = Z; T2 = Y; break;  // 扇区 II
    case 2: T1 = Y; T2 = -X; break; // 扇区 VI
    case 3: T1 = -Z; T2 = X; break; // 扇区 I
    case 4: T1 = -X; T2 = Z; break; // 扇区 IV
    case 5: T1 = X; T2 = -Y; break; // 扇区 III
    case 6: T1 = -Y; T2 = -Z; break; // 扇区 V
}

这里有个坑:T1 + T2 可能超过 PWM 周期 Ts。一旦超过,就进入过调制区了。

4.3 占空比更新——七段式 vs 五段式

算出 T1、T2 之后,还要插入零矢量(V0 或 V7)来填满整个周期。我常用的是 七段式SVPWM,谐波特性好,电流纹波小。

先算三个比较值:

Ta = (Ts - T1 - T2) / 4
Tb = Ta + T1 / 2
Tc = Tb + T2 / 2

然后根据扇区,把 Ta、Tb、Tc 分配给三相占空比寄存器:

扇区 U相 V相 W相
I Tb Ta Tc
II Ta Tb Tc
III Ta Tc Tb
IV Tc Tb Ta
V Tc Ta Tb
VI Tb Tc Ta
注意: 占空比更新一定要在 PWM 周期开始的 下溢中断 里做。我曾经在周期中间更新,结果波形出现毛刺,电机嗡嗡响了好久才排查出来。

4.4 过调制处理——电压不够用怎么办

当 T1 + T2 > Ts 时,说明电压指令已经超出了六边形内切圆的范围。这时候如果不处理,输出波形会严重畸变。

我常用的过调制策略分两级:

  1. 轻度过调制(调制比 0.907~0.952): 等比例缩小 T1 和 T2,保持矢量方向不变。
  2. 深度过调制(调制比 0.952~1.0): 调整矢量角度,牺牲一点谐波性能,换取更高的电压利用率。
// 轻度过调制处理
if (T1 + T2 > Ts) {
    float scale = Ts / (T1 + T2);
    T1 *= scale;
    T2 *= scale;
}

这个缩放操作,说白了就是让合成矢量沿着六边形边界走。虽然电压利用率能提升到 1.0,但电流谐波会明显增大。我在做风机项目时,过调制开到 1.05 倍,结果电机温度直接飙了 15 度——散热设计一定要留余量。

4.5 整体流程图

下面这张图把整个 SVPWM 的流程串起来了,建议你收藏起来,调试时对照着看:

SVPWM 算法流程图 SVPWM 算法完整流程 输入 Vα, Vβ 扇区判断 (N=1~6) 计算 X, Y, Z 查表得 T1, T2 T1+T2 > Ts ? 是 过调制处理 否 计算占空比 Ta,Tb,Tc 更新 PWM 寄存器 关键参数 • Ts: PWM 周期 • Vdc: 母线电压 • 调制比 = |Vref| / (Vdc/√3)

4.6 调试中的常见坑

  • 扇区跳变不连续: 检查 Vα/Vβ 的符号和幅值,尤其是 Clarke 变换的系数对不对。
  • 电流波形有缺口: 大概率是占空比更新时机不对,改用 PWM 下溢中断更新。
  • 过调制后电机抖动: 先确认母线电压采样是否准确,再检查缩放系数有没有溢出。
  • GD32 的定时器配置: 注意互补通道的死区时间,我一般设 500ns~1μs,具体看功率管规格。
调试利器: 用 DAC 输出 T1 和 T2 的实时值,示波器一看就知道有没有进入过调制区。这个方法比看电流波形直观多了。

嗯,SVPWM 这块内容就这些。代码写起来其实不多,但每个细节都影响最终效果。你动手实现的时候,建议先从开环 V/F 控制开始,把 SVPWM 调稳了,再上 FOC 闭环。这样排查问题会轻松很多。