单环PID控制Buck电路实现方案

系统概述

单环PID控制是Buck电路中最基础也是最常用的控制策略,主要通过调节PWM占空比来稳定输出电压。

硬件系统设计

核心组件配置

组件 型号/参数 作用
主控制器 STM32F103 PID算法执行,PWM生成
功率开关 MOSFET IRF540 高频开关
输出电感 100μH 能量存储,滤波
输出电容 470μF 输出滤波
电压采样 电阻分压+ADC 输出电压检测
电流采样 采样电阻+运放 可选,用于过流保护

关键参数计算

c 复制代码
// Buck电路参数
#define INPUT_VOLTAGE 12.0f      // 输入电压12V
#define OUTPUT_VOLTAGE 5.0f      // 目标输出电压5V
#define SWITCHING_FREQ 50000     // 开关频率50kHz
#define INDUCTOR_VALUE 100e-6    // 电感值100μH
#define CAPACITOR_VALUE 470e-6   // 电容值470μF
#define LOAD_RESISTANCE 10.0f    // 负载电阻10Ω

// PWM配置
#define PWM_PERIOD 1599          // 72MHz/(50kHz-1)
#define MAX_DUTY 0.95f           // 最大占空比限制
#define MIN_DUTY 0.05f           // 最小占空比限制

软件实现

1. PID控制器结构

c 复制代码
// PID控制器结构体
typedef struct {
    float Kp;           // 比例系数
    float Ki;           // 积分系数
    float Kd;           // 微分系数
    float Ts;           // 采样周期
    float integral;     // 积分项
    float prev_error;   // 上一次误差
    float output;       // 输出值
    float output_max;   // 输出上限
    float output_min;   // 输出下限
} PID_Controller;

// PID参数初始化
void PID_Init(PID_Controller *pid, float kp, float ki, float kd, float ts, float out_max, float out_min)
{
    pid->Kp = kp;
    pid->Ki = ki;
    pid->Kd = kd;
    pid->Ts = ts;
    pid->integral = 0.0f;
    pid->prev_error = 0.0f;
    pid->output = 0.0f;
    pid->output_max = out_max;
    pid->output_min = out_min;
}

// PID计算函数(位置式)
float PID_Calculate(PID_Controller *pid, float setpoint, float feedback)
{
    float error, derivative;
    
    // 计算误差
    error = setpoint - feedback;
    
    // 积分项(带抗饱和)
    pid->integral += error * pid->Ts;
    
    // 积分限幅
    if(pid->integral > pid->output_max) 
        pid->integral = pid->output_max;
    else if(pid->integral < pid->output_min) 
        pid->integral = pid->output_min;
    
    // 微分项
    derivative = (error - pid->prev_error) / pid->Ts;
    
    // PID输出计算
    pid->output = pid->Kp * error + 
                  pid->Ki * pid->integral + 
                  pid->Kd * derivative;
    
    // 输出限幅
    if(pid->output > pid->output_max) 
        pid->output = pid->output_max;
    else if(pid->output < pid->output_min) 
        pid->output = pid->output_min;
    
    // 更新上一次误差
    pid->prev_error = error;
    
    return pid->output;
}

2. 增量式PID实现

c 复制代码
// 增量式PID结构体
typedef struct {
    float Kp, Ki, Kd;
    float Ts;
    float prev_error;
    float prev2_error;
    float output;
} Incremental_PID;

// 增量式PID计算
float Incremental_PID_Calculate(Incremental_PID *pid, float setpoint, float feedback)
{
    float error, delta_output;
    
    error = setpoint - feedback;
    
    // 增量计算
    delta_output = pid->Kp * (error - pid->prev_error) +
                   pid->Ki * error * pid->Ts +
                   pid->Kd * (error - 2*pid->prev_error + pid->prev2_error) / pid->Ts;
    
    // 累加输出
    pid->output += delta_output;
    
    // 输出限幅
    if(pid->output > MAX_DUTY) pid->output = MAX_DUTY;
    if(pid->output < MIN_DUTY) pid->output = MIN_DUTY;
    
    // 更新误差历史
    pid->prev2_error = pid->prev_error;
    pid->prev_error = error;
    
    return pid->output;
}

3. ADC采样处理

c 复制代码
// 电压采样参数
#define VOLTAGE_DIVIDER_RATIO 0.4f    // 分压比
#define ADC_REF_VOLTAGE 3.3f          // ADC参考电压
#define ADC_RESOLUTION 4095.0f        // 12位ADC

