とうふ荘の手記てき!

プログラムとか

M5StickCのバッテリーでの動作時間

日時 更新内容
2020/05/14 PreferenceクラスによるNVS領域への書き込みをクリアする内容を追記・バッテリー残量を電圧からパーセンテージで計算するように変更

M5StickCを買いました。

M5StickCとは
  • 小型!
  • 画面がある
  • ESP32 Pico を搭載するためWiFiBluetoothが使える
  • ジャイロと加速度センサーが付いている
  • 腕時計マウンタが付いている(公式ショップでは付いていないバージョンもあるそうです)
  • (人によるとは思いますが)安い!

ことを特徴としたマイコンキットです。

www.switch-science.com

バッテリーでの動作時間を測ってみた

M5StickCには80mAhのLiPoバッテリーが搭載されており、ある程度の単独で動かすことが出来ます。(とはいえ、容量はM5Stack Basicの500mAhからは大きく減少しているため、あまり長時間の稼働は見込めません……)

実際に使用する上では環境や動かすプログラム(WiFiBluetoothの電力消費は大きそう……)によって大幅に違ってしまい、あまり参考になるかわかりませんが今回は動作時間を測ってみました。

主な条件

測定に用いるソースコードでは以下のようなプログラムが稼働しています。

  • バッテリー監視
  • リアルタイムクロック
  • シャットダウン時はDeepSleepを利用
  • loop毎に100のdelay
ソースコード

ソースコードは以下のようになります。

//M5StickCのバッテリーについて測定
#include <M5StickC.h>
#include <Preferences.h>

const float     bat_percent_max_vol = 4.1f;     // バッテリー残量の最大電圧
const float     bat_percent_min_vol = 3.3f;     // バッテリー残量の最小電圧

int             scrBright           = 9;        // 明るさ
float           bat_per             = 0;        // バッテリー残量のパーセンテージ
float           bat_per_inclination = 0;        // バッテリー残量のパーセンテージ式の傾き
float           bat_per_intercept   = 0;        // バッテリー残量のパーセンテージ式の切片
float           bat_vol             = 0;        // バッテリー電圧
RTC_TimeTypeDef t_st;                           // 時間の構造体
bool            updatingTime        = false;    // 時間を更新中か管理するフラグ
Preferences     preferences;                    // 不揮発領域へのアクセス

void setup() {
    M5.begin();
    M5.Lcd.setRotation(1);
    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.setTextSize(1);
    M5.Lcd.setCursor(40, 0);
    M5.Lcd.println("M5 Battery Test");
    M5.Axp.begin();
    // 前回の時間を読み込み
    preferences.begin("Time", true);
    t_st.Hours = preferences.getUInt("Hours");
    t_st.Minutes = preferences.getUInt("Minutes");
    t_st.Seconds = preferences.getUInt("Seconds");
    preferences.end();
    // 明るさを設定
    M5.Axp.ScreenBreath(scrBright);
    // バッテリー残量のパーセンテージ式の算出
    // 線分の傾きを計算
    bat_per_inclination = 100.0F/(bat_percent_max_vol-bat_percent_min_vol);
    // 線分の切片を計算
    bat_per_intercept = -1 * bat_percent_min_vol * bat_per_inclination;
}

void loop() {
    M5.update();    // ボタンの状況を更新
    
    // Aボタンで画面の明るさを操作
    if(M5.BtnA.isPressed()){
        scrBright = (scrBright == 15)? 7 : scrBright + 1;
        M5.Axp.ScreenBreath(scrBright); // 明るさを設定
    }
    // 明るさ設定の表示
    M5.Lcd.setCursor(1, 15);
    M5.Lcd.printf("Brightness: %02d\n", scrBright);

    // バッテリー電圧取得
    bat_vol = M5.Axp.GetVbatData() * 1.1 / 1000;   // V
    M5.Lcd.setCursor(1, 30);
    M5.Lcd.printf("Battery vol: %3.1f[V]", bat_vol);

    // バッテリーの残量を簡易的なパーセンテージで表示
    bat_per = bat_per_inclination * bat_vol + bat_per_intercept;    // %
    if(bat_per > 100.0f){
        bat_per = 100;
    }
    M5.Lcd.setCursor(1, 45);
    M5.Lcd.printf("Battery per: %4.1f%%", bat_per);

    // タイマー機能
    // Bボタンを押すことでタイマーを初期化し、カウント表記を更新開始
    if(M5.BtnB.pressedFor(1000) && updatingTime == false){
        t_st.Hours = 0;
        t_st.Minutes = 0;
        t_st.Seconds = 0;
        M5.Rtc.SetTime(&t_st);
        updatingTime = true;
    }
    if(updatingTime) M5.Rtc.GetTime(&t_st);
    M5.Lcd.setCursor(1, 60);
    M5.Lcd.printf("%02d:%02d %02d (%-11s)\n", t_st.Hours, t_st.Minutes, t_st.Seconds, (updatingTime == true)?"Counting..." : "Stop");

    // 低電圧状態でスリープへ移行
    if(M5.Axp.GetWarningLeve() == 1 || (M5.BtnB.pressedFor(2000) && updatingTime == true) ){
        updatingTime = false;
        // 時間を書き込む
        preferences.begin("Time", false);
        preferences.putUInt("Hours", t_st.Hours);
        preferences.putUInt("Minutes", t_st.Minutes);
        preferences.putUInt("Seconds", t_st.Seconds);
        preferences.end();
        
        M5.Axp.DeepSleep(); // ディープスリープ状態へ移行
    }

//    // 低電圧状態取得
//    M5.Lcd.setCursor(1, 60);
//    M5.Lcd.printf("Battery Warning: %d\n", M5.Axp.GetWarningLeve());

    delay(100);
}
使い方
  1. Bボタンを長押しすると測定が開始されます。
  2. バッテリー電圧がおよそ3.4[V]の時、M5.Axp.GetWarningLeve()が1を返すのでそれを検知したら、不揮発領域に時間を書き込んで、DeepSleepに移行します。
  3. バッテリーを充電しながら起動し直すと、バッテリーが切れるのにかかった時間が表示されます。
  4. また、Aボタンで明るさを7~15の間で調節できます。
測定結果

測定結果を以下に示します。(古いソースコードにおける結果です。電力に関係する処理にはほとんど手を加えていないため、結果はあまり変わらないと思います。)

明るさ 7 明るさ 15
1:35:26 0:53:16
1:32:37 0:53:03
1:23:35 0:52:10

よって、明るさが見える最低ラインとされる7のときは、およそ1時間30分。

明るさが最大の15のときは、およそ53分稼働できるようです。

画面の明るさだけでも稼働時間に大きな差異が認められました。

また、一定の頻度でライトスリープを挟んだり、CPU周波数を下げることで、もっと長時間の稼働を実現することもできそうです。

Twitterで実際に調べてる方もいるようです。

もっとdelayする時間を大きくすれば2時間ぐらいは行けそう……

使用後

バッテリーが切れるまでの動作時間を記録するために、不揮発のNVS(Non-Voltage Storage)領域に動作時間を書き込んでいます。

使用後は動作時間の記録をクリアするために、NVS領域のデータをクリアするのが良いかもしれません。

tofu-so.hatenablog.jp