[学习资料] 锂电池充电算法

[复制链接]
2423|11
 楼主| xinxianshi 发表于 2023-8-15 10:12 | 显示全部楼层 |阅读模式

18650锂电池充电算法通常包括恒流充电、恒压充电和涓流充电三个阶段。

  • 恒流充电阶段:在此阶段,电流保持恒定,充电电压逐渐升高。当电池电压达到设定的充电截止电压时,进入恒压充电阶段。
  • 恒压充电阶段:在此阶段,充电电压保持恒定,电流逐渐降低。当电流降低到设定的充电结束电流时,进入涓流充电阶段。
  • 涓流充电阶段:在此阶段,充电电流保持非常小,充电电压也保持恒定。此阶段的目的是将电池电压充满,并防止过充。

以下是一个简单的18650锂电池充电算法示例:

  1. // 充电截止电压
  2. #define CHARGE_CURRENT 0.5 // 0.5A
  3. #define CHARGE_VOLTAGE 4.2 // 4.2V
  4. #define CHARGE_CURRENT_THRESHOLD 0.05 // 0.05A
  5. #define CHARGE_END_CURRENT_THRESHOLD 0.01 // 0.01A

  6. // 充电状态
  7. enum ChargeStatus {
  8.     CHARGING,
  9.     CHARGE_COMPLETE,
  10.     CHARGE_OVERCHARGE
  11. };

  12. // 充电函数
  13. void charge_battery() {
  14.     // 初始化充电状态
  15.     ChargeStatus chargeStatus = CHARGING;

  16.     // 充电电流
  17.     float chargeCurrent = CHARGE_CURRENT;

  18.     // 充电电压
  19.     float chargeVoltage = CHARGE_VOLTAGE;

  20.     // 充电结束电流
  21.     float chargeEndCurrent = CHARGE_CURRENT_THRESHOLD;

  22.     // 充电结束电压
  23.     float chargeEndVoltage = CHARGE_VOLTAGE + 0.05;

  24.     // 记录充电时间
  25.     float chargeTime = 0;

  26.     // 记录充电次数
  27.     int chargeCount = 0;

  28.     // 记录充电电流变化
  29.     float chargeCurrentDelta = 0;

  30.     // 记录充电电压变化
  31.     float chargeVoltageDelta = 0;

  32.     // 记录充电温度变化
  33.     float chargeTemperatureDelta = 0;

  34.     // 记录充电状态变化
  35.     ChargeStatus chargeStatusDelta = CHARGING;

  36.     // 循环充电
  37.     while (chargeStatus == CHARGING) {
  38.         // 获取充电电流
  39.         float current = get_battery_current();

  40.         // 获取充电电压
  41.         float voltage = get_battery_voltage();

  42.         // 获取充电温度
  43.         float temperature = get_battery_temperature();

  44.         // 记录充电电流变化
  45.         chargeCurrentDelta = abs(chargeCurrent - current);

  46.         // 记录充电电压变化
  47.         chargeVoltageDelta = abs(chargeVoltage - voltage);

  48.         // 记录充电温度变化
  49.         chargeTemperatureDelta = abs(chargeTemperature - temperature);

  50.         // 记录充电状态变化
  51.         if (chargeStatusDelta == CHARGING && current < chargeEndCurrent) {
  52.             chargeStatusDelta = CHARGE_COMPLETE;
  53.         } else if (chargeStatusDelta == CHARGE_COMPLETE && current > chargeEndCurrent) {
  54.             chargeStatusDelta = CHARGE_OVERCHARGE;
  55.         }

  56.         // 判断充电状态
  57.         if (chargeCurrentDelta < CHARGE_CURRENT_THRESHOLD || chargeVoltageDelta < 0.01 || chargeTemperatureDelta > 5) {
  58.             // 充电结束
  59.             chargeStatus = CHARGE_COMPLETE;
  60.         } else if (chargeStatusDelta == CHARGE_OVERCHARGE) {
  61.             // 充电过充
  62.             chargeStatus = CHARGE_OVERCHARGE;
  63.         } else {
  64.             // 继续充电
  65.             if (chargeStatusDelta == CHARGE_COMPLETE) {
  66.                 // 恒流充电结束,进入恒压充电阶段
  67.                 chargeVoltage += 0.05;
  68.                 chargeCurrent = chargeCurrent * 0.9;
  69.             } else if (chargeStatusDelta == CHARGE_OVERCHARGE) {
  70.                 // 恒压充电结束,进入涓流充电阶段
  71.                 chargeCurrent = chargeEndCurrent;
  72.             }
  73.         }

  74.         // 记录充电时间
  75.         chargeTime += 1;

  76.         // 记录充电次数
  77.         chargeCount++;

  78.         // 打印充电状态和信息
  79.         printf("Charge status: %s, current: %f A, voltage: %f V, temperature: %f C, time: %d s, count: %d\n",
  80.                chargeStatusToString(chargeStatus), current, voltage, temperature, chargeTime, chargeCount);

  81.         // 等待1s
  82.         delay(1000);
  83.     }
  84. }

  85. // 获取电池电流
  86. float get_battery_current() {
  87.     // TODO: 获取电池电流
  88.     return 0;
  89. }

  90. // 获取电池电压
  91. float get_battery_voltage() {
  92.     // TODO: 获取电池电压
  93.     return 0;
  94. }

  95. // 获取电池温度
  96. float get_battery_temperature() {
  97.     // TODO: 获取电池温度
  98.     return 0;
  99. }

  100. // 获取充电状态字符串
  101. const char *chargeStatusToString(ChargeStatus chargeStatus) {
  102.     switch (chargeStatus) {
  103.         case CHARGING:
  104.             return "charging";
  105.         case CHARGE_COMPLETE:
  106.             return "complete";
  107.         case CHARGE_OVERCHARGE:
  108.             return "overcharge";
  109.         default:
  110.             return "unknown";
  111.     }
  112. }

