概要
CoreInk発売直後に放電についての実験を行っていたのですが、やっとまとめることができました。CoreInkのバッテリーに関してですが多くの場合M5Paperでも共通です。
CoreInkのバッテリー放電実験
CoreInkのバッテリー特定を確認するために、BluetoothとWi-Fiを有効にした状態で放置して、プログラムから取得したバッテリー電圧と、テスターを利用してBAT端子からのバッテリー電圧を計測してみました。

こちらがプログラムで取得したバッテリー電圧です。4.2Vから始まって3.65Vぐらいで止まってしまいました。これは消費電力を増やすためにWi-Fiを使っていたので、ちょっと予想より高い電圧で止まっています。動作時間は2時間38分でした。なるべく早く放電するように設定した時間ですので、この時間自体はあまり気にしないでください。

こちらだと3時間45分以上動いていますね。
使ったテスターはこれです。結構きれいにデータ取れていますね。時間はずれていますがこちらも3.6Vぐらいから急激に電圧が落ちていますね。やっぱりこれぐらいの電圧までが限界のようです。
CoreInkの電源構成

本体の裏側に構成図がかいてありますね。390mAhのバッテリーが接続されていて、TP4057はバッテリー充電用ICですね。それがMOSにつながれています。このMOSは電気的な電源スイッチと理解してください。電源ONはRTCからの通知、G12の信号レベル、PWRボタンを押すの3種類ですね。実際にはこの他にUSB接続をすると電源ONになります。
MOSからの出力はG35に接続されています。これはバッテリー電圧を取得するための接続になりますが、ESP32は3.3V以上は計測できないので、分圧した状態でG35に接続されていると推測されます。実際のバッテリー出力はSY7088というレギュレーションを利用して5Vに昇圧されています。またその出力をSY8089というレギュレーターを利用して3.3Vに降圧しています。
電源ON条件
- USB接続で電源供給
- RTCでタイマー通知
- GPIO12をHIGH出力
- 電源ボタンON
電源ONを維持するためには上記の4条件のどれかが達成されている必要があります。たとえばUSB接続で電源供給されている間はどうやっても電源OFFにはできません。USB接続をしていない場合には、GPIO12の出力によって電源ONを維持しています。このためESP32が起動した直後にGPIO12をHIGH出力に設定しているコードが中で動いています。そしてGPIO12をLOW出力にすることで擬似的に電源OFFを実施しています。
USB接続を除くと、電源OFFからは電源ボタンを押すか、RTCからのタイマー通知の信号を使ってESP32を起動し、GPIO12をHIGHにして電源ONをキープ。処理が終わったらRTCにタイマーをセットしてから、GPIO12をLOWにして電源OFFという流れで定期起動する流れになります。
また、5Vインからの給電では起動しないようでした。
他の機種での放電実験

上記がM5StickCの場合です。グラフをみてみると3.4Vぐらいから急激に電圧が下がっています。CoreInkと比べるとヘタリが遅いですね。バッテリーからの接続経路が違うためだと思います。
CoreInkの場合
- バッテリー → ダイオード(逆流防止) → MOS → SY7088(5Vへ昇圧) → SY8089(3.3Vに降圧)
上記の流れになっています。USBからの充電があるので、逆流同士にダイオードが間に挟まっているみたいです。ESP32は3.3Vで動いているのでバッテリーまでの経路が遠いですね。
M5StickCの場合
- バッテリー → AXP192(電源管理IC)のLDO(3.3Vに降圧) → レギュレーター(5Vへ昇圧)
M5StickCはAXP192という電源管理のICが搭載されています。この中でバッテリーの充電やUSBからの給電などを管理し、直接3.3Vに降圧することができます。この3.3VをESP32は利用しています。Grove端子などは5Vを出力していますので、外部にレギュレーターを入れて5Vに昇圧しているようです。
シンプルな構造ですが、AXP192が結構消費電力が高いので長時間動かすことが難しい欠点があります。
M5Stack Core2の場合
- バッテリー → AXP192(電源管理IC)のLDO(3.3Vに降圧) → レギュレーター(5Vへ昇圧)
解析が不十分ですが、基本構成はM5StickCと変わらないのではと思っています。ただしタイマースリープ時にAXP192を電源OFFにすることができます。
3機種の違い
条件 | CoreInk | M5StickC | M5Stack Core2 |
電源ボタンON | ○ | ○ | ○ |
USBから給電 | ○ | ○ | ○ |
5Vインから給電 | ✕ | ○ | ○ |
RTCでタイマー通知 | ○ | ✕ | ○ |
GPIO12をHIGH出力 | ○ | ✕ | ✕ |
機種別の起動条件です。電源ボタンとUSBからの給電ははすべて共通ですが、5Vインからの給電はAXP192の起動条件ですのでCoreInkは対応していません。RTCからのタイマー起動はM5StickCは対応していません。M5StickCも同じRTCを搭載しているのですが、ESP32が通知を取得することはできるのですが電源ONには利用できません。この通知をCore2ではAXP192の起動に接続しています(逆にESP32からは通知取得できない)。同じ用にCoreInkではMOSの起動に利用しているためRTCで起動できるようになっています。
この辺の変更はTimer Cameraシリーズから入っているようなのですが、日本未発売なのであまり詳しい解説記事はないと思います。Timer Camera自体は技適ありなのですが、なかなか日本では発売されませんね。手元にはあるのですが未開封です。。。
CoreInkとM5Paperのバッテリー電圧取得方法
CoreInkの場合
公式ライブラリにはバッテリー電圧取得関数はありません。ただしスケッチ例に取得例がありますので、そちらを流用する場合が多いようです。
float getBatVoltage()
{
analogSetPinAttenuation(35,ADC_11db);
esp_adc_cal_characteristics_t *adc_chars = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t));
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 3600, adc_chars);
uint16_t ADCValue = analogRead(35);
uint32_t BatVolmV = esp_adc_cal_raw_to_voltage(ADCValue,adc_chars);
float BatVol = float(BatVolmV) * 25.1 / 5.1 / 1000;
return BatVol;
}
上記が該当関数です、GPIO35で電圧を取得したあとに電圧補正をしてから* 25.1 / 5.1(4.92)という係数で電圧に変更していますね。流れとしてESP32は3.3Vまでしか電圧測定できません。バッテリー電圧は3Vぐらいから4.2Vのため直接計測できないことになります。そのためアッテネーターと呼ばれる減衰器を使って、分圧した電圧を入力させてあげる必要があります。
入力する電圧を下げているので、誤差がより大きくなります。仮に半分の電圧に分圧した場合、計測結果が2.5Vだった場合5Vの入力になります。測定誤差が0.1Vだとしたら、実際の電圧に換算すると0.2Vの誤差に相当します。このように減衰器を使うと誤差が結構でてしまいます。もともとESP32は0Vから1Vまでしか計測することはできず、内部で減衰器を接続して3.3Vを計測しています。つまり5Vぐらいまで測定するためには、元の電圧を5分の1以下に分圧する必要があります。0.1Vの誤差が0.5Vになってしまいます。そこまでの誤差はないのですが、ESP32のADCは精度があまり高くありません。
そこで利用するのが、出荷時に設定するADCの補正データです。何種類かの基準電圧を実際に測定して、計測した値を個別のチップに保存しています。つまり、個体差があるESP32のADCで実際に計測してみて計測した値から、ADCの測定ズレを補正することができます。
analogRead(35)がESP32で測定した素の値なのですが、esp_adc_cal_raw_to_voltage()関数で補正しています。

