一、题目要求简述



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


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


二、软件整体框架
- HRTIM定时器中断跑所有控制算法
- 中断里顺序做:
- 采样电压、电流
- 判断当前工作模式(基础/发挥)
- 执行对应控制策略
- 更新PWM占空比
- 主循环:屏幕刷新、保护
-普通定时器中断:按键扫描、状态切换
三、控制算法具体代码实现
3.1 逆变器双环控制(基础部分)
- 有效值外环:
-
滑动窗口计算有效值
– 窗口大小配置为 5000 点(对应 25kHz 采样率下约 200ms 窗口)
– 采用滑动平均策略,避免突变,保证数值稳定性// 滑动窗口RMS计算核心代码
float32_t RMS_Update(rms_update_typedef* state, float32_t value) {
state->sum_sq += value * value; // 累加平方值
state->count++;
float32_t rms = 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); // 开方得到RMS
return state->rms_value;
}- PI离散化与积分饱和防护
- 防积分饱和策略 :直接对PI输出进行硬限幅,限制范围为 [0, 33] (单位:V)
// PI控制器调用(使用ARM CMSIS-DSP库)
float v_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;
- PI离散化与积分饱和防护
-
- 瞬时值内环:
- 给定参考: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);
- 给定参考:ref = 外环输出 * sin_table[index]// 参考值 = 外环输出 * sin_table[index]
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的离散公式:void pr_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;
}
void pr_init(pr_typedef *p, float kp, float kr, float fs, float wc, float wo) {
p->Ts = 1 / fs;
float temp = 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;
} - 电流参考怎么生成: float i_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.256 rad/s
– 谐振频率 wo = 50*2π ≈ 314.16 rad/s (电网频率)
- PR的离散公式:void pr_control(pr_typedef *p) {
3.3 SVPWM的尝试(简单提)
- 我也用了SVPWM,但能量回馈时电流3次谐波没改善
- 给新手一个结论:在这个应用里SVPWM未必是灵药,先跑通SPWMvoid saddle_wave_modulation_function(adc_ab_dq_typedef *saddle_sine) {
// SVPWM调制计算
float max_val = MAX(saddle_sine->a, MAX(saddle_sine->b, saddle_sine->c));
float min_val = MIN(saddle_sine->a, MIN(saddle_sine->b, saddle_sine->c));float offset = (max_val + min_val) / 2.0f; // 三次谐波注入
saddle_sine->a -= offset;
saddle_sine->b -= offset;
saddle_sine->c -= offset;
}
四、给想上手的新手的几个建议
- 先调通基础部分的双环,不要一上来就SVPWM
- 所有波形都用串口或DAC引出来看,不要猜






