放电容量检测(DIY电池容量内阻测试仪程序源码)

Posted

篇首语:只愿我永远在爱里,不断地学习,即使悲伤本文由小常识网(cha138.com)小编为大家整理,主要介绍了放电容量检测(DIY电池容量内阻测试仪程序源码)相关的知识,希望对你有一定的参考价值。

放电容量检测(DIY电池容量内阻测试仪程序源码)

//DIY低成本电池容量测试仪,测试原理:测试有负载与无负载间的电压差,

//通过已知外部电阻计算电池内阻。通过每隔一秒测一下电压,通过已知外部放电电阻计算电流

//累积计算毫安时

//电源为USB5V

//12864接PORTC,* 0: SDI 1: SCK 2: A0 3: RS 4: CS1

//12864 面向正面gnd|VCC|SDI|SCK|A0|RES|CS1,CS1标的1脚

//电池接PORTA 0,通过1K+1K分压接入AD,AD参考源为内部2.56V参考源,PORTA置为AD转换器,可同时测8路电池

//电池通过6.8水泥电阻放电

//继电器接PORTD 7,用于控制电池放电启停

//旋转编码器K关接INT 0,PORTD 2,用于操作放电启停

//旋转编码器A接INT 1,PORTD 3,B接PORT D 4,用于调整放电截止电压,

//注意施转编码器各脚需接104电容到地,通过510电阻到各脚

//开发平台ICCAVR 6.31A,使用了num2str-数字转字符串,mygraphic-抽象图形库,mzl05-针对铭正同创mzl05-12864的硬件层接口

// Target : M16

// Crystal: 8M外部晶振

//发现问题,AD接地仍有电压,可能电AREF没有外接电容,好象不是,PORTA=0x00后解决,但比万用表高0.1

#include <iom16v.h>

#include <macros.h>

#include <eeprom.h>

#include "num2str.h"

#include "mzl05.h"

#include "myGRAPHICS.h"

extern char glcdhalf;//由于M16内存局限每次只刷新半个屏幕

int count;//timer0计数

int adc;//ADC转换结果

float adcfloat;//ADC转换结的浮点表示

int adcnoloadvalue=0,adcloadvalue=0;//无载电压与有载电压,用于计算内阻

unsigned char firststart=0;//第一次进入有载

unsigned char adcbuffer[8];//ADC字符串结果

unsigned char rotate_key=0;//旋转编码器开关状态

unsigned char rotate_code=0;//PIND,用于判断旋转方向

unsigned char rotate_dir=0;//旋转编码器方向

unsigned char hour,minute,second;

unsigned int secondcount;

unsigned int stopvalue=512;//停止放电电压

//unsigned char tempunsignedchar;

float res;//电池内阻

float cap;//电池容量

unsigned int adccap=0;//电池容量整数表示

unsigned char adccurv[128];//放电电压曲线,每分钟一记,可记2小时

unsigned char adccurvcount;

unsigned int i;

void port_init(void)

PORTA = 0x00;

DDRA = 0x00;

PORTB = 0xFF;

DDRB = 0xFF;

PORTC = 0xFF;

DDRC = 0xFF;

PORTD = 0x7F;

DDRD = 0x80;//PORTD PIN7为继电器控制

//外部中断0

#pragma interrupt_handler int0_isr:2

void int0_isr(void)

if(rotate_key==0)//未放电状态

PORTD |=1<<7; //关闭常开触点,开始放电

rotate_key=1; //记录标志

hour=minute=second=0; //初始化计时器

firststart=1; //第一次进入放电状态

else

PORTD &=~(1<<7); //断开继电器

rotate_key=0; //记录标志

//外部中断1

//在旋转编码器A相下降沿查看B相电平,如果是高++

#pragma interrupt_handler int1_isr:3

void int1_isr(void)

rotate_code=PIND;

if((rotate_code & 0x10) == 0x10)

stopvalue++;

else

stopvalue--;

//tempunsignedchar=stopvalue % 256;

//EEPROMwrite(1,tempunsignedchar);

//tempunsignedchar=stopvalue / 256;

//EEPROMwrite(2,tempunsignedchar);

void timer0_init(void) //定时器初始化程序

TCCR0 = 0x00; //停止定时器

//TCNT0 = 0x3A; //设置初始值,75us,合计0.075X256=20ms//3A好用,计算值44

TCNT0=0xCF;//75us/4

TCCR0 = 0x02; //开动定时器,可能是主频/8

void ADInit(void)

ADMUX|=(1<<REFS1)|(1<<REFS0); //选择内部2.56V为ADC的参考电压

ADMUX&=~(1<<ADLAR); //转换结果右对齐

ADMUX&=~(1<<MUX4);

ADMUX&=~(1<<MUX3);

ADMUX&=~(1<<MUX2);

ADMUX&=~(1<<MUX1);

ADMUX&=~(1<<MUX0); //选择通道ADC0

ADCSRA|=(1<<ADPS2)|(1<<ADPS0);

ADCSRA&=~(1<<ADPS1); //时钟分频系数为64

ADCSRA|=(1<<ADEN);//使能AD