注意:此充电算法仅供参考,实际应用中需要根据具体情况进行调整和优化。


评论

正好在看这块,学习一下  发表于 2023-9-15 09:13
 楼主| xinxianshi 发表于 2023-8-15 10:17 | 显示全部楼层
以下是一个基于PIC18F系列单片机的充电算法控制实现的示例代码:
首先,需要在程序中初始化单片机的各种外设,包括ADC、PWM、定时器等。
  1. // 初始化ADC
  2. void adc_init() {
  3.     ANSELA = 0x00; // ANSEL为0,禁止所有外部输入
  4.     P0M1 = 0x00; // P0M1为0,将P0.0作为ADC输入
  5.     P0M2 = 0x80; // P0M2为1,将P0.1作为ADC输入
  6.     P0SEL = 0x00; // P0SEL为0,将P0.0和P0.1作为普通输入
  7.     ADCON0 = 0x80; // ADCON0为1,启动ADC转换
  8.     ADCON1 = 0x00; // ADCON1为0,设置ADC输入通道为0和1
  9.     ADCON2 = 0x00; // ADCON2为0,设置ADC转换速率为100kHz
  10.     TRISC = 0x00; // TRISC为0,将P0.0和P0.1作为普通输入
  11. }

  12. // 初始化PWM
  13. void pwm_init() {
  14.     T1CON = 0x00; // T1CON为0,关闭定时器1
  15.     TMR1H = 0x00; // TMR1H为0,设置定时器1的高位为0
  16.     TMR1L = 0x00; // TMR1L为0,设置定时器1的低位为0
  17.     PR1 = 0x00; // PR1为0,设置定时器1的分频因子为1
  18.     T1CON = 0x80; // T1CON为1,启动定时器1
  19.     PWM1CON = 0x00; // PWM1CON为0,关闭PWM1
  20.     PWM1CFG = 0x00; // PWM1CFG为0,设置PWM1占空比为0
  21.     PWM1DMD = 0x00; // PWM1DMD为0,设置PWM1调制方式为正弦波
  22.     PWM1RFL = 0x00; // PWM1RFL为0,设置PWM1调制倍率为1
  23.     PWM1FMD = 0x00; // PWM1FMD为0,设置PWM1调制方式为正弦波
  24.     PWM1FL = 0x00; // PWM1FL为0,设置PWM1调制倍率为1
  25. }

  26. // 初始化定时器
  27. void timer_init() {
  28.     TMOD = 0x01; // TMOD为1,设置定时器0为16位模式
  29.     TH0 = 0x00; // TH0为0,设置定时器0的高位为0
  30.     TL0 = 0x00; // TL0为0,设置定时器0的低位为0
  31.     TR0 = 1; // TR0为1,启动定时器0
  32.     ET0 = 1; // ET0为1,允许定时器0中断
  33.     EX0 = 1; // EX0为1,允许定时器0中断
  34. }
