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变换的输出到最终得到扇区号:
4.5 工程中的注意事项
最后聊几个实际开发中容易踩的坑:
- 阈值处理:Vα和Vβ接近0的时候,判断结果会抖动。我一般加个死区,小于某个值就强制归零。
- 定点化:如果MCU没有FPU,建议把√3/2和1/2转成Q15格式的定点数,用移位代替乘法。
- 扇区边界:当矢量正好落在扇区边界上(比如正好60度),理论上两个扇区都可以。我习惯归到编号小的那个扇区。
- 调试技巧:刚开始调的时候,可以先用atan2算个参考值,跟三值逻辑的结果对比一下,确保映射表没错。
总结一下:扇区判断是整个SVPWM的“指路牌”。三值逻辑法用最少的计算量完成了这个任务,是工程上的标准做法。记住三个参考量、三个符号位、一个查表,就掌握了核心。