ADCSRA&=~(1<<ADATE);//不自动转换

ADCSRA&=~(1<<ADIE);//禁用AD中断

#pragma interrupt_handler timer0_ovf_isr:10

void timer0_ovf_isr(void) //定时器溢出中断程序,大约49*8机器周期中断一次

//TCNT0 = 0x3A; //从新调入初始值

TCNT0=0xCF;

secondcount++;

if(rotate_key==1)//如果开始测量容量,记时,开始计算容量

if(secondcount>10933)//大约一秒,可能还要调一下

secondcount=0;

second++;

if(second>59)

second=0;minute++;

adccurv[adccurvcount]=63-(unsigned char)(adccap/16);

adccurvcount++;

if(minute>59)

minute=0;hour++;

//adccap来自前一次测试时的电压,电压/电阻等于电流,每一秒累加电流*时间等于mAh

cap+=(((float)adccap*2.0*2.56*1000.0)/1024.0)/6.8; //ma,计算mAs


//cap=(((adccap*2.0*2.56/1024.0)/6.8)*1000.0) //ma

// *(hour+minute/60.0+second/3600.0);//hour

count++; //每中断一次加1

if (count>4096) //需要估算时间

//AD转换


ADCSRA|=(1<<ADSC); //启动一次AD转换

while(!(ADCSRA &(1<<ADIF)))

;//ADIF 为1时表示AD转换完成

adc=ADCL;

adc|=(int)(ADCH<<8);

adccap=adc;//随时采集电压用于计算容量

ADCSRA|=(1<<ADIF);

//AD转换结束

if(rotate_key==0)adcnoloadvalue=adc;

if(rotate_key==1 && firststart==1)

firststart=0;

adcloadvalue=adc;

//计算内阻,(无载电压-带载电压)/电流

res=(((adcnoloadvalue-adcloadvalue)*2.0*2.56)/1024.0) //电压差

/((adcloadvalue*2.0*2.56/1024.0)/6.8);//电流,6.8为水泥电阻阻值

cap=0.0;//初始化容量

for(i=0;i<128;i++)adccurv[i]=0;//初始化曲线

adccurvcount=0;

//如果电压低于终止电压,停计容量,断继电器

if(adc<stopvalue && rotate_key==1)

PORTD &=~(1<<7);

rotate_key=0;

adcfloat=2.56*adc/1024.0;

adcfloat=adcfloat*2;//真实电路中电压被分压1/2


Float2Str(adcbuffer,adcfloat,1,3);//格式化成为字符串


glcdhalf=0;

glcd_fillScreen(0);

//当前电压

glcd_text57(2,2,adcbuffer,2,1);

//是否开始,如果已经开始测容量显示stop

if(rotate_key==1)

glcd_text57(96,2,"stop",1,1);

else

glcd_text57(96,2,"start",1,1);

//时钟

Num2Str(adcbuffer,hour,2);

glcd_text57(80,12,adcbuffer,1,1);

glcd_text57(92,12,":",1,1);

Num2Str(adcbuffer,minute,2);

glcd_text57(98,12,adcbuffer,1,1);

glcd_text57(110,12,":",1,1);

Num2Str(adcbuffer,second,2);

glcd_text57(116,12,adcbuffer,1,1);

//时钟end

//终止电压

adcfloat=2.56*stopvalue/1024.0;

adcfloat=adcfloat*2;//真实电路中电压被分压1/2

Float2Str(adcbuffer,adcfloat,1,3);

glcd_text57(96,24,adcbuffer,1,1);

//终止电压end

//内阻

Float2Str(adcbuffer,res,1,3);

glcd_text57(2,18,adcbuffer,2,1);

glcd_text57(60,23,"R",1,1);

//内阻end

//容量

Float2Str(adcbuffer,cap/3600.0,5,1);

glcd_text57(2,40,adcbuffer,2,1);

glcd_text57(80,45,"mAh",1,1);

//容量end

for(i=0;i<adccurvcount;i++)

glcd_pixel(i,adccurv[i],1);

//glcd_line(1,1,64,63,1);

glcd_update();

glcdhalf=1;

glcd_fillScreen(0);

glcd_text57(2,2,adcbuffer,2,1);

if(rotate_key==1)

glcd_text57(96,2,"stop",1,1);

else

glcd_text57(96,2,"start",1,1);

//终止电压

adcfloat=2.56*stopvalue/1024.0;

adcfloat=adcfloat*2;//真实电路中电压被分压1/2

Float2Str(adcbuffer,adcfloat,1,3);

glcd_text57(96,24,adcbuffer,1,1);

//终止电压end

//内阻

Float2Str(adcbuffer,res,1,3);

glcd_text57(2,18,adcbuffer,2,1);

glcd_text57(60,23,"R",1,1);

//内阻end

//容量

Float2Str(adcbuffer,cap/3600.0,5,1);

glcd_text57(2,40,adcbuffer,2,1);

glcd_text57(80,45,"mAh",1,1);

//容量end

for(i=0;i<adccurvcount;i++)

glcd_pixel(i,adccurv[i],1);

