4. SVPWM扇区判断:扇区划分原理、扇区判断算法、基于电压分量的扇区判定

各位工程师朋友,欢迎来到SVPWM的第四讲。前面我们聊了电压矢量的合成原理,也讲了如何用六个基本矢量去逼近一个旋转的参考矢量。但有个问题一直悬着:我怎么知道当前要合成的参考电压矢量落在哪个扇区?

这个问题不解决,后面的矢量作用时间计算就无从谈起。今天我们就来彻底搞定它。

4.1 扇区划分的底层逻辑

先看一张图,这是我个人习惯用的扇区划分方式——按空间角度每60°一个扇区,逆时针编号I~VI。

核心要点:扇区划分的本质,就是把360°的电压矢量空间切成6块,每块对应一对基本矢量的合成区域。

SVPWM六扇区划分示意图 V₁(100) V₂(110) V₃(010) V₄(011) V₅(001) V₆(101) I II III IV V VI 0° 60° 120° 180° 240° 300° 扇区I: 0°~60° | 扇区II: 60°~120° | 扇区III: 120°~180° | 扇区IV: 180°~240° | 扇区V: 240°~300° | 扇区VI: 300°~360°

你看,六个基本矢量把平面分成六个60°的扇形区域。每个扇区内的任意参考矢量,都可以用该扇区边界的两个基本矢量来合成。比如扇区I,就是用V₁(100)和V₂(110)来合成。

这里有个细节我提醒一下:扇区边界本身也是基本矢量的方向。如果参考矢量正好落在边界上,那就只用两个矢量中的一个,另一个作用时间为零。这种情况在实际控制中很少见,但做算法时要考虑到。

4.2 扇区判断的数学原理

好了,扇区画出来了。现在的问题是:给定一个参考电压矢量Vref,我怎么知道它在哪个扇区?

最直观的方法是用角度。算出Vref与α轴的夹角θ,然后看θ落在哪个区间:

扇区 角度范围 对应基本矢量
I 0° ≤ θ < 60° V₁(100), V₂(110)
II 60° ≤ θ < 120° V₂(110), V₃(010)
III 120° ≤ θ < 180° V₃(010), V₄(011)
IV 180° ≤ θ < 240° V₄(011), V₅(001)
V 240° ≤ θ < 300° V₅(001), V₆(101)
VI 300° ≤ θ < 360° V₆(101), V₁(100)

这个方法理论上没问题,但实际工程中我基本不用。为什么?因为要算反正切函数,计算量大,而且角度判断还有边界模糊的问题。

我的经验:在DSP或MCU里,反正切函数通常要几十个指令周期。如果PWM频率是10kHz,每个周期都要算一次,CPU开销不小。更关键的是,角度法对电压采样噪声敏感——采样抖动一下,角度跳变,扇区判断就可能出错。

4.3 基于电压分量的扇区判定算法

那实际工程中用什么方法?用电压分量直接判断。这个方法不需要算角度,只需要比较Vα和Vβ的大小关系。

具体怎么做?我们先定义三个中间变量:

// 定义三个判定变量
V_a = V_beta
V_b = (sqrt(3)/2) * V_alpha - (1/2) * V_beta
V_c = -(sqrt(3)/2) * V_alpha - (1/2) * V_beta

然后根据这三个变量的符号,就能唯一确定扇区。判断规则如下:

V_a 符号 V_b 符号 V_c 符号 扇区编号
+ + - I
+ - - II
+ - + III
- - + IV
- + + V
- + - VI

你想想看,这个判断过程只需要比较和加减运算,没有三角函数,没有除法,计算量极小。在C代码里实现就是几条if语句的事。

算法优势:基于电压分量的扇区判定,计算量只有角度法的1/10左右,且对采样噪声的鲁棒性更好。

4.4 工程实现:C代码示例

下面是我在一个电机驱动项目里实际用过的代码片段。这个项目用的是STM32F4,PWM频率8kHz,电流环周期125μs。

// 扇区判断函数
// 输入: V_alpha, V_beta (标幺值)
// 输出: 扇区编号 1~6
int SVPWM_CalcSector(float V_alpha, float V_beta)
{
    float V_a, V_b, V_c;
    int sector = 0;
    
    // 计算三个判定变量
    V_a = V_beta;
    V_b = 0.8660254f * V_alpha - 0.5f * V_beta;   // sqrt(3)/2 ≈ 0.866
    V_c = -0.8660254f * V_alpha - 0.5f * V_beta;
    
    // 根据符号组合判断扇区
    if (V_a > 0) sector = 1;      // V_a为正,扇区在I/II/III
    if (V_b > 0) sector |= 2;     // V_b为正,扇区在I/V/VI
    if (V_c > 0) sector |= 4;     // V_c为正,扇区在III/IV/V
    
    // 查表得到最终扇区编号
    const int sector_map[8] = {0, 2, 6, 1, 4, 3, 5, 0};
    return sector_map[sector];
}

我曾经踩过的坑:一开始我用的是角度法判断扇区,结果在电机低速运行时,电流采样噪声导致角度抖动,扇区频繁误判,电机噪音很大。后来换成电压分量法,问题立刻解决。所以我的建议是——能用电压分量法就别用角度法。

4.5 扇区判断的边界处理

实际运行中,参考矢量可能正好落在扇区边界上。比如Vβ = 0且Vα > 0时,矢量在0°方向,属于扇区I和扇区VI的边界。

这种情况下怎么处理?我的做法是:统一归到编号较小的扇区。比如0°边界归到扇区I,60°边界归到扇区II,以此类推。这样处理的好处是避免扇区在边界处来回跳变。

另外,当Vα和Vβ都很小(接近零矢量)时,扇区判断会变得不稳定。这时候我通常会加一个死区判断:如果Vref的幅值小于某个阈值,直接输出零矢量,不做扇区判断。

实用技巧:阈值一般取母线电压的1%~2%。比如母线电压300V,阈值设3~6V。这样既不影响正常调制,又能避免零矢量附近的误判。

4.6 本章小结

扇区判断是SVPWM的"入口"环节,判断错了后面全错。记住三个要点:

  • 扇区划分:六个60°扇区,每个扇区用两个相邻基本矢量合成
  • 判断方法:用Vα、Vβ计算三个判定变量,查符号表得到扇区
  • 工程注意:边界统一归小扇区,零矢量附近加死区判断