これが実験したときの生のデータと補正後のデータの比較です。私のCoreInkは3.8V相当ぐらいはあっていますが、低い電圧はより低く、高い電圧はより高く生データがでていますね。
esp_adc_cal_characterize()で、この補正をするための表を作っているのですがadc_chars変数をcallocして確保していますが、開放していない。。。
M5Paperの場合
M5Paperは後発なので、ちゃんと公式ライブラリにバッテリー電圧取得関数があります。この辺のライブラリに差があるところと、なかなか更新されないところがM5Stackさんの弱点ですね。あれだけ製品があったら仕方ないところがありますが、、、
void M5EPD::BatteryADCBegin()
{
if(_is_adc_start)
{
return;
}
_is_adc_start = true;
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(BAT_ADC_CHANNEL, ADC_ATTEN_DB_11);
_adc_chars = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t));
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, BASE_VOLATAGE, _adc_chars);
}
初期化関数と、取得関数に分かれました。これで開放漏れはなくなりますね。
uint32_t M5EPD::getBatteryVoltage()
{
uint32_t adc_raw_value = 0;
for (uint16_t i = 0; i < ADC_FILTER_SAMPLE; i++)
{
adc_raw_value += adc1_get_raw(BAT_ADC_CHANNEL);
}
adc_raw_value = adc_raw_value / ADC_FILTER_SAMPLE;
uint32_t voltage = (uint32_t)(esp_adc_cal_raw_to_voltage(adc_raw_value, _adc_chars) / SCALE);
return voltage;
}
こちらが取得部分です。8回ADCを取得して平均を取ってから補正していますね。Arduino IDEでも補正しているのでどこまで精度があがるかは微妙なところです。SCALEは0.5でした。
計算方法のまとめ
機種 | 計算方法 |
CoreInk | 電圧(V) = ADC × 25.1 ÷ 5.1 ÷ 1000 |
M5Paper | 電圧(mV) = ADC ÷ 0.5 |
はい、単位が違うところがM5Stackっぽいですよね。係数が違うので減衰器の値も違うようですね。
CoreInkのスケッチ例
簡易計算
#include "M5CoreInk.h"
uint32_t getBatteryVoltage(void) {
return analogRead(35) * 25.1 / 5.1;
}
void setup() {
M5.begin();
}
void loop() {
Serial.println(getBatteryVoltage());
delay(1000);
}
シンプルです。補正をしなくても大まかな電圧は把握できます。概ね3.65Vから4Vまでぐらいで計算すれば残容量もそこまで間違った数値にはならないと思います。
補正計算
#include "M5CoreInk.h"
#include "esp_adc_cal.h"
static esp_adc_cal_characteristics_t adc_chars;
uint32_t getBatteryVoltage(void) {
uint16_t adCValue = analogRead(35);
uint32_t batVolmV = esp_adc_cal_raw_to_voltage(adCValue, &adc_chars);
return float(batVolmV) * 25.1 / 5.1;
}
void setup() {
M5.begin();
// Init ADC
memset(&adc_chars, 0, sizeof(esp_adc_cal_characteristics_t));
analogSetPinAttenuation(35, ADC_11db);
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 3600, &adc_chars);
}
void loop() {
Serial.println(getBatteryVoltage());
delay(1000);
}
スケッチ例のreturnの前にfree(adc_chars)を追加するだけでもいいのですが、私が組むのであれば上記のようにグローバル変数として確保すると思います。そして補正しない簡易版で計算しちゃうと思います、、、
まとめ
一ヶ月放置していたデータですが、公開しておきたいと思います。ちょっとバッテリー、電源まわりは難しいですね。M5Stackはわりと設計が古いので、M5StickCから変わってきている感じです。このへんは過去のボードを知らないとなかなか設計の意図がわかりにくいかもしれません。
コメント