2025年能量回馈的变流器负载试验装置(A题)的软件部分实现(全国大学生电子设计竞赛)

一、题目要求简述



二、控制方法总览

  • 基础部分:逆变器带阻性负载
    • 电压有效值外环 + 电压瞬时值内环
    • 外环算有效值,PI调节得到幅值;内环用瞬时误差直接控制,生成SVPWM

  • 发挥部分:逆变接整流器(能量回馈)
    • 逆变器:开环,直接给固定调制比输出约32V交流
    • 整流器:单电流环,用PR控制器让电流与逆变器电压同相
    • 启动逻辑:一键触发 → 逆变器先开 → 等2秒 → 整流器闭环自动切入


二、软件整体框架

  • HRTIM定时器中断跑所有控制算法
  • 中断里顺序做:
    1. 采样电压、电流
    2. 判断当前工作模式(基础/发挥)
    3. 执行对应控制策略
    4. 更新PWM占空比
  • 主循环:屏幕刷新、保护
    -普通定时器中断:按键扫描、状态切换

三、控制算法具体代码实现

3.1 逆变器双环控制(基础部分)

  • 有效值外环
    • 滑动窗口计算有效值
      - 窗口大小配置为 5000 点(对应 25kHz 采样率下约 200ms 窗口)
      - 采用滑动平均策略,避免突变,保证数值稳定性

      // 滑动窗口RMS计算核心代码float32_tRMS_Update(rms_update_typedef*state,float32_tvalue){state->sum_sq+=value*value;// 累加平方值state->count++;float32_trms=state->sum_sq/(float32_t)state->count;// 计算平均值if(state->count>=state->window_size){state->sum_sq=rms*(state->window_size-1);// 滑动更新state->count=state->window_size-1;}state->rms_value=sqrtf(rms);// 开方得到RMSreturnstate->rms_value;}
      • PI离散化与积分饱和防护
        • 防积分饱和策略 :直接对PI输出进行硬限幅,限制范围为 [0, 33] (单位:V)
        // PI控制器调用(使用ARM CMSIS-DSP库)floatv_set_o=invv.set_value*0.57735f;// 目标值转换为相电压dsp_arm_pid_function(&pi_inv_a,v_set_o-invv.ao_rms_fit_value);// 积分饱和防护 - 输出限幅if(pi_inv_a.out>33.0f)pi_inv_a.out=33.0f;if(pi_inv_b.out>33.0f)pi_inv_b.out=33.0f;if(pi_inv_c.out>33.0f)pi_inv_c.out=33.0f;
  • 瞬时值内环
    • 给定参考:ref = 外环输出 * sin_table[index]
      // 参考值 = 外环输出 * sin_table[index]pr_inv_a.xi=pi_inv_a.out*1.4142f*arm_sin_f32(theta)-invv.ao_fit_value;pr_inv_b.xi=pi_inv_b.out*1.4142f*arm_sin_f32(theta-2.0944f)-invv.bo_fit_value;pr_inv_c.xi=pi_inv_c.out*1.4142f*arm_sin_f32(theta+2.0944f)-invv.co_fit_value;pr_control(&pr_inv_a);pr_control(&pr_inv_b);pr_control(&pr_inv_c);

3.2 开环逆变 + PR整流(发挥部分)

  • 逆变开环:直接设调制波幅值,无需反馈
    // 直接设置调制波幅值,无需反馈inv_saddle_sine.a=modulation_ratio_inv*arm_sin_f32(theta);inv_saddle_sine.b=modulation_ratio_inv*arm_sin_f32(theta-2.0944f);inv_saddle_sine.c=modulation_ratio_inv*arm_sin_f32(theta+2.0944f);saddle_wave_modulation_function(&inv_saddle_sine);
  • 整流器PR电流环
    • PR的离散公式:
      voidpr_control(pr_typedef*p){// 差分方程:y[n] = -a1*y[n-1] -a2*y[n-2] + b0*x[n] + b1*x[n-1] + b2*x[n-2]p->yo=-p->a1*p->yo_1-p->a2*p->yo_2+p->b0*p->xi+p->b1*p->xi_1+p->b2*p->xi_2;// 更新状态寄存器p->yo_2=p->yo_1;p->yo_1=p->yo;p->xi_2=p->xi_1;p->xi_1=p->xi;}voidpr_init(pr_typedef*p,floatkp,floatkr,floatfs,floatwc,floatwo){p->Ts=1/fs;floattemp=4/p->Ts/p->Ts+4*p->wc/p->Ts+p->wo*p->wo;p->b0=(4*p->kp/p->Ts/p->Ts+4*p->wc*(p->kp+p->kr)/p->Ts+p->kp*p->wo*p->wo)/temp;p->b1=(-8*p->kp/p->Ts/p->Ts+2*p->kp*p->wo*p->wo)/temp;p->b2=(4*p->kp/p->Ts/p->Ts-4*p->wc/p->Ts*(p->kp+p->kr)+p->kp*p->wo*p->wo)/temp;p->a1=(-8/p->Ts/p->Ts+2*p->wo*p->wo)/temp;p->a2=(4/p->Ts/p->Ts-4*p->wc/p->Ts+p->wo*p->wo)/temp;}
    • 电流参考怎么生成:
      floati_set_m=rec.set_value*1.4142135623730950488016887242097f;pr_rec_a.xi=i_set_m*arm_sin_f32(theta)-rec.ao_fit_value;pr_rec_b.xi=i_set_m*arm_sin_f32(theta-2.094395102f)-rec.bo_fit_value;pr_rec_c.xi=i_set_m*arm_sin_f32(theta+2.094395102f)-rec.co_fit_value;pr_control(&pr_rec_a);pr_control(&pr_rec_b);pr_control(&pr_rec_c);rec_saddle_sine.a=-pr_rec_a.yo;rec_saddle_sine.b=-pr_rec_b.yo;rec_saddle_sine.c=-pr_rec_c.yo;if(rec_saddle_sine.a>1.15f)rec_saddle_sine.a=1.15f;if(rec_saddle_sine.a<-1.15f)rec_saddle_sine.a=-1.15f;if(rec_saddle_sine.b>1.15f)rec_saddle_sine.b=1.15f;if(rec_saddle_sine.b<-1.15f)rec_saddle_sine.b=-1.15f;if(rec_saddle_sine.c>1.15f)rec_saddle_sine.c=1.15f;if(rec_saddle_sine.c<-1.15f)rec_saddle_sine.c=-1.15f;saddle_wave_modulation_function(&rec_saddle_sine);```-关键参数 :-采样频率 fs=25000Hz-截止频率 wc=0.2*2π ≈1.256rad/s-谐振频率 wo=50*2π ≈314.16rad/s (电网频率)

3.3 SVPWM的尝试(简单提)

  • 我也用了SVPWM,但能量回馈时电流3次谐波没改善
  • 给新手一个结论:在这个应用里SVPWM未必是灵药,先跑通SPWM
    voidsaddle_wave_modulation_function(adc_ab_dq_typedef*saddle_sine){// SVPWM调制计算floatmax_val=MAX(saddle_sine->a,MAX(saddle_sine->b,saddle_sine->c));floatmin_val=MIN(saddle_sine->a,MIN(saddle_sine->b,saddle_sine->c));floatoffset=(max_val+min_val)/2.0f;// 三次谐波注入saddle_sine->a-=offset;saddle_sine->b-=offset;saddle_sine->c-=offset;}

四、给想上手的新手的几个建议

  • 先调通基础部分的双环,不要一上来就SVPWM
  • 所有波形都用串口或DAC引出来看,不要猜