4、扇区判断:扇区划分逻辑、扇区编号规则、基于反Park变换的扇区判断方法

好,咱们继续往下走。前面我们把反Park变换搞清楚了,得到了Vα和Vβ。现在问题来了——这两个分量摆在这,我怎么知道当前要合成的电压矢量落在哪个扇区?

说白了,扇区判断就是SVPWM的第一步“定位”。你连目标在哪个区域都不知道,后面的开关管切换时序根本没法算。我刚开始学SVPWM的时候,就是卡在这一步,总觉得扇区判断很玄乎。后来自己手算了一遍,才发现其实特别简单。

4.1 扇区划分的逻辑

先说说为什么要把空间分成6个扇区。三相逆变器有6个开关管,组合出8个基本电压矢量——6个非零矢量和2个零矢量。这6个非零矢量在空间上正好相隔60度,把整个360度平面切成了6块。

你想想看,这就像切披萨。一刀切下去是60度,切6刀正好一圈。每个扇区里,我们都可以用相邻的两个基本矢量去合成任意想要的电压矢量。

核心逻辑:扇区划分的本质,就是把连续的电压空间离散化成6个可管理的区域。每个区域用两个边界矢量来合成内部任意矢量。

我在项目里遇到过一个问题:有人把扇区编号搞反了,导致电机反转。后来我养成了一个习惯——每次做扇区判断之前,先画个矢量图确认一下编号顺序。

4.2 扇区编号规则

扇区编号其实没有统一标准,不同文献可能编号方式不一样。我这里用的是最主流的规则——按逆时针方向,从α轴开始编号。

扇区编号 角度范围 边界矢量 说明
I 0° ~ 60° V1(100), V2(110) α轴正方向开始
II 60° ~ 120° V2(110), V3(010)
III 120° ~ 180° V3(010), V4(011)
IV 180° ~ 240° V4(011), V5(001)
V 240° ~ 300° V5(001), V6(101)
VI 300° ~ 360° V6(101), V1(100) 回到V1闭合

我的习惯:扇区编号从I到VI,对应二进制编号0~5。在代码里我通常用0~5而不是I~VI,这样数组索引方便。但画图分析时用罗马数字更直观。

4.3 基于反Park变换的扇区判断方法

好,重头戏来了。怎么用Vα和Vβ判断扇区?

最直接的方法——算角度。反正切一下:θ = atan2(Vβ, Vα),然后看θ落在哪个区间。但问题是,反正切计算量太大,在MCU上跑起来很慢。我早期用DSP做的时候,一个atan2要几十个时钟周期,太奢侈了。

所以工程上常用的是另一种方法——三值逻辑判断法。不需要算角度,只用比较和加减法。

4.3.1 三值逻辑的原理

这个方法的核心思想是:把Vα和Vβ组合成三个中间变量,然后看这三个变量的正负号。

定义三个参考量:

// 三个参考量
Vref1 = Vβ
Vref2 = (√3/2) * Vα - (1/2) * Vβ
Vref3 = -(√3/2) * Vα - (1/2) * Vβ

然后对每个参考量做符号判断:

  • 如果 Vref1 > 0,则 A = 1,否则 A = 0
  • 如果 Vref2 > 0,则 B = 1,否则 B = 0
  • 如果 Vref3 > 0,则 C = 1,否则 C = 0

最后算扇区号:

N = A + 2*B + 4*C

这个N值对应关系如下:

N值 扇区编号
3 I
1 II
5 III
4 IV
6 V
2 VI

注意:这个N值到扇区的映射表不是唯一的。不同文献可能用不同的映射关系。我曾经因为直接复制网上的代码,没检查映射表,结果电机转起来一顿一顿的。后来自己画矢量图重新推了一遍才搞定。

4.3.2 为什么这样能行?

你可能会问:这三个参考量是怎么来的?

其实很简单。Vref1就是Vβ本身,它判断的是矢量在α轴上方还是下方。Vref2和Vref3是把坐标系旋转了±60度后的投影。三个判断条件合在一起,正好把360度空间切成6份。

我个人觉得这个方法特别巧妙——只用加减法和比较,没有三角函数,没有除法,在定点MCU上跑起来飞快。

4.3.3 完整的判断代码

下面是我在实际项目中用的代码片段,加了注释:

// 输入:Valpha, Vbeta(反Park变换后的结果)
// 输出:sector(0~5,对应扇区I~VI)

int svpwm_sector_detect(float Valpha, float Vbeta)
{
    float Vref1, Vref2, Vref3;
    int A, B, C;
    int N;
    
    // 计算三个参考量
    Vref1 = Vbeta;
    Vref2 = 0.866025f * Valpha - 0.5f * Vbeta;   // √3/2 ≈ 0.866025
    Vref3 = -0.866025f * Valpha - 0.5f * Vbeta;
    
    // 符号判断
    A = (Vref1 > 0) ? 1 : 0;
    B = (Vref2 > 0) ? 1 : 0;
    C = (Vref3 > 0) ? 1 : 0;
    
    // 计算中间值
    N = A + 2*B + 4*C;
    
    // 查表映射到扇区
    switch(N)
    {
        case 3: return 0;  // 扇区I
        case 1: return 1;  // 扇区II
        case 5: return 2;  // 扇区III
        case 4: return 3;  // 扇区IV
        case 6: return 4;  // 扇区V
        case 2: return 5;  // 扇区VI
        default: return 0; // 容错处理
    }
}

避坑指南:注意浮点数比较时的精度问题。如果Vref1刚好等于0,理论上应该算正还是负?我一般把阈值设成1e-6,小于这个值就当0处理。另外,√3/2这个系数建议预计算成常量,别每次算都开根号。

4.4 扇区判断的SVG流程图

下面这张图把整个扇区判断的流程串起来了,从反Park变换的输出到最终得到扇区号:

扇区判断流程图 反Park变换输出 Vα, Vβ 计算三个参考量 Vref1=Vβ, Vref2=√3/2·Vα - 1/2·Vβ, Vref3=-√3/2·Vα - 1/2·Vβ 符号判断 A=(Vref1>0), B=(Vref2>0), C=(Vref3>0) N = A + 2B + 4C 查表得到扇区号 0~5 映射关系示例 N=3 → 扇区I N=1 → 扇区II N=5 → 扇区III 注意事项 浮点比较加阈值 系数预计算为常量 映射表需验证

4.5 工程中的注意事项

最后聊几个实际开发中容易踩的坑:

  • 阈值处理:Vα和Vβ接近0的时候,判断结果会抖动。我一般加个死区,小于某个值就强制归零。
  • 定点化:如果MCU没有FPU,建议把√3/2和1/2转成Q15格式的定点数,用移位代替乘法。
  • 扇区边界:当矢量正好落在扇区边界上(比如正好60度),理论上两个扇区都可以。我习惯归到编号小的那个扇区。
  • 调试技巧:刚开始调的时候,可以先用atan2算个参考值,跟三值逻辑的结果对比一下,确保映射表没错。

总结一下:扇区判断是整个SVPWM的“指路牌”。三值逻辑法用最少的计算量完成了这个任务,是工程上的标准做法。记住三个参考量、三个符号位、一个查表,就掌握了核心。