// 读取输出电压
float Read_Output_Voltage(void)
{
    uint16_t adc_value;
    float voltage;
    
    // 启动ADC转换
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
    adc_value = ADC_GetConversionValue(ADC1);
    
    // 转换为电压值
    voltage = (adc_value / ADC_RESOLUTION) * ADC_REF_VOLTAGE;
    voltage = voltage / VOLTAGE_DIVIDER_RATIO;  // 考虑分压比
    
    return voltage;
}

// 移动平均滤波
#define FILTER_WINDOW_SIZE 8
float Moving_Average_Filter(float new_sample)
{
    static float buffer[FILTER_WINDOW_SIZE] = {0};
    static uint8_t index = 0;
    static float sum = 0;
    
    // 减去最旧的值,加上最新的值
    sum = sum - buffer[index] + new_sample;
    buffer[index] = new_sample;
    
    // 更新索引
    index = (index + 1) % FILTER_WINDOW_SIZE;
    
    return sum / FILTER_WINDOW_SIZE;
}

4. PWM生成与控制

c 复制代码
// PWM初始化
void PWM_Init(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    
    // 开启时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    
    // 配置GPIO
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  // TIM2_CH1
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 配置定时器
    TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD;
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    
    // 配置PWM通道
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_Pulse = 0;  // 初始占空比0
    TIM_OC1Init(TIM2, &TIM_OCInitStructure);
    
    // 启动定时器
    TIM_Cmd(TIM2, ENABLE);
    TIM_CtrlPWMOutputs(TIM2, ENABLE);
}

// 设置PWM占空比
void Set_PWM_Duty(float duty_cycle)
{
    uint16_t pulse;
    
    // 限制占空比范围
    if(duty_cycle > MAX_DUTY) duty_cycle = MAX_DUTY;
    if(duty_cycle < MIN_DUTY) duty_cycle = MIN_DUTY;
    
    // 计算脉冲值
    pulse = (uint16_t)(duty_cycle * PWM_PERIOD);
    
    // 更新比较寄存器
    TIM_SetCompare1(TIM2, pulse);
}

5. 主控制循环

c 复制代码
// 全局变量
PID_Controller voltage_pid;
float output_voltage = 0.0f;
float setpoint_voltage = 5.0f;  // 目标输出电压5V

// 系统初始化
void System_Init(void)
{
    // 初始化PID控制器
    // Kp=0.5, Ki=10.0, Kd=0.001, Ts=0.0001(100μs), 输出范围0-0.9
    PID_Init(&voltage_pid, 0.5f, 10.0f, 0.001f, 0.0001f, 0.9f, 0.0f);
    
    // 初始化外设
    ADC_Init();
    PWM_Init();
    
    // 启用定时中断
    Timer_Init(100);  // 100us定时中断
}

// 定时中断服务函数(100us)
void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
    {
        // 清除中断标志
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
        
        // 执行控制算法
        Buck_Control_Loop();
    }
}

// Buck控制主循环
void Buck_Control_Loop(void)
{
    static uint16_t sample_counter = 0;
    float duty_cycle;
    
    // 每10次中断采样一次(1ms采样率)
    if(++sample_counter >= 10)
    {
        sample_counter = 0;
        
        // 读取输出电压
        output_voltage = Read_Output_Voltage();
        
        // 数字滤波
        output_voltage = Moving_Average_Filter(output_voltage);
        
        // PID计算
        duty_cycle = PID_Calculate(&voltage_pid, setpoint_voltage, output_voltage);
        
        // 更新PWM输出
        Set_PWM_Duty(duty_cycle);
    }
}

// 主函数
int main(void)
{
    System_Init();
    
    while(1)
    {
        // 主循环可执行其他任务
        // 如通信、状态监测、参数调整等
        Monitor_System_Status();
    }
}

保护功能实现

过压/欠压保护

c 复制代码
// 保护参数
#define OVER_VOLTAGE_THRESHOLD 6.0f    // 过压阈值6V
#define UNDER_VOLTAGE_THRESHOLD 4.0f   // 欠压阈值4V

// 电压保护检查
void Voltage_Protection_Check(void)
{
    if(output_voltage > OVER_VOLTAGE_THRESHOLD)
    {
        // 过压保护:关闭PWM输出
        Set_PWM_Duty(0.0f);
        // 触发故障处理
        Handle_OverVoltage_Fault();
    }
    else if(output_voltage < UNDER_VOLTAGE_THRESHOLD)
    {
        // 欠压保护:可记录故障或采取其他措施
        Handle_UnderVoltage_Fault();
    }
}

软启动功能

