pic 簡易バッテリ残量モニタ

投稿日 2011/06/03

シールバッテリは使用中、保管中にかかわらず過放電に注意する必要があります。

 

シールバッテリの残量は式 Vout x 70 - 800 でおおよそ知ることができます。

 

これに基づいて、残量割合をLED 4個で表示する簡易な残量モニタを作ってみました。

 

残量割合を以下のように表示します。

 

10%以下 ●●●● 0 11.56V以下
10%以上 ●●●○ 1 11.56V以上11.72V以下
20%以上 ●●○● 2 11.72V以上11.86V以下
30%以上 ●●○○ 3 11.86V以上12.00V以下
40%以上 ●○●● 4 12.00V以上12.14V以下 ->要充電
50%以上 ●○●○ 5 12.14V以上12.28V以下
60%以上 ●○○● 6 12.28V以上12.42V以下
70%以上 ●○○○ 7 12.42V以上12.56V以下
80%以上 ○●●● 8 12.56V以上12.72V以下
90%以上 ○●●○ 9 12.72V以上12.86V以下
100%以上 ○●○● 10 12.86V以上13.00V以下
110%以上 ○●○○ 11 13.00V以上13.14V以下 ->フル充電
120%以上 ○○●● 12 13.14V以上13.28V以下
130%以上 ○●●○ 13 13.28V以上13.42V以下
140%以上 ○●○● 14 13.42V以上13.58V以下

 

○はLEDが点灯、●は消灯を示します。
LEDが○●○●つまり10を表示していたら100%から110% 電圧にすると12.86Vから13.00V ほぼフル充電状態であることを示します。

battery_monitor.jpg

モニタ中。○●○●は100% ほぼフル充電であることを示す。

 

回路はPIC 12F683を使用した簡単なものです。

 

クロックは内部クロックの31KHzを使用し低速で動かします。

 

LED4個はGP5, 2, 1, 0につなぎます。保護抵抗は10KΩで少し暗めに点灯させます。

 

A/DコンバータはAN3(GP4)を使います。リファレンス電圧は電源、つまり80L05の出力で+5Vです。

 

リファレンス電圧が安定しないとふらつくので、必ず0.1uFを入れておきます。

 

念のためバッテリの近くにポリスイッチを入れておきます。

battery_monitor_kairozu.jpg

PIC 12F683のA/Dコンバータは10bitなので分解能は、5 / 1024 = 0.00488Vです。

 

バッテリの電圧は分圧して、14Vのとき5VになるようにA/Dコンバータに与えます。

 

分圧は18Kと10KΩで行います。抵抗は精度のよいものは不要ですが、使用する抵抗をデジタルテスター等で、なるべく正確に測り、その値から分圧値を求め、さらにその電圧のA/Dコンバータのバイナリ値をリストアップしておきます。エクセルを使用すると便利です。バッテリ電圧の0.01Vの精度があります。

 

タイマー0(TMR0)の1秒間隔の割り込みで、A/Dコンバータの値を読み取りLEDに表示します。もちろん1秒である必要はありません。

 

小型に作って常にバッテリにつないでおけば、いつでも残量がわかり便利です。

 

消費電流はLEDがすべて点灯して5.5mAくらいです。

 

私は、LEDの点灯が●○●● = 4つまり残量割合40%になったら使用を止め、充電するようにします。
冒頭にも書きましたが、シールバッテリは過放電は禁物です。
このモニタで保管中でもときどきLEDをチェックして、過放電にならないよう心がけたいものです。

 

以下はプログラムソースです。(mikroC)

 

void interrupt() {
unsigned int ad_value;

 

ad_value = ADC_Read(ANS3);

if (ad_value <= 0x351) GPIO = 0; //10%未満
else if (ad_value <= 0x35D) GPIO = 0x01; //10%以上
else if (ad_value <= 0x367) GPIO = 0x02; //20%
else if (ad_value <= 0x372) GPIO = 0x03; //30%
else if (ad_value <= 0x37C) GPIO = 0x04; //40%
else if (ad_value <= 0x386) GPIO = 0x05; //50%
else if (ad_value <= 0x391) GPIO = 0x06; //60%
else if (ad_value <= 0x39B) GPIO = 0x07; //70%
else if (ad_value <= 0x3A7) GPIO = 0x20; //80%
else if (ad_value <= 0x3B1) GPIO = 0x21; //90%
else if (ad_value <= 0x3BB) GPIO = 0x22; //100%
else if (ad_value <= 0x3C6) GPIO = 0x23; //110%
else if (ad_value <= 0x3D0) GPIO = 0x24; //120%
else if (ad_value <= 0x3DA) GPIO = 0x25; //130%
else if (ad_value <= 0x3E6) GPIO = 0x26; //140%
else GPIO = 0x27; //150%

TMR0 = 256 - 30;
INTCON.T0IF = 0;

}

 

void main() {
//Internal Clock = 31KHz
OSCCON.IRCF2 = 0;
OSCCON.IRCF1 = 0;
OSCCON.IRCF0 = 0;

//AD Convertion Clock Internal
ANSEL.ADCS1 = 1;
ANSEL.ADCS0 = 1;

ANSEL.ANS3 = 1; //AD AN3(GP4)

GPIO = 0;
TRISIO = 0b00010000; //GP4 in、GP0,1,2,5 Out

OPTION_REG = 0x07; //Prescaler 256
TMR0 = 256 - 30; //TMR0 30 -> 1sec Interval
INTCON.T0IE = 1;
INTCON.GIE = 1;

while(1) {

//Do not nothing!

 

}
}


 

(JF1VRR)