2. Buck变换器电压模式PID控制设计
任务定义
设计并实现Buck变换器电压模式PID控制器,输入为输出电压采样值,输出为PWM占空比指令。控制器需包含抗积分饱和与输出限幅,并通过离散化差分方程在数字控制器中直接执行。本案例提供完整C语言实现及开环被控对象模型,用于闭环仿真验证。
被控对象与控制器设计
Buck变换器连续域传递函数(忽略寄生参数)为:
G(s) = Vin / (L·C·s² + (L/R)·s + 1)
设计参数:Vin=12V,L=100μH,C=470μF,R=2Ω,开关频率fsw=100kHz,采样频率与控制频率均为fsw。穿越频率fc=5kHz(约为开关频率的1/20),相位裕度PM≥50°。
采用零极点法设计连续域PID补偿器:
C(s) = Kp·(1 + 1/(Ti·s) + Td·s)
在fc处提供约60°相位提升,计算得:Kp=0.85,Ti=0.0002s,Td=0.00005s。使用双线性变换(Tustin)离散化,采样周期Ts=10μs,得到差分方程系数:
u[k] = u[k-1] + b₀·e[k] + b₁·e[k-1] + b₂·e[k-2]
其中b₀=0.8925,b₁=-0.8512,b₂=0.0413(由Kp、Ti、Td与Ts经双线性变换推导)。
代码实现
// pid_buck.h
#ifndef PID_BUCK_H
#define PID_BUCK_H
typedef struct {
float b0, b1, b2; // 差分方程系数
float u_prev; // u[k-1]
float e_prev1, e_prev2; // e[k-1], e[k-2]
float out_min, out_max; // 输出限幅(占空比0~1)
float integral_state; // 抗积分饱和状态
} PIDBuck_t;
void PIDBuck_Init(PIDBuck_t *pid);
float PIDBuck_Update(PIDBuck_t *pid, float ref, float feedback);
#endif
// pid_buck.c
#include "pid_buck.h"
void PIDBuck_Init(PIDBuck_t *pid) {
pid->b0 = 0.8925f;
pid->b1 = -0.8512f;
pid->b2 = 0.0413f;
pid->u_prev = 0.0f;
pid->e_prev1 = 0.0f;
pid->e_prev2 = 0.0f;
pid->out_min = 0.0f;
pid->out_max = 1.0f;
pid->integral_state = 0.0f;
}
float PIDBuck_Update(PIDBuck_t *pid, float ref, float feedback) {
float error = ref - feedback;
float u_unclamped;
// 差分方程计算
u_unclamped = pid->u_prev
+ pid->b0 * error
+ pid->b1 * pid->e_prev1
+ pid->b2 * pid->e_prev2;
// 输出限幅(占空比限幅)
float u_clamped = u_unclamped;
if (u_clamped > pid->out_max) u_clamped = pid->out_max;
if (u_clamped < pid->out_min) u_clamped = pid->out_min;
// 抗积分饱和:当输出饱和时,将未限幅值拉回限幅值,防止积分累积
pid->integral_state = u_clamped;
// 更新状态
pid->u_prev = u_clamped;
pid->e_prev2 = pid->e_prev1;
pid->e_prev1 = error;
return u_clamped;
}
// main.c 示例调用
#include <stdio.h>
#include "pid_buck.h"
// 被控对象离散化模型(前向欧拉,Ts=10us)
typedef struct {
float vout;
float il;
float vin;
float L, C, R;
float Ts;
} BuckPlant_t;
void BuckPlant_Init(BuckPlant_t *p) {
p->vout = 0.0f;
p->il = 0.0f;
p->vin = 12.0f;
p->L = 100e-6f;
p->C = 470e-6f;
p->R = 2.0f;
p->Ts = 10e-6f;
}
void BuckPlant_Step(BuckPlant_t *p, float duty) {
float vout_new, il_new;
// 电感电流方程:diL/dt = (d*Vin - vout)/L
il_new = p->il + (duty * p->vin - p->vout) / p->L * p->Ts;
// 电容电压方程:dvout/dt = (iL - vout/R)/C
vout_new = p->vout + (p->il - p->vout / p->R) / p->C * p->Ts;
p->il = il_new;
p->vout = vout_new;
}
int main() {
PIDBuck_t pid;
BuckPlant_t plant;
float ref = 5.0f; // 目标输出电压5V
float duty = 0.0f;
int i;
PIDBuck_Init(&pid);
BuckPlant_Init(&plant);
// 仿真2000步(20ms)
for (i = 0; i < 2000; i++) {
duty = PIDBuck_Update(&pid, ref, plant.vout);
BuckPlant_Step(&plant, duty);
if (i % 500 == 0) {
printf("t=%.4fs duty=%.4f vout=%.4fV\n",
i * 10e-6f, duty, plant.vout);
}
}
return 0;
}
验证方法
编译并运行:gcc main.c pid_buck.c -o buck_sim -lm,然后执行./buck_sim。观察输出:
- 启动阶段占空比应接近0.42(5V/12V),随后由PID调节;
- 稳态时输出电压应收敛至5V±0.1V范围内;
- 输出占空比始终在[0,1]区间内,无超限。
判定标准:若仿真最后一步打印的vout在4.9V~5.1V之间,且过程中duty未超出[0,1],则PID控制器设计正确,抗积分饱和与限幅逻辑有效。