PIC16F877応用NiCdバッテリ充放電器

PIC16F877のA/D変換機能を利用して、最大6本のバッテリの
電圧を監視しながら最適な充電を制御します。



【概要】

NiCdバッテリの寿命を最大にし、出力性能を長持ちさせるためには、充電の
仕方にポイントがあります。
そこで、PIC16F877に新たに内蔵された、10ビット分解能のA/D変換機能を
有効に活用して、個々のバッテリの電圧を常時チェックしながら、最良の充電
をするよう制御する充電器を作ってみました。
最良の充電条件にするためには、メモリ効果を避ける必要があります。そこで
これを避けるために放電機能も内蔵させることにしました。


【充放電器の仕様】

今回製作したNiCdバッテリの充電、放電機能の仕様は下記としました。

バッテリ個数  最大6個 個別制御(1個づつ独立制御)
対象バッテリ  単3型NiCd電池(500mAH〜1000mAH)
入力電源    商用AC100V 消費電力 約5W
表示       16文字2行の液晶表示器にて状態表示
          表示内容は下記
            バッテリNo   状態  充電、放電時間  バッテリ電圧
          また充電中は個々に発光ダイオードが点灯
充電電流    1個当たり 約85mA
放電電流    1個当たり 約150mA at 1V

制御方式    実際の充電放電の制御は、NiCdバッテリの充電、放電特性から
          下記としました。
    放電   バッテリが装着されたことを自動認識し、バッテリ電圧が0.9V
          以上であれば放電を先に開始する。
    充電   放電が0.9V以下になったら自動的に充電に切り替わり
          下記3つの条件のいずれかで充電終了とする。
           (1) 充電継続時間が15時間を超えた。
           (2) バッテリ電圧が1.50Vを超えた。
           (3) バッテリ電圧上昇率が4%/分を超えた。
             これはバッテリの満充電付近で急に端子電圧が上昇する
             ことを利用しています。


【NiCdバッテリ充放電器の構成】

本器の全体構成は下図のようになっています。図の中で全体の制御を取り
仕切っているのはPIC16F877で、充電、放電の回路を除けばPICしかありません。
PIC16F877は、色々な周辺回路が内蔵されているので便利に使えます。
まず、このPICから内蔵された10ビットのA/D変換でバッテリの電圧計測をします。
10ビットありますから、1024の分解能があることになります。
そこで、Vref+の基準電圧に「2.047V」を入力して、フルスケールが2.047V
となるようにすれば、バッテリ電圧を0〜2.047Vまで、2mVステップで計測でき
ることになります。これなら十分の分解能でバッテリ電圧を計測することが出来ま
す。従来の8ビット精度では、256の分解能しか無く、電圧を測定するには10mV
単位が限界であるため、ちょっと精度不足でしたが、これで十分の分解能を得る
ことが可能になりました。




【充電放電回路】

バッテリを充電、放電する回路の部分は下図のようにしました。

(1) 放電時の回路
 放電回路は、放電終止電圧(0.9V)まで確実に放電できるように、MOSトラン
ジスタと抵抗の直列回路でショートするようにしました。



図のようにMOSトランジスタのON時の抵抗は0.2Ω以下にできますので、
5Ωの抵抗と比べても十分低く、直列にしても、十分電池を放電させることができ
ます。
放電電流は、バッテリが1Vの時で、1V/5Ω=200mA流れるはずですが、
電池自身の内部抵抗のため実際に流れる放電電流は150mA程度です。

大部分の発熱を抵抗側で消費することができるので、MOSトランジスタの発熱を
抑えることが出来ます。しかし、抵抗でほぼ大部分の放電を行いますので、全て熱
に変わります。従って抵抗は容量の大きなものが必要となります。
ここでは、150mA×1V=0.15Wですから、ちょっと大き目の1Wの抵抗を使いました。
尤も、最近の抵抗は、1Wといっても1/4Wタイプの抵抗と大きさは余り変わらなく
なってしまいましたので、実装に苦労することは無いでしょう。

