AVR智能充电器PID控制程序(基于ATmega16ATmega328)

AVR智能充电器PID控制程序(基于ATmega16/ATmega328)

一、系统硬件架构

1. 硬件连接方案

AVR ATmega16
├── ADC0 (PC0) → 电池电压采样(分压电阻)
├── ADC1 (PC1) → 充电电流采样(分流电阻+运放)
├── OC1A (PB1) → PWM输出 → MOSFET驱动 → 充电控制
├── INT0 (PD2) → 过温保护(NTC热敏电阻)
├── PC4/PC5 → I2C接口 → OLED显示(可选)
└── PD0/PD1 → UART → 上位机监控(可选)

电源部分:
输入12V/2A适配器 → 同步Buck降压 → 锂电池/铅酸电池

2. 关键参数设计

参数 数值 说明
开关频率 31.25kHz PWM分频,降低开关损耗
电压采样 12位ADC 分压比1/10,分辨率10mV
电流采样 50mV/10A 分流电阻0.005Ω,运放增益20
控制周期 10ms PID计算周期,响应速度适中

二、PID算法核心程序(整型PID,适合AVR)

1. PID结构体与初始化

#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>

// PID控制器结构体(整型,避免浮点运算)
typedef struct {
    int16_t Kp;           // 比例系数(放大100倍)
    int16_t Ki;           // 积分系数(放大10000倍)
    int16_t Kd;           // 微分系数(放大100倍)
    int16_t setpoint;     // 设定值(电压或电流)
    int16_t feedback;     // 反馈值
    int32_t integral;     // 积分项(扩大100倍防溢出)
    int16_t prev_error;   // 上次误差
    int16_t output;       // 输出值(0-1000对应0-100%占空比)
    int16_t output_min;   // 输出最小值
    int16_t output_max;   // 输出最大值
} PID_Controller_t;

// 系统状态
typedef enum {
    CHARGE_STOP = 0,      // 停止充电
    CHARGE_CC,            // 恒流充电
    CHARGE_CV,            // 恒压充电
    CHARGE_TRICLE,         // 涓流充电
    CHARGE_COMPLETE        // 充电完成
} ChargeState_t;

// 全局变量
PID_Controller_t voltage_pid;   // 电压PID
PID_Controller_t current_pid;   // 电流PID
ChargeState_t charge_state = CHARGE_STOP;
uint16_t battery_voltage = 0;   // 电池电压(mV)
uint16_t charge_current = 0;    // 充电电流(mA)

2. 整型PID计算函数(AVR友好)

// PID计算函数(整型版本,适合8位MCU)
int16_t PID_Calculate(PID_Controller_t *pid) {
    int16_t error = pid->setpoint - pid->feedback;
    int32_t output;
    
    // 1. 比例项(Kp已放大100倍)
    int32_t P = (int32_t)pid->Kp * error;  // 结果放大100倍
    
    // 2. 积分项(Ki放大10000倍,积分项放大100倍)
    pid->integral += (int32_t)error * 100;  // 积分累积
    // 积分限幅(防止积分饱和)
    if (pid->integral > (int32_t)pid->output_max * 10000 / pid->Ki) 
        pid->integral = (int32_t)pid->output_max * 10000 / pid->Ki;
    if (pid->integral < -(int32_t)pid->output_max * 10000 / pid->Ki) 
        pid->integral = -(int32_t)pid->output_max * 10000 / pid->Ki;
    
    int32_t I = (pid->Ki * pid->integral) / 10000;  // 结果放大100倍
    
    // 3. 微分项(Kd放大100倍)
    int32_t D = (int32_t)pid->Kd * (error - pid->prev_error);  // 放大100倍
    pid->prev_error = error;
    
    // 4. 计算总输出(所有项都放大100倍)
    output = P + I + D;
    output = output / 100;  // 缩小100倍,得到实际占空比
    
    // 5. 输出限幅
    if (output > pid->output_max) output = pid->output_max;
    if (output < pid->output_min) output = pid->output_min;
    
    pid->output = (int16_t)output;
    return pid->output;
}

3. ADC采样函数

// ADC初始化
void ADC_Init(void) {
    // AVCC为参考电压,右对齐,ADC0通道
    ADMUX = (1<<REFS0) | (0<<ADLAR);
    // 使能ADC,128分频(16MHz/128=125kHz)
    ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
}

// 读取ADC值
uint16_t ADC_Read(uint8_t channel) {
    ADMUX = (ADMUX & 0xF0) | (channel & 0x0F);  // 选择通道
    ADCSRA |= (1<<ADSC);                         // 启动转换
    while (ADCSRA & (1<<ADSC));                 // 等待转换完成
    return ADC;
}

// 获取电池电压(单位:mV)
uint16_t Get_Battery_Voltage(void) {
    uint16_t adc_value = ADC_Read(0);  // ADC0读取电压
    // 分压比1/10,Vref=5V,12位ADC
    uint32_t voltage = (uint32_t)adc_value * 5000 / 1023;  // 单位mV
    return (uint16_t)voltage * 10;  // 乘以分压比
}

// 获取充电电流(单位:mA)
uint16_t Get_Charge_Current(void) {
    uint16_t adc_value = ADC_Read(1);  // ADC1读取电流
    // 分流电阻0.005Ω,运放增益20,Vref=5V
    uint32_t current = (uint32_t)adc_value * 5000 / 1023;  // mV
    current = current * 1000 / (20 * 5);  // mA = mV / (增益 * 分流电阻)
    return (uint16_t)current;
}

4. PWM输出控制