//glcd_line(1,1,64,63,1);

glcd_update();

count=0;



//call this routine to initialise all peripherals

void init_devices(void)

//stop errant interrupts until set up

CLI(); //disable all interrupts

port_init();


MCUCR |= 1<<ISC11;

MCUCR &= ~(1<<ISC10); //外部中断1为下降沿触发,用于旋转编码器

MCUCR |= 1<<ISC01;

MCUCR &= ~(1<<ISC00);//外部中断0为下降沿触发,用于旋转编码器开关


GICR = 0b11000000;//外部中断使能1,0

SFIOR&=~BIT(PUD);//使能上拉电阻

TIMSK = 0x01; //timer interrupt sources,enable timer0

timer0_init();

ADInit();

SEI(); //re-enable interrupts

//all peripherals are now initialised

rotate_key=0;

hour=0;

minute=0;

second=0;

secondcount=0;


//tempunsignedchar=EEPROMread(1);

//stopvalue=(unsigned int)tempunsignedchar;

//tempunsignedchar=EEPROMread(2);

//stopvalue=stopvalue+(unsigned int)tempunsignedchar*256;

stopvalue=512;

adcnoloadvalue=adcloadvalue=0;

firststart=0;


cap=0.0;


for(i=0;i<128;i++)adccurv[i]=0;

adccurvcount=0;

void main(void)

init_devices();


glcd_init();

glcd_update();

//glcd_fillScreen(0x01);



//insert your functional code here...

while (1)

;

相关参考

湿润角检测仪(锂离子电池隔膜性能参数与测试方法汇总)

...电池的界面结构和内阻等,进而影响电池整体的容量、充放电电流密度、循环性能以及安全性等。本文通过对国内外电池隔膜测评标准的归纳和整理,较为全面系统地介绍各测试项目,包括其原理、现有标准及测试方法等,并对...

湿润角检测仪(锂离子电池隔膜性能参数与测试方法汇总)

...电池的界面结构和内阻等,进而影响电池整体的容量、充放电电流密度、循环性能以及安全性等。本文通过对国内外电池隔膜测评标准的归纳和整理,较为全面系统地介绍各测试项目,包括其原理、现有标准及测试方法等,并对...

智能蓄电池组负载测试仪(通信动力维护中,蓄电池后备容量与后备时长测算了解一下)

...量放电试验(10小时率、或者3小时率)获得。蓄电池放电测试仪蓄电池组所标注容量均为标准工况下10小时率标称容量(C10),如500AH,指工作温度为25℃,放电电流为50A(I10=0.1C10),可放电1

报废18650处理(拒绝拆机电池 疑似耐时新品18650动力电池曝光)

...3mΩ要小,初步判断该型号电池为准动力电池。在网友的4A放电测试中,发现该电池充满共放出电量2844mAh,也就是该准动力电池的实际容量约为2800mAh,在之后多次测量中数据保持一致。在低温-20℃下,依然能够放出2400mAh的电量,...

放电欠压(电瓶修复技术-充电可以估算电池容量吗?)

...业的电池知识,最简单怎样测容量?干点啥  如果没有放电仪检测容量,可以使用充电估算法。  当电池放电至欠压灯亮,充电(单独一个标准充电器),如果充电时间为8小时转灯的电池容量为12AH,充电时间为6小时为9AH,...

成型弹片(锂电池pack性能测试标准,电池测试模组就选弹片微针模组)

...单个使用的电池叫做电芯,只有连接上保护板,有充电、放电功能的成品电池组才被称为锂电池pack。锂电池pack指的是组合电池,它是通过单体锂电池的串联和并联组成一定的电压和容量,再加装保护板,使成品锂电池可以进行...

开关电源主滤波电容容量下降(开关电源维修,输出滤波电容问题?)

...因为输出滤波电容损坏,滤波电容是有寿命的,长时间充放电会增加内阻ESR,电容内部是有内阻ESR和电感ESL,由于制作工艺,内阻ESR不可能为零,只有在理想状态下是零,当在对电容反复充电过程中,由于内阻ESR的存在,会

快巴纸的(锂电池串并联,电池串联和并联的区别)

锂电池串并联定义由于单体电池的电压和容量有限,在实际使用中都需要进行串并联组合,以获得更高的电压和容量,才能满足设备的实际供电需求。锂电池串联:电压相加,容量不变,内阻增大。锂电池并联:电压不变,容量相...

消防应急电源系统(应急电源介绍,安装,测试,施工必备)

...器全自动固态恒压型,装备有电子电路,保护电池过充或过放电。充电系统能使电池在全部放电后于24小时内再充电至满容量。灯具的控制电路可用于主电源上,应急照明器和正常传统照明器的操作一样。主电源发生故障时,不管接触...

消防应急电源系统(应急电源介绍,安装,测试,施工必备)

...器全自动固态恒压型,装备有电子电路,保护电池过充或过放电。充电系统能使电池在全部放电后于24小时内再充电至满容量。灯具的控制电路可用于主电源上,应急照明器和正常传统照明器的操作一样。主电源发生故障时,不管接触...