リチウムイオン電池チェッカー
手元にリチウムイオン電池が沢山あります。中古品購入で分解して得たもの、中古カメラに付属していたもの、新品からかなり使ったもの、などなど。共通点は容量がかなり減っていそうでどれくらい使えるかわからないこと。
抵抗で放電させて電圧が降下するまでの時間を測って残存容量を調べたいと考えています。
部品箱に10Ω2Wの抵抗があったので2本をパラにして5Ω4Wとして使うと最大の4.2Vで 0.84A 3.5W になり、公称値の 3.7V ですと 0.74A 2.7W になります。抵抗の容量が心配ですが、燃えるか、断線するか、ですから見つめていると大事には至らないと思っています。
大まかな構想
MCはatmega48を使って、
1 水晶発振から経過時間を作りLCDに書き出す(廃物利用でセラミック振動子に変更)
2 負荷抵抗の両端の電圧を取り出し、AD変換でLCDに電圧を書き出す
3 終わりの電圧3.5Vを検知したら時間と電圧の表示を固定する
4 パワーFETを制御して電池から放電回路を切り離す
これらのコントロールを考えます。
作って見ると
こんな形になりました。
回路図です。
プログラムa12_m48_cellCheker2.zipです。
メインプログラムは次のとおりです。
// main.c
/******************************************************************
2017.11.07 CellCheker へ発展
_m48_LCDtest01←lcd_test01.c
mega328pのlcdテスト 160923 im
atmega48でテスト 20170512
I2CドライブLCDモジュールを作るための基礎。
lcd接続は lcd.hで。
今回の設定は data4-7 = portD-D3 RS=portD4 E=portD5 とした。
portB0にテスト用LED
「Hello!」その他の表示だけ
lcdライブラリでは(桁,行)でいずれも0で始まる。
(0,0) 1行目1桁から、 (0,1) 2行目1桁から (2,0) 1行目3桁から
******************************************************************/
#include <avr/io.h>
//#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "lcd.h"
uint8_t f=0;
ISR( TIMER1_COMPA_vect){ // コンペアマッチA割込が発生したときの処理を行います。
f=1;
}
/* メインルーチン *******************************************************************************************/
int main (void) {
uint8_t d[10];
char msg[18];
char tt[9];
uint8_t h=0,m=0,s=0;
uint8_t k=0;
uint8_t a=0; //変換用
int b;
// ポートB初期設定
DDRB = 0xff; // PB7〜PB0を出力に設定します。
PORTB = 0b11111101; // PB1以外に'H'を出力します。
//タイマの初期設定
TCCR1B |= (1 << WGM12); // タイマ1をCTCモードに設定
OCR1A = 31249; // コンペアマッチAレジスタに31249を設定
TIMSK1 |= (1 << OCIE1A); // コンペアマッチA一致で割込を許可します。
TCCR1B |= (1 << CS12); // 256分周でタイマをスタートさせます。
ADCSRA = 0b10000100; // AD許可:1 AD開始:0 AD自動起動:0 AD割込:0 AD完了割込:0 ck/16
ADMUX = 0x00; //AREF外部電圧、入力PC0
lcd_init(); //ここでLCDポートの方向が設定される
sei(); // cli()
lcd_cls();
while(1){
if(f>0){ // 1秒割り込みがあれば
f=0;
s++;
if(s==60){s=0; m+=1; if(m==60){m=0; h+=1;}}
tt[0]=h/10+'0'; tt[1]=h%10+'0'; tt[2]=':'; tt[3]=m/10+'0'; tt[4]=m%10+'0';
tt[5]=':'; tt[6]=s/10+'0'; tt[7]=s%10+'0'; tt[8]=0;
lcd_gotopos(0,0); lcd_putstr("time ");
lcd_gotopos(5,0); lcd_putstr(tt);
ADCSRA |= _BV(ADSC); //変換開始 要ループ内
loop_until_bit_is_set(ADCSRA,ADIF); //変換終了時ADIFがセットされる
a = ( ADC >> 3 ); //AD変換結果 3bitシフト= 7bit:0-127
b=(int)a;
b=(b*10)/25+0;
d[0]=b/10+'0';d[1]='.';d[2]=b%10+'0';d[3]=0;
lcd_gotopos(0,1); lcd_putstr("cell volt ");
lcd_gotopos(10,1); lcd_putstr(d);
lcd_gotopos(13,1); lcd_putstr("v ");
if(b<36){
PORTB |= 0x02;
while(1){};
}
k++;
PORTB &=0xfe;
_delay_ms(20);
PORTB |=0x01;
}
_delay_ms( 10);
}
}
感想
なんとか思い通りになりましたが、すんなりとは進みませんでした。
久しぶりのAVRで殆ど忘れています。1秒の割り込みやADCの使い方などは以前はデータシートで調べたのですが、今回はその力が続かずnetの事例を参考に(コピペで)組み立てました。一時はAVCCの配線忘れがあってAD変換はするものの正確に動かず思案のときもありました。
試験電池を繋いで、リセットSWを押すと1秒毎に黄色LEDが短く光り 時:分:秒 がカウントアップします。同時に電池の電圧が0.1V単位で表示されます。電池の負荷抵抗は10Ωと10Ω2個並列の5Ωから選びます。10Ω負荷で電圧が3.8Vだと0.38A流れることになります。電圧が4.2V程度から3.6Vまで変化するので定電流にはなりませんが3.5Vになるまでの時間で電池の容量が推測できます。
デジカメの電池が弱っていたので試してみると本来は750mAhのはずですが10Ω負荷で24分程しか持ちません。370*24/60=150mAhしか無いことになります。これでは実用にならないはずです。
測定に時間がかかりますが、ぼつぼつと調べたいと思っています。
なお、余談ですが最近、5Vと3.3Vの電源コネクタをピンヘッダとピンソケットで統一することにしました。端子の形状が小さくかさばらずまた着脱が簡単なので便利です。ただ、プラスマイナスが同じなので逆接続しないように注意が必要ですがプラス側を赤マジックで色付けして間違わないようにしています。場合によってはエポキシ接着剤で補強しています。
試しに中国製の安価な片面基板を使いましたがこれは失敗でした。ハンダの乗りが悪く、かつ、少し長引くとランドが熱で剥がれてしまいます。大事なところは銅線で固定してからはんだ付けしました。
久しぶりのTQFPの端子のハンダは0.2mmUEWを1C型こて先で行いました。ルーペの下、ピンセットでUEWを挟んで固定してはんだ付けしました。思ったより簡単にできました。
工事中