// PWM初始化(Timer1,10位快速PWM)
void PWM_Init(void) {
    // OC1A输出,快速PWM,10位模式
    TCCR1A = (1<<COM1A1) | (1<<WGM11) | (1<<WGM10);
    TCCR1B = (1<<WGM12) | (1<<CS11);  // 8分频,31.25kHz PWM频率
    OCR1A = 0;  // 初始占空比0%
    DDRB |= (1<<PB1);  // PB1设为输出
}

// 设置PWM占空比(0-1000对应0-100%)
void PWM_SetDuty(uint16_t duty) {
    if (duty > 1000) duty = 1000;
    OCR1A = duty;  // 10位PWM,0-1023
}

5. 智能充电状态机

// 充电状态机处理
void Charge_State_Machine(void) {
    static uint16_t cc_current = 1000;  // 恒流电流1000mA
    static uint16_t cv_voltage = 4200;   // 恒压电压4200mV(4.2V锂电)
    static uint16_t trickle_current = 100; // 涓流电流100mA
    
    switch (charge_state) {
        case CHARGE_STOP:
            PWM_SetDuty(0);  // 关闭PWM
            break;
            
        case CHARGE_CC:  // 恒流充电
            // 使用电流PID控制
            current_pid.setpoint = cc_current;
            current_pid.feedback = charge_current;
            PWM_SetDuty(PID_Calculate(&current_pid));
            
            // 当电压达到恒压值时,切换到CV模式
            if (battery_voltage >= cv_voltage) {
                charge_state = CHARGE_CV;
            }
            break;
            
        case CHARGE_CV:  // 恒压充电
            // 使用电压PID控制
            voltage_pid.setpoint = cv_voltage;
            voltage_pid.feedback = battery_voltage;
            PWM_SetDuty(PID_Calculate(&voltage_pid));
            
            // 当电流降低到涓流阈值时,切换到涓流模式
            if (charge_current <= trickle_current) {
                charge_state = CHARGE_TRICLE;
            }
            break;
            
        case CHARGE_TRICLE:  // 涓流充电
            // 小电流维持
            PWM_SetDuty(50);  // 5%占空比
            
            // 充电完成判断(电流持续低于50mA 10分钟)
            static uint16_t complete_counter = 0;
            if (charge_current < 50) {
                complete_counter++;
                if (complete_counter >= 6000) {  // 10分钟 * 600次/分钟
                    charge_state = CHARGE_COMPLETE;
                }
            } else {
                complete_counter = 0;
            }
            break;
            
        case CHARGE_COMPLETE:
            PWM_SetDuty(0);  // 充电完成,关闭输出
            break;
    }
}

6. 主函数

int main(void) {
    // 初始化PID参数
    voltage_pid.Kp = 800;    // 比例系数8.0
    voltage_pid.Ki = 200;    // 积分系数0.02
    voltage_pid.Kd = 100;    // 微分系数1.0
    voltage_pid.output_min = 0;
    voltage_pid.output_max = 1000;
    
    current_pid.Kp = 600;    // 比例系数6.0
    current_pid.Ki = 150;    // 积分系数0.015
    current_pid.Kd = 50;     // 微分系数0.5
    current_pid.output_min = 0;
    current_pid.output_max = 1000;
    
    // 初始化外设
    ADC_Init();
    PWM_Init();
    
    // 充电开始
    charge_state = CHARGE_CC;
    
    while (1) {
        // 1. 读取电池参数
        battery_voltage = Get_Battery_Voltage();
        charge_current = Get_Charge_Current();
        
        // 2. 安全检查(过压、过流、过温)
        if (battery_voltage > 4300 || charge_current > 1500) {
            charge_state = CHARGE_STOP;  // 安全保护
        }
        
        // 3. 执行充电状态机
        Charge_State_Machine();
        
        // 4. 延时10ms(100Hz控制频率)
        _delay_ms(10);
    }
}

三、参数整定指南

1. PID参数推荐值(锂电充电)

参数 恒流模式(CC) 恒压模式(CV) 说明
Kp 600-800 800-1000 决定响应速度
Ki 100-200 150-250 消除稳态误差
Kd 30-80 50-100 抑制超调震荡

2. 整定步骤

1. 先调CC模式:设置目标电流1000mA,逐步增大Kp直到电流快速跟随
2. 再加入Ki:消除电流稳态误差,避免积分饱和
3. 最后调CV模式:设置目标电压4200mV,用Kd抑制电压超调
4. 切换测试:验证CC→CV切换时的平滑性

参考代码 AVR智能充电器PID算法程序 www.youwenfan.com/contentcnt/123398.html

四、扩展功能

1. 温度补偿充电

// 根据电池温度调整充电电压
uint16_t Get_Temperature_Compensated_Voltage(uint16_t temp) {
    // 锂电:-3mV/℃/cell,25℃基准
    int16_t compensation = (25 - temp) * 3;  // 温度补偿量
    return 4200 + compensation;  // 补偿后的目标电压
}

2. 电池类型识别

// 识别电池类型(锂电/铅酸)
BatteryType_t Identify_Battery(void) {
    uint16_t voltage = Get_Battery_Voltage();
    if (voltage < 2000) return BATTERY_LIION;    // <2V:锂电池
    else if (voltage < 3000) return BATTERY_LEAD_ACID; // 2-3V:铅酸电池
    else return BATTERY_UNKNOWN;
}

五、调试建议

  1. 安全第一:先断开电池,用可调电阻模拟电池负载调试PID
  2. 分步验证:先验证PWM输出→再验证ADC采样→最后整定PID
  3. 保护测试:故意制造过压/过流条件,验证保护功能是否生效
  4. 散热设计:MOSFET和大电流路径要做好散热,避免热失控

专注于matlab/simulink,电子电路,编程