0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

M5Stack Tab5 の初期ファームウェアをカスタマイズする(その2)

Posted at

↑ 前回記事の関連です。

1. はじめに

↓ 上部中央付近に、バッテリーに関する情報が出力されていますが、バッテリーパックのバッテリー残量の表示がありません。
今回のカスタマイズは、この付近に バッテリー残量の表示を追加する 内容です。

IMG_6588.jpeg
  • バッテリーで動作中は、バッテリーが放電している 電圧(V) と 電流(A) が表示されます
  • 外部電源で動作中は、電流(A)は マイナス値となって(電流の流れる向きが反転して)、バッテリー充電中の 電圧 と 電流 が表示されます
  • バッテリーパックを装着していない場合は(電流は流れないため)、0(-0.00A)が表示されます

M5Stack Tab5 の回路図によると、INA226 に 5mΩのシャント抵抗を使って バッテリーから流れる電流を測定しているようです。
ina226.png
「M5Stack User Demo」の画面上にも「5mR」の表示があります。

2. バッテリー残量の求め方

Arduino環境の場合、M5.Battery.getBatteryLevel()で得ることができます。

batteryLevel.ino
#include <M5Unified.h>

void setup() {
  M5.begin();
  Serial.begin(115200);
}

void loop() {
  int bat_level = M5.Power.getBatteryLevel();
  Serial.printf("Battery Level: %d\n", bat_level);
  delay(1000);
}
  • バッテリー充電中は、少しずつ増えていくことが確認できます。
    Battery Level: 79
    Battery Level: 80
    Battery Level: 81
        :     :
    

  • バッテリーで動作中は、少しずつ減っていくことが確認できます。
    Battery Level: 70
    Battery Level: 69
    Battery Level: 68
        :     :
    

そこで、M5Unifiedのソースコードから、M5.Battery.getBatteryLevel()の実装を確認しました。

2.1 M5.Battery.getBatteryLevel()実装確認

M5Unifiedsrc/utility/Power_Class.cppの1266行目からのPower_Class::getBatteryLevelの処理を解析し、M5Tab5/esp32-p4 の処理を抜き出すと、おおよそ 次の処理であることが分かります。

src/utility/Power_Class.cpp
std::int32_t Power_Class::getBatteryLevel(void)
{
    float mv = 0.0f;
    switch (_pmic) 
    {
    case pmic_t::pmic_aw32001:
    (略)

    default:
      switch (M5.getBoard()) {
      case board_t::board_M5Tab5:
        // 2S Li-Po ( * 1000 / 2 == * 500)
        mv = Ina226.getBusVoltage() * 500;
        break;
      (略)
      }
    }

    int level = (mv - 3300) * 100 / (float)(4150 - 3350);

    return (level < 0) ? 0
         : (level >= 100) ? 100
         : level;
}

M5Tab5は _pmic == M5.Battery.getType() == pmic_unknownのため、switch文のdefault句に行き、ボードタイプのswitch文でboard_M5Tab5に行き、Ina226.getBusVoltage()で得た値が使われていることが分かります。

その後の計算も含め、M5Stack User Demoでは、次のコードで求めることができます。これを表示に追加します。

"M5Stack User Demo"におけるgetBatteryLevel()相当
float mv = GetHAL()->powerMonitorData.busVoltage * 500;
int level = (mv - 3300) * 100 / (float)(4150 - 3350);
if (level < 0) level = 0;
if (level > 100) level = 100;

`GetHAL()->powerMonitorData.busVoltage`は、`ina226.readBusVoltage()`の値です。
platforms/tab5/main/hal/components/hal_power.cpp#21行目〜
void HalEsp32::updatePowerMonitorData()
{
    powerMonitorData.busVoltage   = ina226.readBusVoltage();
    powerMonitorData.shuntVoltage = ina226.readShuntVoltage();
    powerMonitorData.busPower     = ina226.readBusPower();
    powerMonitorData.shuntCurrent = ina226.readShuntCurrent();
}

計算式の考察

  • mv:INA226センサーが測定した、Li-Poバッテリーの電圧の半分(mV)
  • mv - 3300:バッテリーの最低電圧(0%残量)を3300mVとする
  • 4150 - 3350: バッテリーの満充電時電圧の目安4150mVと、ほぼ空の電圧の目安3350mVの差分、つまり使用可能な電圧範囲の総量を表す
  • * 100: 百分率に変換

つまり、電圧範囲(3.35V〜4.15V)内でバッテリー残量がリニアに変化すると仮定して、現在の電圧値を0%〜100%のスケールにマッピングしている式である。

2.2 カスタマイズ(BatteryLevelを表示)

次の2ファイルを変更します。

  • app/apps/app_launcher/view/view.h
  • app/apps/app_launcher/view/panel_power_monitor.cpp

(1) view.h

view.hの97行目あたりに、次の1行を追加します。

view.h
    std::unique_ptr<smooth_ui_toolkit::lvgl_cpp::Image> _img_chg_arrow_down;
+   std::unique_ptr<smooth_ui_toolkit::lvgl_cpp::Label> _label_bat_level; //battery level

(2) panel_power_monitor.cpp

  1. panel_power_monitor.cppの55行目あたりに、次の処理を追加します。
