M5Unifiedの長押しと短押し使い分けのポイント(追記:電源ボタンも)

M5Stack

M5StackのM5StickCの少ないボタンでメニューをなんとかしようと検討中。Claudeでやってたのだけど、うまくいかない。そこで、M5StackのCHATにポイントを聞いてみた。とりあえず記録。

質問は
「M5UnifiedをM5StickCで使う。ボタンの短押しと長押しを使い分けるときのポイントを教えて。」

以下、答え。

M5Unifiedライブラリを使ったM5StickCのボタン短押し/長押しの使い分けポイントは以下の通りです。

  1. 基本設定と M5.update() の必須呼び出し

void setup() で M5.begin() を実行し、loop() 内で必ず M5.update() を呼び出す。これによりボタン状態が更新されます。

void setup() {
  auto cfg = M5.config();
  M5.begin(cfg); // M5StickCの初期化
}

void loop() {
  M5.update(); // ボタン状態更新(必須)
 // ボタン処理…
}

include

  1. 短押しの検出方法

wasPressed(): ボタンが「押された瞬間」を検出(押下時1回のみ反応)。
wasClicked(): 短押し(軽くタッチして離した場合)を検出する高レベルAPI。

if (M5.BtnA.wasPressed()) {
  M5.Lcd.println("BtnA 短押し (wasPressed)");
}

if (M5.BtnA.wasClicked()) { // 推奨
  M5.Lcd.println("BtnA 短押し (wasClicked)");
}
  1. 長押しの検出方法

pressedFor(ms): ボタンが指定時間(ms)以上「押され続けている間」検出。
wasHold(): 長押し状態が確定した瞬間を検出(デフォルト500ms、setHoldThresh() で変更可)。

// 2秒間押し続けた場合(押下中に連続検出)
  if (M5.BtnA.pressedFor(2000)) {
  M5.Lcd.println("BtnA 2秒長押し中");
}

// 長押し確定時(1回のみ反応、デフォルト500ms)
if (M5.BtnA.wasHold()) { // 推奨
  M5.Lcd.println("BtnA 長押し (wasHold)");
}
  1. 長押し閾値のカスタマイズ

setHoldThresh(ms) で長押し判定時間を変更(例:1000msに設定)。

void setup() {
  M5.begin();
  M5.BtnA.setHoldThresh(1000); // 長押し判定を1秒に設定
}

  1. 短押しと長押しの競合回避

「長押し後に短押しが誤検出される」問題を防ぐため、wasHold() を先に判定する。

void loop() {
  M5.update();
  if (M5.BtnA.wasHold()) {
    M5.Lcd.println("長押し処理"); // 長押しを優先判定
  } else if (M5.BtnA.wasClicked()) {
    M5.Lcd.println("短押し処理");
  }
}
  1. 電源ボタン(BtnPWR)の注意点

M5StickCの電源ボタン(AXP192 PMIC制御)は M5.Power.getKeyState() で検出します。

uint8_t keyState = M5.Power.getKeyState();
if (keyState == 2) { // 短押し
  M5.Lcd.println("PWR短押し");
} else if (keyState == 1) { // 長押し
  M5.Lcd.println("PWR長押し");
}

 以上については、それぞれ動作することを確認した。特に電源ボタンが使えるのは、かなり有用だなあ、と感じた。3ボタン使えればメニュー項目の「進む」「戻る」「決定」に割当ができる。なんでもできそうではないか。

 と、ここまでは思ってたんだよなあ。そこから数日。

M5StickC Plus2ではこれがまた違う

 追記で続き。M5StickC Plus2を購入したんですが、これがまた違う。上の方法ではうまくいかない。また、聞いてみた。

M5StickC-Plus2 (SKU:K016-P2) では電源ボタンの検出方法が変更されています。同シリーズのM5StickCやPlusが電源管理IC(AXP192)を搭載していたのに対し、Plus2ではAXP192が削除され、代わりにGPIOピン(G35)で直接「BUTTON C」を検出する仕様になっています。そのため、M5.Power.getKeyState()(AXP192依存のAPI)は使用できず、代わりにGPIOピンの状態を直接読み取る必要があります。

あやしい気がしたので質問。

「M5UnifiedのBtnCとかでもうまくいく?」

M5Unifiedライブラリを使用すると、M5StickC-Plus2の電源ボタン(BtnC)をM5.BtnCで正しく検出できます。M5Unifiedはデバイスごとのハードウェア差異を吸収しており、Plus2のBtnC(GPIO35)は自動的に認識されます。

使用例:

#include <M5Unified.h>

void setup() {
  auto cfg = M5.config();
  M5.begin(cfg); // M5Unifiedの初期化
}

void loop() {
  M5.update(); // ボタン状態の更新(必須)
  
  if (M5.BtnC.wasPressed()) {       // 短押し検出
    M5.Display.println("BtnC Pressed");
  } else if (M5.BtnC.pressedFor(2000)) { // 2秒長押し検出
    M5.Display.println("BtnC Long Press");
  }
}

ところが、これもうまくいかない。

「ほんとにBtnCで取得できる? 今試したらできないんだけど。」

と、聞いてみた。

M5StickC-Plus2でM5UnifiedのBtnCが動作しない場合は、以下のチェックポイントと対処法を試してください:

1. ライブラリのバージョン確認
M5Unifiedライブラリが1.2.0以降であることを確認してください。古いバージョンではPlus2のBtnC(GPIO35)のマッピングが正しく設定されていない場合があります。
Arduino IDEの「ライブラリマネージャー」からM5Unifiedを更新してください。


2. 正しい初期化コード
M5.begin()前にM5.config()で明示的にデバイスを指定することで、認識精度が向上します:


#include <M5Unified.h>

void setup() {
  auto cfg = M5.config();
  cfg.device = M5DEVICE_STICKCPLUS2; // Plus2を明示的に指定
  M5.begin(cfg);
}

void loop() {
  M5.update(); // 必須:ボタン状態更新
  if (M5.BtnC.wasPressed()) {
    M5.Display.println("BtnC Pressed!");
  }
}

3. M5StickCPlus2ライブラリとの競合
M5Unifiedと従来のM5StickCPlus2.hは共存できません(同名のM5インスタンスが競合)。コード中に#include <M5StickCPlus2.h>がある場合は削除し、ライブラリをアンインストールしてください。


4. ハードウェアリセット
電源ボタンを長押し(5秒)して強制リセットした後、再度プログラムを書き込んでください。

 今回は同じバイナリで無印からPlus、Plus2まで動かしたかったので、初期化コードは使えず。結局、Plus2でいろいろ試したところ、 M5.BtnPWR.wasPressed() で拾えた。

 とりあえず、わかったことをメモ。また、なんかあったら書く。

コメント

タイトルとURLをコピーしました