接下来,需要实现一个函数来读取ADC采样值,并将其转换为电压值。
  1. // 读取ADC采样值,并转换为电压值
  2. float read_voltage() {
  3.     uint16_t adc_value = ADC0_RA; // 读取ADC采样值
  4.     float voltage = (float)adc_value / 1024.0 * 3.3; // 转换为电压值
  5.     return voltage;
  6. }
然后,需要实现一个函数来控制充电过程,包括恒流充电、恒压充电和涓流充电。
  1. // 控制充电过程
  2. void control_charge() {
  3.     float voltage = read_voltage(); // 读取电压值
  4.     float current = read_current(); // 读取电流值
  5.     float capacity = get_capacity(); // 获取电池容量
  6.     float efficiency = get_efficiency(); // 获取电池效率
  7.     float time = get_time(); // 获取充电时间
  8.     float percent = get_percent(); // 获取充电进度
  9.     if (percent == 100) { // 充电完成
  10.         // 充电完成后的操作
  11.     } else if (voltage < 4.2) { // 恒流充电
  12.         // 控制恒流充电
  13.     } else if (voltage > 4.2) { // 恒压充电
  14.         // 控制恒压充电
  15.     } else { // 涓流充电
  16.         // 控制涓流充电
  17.     }
  18. }
最后,需要在主函数中实现充电的控制和监测。
  1. // 主函数
  2. void main() {
  3.     // 初始化单片机
  4.     adc_init();
  5.     pwm_init();
  6.     timer_init();
  7.     // 开始充电
  8.     while (1) {
  9.         control_charge(); // 控制充电过程
  10.         // 监测充电状态
  11.         // ...
  12.     }
  13. }


sanzi666 发表于 2023-8-29 10:44 | 显示全部楼层
有没有充电控制部分啊,
sanzi666 发表于 2023-8-29 11:13 | 显示全部楼层
float capacity = get_capacity(); // 获取电池容量

    float efficiency = get_efficiency(); // 获取电池效率

    float time = get_time(); // 获取充电时间

    float percent = get_percent(); // 获取充电进度
这四个函数有吗,
单片小菜 发表于 2023-8-31 14:20 | 显示全部楼层
充电控制部分在哪来?
便携手到老 发表于 2023-8-31 14:26 来自手机 | 显示全部楼层
感谢楼主的分享,学习了
 楼主| xinxianshi 发表于 2023-9-8 10:14 | 显示全部楼层
sanzi666 发表于 2023-8-29 10:44
有没有充电控制部分啊,

这个只是一个思路,充电控制部分还需要根据实际情况考虑。
 楼主| xinxianshi 发表于 2023-9-8 10:15 | 显示全部楼层
sanzi666 发表于 2023-8-29 11:13
float capacity = get_capacity(); // 获取电池容量

    float efficiency = get_efficiency(); // 获取电 ...

这四个函数需要根据电池的参数自行设定。
 楼主| xinxianshi 发表于 2023-9-8 10:15 | 显示全部楼层
sanzi666 发表于 2023-8-29 10:44
有没有充电控制部分啊,

这是一个简单的框架,实际应用要根据所选的具体电池来确定具体方案。
sanzi666 发表于 2023-9-15 08:02 | 显示全部楼层
xinxianshi 发表于 2023-9-8 10:15
这四个函数需要根据电池的参数自行设定。

这四个函数需要根据电池的参数自行设定。
更多操作。
能具体讲讲怎么做的吗,现在需要这个
您需要登录后才可以回帖 登录 | 注册

本版积分规则

102

主题

1019

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部