4、SVPWM原理与实现:空间矢量调制原理、扇区判断与作用时间、七段式与五段式SVPWM、代码实现与波形分析

好,咱们今天来啃一块硬骨头——SVPWM。

说实话,我刚入行那会儿,看到SVPWM的矢量图就头大。什么αβ坐标系、扇区判断、作用时间计算,感觉像在看天书。后来在项目里被波形畸变折磨了几个通宵,才真正搞明白这东西到底是怎么回事。

你想想看,FOC的核心目标是什么?就是让电机转得又稳又顺。而SVPWM,就是那个把理想电压矢量变成实际PWM波形的关键桥梁。没有它,你算出来的Ud、Uq再漂亮,也只是一堆没用的数字。

4.1 空间矢量调制原理

咱们先抛开公式,用直觉来理解。

三相逆变器有6个开关管,上下桥臂互补导通。所以一共就8种开关状态:6个非零矢量和2个零矢量(000和111)。

这6个非零矢量,在空间上把360°分成了6个扇区,每个扇区60°。你想想看,这就像你手里有6把尺子,但你要量出任意角度和长度的矢量——怎么办?

核心思想:用相邻的两个基本电压矢量,通过时间加权合成任意目标矢量。这就是「伏秒平衡」原则。

举个例子。假设你想要的电压矢量在扇区I,那就用V1(100)和V2(110)来合成。T1时间给V1,T2时间给V2,剩下的时间给零矢量。只要PWM周期足够短,电机看到的平均效果就是你想要的那个矢量。

我在项目中遇到过一个问题:当调制比接近1时,波形开始失真。后来才发现,是没处理好过调制的情况。嗯,这个后面会细说。

4.2 扇区判断与作用时间

好,理论说完了,咱们来点实际的。

4.2.1 扇区判断

怎么判断目标矢量在哪个扇区?

我个人的习惯是用Uα、Uβ的符号和大小关系来判断。其实很简单,你只需要三个中间变量:

// 扇区判断辅助变量
B1 = Ubeta;
B2 = (sqrt(3)/2)*Ualpha - 0.5*Ubeta;
B3 = (-sqrt(3)/2)*Ualpha - 0.5*Ubeta;

然后根据这三个值的正负,查表就能得到扇区号:

B1B2B3扇区
>0>0<0I
>0<0<0II
>0<0>0III
<0<0>0IV
<0>0>0V
<0>0<0VI

小技巧:实际代码里,我一般用查表法而不是if-else链。查表更快,而且代码更整洁。扇区号 = (B1>0) + 2*(B2>0) + 4*(B3>0),然后查一个6元素的表就行。

4.2.2 作用时间计算

扇区判断完了,接下来就是算T1和T2。

每个扇区的计算公式其实是对称的,只是符号和变量名不同。以扇区I为例:

// 扇区I的作用时间
T1 = (sqrt(3)*Tpwm/Udc) * (Ualpha*sin(60°) - Ubeta*cos(60°));
T2 = (sqrt(3)*Tpwm/Udc) * (-Ualpha*sin(0°) + Ubeta*cos(0°));

// 简化后
T1 = (Tpwm/Udc) * (Ualpha + Ubeta/sqrt(3));
T2 = (Tpwm/Udc) * (2*Ubeta/sqrt(3));

你可能会问:为什么每个扇区公式不一样?

其实本质是一样的,只是坐标系旋转了60°。我建议你把6个扇区的公式统一成一种形式,用查表法处理符号和变量交换。这样代码量能减少一半。

注意:算出来的T1+T2如果大于Tpwm,说明进入了过调制区。这时候需要等比例缩小:T1' = T1 * Tpwm/(T1+T2),T2' = T2 * Tpwm/(T1+T2)。我曾经在这个坑里摔过,波形直接削顶了。

4.3 七段式与五段式SVPWM

好,时间算出来了,怎么安排PWM波形?

这里有两种主流方式:七段式和五段式。

4.3.1 七段式SVPWM

七段式,顾名思义,一个PWM周期里分成7段。以扇区I为例:

// 七段式开关序列(扇区I)
// 000 -> 100 -> 110 -> 111 -> 110 -> 100 -> 000
// 零矢量分布在两端和中间

这样做的好处是:每个周期开关次数固定,谐波特性好。但缺点是开关损耗大——每次切换都有6次开关动作。

我个人习惯在低速时用七段式。因为低速时电流大,谐波引起的发热更明显,七段式的谐波性能更好。

4.3.2 五段式SVPWM

五段式就「偷懒」了。它把其中一个零矢量去掉,只保留一个:

// 五段式开关序列(扇区I)
// 000 -> 100 -> 110 -> 111 -> 110 -> 100
// 或者
// 100 -> 110 -> 111 -> 110 -> 100

