google-site-verification: google3bd66dd162ef54c7.html
fc2ブログ

Arduino を使った電池容量測定器

充電式ドリルドライバーの電池パックの容量測定に使った回路を紹介します。なお中身は、以前の記事で紹介したコードレス電話の子機のバッテリー容量を測定した時の物とほとんど同じなのですが、もっと高い電圧の電池も測定出来るように、入力にアッテネーターを追加しソフトも少し手直ししています。

▼測定の様子
測定中
これは単セルの18650のリチウム電池の容量を測定している様子です。

電池を測定回路に接続しArduinoで電圧をモニタしています。負荷抵抗はかなり発熱するのでUSBファンを使って冷却しています。Arduinoは電池電圧をシリアルに送信すると共に電池が空になったことを検出して放電を自動的に終了させるために使っています。

▼回路図
バッテリー容量測定器の回路図

メインスイッチとして使っている EK104047 は電流容量が80Aもあるので、かなり容量の大きな電池でも使用可能です。回路図の太い線で書いたパスには大きな電流が流れるので、太い線で配線しておきます。
電池電圧をR1, R2で1/14に分圧してArduinoに入力しています.Arduinoではフルスケール 1.1VでADCしているので、最大入力電圧は約15.4Vになります。

▼基板
基板部拡大
Arduinoに接続するピンは出来るだけ集めておいたので、7ピンのピンヘッダで接続しています(二つのピンソケットをまたいで挿入)。なお、Arduinoのコネクタは2.54mmのグリッドに乗っていない位置に実装されている物がありますが、今回の回路で使った部分は大丈夫で、オングリッドに配置されています。

この写真の下側のネジ締め端子に電池を接続し、左側のネジ締め端子に負荷抵抗を接続します。負荷抵抗を外付けにしたので、いろいろな抵抗値の負荷が接続可能になっています。

▼基板裏側
基板配線面
大電流が流れるパスには銅箔テープを使い、出来るだけ配線抵抗が小さくなるように作りました。

▼プログラム
/* バッテリー放電器
FETをONにして放電させ、放電終止電圧以上の間バッテリーを放電させる
放電終止電圧は無負荷時電圧に対する比率で自動設定
2020.8.13 ラジオペンチ http://radiopench.blog96.fc2.com/ 
*/
#include <MsTimer2.h> // 時間はMsTimer2割り込みで制御

#define ATTratio 14.0 // 入力アッテネーター比率
#define PinVoltage A0 // 電圧測定ピン
#define PinDischarge A1 // 放電開始信号ピン
#define PinStart A2 // 測定開始スイッチ
#define PinLed A3 // 状態表示LED


float loadR = 1.0; // 負荷抵抗 (1Ωと仮定して計算)
float dR = 0.7; // 放電電圧終了電圧計算比率 ←要調整
int recInt = 10; // 記録インターバル(秒単位の値で指定)
float kA = 1.0072; // 感度補正係数    標準値=1.0
float kB = 0.053; // オフセット補正係数 標準値=0.0

int ts; // サンプリング周期タイマー(秒)
unsigned long tt; // 合計時間タイマー
float battV; // 現在のバッテリー電圧
float openV; // バッテリーの解放電圧
float mAh = 0.0; // 積算電流
float mWh = 0.0; // 積算電力
float stopV; // 放電停止電圧
boolean runFlag = true;
boolean ledFlag = true;
volatile boolean tUp = false; // time Up フラグ

void setup() {
analogReference(INTERNAL);
Serial.begin(115200);
pinMode(PinDischarge, OUTPUT); // 放電制御 HIGH で放電
pinMode(PinStart, INPUT_PULLUP); // 測定開始ボタン
pinMode(PinLed, OUTPUT); // 放電中表示LED
digitalWrite(PinLed, LOW);
openV = vRead();
stopV = openV * dR; // 無負荷時電圧に対する比率で放電終止電圧を決定

Serial.println(); // 各種情報を出力
Serial.println(" ,BATTERY DISCHARGER v4.0 (mAh mWh values are calcurated at RL=1.0 ohm)");
Serial.print(" ,openVoltage = "); Serial.print(openV, 3);
Serial.print("V. stopVoltage = "); Serial.print(stopV, 3); Serial.println("V.");
Serial.println(" ,waiting start. (Push button for start)");

while (digitalRead(PinStart) == HIGH) { // スタートボタンが押されるまで待つ
}

Serial.println(" ,Discharge start!"); // 測定開始メッセージ
Serial.println(" , sec., voltage, mAh, mWh");
digitalWrite(PinDischarge, HIGH); // 負荷ON(放電開始)
digitalWrite(PinLed, ledFlag);
ledFlag = ! ledFlag;
logPrint(0); // 初回の測定結果を記録
MsTimer2::set(1000, timer2IRQ); // 1秒間隔で割り込み
MsTimer2::start(); // 割り込み開始
}

