2. 扇区判断:参考电压矢量扇区划分、扇区判断逻辑与实现方法

做 SVPWM 的第一步,就是搞清楚当前参考电压矢量落在哪个扇区。这就像导航先定位一样,位置错了,后面全白搭。我刚开始接触 SVPWM 时,觉得扇区判断不就是几个比较嘛,结果在项目里吃过亏——电机低速抖动,查了半天,原来是扇区边界判断不够精细。好,咱们今天就把这块彻底讲透。

2.1 扇区划分:六边形里的六个家

三相逆变器有 8 个开关状态,其中 6 个非零矢量把空间分成了 6 个扇区。每个扇区占 60°,从 0° 开始编号。

扇区编号规则(常用方式):

  • 扇区 I:0° ~ 60°
  • 扇区 II:60° ~ 120°
  • 扇区 III:120° ~ 180°
  • 扇区 IV:180° ~ 240°
  • 扇区 V:240° ~ 300°
  • 扇区 VI:300° ~ 360°

你想想看,为什么是 60°?因为 6 个非零矢量在空间上均匀分布,相邻矢量夹角正好 60°。这 6 个矢量围成一个正六边形,参考电压矢量就在这个六边形里转圈。

下面这张图展示了扇区划分和基本电压矢量的关系:

扇区划分与基本电压矢量 I II III IV V VI V₁(100) V₂(110) V₃(010) V₄(011) V₅(001) V₆(101) V₀(000) V₇(111) 0° 60° 扇区编号从 0° 开始逆时针递增,每个扇区 60°,共 6 个扇区覆盖整个 360° 空间。

2.2 扇区判断逻辑:从 αβ 到扇区号

实际代码里,我们通常用 α-β 坐标系下的分量 Uα 和 Uβ 来判断扇区。为什么要用 αβ?因为 Clark 变换后,三相变量变成了两相正交变量,判断起来特别方便。

判断逻辑的核心是三个中间变量:

三个判断基准量:

  • B₁ = Uβ —— 看 β 轴分量正负
  • B₂ = √3·Uα - Uβ —— 看与 60° 边界的关系
  • B₃ = -√3·Uα - Uβ —— 看与 120° 边界的关系

然后根据这三个量的符号,组合出扇区号。具体规则是这样的:

B₁ 符号 B₂ 符号 B₃ 符号 扇区号
++任意I
+-+II
+--III
-任意-IV
-+-V
-++VI

我的小技巧: 实际工程中,我习惯用查表法代替 if-else 链。把 B₁、B₂、B₃ 的符号位拼成一个 3 位二进制数,直接查表得到扇区号。这样代码更简洁,执行也快。

2.3 实现方法:C 代码实战

说了这么多理论,咱们直接上代码。这是我个人比较喜欢的一种实现方式,在多个项目里验证过,稳定可靠。

// 扇区判断函数
// 输入:Ualpha, Ubeta —— 参考电压的 αβ 分量
// 输出:扇区号 1~6
int svpwm_sector_detection(float Ualpha, float Ubeta)
{
    float B1, B2, B3;
    int sector = 0;
    int N = 0;
    
    // 计算三个判断基准量
    B1 = Ubeta;
    B2 = 1.7320508f * Ualpha - Ubeta;   // √3 ≈ 1.732
    B3 = -1.7320508f * Ualpha - Ubeta;
    
    // 符号判断,拼成 3 位二进制数
    // bit0: B1 > 0
    // bit1: B2 > 0
    // bit2: B3 > 0
    if (B1 > 0) N |= 1;
    if (B2 > 0) N |= 2;
    if (B3 > 0) N |= 4;
    
    // 查表得到扇区号
    // 这个表是我根据扇区分布规律总结的
    switch(N)
    {
        case 3: sector = 1; break;   // 011 -> 扇区 I
        case 1: sector = 2; break;   // 001 -> 扇区 II
        case 5: sector = 3; break;   // 101 -> 扇区 III
        case 4: sector = 4; break;   // 100 -> 扇区 IV
        case 6: sector = 5; break;   // 110 -> 扇区 V
        case 2: sector = 6; break;   // 010 -> 扇区 VI
        default: sector = 0; break;  // 异常情况
    }
    
    return sector;
}

我曾经踩过的坑: 浮点数比较时,边界值处理要小心。Uβ 刚好等于 0 时,B₁ 的符号判断可能因为浮点精度问题出错。我的做法是加一个很小的阈值,比如 1e-6,避免在零附近来回跳变。

2.4 扇区判断的工程优化

实际项目中,扇区判断的代码会被高频调用——PWM 周期通常是几十微秒,每个周期都要算一次。所以效率很重要。

我总结了几点优化经验:

  • 用定点数代替浮点数: 如果 MCU 没有 FPU,把 √3 放大成 Q15 或 Q31 格式,用整数运算。速度能快 3~5 倍。
  • 查表代替分支: 上面代码已经用了 switch-case,其实还可以进一步优化成直接数组索引,避免分支预测失败。
  • 边界处理: 扇区边界处,参考电压矢量可能在两个扇区间来回跳。加个滞环比较器,或者用上一拍的扇区结果做平滑。

扇区判断的完整流程:

  1. 获取 Uα、Uβ(来自 Clark 变换)
  2. 计算 B₁、B₂、B₃
  3. 符号判断,拼成 N 值
  4. 查表得到扇区号
  5. (可选)边界平滑处理

下面这张流程图,把整个扇区判断的逻辑串起来了:

扇区判断流程图 输入 Uα, Uβ 计算三个基准量 B₁=Uβ, B₂=√3Uα-Uβ, B₃=-√3Uα-Uβ 符号判断 → 拼成 N 值 查表得到扇区号 输出扇区号 1~6 整个流程在 PWM 周期内完成,通常耗时不到 1μs(含浮点运算)。

2.5 常见问题与避坑指南

做扇区判断时,有几个地方容易出问题,我挨个说一下:

  • 浮点精度问题: 尤其在扇区边界附近,Uβ 接近 0 时,符号判断可能反复跳变。加死区阈值能解决。
  • 坐标系混淆: 有人把 αβ 和 dq 搞混了。记住,扇区判断是在 αβ 静止坐标系下做的,不是旋转坐标系。
  • 过调制区域: 当参考电压幅值超过六边形内切圆时,扇区判断依然有效,但合成策略要调整。这个后面章节会讲。

我的调试习惯: 先用 MATLAB 或 Python 把扇区判断算法跑一遍,把 Uα、Uβ 和扇区号的对应关系画出来。确认逻辑正确后,再移植到 MCU 上。这样能省很多调试时间。