3. SVPWM调制算法实现

任务目标

实现SVPWM调制算法,输入为静止α-β坐标系下的电压矢量分量(Uα、Uβ),输出为三相逆变器六个功率开关管的占空比信号(Ta、Tb、Tc),并通过仿真验证调制后逆变器输出的相电压波形接近正弦。

实现原理

SVPWM的核心思想是将期望电压矢量分解到由六个非零基本矢量(V1~V6)和两个零矢量(V0、V7)组成的八种开关状态中,通过在一个PWM周期内组合相邻基本矢量与零矢量,使平均输出电压等于期望矢量。实现步骤为:

  1. 判断期望矢量所在扇区;
  2. 计算相邻基本矢量的作用时间(X、Y、Z);
  3. 根据扇区分配各相占空比;
  4. 生成中心对齐的PWM波形。

关键完整代码

#include <stdio.h>
#include <math.h>

#define PI 3.14159265358979
#define T_SAMPLE 0.0001  // PWM周期 100us
#define V_DC 24.0         // 母线电压

typedef struct {
    float u_alpha;
    float u_beta;
} Vector2D;

typedef struct {
    float ta;  // A相上管占空比
    float tb;
    float tc;
} DutyCycles;

// 扇区判断
int calc_sector(Vector2D v) {
    int sector = 0;
    if (v.u_beta > 0) sector |= 1;
    if ((sqrt(3)*v.u_alpha - v.u_beta) > 0) sector |= 2;
    if ((-sqrt(3)*v.u_alpha - v.u_beta) > 0) sector |= 4;
    return sector;
}

// SVPWM核心计算
DutyCycles svpwm_calc(Vector2D v) {
    DutyCycles duty = {0, 0, 0};
    int sector = calc_sector(v);
    
    // 归一化时间
    float t1, t2;
    float x = sqrt(3) * v.u_beta * T_SAMPLE / V_DC;
    float y = (1.5*v.u_alpha + sqrt(3)/2*v.u_beta) * T_SAMPLE / V_DC;
    float z = (-1.5*v.u_alpha + sqrt(3)/2*v.u_beta) * T_SAMPLE / V_DC;
    
    switch(sector) {
        case 1: t1 = z; t2 = y; break;
        case 2: t1 = y; t2 = -x; break;
        case 3: t1 = -z; t2 = x; break;
        case 4: t1 = -x; t2 = z; break;
        case 5: t1 = x; t2 = -y; break;
        case 6: t1 = -y; t2 = -z; break;
        default: t1 = 0; t2 = 0; break;
    }
    
    // 过调制处理
    float t_sum = t1 + t2;
    if (t_sum > T_SAMPLE) {
        float scale = T_SAMPLE / t_sum;
        t1 *= scale;
        t2 *= scale;
    }
    
    float t0 = (T_SAMPLE - t1 - t2) / 2;
    float t1_shift = t1 + t0;
    float t2_shift = t2 + t1_shift;
    
    // 各扇区占空比分配
    switch(sector) {
        case 1: duty.ta = t1_shift; duty.tb = t2_shift; duty.tc = t0; break;
        case 2: duty.ta = t1_shift; duty.tb = t0; duty.tc = t2_shift; break;
        case 3: duty.ta = t0; duty.tb = t1_shift; duty.tc = t2_shift; break;
        case 4: duty.ta = t2_shift; duty.tb = t1_shift; duty.tc = t0; break;
        case 5: duty.ta = t2_shift; duty.tb = t0; duty.tc = t1_shift; break;
        case 6: duty.ta = t0; duty.tb = t2_shift; duty.tc = t1_shift; break;
    }
    
    // 归一化到0~1
    duty.ta /= T_SAMPLE;
    duty.tb /= T_SAMPLE;
    duty.tc /= T_SAMPLE;
    return duty;
}

// 验证主函数:生成一个电周期的调制波形
int main() {
    const int N = 200;  // 每个电周期采样点数
    float freq = 50.0;  // 调制频率50Hz
    float v_amp = V_DC * 0.5;  // 相电压幅值
    
    printf("时间(s), Ualpha(V), Ubeta(V), Ta, Tb, Tc\n");
    for (int i = 0; i < N; i++) {
        float theta = 2 * PI * freq * i * T_SAMPLE;
        Vector2D v_ref;
        // 圆形轨迹电压矢量
        v_ref.u_alpha = v_amp * cos(theta);
        v_ref.u_beta = v_amp * sin(theta);
        
        DutyCycles d = svpwm_calc(v_ref);
        printf("%.6f, %.3f, %.3f, %.4f, %.4f, %.4f\n",
               i*T_SAMPLE, v_ref.u_alpha, v_ref.u_beta, d.ta, d.tb, d.tc);
    }
    return 0;
}

编译与运行

gcc -o svpwm svpwm.c -lm
./svpwm > svpwm_output.csv

验证方法

运行程序后,将生成的svpwm_output.csv导入Excel或Python中绘图:

  1. 占空比波形:绘制Ta、Tb、Tc随时间变化曲线,应观察到三个相位互差120°的马鞍形波形(中心对称,含三次谐波分量);
  2. 线电压合成:计算Vab = V_DC×(Ta-Tb),其波形应为六步阶梯波;
  3. 相电压基波:对Vab进行低通滤波或傅里叶分析,基波频率应为50Hz,幅值接近期望值(v_amp×√3/2 ≈ 10.4V);
  4. 判定通过条件:占空比始终在0~1范围内,且三相占空比之和的平均值约为1.5(中心对齐调制特性)。

预期输出示例

前几行输出数据(截取):

时间(s), Ualpha(V), Ubeta(V), Ta, Tb, Tc
0.000000, 12.000, 0.000, 0.5000, 0.5000, 0.5000
0.000100, 11.976, 0.754, 0.5337, 0.5000, 0.4663
0.000200, 11.905, 1.508, 0.5673, 0.5000, 0.4327

当θ=0时,三相占空比均为0.5(零矢量输出);随θ增大,A相占空比上升、C相下降,符合SVPWM调制规律。

SVPWM扇区分布与基本矢量 V1(100) V2(110) V3(010) V4(011) V5(001) V6(101) 扇区1 扇区2 扇区3 扇区4 扇区5 扇区6 O(000/111) Vref

上图展示了六个基本电压矢量将空间划分为六个扇区,任一期望电压矢量Vref可由所在扇区的两个相邻基本矢量合成。本实现中calc_sector()函数通过三个比较条件完成扇区判断,svpwm_calc()计算各矢量作用时间并输出三相占空比。