最可靠最准确无误的还是以标准电流放电,全程测量实际放电时间的方式。不同的放电电流,充电电池最终能够释放出的电量是不同的,有一定的差距。蓄电池的容量标注都是有统一标准的。目前使用最多的是10小时率放电容量与20小时率放电容量两种。10小时率放电容量就是电池以恒定电流放电,至电量耗尽放电时间能够维持10个小时左右,这个电流就被称作10小时率电流(衡量电量用尽的标准,不能以电池放电端电压降低到零为准。电池过度放电,会导致电池容量减少,无法恢复,乃至提早损坏、完全失效。所以每种电池放电终止电压都有严格的规定,这个可以查阅相关资料。过度放电与过度充电是造成充电电池不能达到使用年限、提前报废的主要原因)。实时放电的测量方法最大的缺点就是费时费力,因为耗时久这样测量精度也很容易受到各种外部因素的影响。测量过程中如果用10小时率电流持续放电时间至少都要在5个小时以上,作这样长时间的测试更需要足够的耐心与精力以及充裕的时间。科技的发展是非常迅速,今天单片机已经非常普及了。通过单片机程序控制对放电时间,深度进行自动化控制,就很容易精准测出电池的实际容量,实现整个过程的自动控制。模拟实际放电测量容量的方法虽然对能源有一点浪费,但是对于1A、2A以下的小容量充电电池还是完全可行的,对大容量电池进行抽样检查也是很有必要。
下面介绍的电池容量测试仪采用89S51作为控制芯片,图1就是硬件的电路原理图。
图1 硬件的电路原理图
这个电池容量测试仪由放电电路、单片机控制计时两个完全独立部分组合而成。单片机部分制作费时费力,而且市面上单片机已很普及,没必要亲手制作,随便找一片51单片机实验板就可以了。放电电路则是比较简单的,仅由四五只元件构成。单片机部分主要负责对放电时间计时,最终得到一组可靠的数据,用于电池性能的考量。
这种放电电路的实质就是一模拟可控硅。当我们将待测电池接入电路相应位置时,点按启动键,如果电池尚有余量,则电池两端放电电压将维持在设定值以上,三极管VT1就会瞬间饱和,电池通过电阻R2进行放电。这种电路有可靠精确陡峭的开关特性,VT1绝对工作于饱和截止两种状态之下。通过可调电阻对开关电路临界值(即充电电池放电终止电压)进行调节设定,便可适应于各种不同类型充电电池的全程保护放电。由于个人的应用不需要非常精准的测试结果,所以实际测试中电池模拟放电原则上还是以快些为好,只需要得到一个大致的电池容量。为了较快完成电池测试过程,这里的电路设计采用两小时率电流进行放电。通过对各种电池测量结果的横向比较,容量的差异还是显而易见的,以此作为衡量电池优劣的标准,就已经足够了。这里以1000mAH、1.2V规格镍氢电池测试为例,放电电流500mA就需要采用2Ω的放电电阻,电池终止放电电压应控制在1V以上。放电终止电压通过可调电阻R1来调节设定。普通可调电阻精度较差,且容易产生漂移,会导致设定好的终止电压随时间推移以及使用环境变化产生较大的波动。为了保证放电终止电压的精准且易于设定,R1可以使用3296系列精密可调电位器。3296多圈可调精密电位器的可调范围一般在50T,所以每圈的调节范围为2%,每转动一度,阻值变化大约0.005%,所以很容易调节获得一个精确、稳定的阻值。
终止电压的设定必须在实际放电过程中进行,负载电阻R2阻值变动,已经设定的终止电压也会随之改变,需要重新设置。具体的调试方法就不再详述了,参考一下相关资料。
这个放电电路不需要单独的工作电源,而且与电池种类没有相关性,完全可以适应镉镍、镍氢、锂电池、铅酸电池各种类型蓄电池的保护性放电,只是需要根据电池类型以及容量大小重新设置电路的终止电压及放电电流。如果电池容量相对较高,那么三极管VT1、VT2的耗散功率也要相应加大一些,同时不要忘了加大负载电阻R2的功率。
图2是放电电路的印刷电路图,元件数量少,很容易制作。
图2 印刷电路图
各种电池两小时率电流放电能够维持的放电时间一般都是在1.5小时以下的。这里单片机计时系统使用秒计时,4位LED数码管显示。最大计时时间9999秒,大约2.7小时。
图1单只LED数码管内部都是由8只发光管组合而成,分别作为8的7段字型部分,以及一位小数点。这里使用的是共阳极数码管,内部8只发光管的阳极是并连共同引出的,作为使能控制。
在实际电路中,L1就是第一只数码管的共阳极端。单片机的输出、输入接口数量都很有限,所以4位LED数码管驱动都是使用动态显示的方式。4只独立数码管LED的内部a、b、c、d、e、f、g、dp这8段发光管相对应的阴极都是并连的。统一由单片机P0口8位输出进行驱动。数码管要显示出数码还必须在共阳极端同时施加正电压才行。所以要让4位中某一数码管进行显示,只要在P0口输出字型码的同时,给这位数码管共阳极端加上正电压就行了,当然与此同时其他三位数码管的共阳极端要保持低电压,才不致显示出现混乱。数码管共阳极端驱动电流较大,所以采用了三极管进行控制。以第一只数码管为例,在P0端口输出字型码的同时,P37输出低电平,三极管T4导通,则共阳极端L1就得到高电平了,数字就会显示在第一只数码管上了。
程序设计是以单片机P37口作为计时控制端子,P37口输入低电平,计时程序启动,4只数码管显示时间。放电电路中按下启动按键,放电过程触发,VT1导通,电池端电压降落到放电电阻R2两端,A端对地为高电平,通过电阻R4迫使三极管VT3导通,P37口电平就被拉低了,单片机计时程序启动。电池电压降到终止电压以后,放电电路自动关闭,A端电压消失,VT3恢复截止状态,计时程序停止,数码管维持显示当前持续时间。
如要进入下次测试,首先按动单片机复位键,当前计时清零,等待下一次测试开始。
程序设计比较简单。它的大致流程如下:初始化,P3端口置位,设立常量a为时间计数器,依次对a的十进制数值各位进行提取,顺序输送到P0端口,P2端口中的P24、P25、P26、P27各位是依次作为四位数码管的使能控制端,通过P2端口的配合,就可以完成对各位数码管的驱动,时间的动态显示。程序进行中要不断地检测P3端口数值以决定计时状态:如果电池处于放电过程之中,三极管VT3导通,将迫使P37端口电压降到零,P3端口值就是127,单片机程序检测到这一结果,时间常量a将自动加1,指示期间放电时间已经延续1秒种了。这1秒钟的时间精确计算是比较麻烦的。计时程序是一个循环结构,每一周期耗用时间都是一致的。所以在使用keil软件调试过程中,通过对时间计数寄存器sec的观察计算,可以得出一次循环大致需要的时间。以此为据再通过适当改变延时子程序循环次数将常量a计时周期控制在1秒以下,剩余微小的时间差就可以通过插补空指令来校正了。计时精度只要控制在千分之一以下就可以了。在51单片机使用11.0592MHz晶体振荡器的情况下,指令周期大约1.085微秒,所以将计时精度控制在千分之一以下问题不大。误差总是会有的,只能通过精确计算来控制了,也可以通过更换更高频率的晶体振荡器提高单片机时钟频率的方法来进一步提高计时的精度。如果放电过程中,意外原因或者人为终止放电过程,P37端口变为高电平,程序循环依旧会进行下去,只是时间常量a停止自动加一,时间显示维持不变。
编译后,写入单片机内部,做好放电电路部分与51单片机的连接,便可投入使用。
电池接入后,按动轻触按键“启动”,就会进入一次容量测试过程,期间电池取出接入,都不会影响到单片机计时。电池放电完毕,单片机数码管显示锁定,给出总放电持续时间,单位为秒。可以自行人工计算放电小时数。当然也是可以自行对程序进行改进,直接以小时分钟形式进行显示。只要单片机不断电,数码管将持续显示当前放电时长。如果要进入下次测量过程,只需要按动单片机复位键,数码管清零,单片机程序转入起点,你就可以进入新一次的容量测试过程了。
充电电池如果较长时间闲置,它的实际容量将受到影响,重新启用第一次能够释放的容量远远达不到标注容量,放电电压也很不平稳。至少要经过三次以上的充电放电循环,电池完全激活,容量才能恢复到应有的水平。充分考虑这种因素的影响,所以容量测试一般采取多次平均的方式,或者循环充放电三次以后放电持续时间为准,以此衡量电池容量才算是恰当。
#include “reg51.h”
char
code disp[]={40,235,50,162,225,164,36,234,32,160};
//字形码
void delay(unsigned int dt)
{ unsigned int j=0;
for(;dt>0;dt--)
{ for(j=0;j<125;j++)
{;}
}
}
void main()
{ int a,b,c,led1,led2,led3,led4;
P3=255;
a=0;
for(;;)
{b=a;
led1=b%10;
P2=239;
P0=disp[led1];
delay(6);
P2=255;
b=b/10;
led2=b%10;
P2=223;
P0=disp[led2];
delay(6);
P2=255;
b=b/10;
led3=b%10;
P2=191;
P0=disp[led3];
delay(6);
P2=255;
b=b/10;
led4=b%10;
P2=127;
P0=disp[led4];
delay(6);
P2=255;
for(c=44;c>0;c--)
{
P2=239;
P0=disp[led1];
delay(5);
P2=255;
P2=223;
P0=disp[led2];
delay(5);
P2=255;
P2=191;
P0=disp[led3];
delay(5);
P2=255;
P2=127;
P0=disp[led4];
delay(5);
P2=255;
}
if(P3==127)
delay(3);
if(P3==127)
a=a+1;
else a=a;
}
}