panel_power_monitor.cpp
    _img_chg_arrow_down = std::make_unique<Image>(lv_screen_active());
    _img_chg_arrow_down->align(LV_ALIGN_CENTER, 216, -264);
    _img_chg_arrow_down->setSrc(&chg_arrow_down);

+   _label_bat_level = std::make_unique<Label>(lv_screen_active());
+   _label_bat_level->align(LV_ALIGN_RIGHT_MID, _label_voltage_pos_x + 92, _label_voltage_pos_y);
+   _label_bat_level->setText("..");
+   _label_bat_level->setTextColor(lv_color_hex(_label_color));
+   _label_bat_level->setTextFont(&lv_font_montserrat_22);
+   _label_bat_level->setBgColor(lv_color_white());
+   _label_bat_level->setBgOpa(LV_OPA_COVER);
}


2. panel_power_monitor.cppの72行目あたりに、次の処理を追加します。

panel_power_monitor.cpp
    _label_voltage->setText(fmt::format("{:.2f}V", GetHAL()->powerMonitorData.busVoltage));
    _label_current->setText(fmt::format("{:.2f}A", GetHAL()->powerMonitorData.shuntCurrent));
+   if (abs(GetHAL()->powerMonitorData.shuntCurrent) > 0.001) {
+       _label_bat_level->setText(fmt::format("L: {:d}%", []()->int {
+           // see M5Unified/src/utility/Power_Class.cpp#1309
+           float mv = GetHAL()->powerMonitorData.busVoltage * 500;
+           int level = (mv - 3300) * 100 / (float)(4150 - 3350);
+           return (level < 0) ? 0 : (level > 100) ? 100 : level;
+       }()));
+   } else {
+       _label_bat_level->setText("L: -    ");
+   }

3. ビルド & 書き込み

環境準備、ビルド および カスタマイズしたファームウェアの書き込みについては、前回記事を参照してください。

なお、今回のカスタマイズ内容は、前回のカスタマイズ内容とは独立しています。よって、前回のカスタマイズをスキップして 今回のカスタマイズを適用することが可能です。

4. 結果確認

電圧(V)の右側、INA226 の上部に バッテリー残量を追加しました。
下記スクショのように、期待した通りに表示されています。

外部電源で動作中
(バッテリー充電中)
outChage.jpeg
矢印が赤色
外部電源で動作中
(バッテリーパック無し)
noBat.jpeg
なぜか矢印が赤色
バッテリーで動作中 inCharge.jpeg
矢印がグレー

バッテリーパック無しの場合に、矢印が赤い原因を調べました。

panel_power_monitor.cppの83行目
-   if (GetHAL()->powerMonitorData.shuntCurrent < 0) {
+   if (GetHAL()->powerMonitorData.shuntCurrent < -0.001) {

浮動小数点の計算誤差なのか、バッテリーパック無しの場合の電流値が 「真に 0 ではない」 ことが原因です。
この閾値を調整することで、バッテリーパック無しの場合に 矢印がグレーになります。

5. バッテリーパックの充放電時間

使用した NP-F550互換バッテリーパックは こちら のもの。
(電圧:7.2V、容量:2600mAh)

LCDの明るさを 20%に設定。

5.1 バッテリーパックの充電時間

バッテリー残量 0%で動作を停止した状態から、外部電源に切り替えて、バッテリーパックの充電状況(バッテリー残量)を観察した。

ちょうど1時間ほどで100%となったが、充電電流は流れたまま・・・。
タイムラプス(4秒間隔)撮影

その後、しばらく放置していたら 電流値が 0.00A となっていた。

L100.jpeg

5.2 バッテリーパックの放電時間

公式資料に次の説明があります。

標準使用環境(画面輝度 50%、Wi‑Fi 常時接続、バックグラウンドタスク稼働等)において、Tab5 内蔵バッテリー電圧が満充電(8.23 V)からシャットダウン閾値(6.0 V)まで放電し、約 6 時間連続稼働可能。

満充電したバッテリーで動作させて、バッテリーの残量を観察した。

6時間を経過しても40%ほど残っていた。
その後も放置していたら、気付いた時には落ちていました。

5.3 シリアルポートを使った監視

バッテリーレベルと電流値をシリアルポートに出力する処理を加えてモニターした結果をグラフ化しました。

  • USBシリアルから電源を供給させないため、USBシリアルとM5Tab5は、TX / RX / GND のみ接続
  • 画面の明るさは、起動直後に20%に設定
  • 外部電源は、Raspberry Pi 5向けの5.1V 5.0A出力 の電源アダプタを使用

5.3.1 充電

外部電源で動作させて、バッテリーの充電状況をモニター

  • 0%から充電を開始し 57分後にバッテリーレベルは100%となったが、充電電流は流れたまま。充電電流が止まったのは、充電を開始して2時間24分後であった。充電電流値はほぼ一定で、平均値は 0.971A であった。

充電.png

5.3.2 放電

バッテリーパックで動作させて、バッテリーの放電状況をモニター

  • 満充電した100%から放電を開始し 7時間11分後にシステム停止。停止直前のバッテリーレベルは51%であった。電流値は多少の振れはあるが、平均値は 0.237A であった。

放電.png

「M5Stack User Demo」の内容だと、それほど能動的に動作する処理が少ないのか、バッテリーパックの容量が 2600mAh と多めなのか、公称値の「約6時間連続稼働」より1時間以上 長く動作した。




以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?