void loop() {
while (tUp == false) { // MsTimer2の割り込みが入りまで待つ
}
tUp = false;
ts++; // サンプリング周期タイマーをインクリメント
tt++; // 合計時間をインクリメント
if (runFlag == true) { // 放電終了でなければ
digitalWrite(PinLed, ledFlag); // フラグに応じてLED点滅
ledFlag = ! ledFlag;
} else { // 放電終了なら
digitalWrite(PinLed, LOW); // LED 消灯
}
if (ts == recInt) { // 測定インターバルの時刻だったら
logPrint(1); // 測定結果をログ出力
ts = 0;
}
}

void logPrint(int mode) { // 測定結果をログ出力 (mode=0 は初回)
Serial.print(" , "); // タイムスタンプ文字列との境目を入れる
Serial.print(tt); Serial.print(", "); // 経過時間(秒)表示

battV = vRead();
Serial.print(battV, 3); // 電圧の値を出力

if (runFlag == true) { // 放電中で
if (mode == 1) { // 初回でなければ
mAh += (1000.0 * battV / loadR) * (recInt / 3600.0); // 積算電流計算 mAh
mWh += 1000 * (battV * battV / loadR) * (recInt / 3600.0); // 積算電力計算 mWh

Serial.print(", "); Serial.print(mAh); // 積算電流値を出力
Serial.print(", "); Serial.print(mWh); // 積算電力値を出力
} else { // 初回だけは積算値はゼロ
Serial.print(", 0.00, 0.00");
}
if (battV < stopV) { // 放電停止電圧以下になっていたら、
digitalWrite(PinDischarge, LOW); // 放電停止して
runFlag = false; // 次回このルーチンを実行しないようにフラグを消す
Serial.print(" ,End discharge"); // 放電終了表示
}
}
Serial.println(); // ログの行末の改行
}

float vRead() { // バッテリー電圧測定
float d;
d = analogRead(PinVoltage) * 1.1 * ATTratio / 1024.0; // 入力電圧に換算
d = kA * d + kB; // 感度補正 y=ax+b 形式
return d;
}

void timer2IRQ() { // MsTimer2の割り込み処理ハンドラ
tUp = true;
}
18,19 行目の kA と kB はADCのゲインとオフセットの調整用に設けた定数です。実際の電池電圧とログに記録される電圧のずれが気になる場合はここの定数を調整します。なお、補正は Y = aX + b の式の形で反映されます。

▼放電カーブの測定例
18650の放電カーブ
これは最初の写真に写っている18650の電池(Trust Fire 3000mAh) の放電カーブです。負荷抵抗は2Ωで測定していて、平均3.4Vで放電時間は約90分です。つまり大雑把には、電池容量は 1.5h*3.4V/2Ω = 2.55Ah = 2555mAh だったことになります。なおArduinoからは正確な積算電流の値を出力していますが、その値は2664mAhでした。
ちなみにこの電池の公称容量は3000mAhですが、購入後2年以上は経っているので10%以上容量が減っているようです。

◆まとめ
この測定基板は汎用性が高いのでいろいろ便利に使えそうです。いつでも使えるように、この記事を印刷した物と一緒にビニール袋にいれて保管しておくことにします。

この基板を作った時に、最初は電圧検出のアッテネーターを可変抵抗にして、広い電圧範囲で使えるようにしてみました。しかしそうやると、測定結果を換算する操作が常に必要になってしまうので使い難いものになってしまいました。そんなことでアッテネーターは1/14の決め打ちにしました。ちなみに、基板に大きな穴が開いているのは、可変抵抗を付けていた名残です。
これなら、電圧が直読出来るので便利です。なお、固定アッテネーターとしたため、1.5Vの電池の測定では分解能が不足気味になりますが、実用上は問題無いと判断しています。
関連記事

コメントの投稿

管理者にだけ表示を許可する

参考にさせていただきます。

前から、このラジオペンチ式充電池放電テスターを作ろうとブックマークにいれてあります。

130Ωと10Ωで1/14に分圧する、R1とR2を変更すれば、15〜22Vの 18Vバッテリーも測れるってメモっていたので、ちょうど、タイムリーで良かったです。
ということで、まんまパクら ちがう、参考にさせていただきます。
放熱の抵抗に、安定化電源のジャンクを手に入れたので、分解して、それをつなごうと思っています。すごいフィンがはいっていたのでw

re:参考にさせていただきます。

18Vバッテリーなら、R1=200kΩ、R2=10Ωで、1/21に分圧くらいが良さそうです。これでフルスケールは 1.1V×21倍=23.1V。
プログラムの8行目のATTratio 14 を 21に修正すればそのまま行けるのではないかと思います。

ただパワーが大きいので熱の処理が大変そうですね。あと、PCインターフェイス付きのDMMをお持ちだから、測定はそっちでやった方が絶対精度が確保出来て良いかもです。

あと、そちらのブログ拝見してます。電動ツールはマキタの18Vで統一ですね。

No title

200k/10 の 1/21の分圧ですね。 で、プログラムのAttレシオを21にと 了解です。

マキタの18V、ボッシュの10.8Vなど、互換バッテリーの怪しい挙動をしらべるのに、都合が良いので、参考にさせていただきます。(..;)ぺこり
カレンダー
08 | 2023/09 | 10
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。
記事の内容のご利用は読者の自己責任でお願いします。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード