1
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?

[M5StickS3入門] Arduinoで始める:バッテリー表示とボタン入力の最初の一歩

1
Last updated at Posted at 2026-03-27

[M5StickS3入門] Arduinoで始める:バッテリー表示とボタン入力の最初の一歩

M5StickS3 を Arduino IDE で触り始めたときの流れを、環境設定から実際の表示コードまでまとめました。
この記事では、次の 3 つを手早く確認できます。

  • 書き込み時の定番エラーの意味と対処
  • バッテリー情報の表示(充電状態・残量・電圧)
  • ボタン入力の表示(A / B / 同時押し)

公式の手順ページはこちらです。
M5StickS3 Arduino プログラムのコンパイルとアップロード

開発環境

  • Arduino IDE
  • ボード: M5StickS3(ESP32-S3)
  • ライブラリ: M5Unified, M5GFX

最初に出たエラー

書き込み時に以下のエラーが出ることがあります。

This chip is ESP32-S3, not ESP32-P4. Wrong chip argument?

これは、接続中の実機が ESP32-S3 なのに、アップロード設定が ESP32-P4 になっているという意味です。
ボード設定を M5StickS3(または ESP32-S3 系)に合わせると解消します。

ダウンロードモードの出入り

  • 入る: リセットボタンを長押し(緑 LED 点滅)
  • 出る: リセットボタンを短押し

通常は、書き込み完了後の再起動でも通常モードに戻ります。

バッテリー情報を表示する

まずは電源まわりの値を確認できるコードです。
充電中は緑、低電池(20%以下または3600mV以下)は赤で表示します。

このコードで使う主な要素は次のとおりです。

  • #include "M5Unified.h": M5デバイス本体、画面、電源情報などをまとめて扱うためのライブラリ
  • setup(): 電源ON直後に1回だけ実行される初期化処理
  • loop(): 初期化後に繰り返し実行されるメイン処理
  • M5.Power.getBatteryLevel(): バッテリー残量(%)を取得
  • M5.Power.getBatteryVoltage(): バッテリー電圧(mV)を取得
// M5StickS3を含むM5シリーズ向けの基本ライブラリ。
// 画面、ボタン、電源情報などを M5.*** で扱えるようになる。
#include "M5Unified.h"

void setup() {
  // M5デバイス初期化用の設定オブジェクトを作る
  auto cfg = M5.config();
  // 画面・ボタン・電源管理などを初期化する
  M5.begin(cfg);

  // 画面を横向き表示にする(数値は機種ごとに見やすい向きが異なる)
  M5.Display.setRotation(1);
  // 表示フォントを設定
  M5.Display.setTextFont(&fonts::FreeMonoBold9pt7b);
  // 文字サイズを1倍に設定
  M5.Display.setTextSize(1);
}

void loop() {
  // ボタンや内部状態を毎ループ更新する(M5Unifiedの基本)
  M5.update();
  // 前フレームの表示を消して描き直す
  M5.Display.clear();

  // 充電中かどうか(true/false)
  bool isCharging = M5.Power.isCharging();
  // バッテリー残量(0〜100の目安)
  int level = M5.Power.getBatteryLevel();
  // バッテリー電圧(mV)
  int voltage = M5.Power.getBatteryVoltage();
  // 低電池とみなす条件を定義
  bool lowBattery = (level <= 20) || (voltage <= 3600);

  // 1行目: 充電状態を表示
  M5.Display.setCursor(0, 30);
  // 充電中なら緑、それ以外は白
  M5.Display.setTextColor(isCharging ? TFT_GREEN : TFT_WHITE, TFT_BLACK);
  M5.Display.printf("Charging: %s", isCharging ? "Yes" : "No");

  // 2行目: 残量を表示(低電池なら赤)
  M5.Display.setCursor(0, 60);
  M5.Display.setTextColor(lowBattery ? TFT_RED : TFT_WHITE, TFT_BLACK);
  M5.Display.printf("Bat_level: %d%%", level);

  // 3行目: 電圧を表示
  M5.Display.setCursor(0, 90);
  M5.Display.printf("Bat_voltage: %d mV", voltage);

  // 2秒ごとに更新(変化が速すぎないので見やすい)
  delay(2000);
}

