Arduinoで実験 (リチウムイオンポリマー電池)

2013/07/31


◆ リチウムイオンポリマー電池

以前 Arduino FIO と一緒にリチウムイオンポリマー電池を購入しました。SparkFun に代表される Arduino 関連の電池ソケットは JST型の 2 ピンコネクタがほぼ標準となっているので、 プラスとマイナスのさし間違いがなく割と気軽に扱えます。

ただし、リチウムイオンポリマー電池は扱いに注意が必要で簡単に爆発するようです。 スイッチサイエンスのこのページに詳しく書いてあるので一度は見ておいた方が良いです。

リチウムイオンポリマー電池の充電回路については別ページにまとめています。 本ページでは入手した製品等の使用方法をまとめます。


◆ LiPo 燃料ゲージ

スイッチサイエンスで購入した Sparkfun の燃料ゲージです。 この商品は I2C で通信しリチウムイオンポリマー電池の残量を測定することができます。また、一定割合の電圧降下になるとアラートピンが出力となるので、マイコンなどで割込み処理に使用できます。

この燃料ゲージに使用されている IC は MAX17043 で 1 セルのバッテリー用です、2 セル用には MAX17044 という IC があります。

電源は 2.5V ~ 4.5V ですが IO ピンは 5.5V MAX なので Arduino UNO 等の 5V 製品でも使用できます。

MAX17043/MAX17044 Slave Address 0110110 (0x36)
マスタが送信 → 0 (0x6C)
マスタが受信 → 1 (0x6D)
VCC
GND
既にモジュール内でバッテリーのコネクタと接続されているので外部との接続はしない方がよい。
SDA
SCL
A4 ⇔ SDA
A5 ⇔ SCL
ALT(ALERT interrupt) 設定値以下になると High
QST(Quick Start) 電源投入時のノイズによる誤作動対策のリセットピン。ソフトウェアでもリセットが行える。

MAX17043 のコマンド

0x02, 0x03 VCELL R バッテリー電圧測定量
測定量は 12 ビットで表現され、下位バイト中、bit3 ~ bit0 は無視。
0x04, 0x05 SOC R バッテリー容量(%)
下位バイトは捨てて、上位バイトの観測で十分らしい。
測定間隔は 125ms 開ける必要がある。
0x06, 0x07 MODE W  
0x08, 0x09 VERSION R バージョン
0x0C, 0x0D CONFIG R/W MAX17043 の設定
Alert レベルや Sleep モードの設定ビット。
0xFE, 0xFF COMMAND W MAX17043 の動作に関する命令。
一般的な使用に対しては特に扱わないので無視する。
デフォルト 0x971C はしきい値 4 %
Alert ビットは割込み発生時に 1 となる
0x4000 Quick Start    
0x5400 Power on Reset    

●MAX17043 の警告しきい値の設定

しきい値は、 5 ビットで 1 ~ 32 を設定する。 0b11111 が 1%、0b00000 が 32 %となるので注意が必要である。 初期値は 0b11100 で 4% となっている。

しきい値の設定は CONFIG レジスタで行い、下位バイトの bit4 ~ bit0 で設定する。

●Quick Start

Mode レジスタへ 0x4000 を書き込むことによりクイックスタートが始まる。

●バッテリー容量の読み取り

SOC レジスタを読み込む。

上位バイトがパーセンテージを表し、下位バイトが 1/256 %を表す。 精密なバッテリー容量等は温度や使用状況により変化するのであまり意味がない。 正直、10%単位や携帯電話のように 4 段階表示でも十分な機能だと思う。

●Arduino スケッチ

シリアル通信でコマンドを受信したらバッテリー容量を読み取り、シリアル通信で値を出力するスケッチ。

#include <Wire.h>

#define I2C_ADDR 0x36

void setup() {
Serial.begin(9600); Serial.println("Start"); Wire.begin(); quickStart(); } void loop() { byte cmd; if(Serial.available() > 0) { cmd = Serial.read(); if (cmd == 'R') readData(); } } void readData(void) { unsigned int vcell = 0; byte soc = 0; float per; //Quick Start quickStart(); //read VCELL Wire.beginTransmission(I2C_ADDR); Wire.write(0x02); Wire.endTransmission(); Wire.requestFrom(I2C_ADDR, 2); while (Wire.available() < 2); vcell = Wire.read() << 8; vcell |= Wire.read(); vcell = vcell >> 4; Serial.print("VCELL = "); Serial.println(vcell, DEC); //read SOC Wire.beginTransmission(I2C_ADDR); Wire.write(0x04); Wire.endTransmission(); Wire.requestFrom(I2C_ADDR, 2); while (Wire.available() < 2); soc = Wire.read(); per = (soc << 8) + (Wire.read() / 256); Serial.print("SOC(High) = "); Serial.println(soc, DEC); Serial.print("SOC(%) = "); Serial.print(per, 6); Serial.println(" %"); } void quickStart(void) { //Quick Start Wire.beginTransmission(I2C_ADDR); Wire.write(0x06); Wire.write(0x40); Wire.write(0x00); Wire.endTransmission(); delay(500); }