とある実験のーと

趣味ブログ

Arduino MKR WiFi 1010で18650 Li-ion電池を使ってみる (その1)

Arduino MKR シリーズ(WiFI1010, WiFi1000, MAN1310あたり)にはシングルセル 3.7V Li-Poバッテリーの充電管理チップ( BQ24195L)が付いており、Li-Poバッテリーの充放電ができるようになっている。

WiFi越しのArduino IoT Cloudの利用でバッテリーがどのぐらい実用範囲なのか最終的に確かめたく、まずは導入を試みた。

基板にはJST PHのメスコネクタが設置されており BQ24195L の設定をいじるライブラリも公開されている。 docs.arduino.cc

Li-Poバッテリーは費用対容量的に若干高価でハンドリング性も微妙なので、公式チュートリアルに並列で書かれていたLi-ion (18650) 電池で試してみた。

使用したバッテリーはKEEPPOWERの18650電池である。不意に発火したら嫌なので保護回路付、日本の代理店が扱っている信頼できそうなものをチョイスした。


バッテリーボックスの設計

保護回路付きの18650電池は少し背が高いらしく、Amazonなどで売ってる18650用の電池ボックスでははまらないらしい・・・。よって電池ボックスから作った。

作ったものはBOOTHに置いているので、もし興味があれば・・・。

azospilab.booth.pm

保護回路付18650 Li-ion電池用電池ホルダー (3Dデータ) - あぞすぴラボ - BOOTH

売ってる線付きコネクタによっては、プラス側に黒線が来てるものがあるようでコネクタの極性を間違わないように要要チェック。。。ボードをUSBコネクタが右側に来るように置いて上から見たとき、JST-PHコネクタの右側が+, 左側が−。 コネクタ付きも一応BOOTHに置いておきました。

設定

公式チュートリアルのコードをコピペして18650電池の充電用にパラメータを少し改変。

float batteryFullVoltage = 4.2;
float batteryEmptyVoltage = 3.0;
float batteryCapacity = 3.5; //Ah
//(中略)
PMIC.setChargeCurrent(0.5); // 500mA

FullVoltageはバッテリーの充電電圧のようなので、専用充電器の仕様に従って4.2Vに設定した。PMIC.setChargeCurrentは、デフォルト値ではbatteryCapacityの1/2で設定されている。しかし、Li-ion電池は高い電流で充電するとバッテリーが劣化するらしいので、専用充電器の設定にもあるように最大(高速充電)で1A, 常用で500 mAが良いのではないかと考え、今回は0.5に設定した。

EmptyVoltageに関しては正直これで良いのかはっきりしない。下記のように後段でのコードでFullVoltageとEmptyVoltageの値を用いてバッテリーの充電レベルを%で表示する計算を行っている。

int new_batt = (voltBat - batteryEmptyVoltage) * (100) / (batteryFullVoltage - batteryEmptyVoltage); //Battery levelの計算

18650電池の仕様では2.8Vぐらいまで低下するらしいが、3.3Vを下回ってもArduino自体が動くのか定かではないので、いまのところ一応、3.0Vとした。

PMIC.enableCharge();

これを

PMIC.disableCharge();

とすると、充電機能が停止して現時点の電池電圧をモニタ出来るらしい。

モニタリング

まずは専用充電器で満充電(4.2V)した電池を付けて、デモコードでモニタリングしてみた。

このままだとマルチメータで4.18Vの電池電圧が3.98Vに表示されるため、シリアル通信に出力される値が明らかにおかしい。ここで回路図からの計算式を見直してみた。

https://docs.arduino.cc/static/15d3e938fbfc2e3cc7a03a4f7d1e2188/29114/voltage-divider-samd21.png

MKR WiFi 1010での回路図 (引用)

MKRシリーズはADCのマックスが3.3Vなので、電池の4.2Vは直接測定できない。よって既知抵抗を挟んで電圧を下げてから測定することになるが、回路上にはR1として330kΩ, R2として1MΩが載っており、R2の部分の電圧をPB09で測定しているらしい。計算式を見てみる。

 max_Source_voltage = (3.3 * (R1 + R2))/R2;
//(中略)
rawADC = analogRead(ADC_BATTERY);
 voltADC = rawADC * (3.3/4095.0);
 voltBat = voltADC * (max_Source_voltage/3.3);
 int new_batt = (voltBat - batteryEmptyVoltage) * (100) / (batteryFullVoltage - batteryEmptyVoltage);

まず、,max_Source_voltageでVBattにかけて測定出来る最大電圧値を求めている。PB09で測れる電圧最大値が3.3Vなので、max_Source_voltage = 4.389 V

つぎにrawADCでPB09の電圧値をアナログ値で読み取り、voltADCでPB09の電圧値に変換している。12bit(4095)で3.3Vを表現するので、ここも間違ってなさそう。 最後にvoltBat(問題の値)を算出するが、ここの式がおかしい?

VoltADCは既にPB09地点の電圧値なので、これに((R1+R2)/R2)を掛ければVsource(所謂電池の電圧値)は求まるはずである。というか、max_Source_voltageの計算式を見ると同じ意味・・・。あれ?

原因は、max_Source_voltageをint型にしていたために "4.389" が "4" と丸められてたためだった。なので冒頭で

  float max_Source_voltage;

とすれば解決した。本家のGithubにも修正を提案しておきました。この修正で4.36Vと出たのでマルチメータと0.18Vぐらいのズレだが、モニタリングには問題無いかと思う。

何かと時間がかかってしまったので、一先ず、今日はここまですみません・・・。

バッテリーでの駆動や、充電状況などモニタリングできたらまた報告します。