ここで放電終止電圧を何ボルトにするかですが、NiCdバッテリの資料によれば
放電特性は下図のようになっており、終止電圧を0.9V〜1.0V程度にするよう
推奨されています。そこで、放電終止電圧は最低電圧の0.9Vとしました。
図で「C」はバッテリの容量を示しています。例えば500mAhのバッテリなら
2CmA=1000mA ということです。





(2) 充電時の回路
 充電回路は定電流充電をするため、定電流回路となっています。この回路は下図
の回路で実現しています。




この充電回路では、2SC1815がOffされると、2SD415がOnとなり充電電流が流れ
始めます。この時の電流は、15Ωの抵抗で制限されますが、この制限される内容
は、発光ダイオード(LED)とトランジスタのBE間電圧で決まります。
この両者の電圧は電流にかかわらずほぼ一定で、LEDの順電圧=約2V、トランジ
スタBE間電圧=0.7Vとなっています。
そのため、15Ωでの電圧降下が、2-0.7=1.3V 以上となるとトランジスタのベース
電圧が見かけ上下がるためCE間電流を小さくして15Ωの電圧降下を小さくします。
逆に、15Ωでの電圧降下が小さくなると、ベース電圧が上がり電流をもっと流そうと
します。

この動作により、15Ωを流れる電流は、(2V−0.7V)/15Ω=85mA で一定
となります。つまり充電電流が一定の85mAの定電流となったことになります。

10D1のダイオードはバッテリから逆向きに電流が流れてしまうのを防止します。
1kΩの抵抗は、バッテリの電圧測定の時、放電も充電も中止して測定するので
バッテリが完全に開放の状態になってしまうのを避けるのと、バッテリが実装されて
いないとき、測定電圧が0Vになるようにします。
200Ωの抵抗は発光ダイオード(LED)に電流を流して点灯させる働きをします。

次に充電の終了を何で判断すれば最適かということになります。
これも、NiCdバッテリの充電特性が下図のようになっていますので、図中に吹き出
しで示したように、3通りのいずれかの条件を超えたら充電を終わらせます。



【基準電圧回路】

バッテリの電圧を測定するために、PICのA/D変換機能を使っていますが、これの
フルスケールを決めるリファレンス電圧には、精度の良い基準電圧が必要です。
今回は、基準電圧を2.047Vにすることにしましたから、これに丁度使える基準
電圧発生用のICには、一寸古いICですが、ナショナルセミコンダクタ社の
LM336H-2.5V」が使えます。
これを使った基準電圧回路は下図のようにしました。LM336の端子電圧が安定な
2.5Vとなるので、その電圧を抵抗とボリュームで分割して、2.047Vに調整しま
す。これで、安定な基準電圧が得られたことになります。
これをPICのRA3端子に接続して+のリファレンス電圧とすれば、フルスケールが
2.047VのA/D変換が出来ることになります。


【製作】

実際の製作には、ちょっと大きめのプリント基板に大部分の回路を組み込んでしまい
ました。充電、放電回路が6組必要になりますので、これが大部分を占めています。
まず基板の回路図は下図のようになります。これに電源とバッテリーソケットを外部に
追加してケースに組み込みます。

 ★PIC16F877応用NiCdバッテリチャージャ回路図

左写真が全体の外観で、アルミのケースに
全てを組み込みました。
上部に金属製のバッテリソケットで単3を2個づつの
ものを3組固定しています。真中は液晶表示器です。


ケース内部は左写真のようにカバー側に基板を、
底側に電源トランスとダイオード、平滑コンデンサを
取りつけています。

基板の全体外観です。上側が充放電回路で6組
あります。PICは液晶表示器の下側となっています。

基板の液晶表示器を取り外したところ。
PIC16F877が中心になっています。

電源部。トランスは5,6,7,8Vタップ付きで
0.5Aの出力容量です。ちょっと6本全部
充電になった時には容量ギリギリですが
何とか間に合っています。

基板の取りつけはカラースペーサで浮かせて
液晶表示器がピッタリシャーシに付くように
取りつけます。


【プログラム概要】

本バッテリチャージャのプログラムは全てCCS社のCコンパイラで作成しました。そのため
意外と簡単にプログラムを書くことができました。
特に液晶表示器に表示出力するには、printf文が有効に活用できるため、非常に楽に
プログラムすることが出来ました。

全体は本体のプログラムと、液晶表示器制御ライブラリ、標準ヘッダーの3つで構成され
ています。標準ヘッダーファイルは、CCS Cコンパイラの中に含まれています。
その他の2つは下記のようになっています。

  ★PIC16F877応用NiCdバッテリチャージャプログラムリスト(C言語です)
  ★上記用液晶表示器制御ライブラリ


メインプログラム部は、スイッチの入力チェックを常時繰り返しており、入力があれば
それぞれの処理を行います。
  スイッチ1:バッテリの選択で1〜6をサイクリックに切り替えます。
  スイッチ2:予備、なにもせず
  スイッチ3:状態の更新で、そのときに選択されているバッテリの状態を順次更新
         します。この状態は 放電→充電→終了をサイクリックに繰り返します。

タイマ1の割込みが1秒毎に入るようにセットし、毎秒の割込み処理で、現在選択中の
バッテリの状態表示を更新します。これでバッテリ電圧をチェックすることが出来ます。
また全バッテリの状態をチェックし、条件が整えば次の状態に進みます。

   バッテリ無しからバッテリを実装 → 電圧をチェックし0.9V以上なら放電にする
   放電中に0.9V以下になった   → 充電にする
   充電終了の条件になった     → 充電終了とする
   電圧が0.5V以下になった    → Non BAT(バッテリ無し)状態とする

また1分毎に、全バッテリの状態をチェックし、充電中か、放電中であれば各バッテリの
状態継続時間タイマをカウントアップします。



   
≪プログラムテクニック≫
 (1) 液晶表示器への表示出力
   printf文を下記フォーマットで使うことで、電圧表示も簡単に出来ました。ここでの
   lcd_data関数は、自作の液晶表示器に1文字を出力する関数で、このように自作
   の関数もprintf文の出力機器を指定するフォーマットでうまく使うことが出来ます。
   浮動小数点数もprintf文のフォーマット文で簡単に指定することが出来ます。

  printf(lcd_data,"%2u",hour);      //time display
  lcd_data("H");
  printf(lcd_data,"%2u",minu);
  printf(lcd_data,"M %1.3f V",value);  //voltage display

(2) 電圧計測値の浮動小数点数化
  バッテリ電圧を測定するのに、10ビットのA/D変換を使うのですが、結果を浮動
  少数点数で扱いたいときには、A/D変換の入力をfloatで指定すれば、そのまま
  浮動少数点数として扱うことが出来ます。下記でdata変数をfloat指定しておいて
  data=read_adc();とするだけでOKです。
  またバッテリの電圧を計測するときには、充電も放電もしないで開放電圧を測定
  する必要があります。そうしないと正確なバッテリ電圧が測定できません。

 float mesure(int bat) {
   float data;       //redefine
   if(bat > 3)       //convert to port number
     bat=6-bat;      //Channnel adjust
   else
     bat=7-bat;
   set_adc_channel(bat);  //set channel
   delay_us(50);      //wait charging
   data = read_adc();    //get data
   return(data/500);    //return real voltage data
 }

(3) キーのチャッタリングの回避
  今回のスイッチは大き目の押しボタンであったためチャッタリング時間が長く、
  それによる誤動作を回避するため下記のようにしました。

 if(input(PIN_B0)==0) {
   delay_ms(100);
   if(input(PIN_B0)==0) {
     中略(ここにキーの処理を記述)
   }
 }




  目次ページに戻る