c 复制代码
// 软启动实现
void Soft_Start(float target_voltage, uint32_t start_time_ms)
{
    static uint32_t start_tick = 0;
    static uint8_t soft_start_active = 0;
    
    if(!soft_start_active)
    {
        soft_start_active = 1;
        start_tick = Get_Tick_Count();
        setpoint_voltage = 0.0f;  // 从0开始
    }
    
    // 线性增加设定值
    uint32_t elapsed = Get_Tick_Count() - start_tick;
    if(elapsed < start_time_ms)
    {
        setpoint_voltage = target_voltage * elapsed / start_time_ms;
    }
    else
    {
        setpoint_voltage = target_voltage;
        soft_start_active = 0;
    }
}

PID参数整定方法

经验整定法

c 复制代码
// Ziegler-Nichols整定法
void Ziegler_Nichols_Tuning(float Ku, float Tu)
{
    // Ku: 临界增益,Tu: 临界振荡周期
    voltage_pid.Kp = 0.6 * Ku;
    voltage_pid.Ki = 1.2 * Ku / Tu;
    voltage_pid.Kd = 0.075 * Ku * Tu;
}

// 试凑法参数调整
void Empirical_Tuning(void)
{
    // 先调整Kp,使系统快速响应但不过冲
    // 再调整Ki,消除稳态误差
    // 最后调整Kd,抑制超调
    
    // 典型Buck电路起始参数:
    voltage_pid.Kp = 0.1f;   // 从小开始
    voltage_pid.Ki = 1.0f;   // 适当积分
    voltage_pid.Kd = 0.001f; // 小微分
}

参考代码 单环PID控制buck电路 www.3dddown.com/csa/73179.html

性能优化技巧

1. 抗积分饱和

c 复制代码
// 改进的PID计算(带抗积分饱和)
float PID_Calculate_AntiWindup(PID_Controller *pid, float setpoint, float feedback)
{
    float error = setpoint - feedback;
    
    // 临时计算输出(不更新积分)
    float temp_output = pid->Kp * error + 
                       pid->Ki * pid->integral + 
                       pid->Kd * (error - pid->prev_error) / pid->Ts;
    
    // 只有输出未饱和时才更新积分
    if(temp_output < pid->output_max && temp_output > pid->output_min)
    {
        pid->integral += error * pid->Ts;
    }
    
    // 其余计算相同...
    // ... 
}

2. 设定值平滑

c 复制代码
// 设定值斜坡变化
void Setpoint_Ramp(float new_setpoint, float ramp_time_ms)
{
    static float current_sp = 0;
    static float target_sp = 0;
    static uint32_t ramp_start = 0;
    
    if(new_setpoint != target_sp)
    {
        target_sp = new_setpoint;
        ramp_start = Get_Tick_Count();
    }
    
    uint32_t elapsed = Get_Tick_Count() - ramp_start;
    if(elapsed < ramp_time_ms)
    {
        setpoint_voltage = current_sp + (target_sp - current_sp) * elapsed / ramp_time_ms;
    }
    else
    {
        setpoint_voltage = target_sp;
        current_sp = target_sp;
    }
}

这个单环PID控制Buck电路的实现方案提供了完整的电压闭环控制,具有较好的动态响应和稳态精度。

相关推荐
seven_不是赛文3 天前
基础电路记录
电力电子·电路
阿拉斯攀登7 天前
嵌入式基本功:掌握硬件电路基本概念
stm32·单片机·嵌入式硬件·集成电路·电路
小菜鸟派大星8 天前
电路学习(九)MOS管
学习·硬件·mos管·电路·电路仿真
切糕师学AI1 个月前
OCP(Over-Current Protection)是什么?
硬件工程·电路·过流保护
brave and determined1 个月前
可编程逻辑器件学习(day3):FPGA设计方法、开发流程与基于FPGA的SOC设计详解
嵌入式硬件·fpga开发·soc·仿真·电路·时序·可编程逻辑器件
你疯了抱抱我2 个月前
【电子元器件·10】低功耗继电器 —— 磁保持继电器;有源蜂鸣器、无源蜂鸣器
嵌入式硬件·电路
【ql君】qlexcel3 个月前
电路中信号线上为什么串联33Ω、100Ω或1K的电阻?
阻抗匹配·电路·串联电阻·33ω·100ω·信号反射
文火冰糖的硅基工坊3 个月前
[硬件电路-194]:NPN三极管、MOS-N, IGBT比较
单片机·嵌入式硬件·系统架构·电路
文火冰糖的硅基工坊3 个月前
[硬件电路-192]:基级与发射极两端的电压超过1.5v可能是什么原因
单片机·嵌入式硬件·系统架构·电路·跨学科融合