手机锂离子电池参数智能校正算法思考

来源:互联网 发布:微信 php location跳转 编辑:程序博客网 时间:2024/04/27 22:37
 

手机电池的种类比较多,常用的有锂离子电池和镍氢电池等。锂离子电池和锂电池是不同的概念,通常我们说的锂电池其实指的是锂离子电池。锂离子常被简称为锂电池,但其实锂电池和锂离子电池是两个不同概念,这里不去研究他们的不同,一律统称锂电池。人们常常认为锂电池是没有记忆效应的,这是厂商的误导。锂电池仍然有记忆,只是远比镍氢电池轻微而已。如果长期采用没事儿就充电的方法,锂电池也会出现严重的记忆效应(所谓记忆效应,就是电池储存的电量越来越难以释放放出来,对外表现就是充满电的电池的使用时间越来越短)。

即使按最科学的方法使用锂电池,锂离子仍然会随着时间的增长而出现记忆效应。这主要是由于氧化引起的内部电阻增加,当电解槽电阻达到某个值,尽管这时电池充满了电,但电池却不能释放已储存的电量引起。而且最重要是锂离子电池也有使用寿命,锂离子电池一般能够充放300-500次,一旦电池下了生产线,时钟就开始走动。不管你是否使用,锂电池的使用寿命都只有两到三年,之后虽然还能使用,但已经很难令人满意。

由于用户使用不善和电池自然寿命等原因,为电池管理软件开发带来了一定的麻烦。反应在手机上,就是我们很难准确的写出直观反应当前电池待机时间的程序。而且锂电池放电过程并不是一个均匀递增或者递减的的曲线,而是如下图一样的曲线。

从图中可以看出,满电池开始的部分很不耐用,中间的部分很耐用,到了快没电的时候又很不耐用了,而且这放电过程还受周围环境温度的影响。如果我们按均匀的放电原则设计手机电池管理程序,就会发现电池满格的那格电很不耐用,中间的的二格电很耐用,最后的一格电也很不耐用,这是我们许多设计电池管理程序的人常常被客户投诉的一个原因,电量显示不准。但是如果我们使用非均匀原则为客户设计电池管理程序,把四格电的待机时间精确的一样,又会出现另一个问题,随着电池老化程度加大,中间两格电的待机时间也会慢慢缩短,这样就会让客户发觉中间两格很不耐用,第一格与第四格相差很多。

电池电量的显示也无法非常的精确,由于充放电曲线也不是绝对平滑的,在毫少级下其实表现为不规则的震荡波,所以为了更准确的反应电池电量,一般会设置一个计数器,让放电或者充电过程中电压多次超过或者低于某个值,才会认定电压达到某个值。

 

锂电池放电需要注意几点:第一,放电电流不能过大,过大的电流导致电池内部发热,有可能会造成永久性的损害。在手机上,这个倒是没有问题的,可以不考虑。第二,绝对不能过放电!锂电池最怕过放电,一旦放电电压低于2.7V,将可能导致电池报废。好在手机电池内部都已经装了保护电路,电压还没低到损坏电池的程度,保护电路就会起作用,停止放电。

锂电池的充电方式是限压横流方式。充电开始时,应先检测待充电电池的电压,如果电压低于3V,要先进行预充电,充电电流为设定电流的1/10,一般选0.05C左右(C一般用作充放电电流作参照,C是对应电池容量的数值。电池容量一般用Ah、mAh表示,如M8的电池容量1200mAh,对应的C就是1200mA。0.2C就等于240mA。)。电压升到3V后,进入标准充电过程。标准充电过程为:以设定电流进行恒流充电,电池电压升到4.20V时,改为恒压充电,保持充电电压为4.20V。此时,充电电流逐渐下降,当电流下降至设定充电电流的1/10时,充电结束。 一般锂电池充电电流设定在0.2C至1C之间,电流越大,充电越快,同时电池发热也越大。而且,过大的电流充电,容量不够满,因为电池内部的电化学反应需要时间。就跟倒啤酒一样,倒太快的话会产生泡沫,反而不满

下面这是充电曲线:

 

一般情况下电池大负荷工作后,减少负荷会出现电压回升现象,就是所说的“回电”现象。如下图,

这也是导致有些客户投诉电池的一个原因,打着电话,突然低电量关机了,再开机发现还有一格电呢,或者开机时零格电,待机过一会儿,竟然又有一格电了。

基于以上各种各样的原因,使电池管理程序变得十分难以准确,可以考虑使用智能电池管理。使用电池校正程序,自主校正参数,写入NV,供电源管理程序调用。具体原理就是在一次充满电放电过程中,记录下每次电压下降0.01V所消耗的时间。最后把这些时间合起来,根据电池格数计算每格电需要的理论时间,最后通过时间来计算各格电需要的达到的电压,并把结果写入NV做为电池管理的依据。为了达到近似的精确,许多时候我们需要在一定周期内重新校正,并且可以根据电池测试结果提示用户淘汰旧的电池,使用新的电池。

 

下面附上一些不完全的样例代码,把他添加到custom_cfg_vbat_level_convert,就能实现电量监控和记录,很早写的代码,未完全测试,了解原理又有兴趣的朋友可以自己试着完善。

#if 1 

#include "app_datetime.h"

typedef struct my_bat_adjust{

       applib_time_struct time;

       kal_int32 bat_value;

}myba;

myba g_my_bat[100];

 

kal_int8 g_arr_index = 0;

kal_int8 my_get_bat_value( kal_int32  vbat)

{

       applib_time_struct mytime;

 

       if (g_arr_index == 0)

       {

              applib_dt_get_date_time(&mytime);

              g_my_bat[g_arr_index].bat_value = vbat;

              memcpy(&g_my_bat[g_arr_index].time, &mytime, sizeof(applib_time_struct));

              g_arr_index++;

       }

       else

       {

              if ((g_my_bat[g_arr_index-1].bat_value/10000)-1 == (vbat/10000))

              {

                     applib_dt_get_date_time(&mytime);

                     g_my_bat[g_arr_index].bat_value = vbat;

                     memcpy(&g_my_bat[g_arr_index].time, &mytime, sizeof(applib_time_struct));

                     g_arr_index++;

              }

       }

}

#endif

该文章的一些电池计算和研究的图表数据参考自

http://www.xker.com/page/e2009/0611/72423.html

这里表示感谢。

原创粉丝点击