ボタン状態を表示する

次に、A / B / 同時押し / 未押下を表示するコードです。
状態が変わったときだけ再描画するので、画面が安定します。

ここで押さえておくポイントです。

  • 「ボタン状態」を数値で定義して管理すると、判定ロジックを整理しやすい
  • getButtonState() で入力(ボタン)を読む
  • drawState() で出力(画面表示)を行う
  • prevState と比較して、変化したときだけ描画する
// M5Unifiedを使って、ボタンと画面をまとめて扱う
#include "M5Unified.h"

// ボタン状態を数値で定義(読みやすさと保守性のため)
static constexpr uint8_t STATE_RELEASED = 0;
static constexpr uint8_t STATE_PRESSED_A = 1;
static constexpr uint8_t STATE_PRESSED_B = 2;
static constexpr uint8_t STATE_PRESSED_BOTH = 3;

// 前回の状態を保存して、状態変化時だけ再描画するために使う
static uint8_t prevState = STATE_RELEASED;

// 現在のボタン状態(未押下/A/B/同時押し)を返す関数
static uint8_t getButtonState() {
  // Aボタンの押下状態を取得
  bool a = M5.BtnA.isPressed();
  // Bボタンの押下状態を取得
  bool b = M5.BtnB.isPressed();

  // 押し方に応じて状態コードを返す
  if (a && b) return STATE_PRESSED_BOTH;
  if (a) return STATE_PRESSED_A;
  if (b) return STATE_PRESSED_B;
  return STATE_RELEASED;
}

// 状態に応じた画面表示を行う関数
static void drawState(uint8_t state) {
  // まず画面をクリアして、表示の重なりを防ぐ
  M5.Display.clear(TFT_BLACK);
  M5.Display.setCursor(0, 0);
  // 文字色(前景色)と背景色を設定
  M5.Display.setTextColor(TFT_WHITE, TFT_BLACK);

  // stateの値に応じて表示内容と色を変更
  switch (state) {
    case STATE_PRESSED_A:
      M5.Display.println("Button Detail:");
      M5.Display.setTextColor(TFT_GREEN, TFT_BLACK);
      M5.Display.println("ButtonA Pressed");
      break;
    case STATE_PRESSED_B:
      M5.Display.println("Button Detail:");
      M5.Display.setTextColor(TFT_CYAN, TFT_BLACK);
      M5.Display.println("ButtonB Pressed");
      break;
    case STATE_PRESSED_BOTH:
      M5.Display.println("Button Detail:");
      M5.Display.setTextColor(TFT_YELLOW, TFT_BLACK);
      M5.Display.println("ButtonA + ButtonB");
      break;
    default:
      M5.Display.println("Button Released");
      break;
  }
}

void setup() {
  // 初期化設定を作成してM5を起動
  auto cfg = M5.config();
  M5.begin(cfg);
  // 画面の向きとフォントを設定
  M5.Display.setRotation(1);
  M5.Display.setFont(&fonts::FreeMonoBold12pt7b);
  // 起動時は未押下表示
  drawState(STATE_RELEASED);
}

void loop() {
  // ボタン状態を更新
  M5.update();

  // 現在のボタン状態を取得
  uint8_t state = getButtonState();
  // 前回と変化があったときだけ描画
  if (state != prevState) {
    drawState(state);
    prevState = state;
  }

  // タスクにCPU時間を譲る(高頻度ループでの負荷軽減)
  vTaskDelay(1);
}

つまずきやすいポイント

  • 1つのスケッチフォルダに .ino を複数置くと、setup() / loop() が重複してビルドエラーになる
  • printf の書式は %d mV のように書く(%mV は無効)
  • ボード設定は実機のチップと合わせる(M5StickS3 は ESP32-S3)

次にやると面白い拡張

  • ボタン短押し・長押しの判定表示
  • バッテリー値のグラフ表示
  • IMU 値(加速度)のリアルタイム表示
  • ボタンで画面を切り替える簡単な UI

最初の一歩としては、電源情報表示とボタン判定が動けば十分です。
この2つができると、センサー表示やUI実装へ自然に進めます。

1
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
1
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?