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控制器设计正确,抗积分饱和与限幅逻辑有效。

Buck变换器电压模式PID控制闭环仿真结构 Vref=5V Σ + PID控制器 差分方程+抗饱和 − PWM占空比 Buck变换器 L=100μH C=470μF Vout反馈 采样频率100kHz 抗积分饱和机制 当输出限幅时,积分状态被钳位至限幅值 防止积分项持续累积导致超调 设计参数 Kp=0.85 Ti=0.2ms Td=0.05ms fc=5kHz PM≥50° 预期输出电压响应(示意) 5V目标 0ms ~10ms 20ms 调节时间≈2ms 超调<5%