第四节:基本电压矢量与扇区划分

好,咱们今天聊点实在的。SVPWM 的核心,说白了就是怎么用八个开关状态去逼近一个旋转的电压圆。这八个状态,就是六个非零矢量和两个零矢量。你想想看,一个三相逆变器,六个开关管,能组合出多少种状态?2³ = 8 种。没错,就是这八种。

4.1 六个非零矢量与两个零矢量

这八个状态,我习惯把它们画在一个复平面上。六个非零矢量,每个相隔 60°,正好把 360° 的圆分成六等份。两个零矢量呢?就是所有上桥臂全通或者全断,输出电压为零。

具体来说,非零矢量 V1(100) 到 V6(101),每个矢量对应一个特定的开关组合。比如 V1(100) 表示 A 相上桥臂导通,B、C 相下桥臂导通。这时候合成的电压矢量指向 0° 方向。V2(110) 指向 60°,以此类推。

关键点:六个非零矢量的幅值都是 (2/3)Vdc,方向固定。两个零矢量 V0(000) 和 V7(111) 幅值为零,位于原点。

我记得刚做电机控制那会儿,总搞不清为什么是 (2/3)Vdc。后来推导了一遍 Clarke 变换才明白——这是等幅值变换的必然结果。你如果做等功率变换,幅值就是 √(2/3)Vdc。嗯,这里要注意,不同变换下的系数不一样,别搞混了。

矢量 开关状态 (A B C) 幅值 角度
V0 000 0 -
V1 100 2/3 Vdc 0°
V2 110 2/3 Vdc 60°
V3 010 2/3 Vdc 120°
V4 011 2/3 Vdc 180°
V5 001 2/3 Vdc 240°
V6 101 2/3 Vdc 300°
V7 111 0 -

我的小技巧:记不住矢量顺序?看开关状态二进制数,从 V1(100) 开始,每次只改变一个 bit,沿着六边形走一圈。V1→V2→V3→V4→V5→V6,刚好一个循环。

4.2 扇区划分方法

六个非零矢量把平面分成六个扇区,每个扇区 60°。扇区 I 在 0°~60°,扇区 II 在 60°~120°,依此类推。为什么要分扇区?因为我们要用相邻的两个非零矢量去合成任意方向的目标矢量。

判断目标矢量在哪个扇区,我见过三种方法:

  1. 角度法:直接算目标矢量的角度 θ,看落在哪个区间。最简单,但需要反正切运算,DSP 里比较费时间。
  2. Clark 分量法:用 Vα、Vβ 的正负和比值来判断。不用算角度,快很多。
  3. 三值逻辑法:通过三个参考值 A、B、C 的符号组合直接查表。我最常用这个,一个 if-else 就搞定。

我个人推荐第三种。为什么?因为嵌入式里最怕浮点运算。三值逻辑法只用比较和移位,纯整数操作,跑起来飞快。

曾经踩过的坑:有一次我用角度法判断扇区,atan2 函数在边界处有 ±1° 的误差,导致扇区判断偶尔跳变,电流波形出现毛刺。后来换成三值逻辑法,问题立刻解决。边界处理一定要留余量,别卡在 0°、60° 这些临界点上。

4.3 三值逻辑法详解

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

// 假设 Vα、Vβ 已经通过 Clark 变换得到
// 定义三个参考值
B1 = Vβ
B2 = (√3/2)*Vα - (1/2)*Vβ
B3 = -(√3/2)*Vα - (1/2)*Vβ

// 然后判断符号
if (B1 > 0) A = 1 else A = 0
if (B2 > 0) B = 1 else B = 0
if (B3 > 0) C = 1 else C = 0

// 扇区号 = A + 2*B + 4*C
sector = A + (B << 1) + (C << 2)

算出来的 sector 值 1~6 分别对应扇区 I~VI。你可能会问,为什么是这三个公式?其实它们对应的是三条直线:Vβ=0、Vβ=√3 Vα、Vβ=-√3 Vα。这三条线正好把平面分成六个 60° 扇区。

下面这张图把整个结构画清楚了:

SVPWM 基本矢量与扇区划分 V1 V2 V3 V4 V5 V6 V0/V7 扇区 I 扇区 II 扇区 III 扇区 IV 扇区 V 扇区 VI 0° 60° 120° 180° 240° 300° 说明: 六个非零矢量将平面分成六个扇区,每个扇区 60°。两个零矢量位于原点。 扇区判断通过三值逻辑法:B1=Vβ, B2=√3/2·Vα - 1/2·Vβ, B3=-√3/2·Vα - 1/2·Vβ

4.4 扇区判断的工程实现

在实际代码里,我一般这么写:

// 扇区判断函数,输入 Vα, Vβ,输出扇区号 1~6
uint8_t svpwm_sector_calc(float Valpha, float Vbeta)
{
    uint8_t sector = 0;
    float B1, B2, B3;
    uint8_t A, B, C;
    
    // 计算三个参考值
    B1 = Vbeta;
    B2 = 0.866025f * Valpha - 0.5f * Vbeta;  // √3/2 ≈ 0.866
    B3 = -0.866025f * Valpha - 0.5f * Vbeta;
    
    // 符号判断
    A = (B1 > 0.0f) ? 1 : 0;
    B = (B2 > 0.0f) ? 1 : 0;
    C = (B3 > 0.0f) ? 1 : 0;
    
    // 组合扇区号
    sector = A + (B << 1) + (C << 2);
    
    return sector;
}

这段代码在 C2000 或者 STM32 上跑,大概只需要几十个时钟周期。我曾经在一个 60MHz 的 MCU 上做过测试,扇区判断加矢量作用时间计算,总共不到 5μs。对于 10kHz 的开关频率来说,绰绰有余。

优化建议:如果 MCU 没有硬件浮点单元,可以把 √3/2 和 1/2 转成 Q15 或 Q12 格式的定点数。这样比较和移位都是整数运算,速度还能再快一倍。

4.5 扇区与矢量作用时间的关系

知道目标矢量在哪个扇区后,下一步就是计算相邻两个非零矢量的作用时间。比如目标矢量在扇区 I,就用 V1 和 V2 来合成。作用时间 T1、T2 由伏秒平衡原理决定:

T1 = Ts * (Vref / Vdc) * sin(60° - θ) / sin(60°)
T2 = Ts * (Vref / Vdc) * sin(θ) / sin(60°)
T0 = Ts - T1 - T2

其中 Ts 是开关周期,Vref 是目标矢量幅值,θ 是目标矢量在扇区内的相对角度(0°~60°)。T0 是零矢量作用时间,用来补满整个周期。

这里有个细节:当 Vref 超过六边形内切圆半径时,T1+T2 会大于 Ts。这就是过调制区。我在做伺服驱动器时遇到过这个问题,电机在高速区转矩突然下降。后来加了过调制处理,把超出部分按比例压缩,才把高速性能提上来。

重要提醒:扇区判断的边界值一定要做滞回处理。比如在 0° 附近,由于采样噪声,Vβ 可能在 0 附近来回跳,导致扇区在 I 和 VI 之间频繁切换。加一个 0.01Vdc 的滞回区间,就能避免这个问题。

好了,扇区划分这部分就聊到这儿。记住三个核心点:六个非零矢量、两个零矢量、三值逻辑判断法。下节课咱们接着聊矢量作用时间的计算和 PWM 占空比的生成。