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 个矢量围成一个正六边形,参考电压矢量就在这个六边形里转圈。
下面这张图展示了扇区划分和基本电压矢量的关系:
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,其实还可以进一步优化成直接数组索引,避免分支预测失败。
- 边界处理: 扇区边界处,参考电压矢量可能在两个扇区间来回跳。加个滞环比较器,或者用上一拍的扇区结果做平滑。
扇区判断的完整流程:
- 获取 Uα、Uβ(来自 Clark 变换)
- 计算 B₁、B₂、B₃
- 符号判断,拼成 N 值
- 查表得到扇区号
- (可选)边界平滑处理
下面这张流程图,把整个扇区判断的逻辑串起来了:
2.5 常见问题与避坑指南
做扇区判断时,有几个地方容易出问题,我挨个说一下:
- 浮点精度问题: 尤其在扇区边界附近,Uβ 接近 0 时,符号判断可能反复跳变。加死区阈值能解决。
- 坐标系混淆: 有人把 αβ 和 dq 搞混了。记住,扇区判断是在 αβ 静止坐标系下做的,不是旋转坐标系。
- 过调制区域: 当参考电压幅值超过六边形内切圆时,扇区判断依然有效,但合成策略要调整。这个后面章节会讲。
我的调试习惯: 先用 MATLAB 或 Python 把扇区判断算法跑一遍,把 Uα、Uβ 和扇区号的对应关系画出来。确认逻辑正确后,再移植到 MCU 上。这样能省很多调试时间。