开关次数从6次降到4次,开关损耗直接减少1/3。但代价是谐波含量增加,电流纹波变大。

对比项七段式五段式
开关次数/周期6次4次
开关损耗低(降33%)
谐波性能较差
适用场景低速、高精度高速、高效率

我的建议:量产项目中,我一般会根据转速动态切换。1000rpm以下用七段式,以上用五段式。这样既保证了低速的平稳性,又兼顾了高速的效率。

4.4 代码实现与波形分析

光说不练假把式。咱们直接上代码。

4.4.1 核心代码实现

// SVPWM主函数
void svpwm_calc(SVPWM_Handle *h)
{
    float Ualpha = h->Ualpha;
    float Ubeta  = h->Ubeta;
    float Tpwm   = h->Tpwm;
    float Udc    = h->Udc;
    
    // 1. 扇区判断
    float B1 = Ubeta;
    float B2 = 0.866f*Ualpha - 0.5f*Ubeta;  // sqrt(3)/2 ≈ 0.866
    float B3 = -0.866f*Ualpha - 0.5f*Ubeta;
    
    uint8_t sector = 0;
    if(B1 > 0) sector |= 0x01;
    if(B2 > 0) sector |= 0x02;
    if(B3 > 0) sector |= 0x04;
    
    // 查表得到实际扇区号(0-5)
    const uint8_t sector_table[8] = {0,1,5,0,3,2,4,0};
    sector = sector_table[sector];
    
    // 2. 计算X,Y,Z
    float X = (sqrt3*Ubeta*Tpwm) / Udc;
    float Y = (1.5f*Ualpha + 0.866f*Ubeta) * Tpwm / Udc;
    float Z = (-1.5f*Ualpha + 0.866f*Ubeta) * Tpwm / Udc;
    
    // 3. 根据扇区查T1,T2
    float T1, T2;
    switch(sector)
    {
        case 0: T1 = Z; T2 = Y; break;
        case 1: T1 = Y; T2 = -X; break;
        case 2: T1 = -Z; T2 = X; break;
        case 3: T1 = -X; T2 = Z; break;
        case 4: T1 = X; T2 = -Y; break;
        case 5: T1 = -Y; T2 = -Z; break;
    }
    
    // 4. 过调制处理
    float Ts = T1 + T2;
    if(Ts > Tpwm)
    {
        float scale = Tpwm / Ts;
        T1 *= scale;
        T2 *= scale;
    }
    
    // 5. 计算占空比(七段式)
    float Ta = (Tpwm - T1 - T2) * 0.5f;
    float Tb = Ta + T1;
    float Tc = Tb + T2;
    
    // 6. 根据扇区分配三相占空比
    switch(sector)
    {
        case 0: h->Ta = Tb; h->Tb = Ta; h->Tc = Tc; break;
        case 1: h->Ta = Ta; h->Tb = Tc; h->Tc = Tb; break;
        case 2: h->Ta = Ta; h->Tb = Tb; h->Tc = Tc; break;
        // ... 其他扇区类似
    }
}

4.4.2 波形分析

代码写完了,怎么验证对不对?

我的习惯是先用仿真看波形。重点关注三个地方:

  1. 相电压波形:应该是马鞍形,而不是正弦波。这是SVPWM的特征——它在正弦波上叠加了三次谐波,提高了母线电压利用率。
  2. 线电压波形:应该是正弦波。如果线电压有畸变,说明扇区切换有问题。
  3. 电流波形:正弦度好不好?有没有明显的6次谐波?

关键指标:SVPWM的母线电压利用率比SPWM高15.47%。也就是说,同样的母线电压,SVPWM能让电机跑得更快。这也是为什么FOC几乎都用SVPWM的原因。

我记得有一次调试,电流波形总是有毛刺。查了半天,发现是PWM死区时间设置不对。死区补偿没做好,电流过零点附近就会出现畸变。嗯,这个后面专门有一章讲死区补偿。

4.5 本章小结

好,咱们捋一捋今天的内容:

  • SVPWM的本质:用相邻矢量合成目标矢量,遵循伏秒平衡
  • 扇区判断:用Uα、Uβ的符号组合查表,简单高效
  • 作用时间:每个扇区公式对称,建议统一处理
  • 七段式 vs 五段式:低速用七段,高速用五段,灵活切换
  • 代码实现:注意过调制处理和扇区查表

下一章咱们聊电流采样和重构。采样时序搞不好,FOC就是空中楼阁。到时候我会分享一个我在采样上踩过的坑——保证让你印象深刻。

课后练习:试着把上面的代码改成五段式SVPWM。提示:只需要修改占空比计算部分,把零矢量的分配方式改一下就行。