M5StackのM5StickCの少ないボタンでメニューをなんとかしようと検討中。Claudeでやってたのだけど、うまくいかない。そこで、M5StackのCHATにポイントを聞いてみた。とりあえず記録。
質問は
「M5UnifiedをM5StickCで使う。ボタンの短押しと長押しを使い分けるときのポイントを教えて。」
以下、答え。
M5Unifiedライブラリを使ったM5StickCのボタン短押し/長押しの使い分けポイントは以下の通りです。
- 基本設定と M5.update() の必須呼び出し
void setup() で M5.begin() を実行し、loop() 内で必ず M5.update() を呼び出す。これによりボタン状態が更新されます。
void setup() {
auto cfg = M5.config();
M5.begin(cfg); // M5StickCの初期化
}
void loop() {
M5.update(); // ボタン状態更新(必須)
// ボタン処理…
}
include
- 短押しの検出方法
wasPressed(): ボタンが「押された瞬間」を検出(押下時1回のみ反応)。
wasClicked(): 短押し(軽くタッチして離した場合)を検出する高レベルAPI。
if (M5.BtnA.wasPressed()) {
M5.Lcd.println("BtnA 短押し (wasPressed)");
}
if (M5.BtnA.wasClicked()) { // 推奨
M5.Lcd.println("BtnA 短押し (wasClicked)");
}
- 長押しの検出方法
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)");
}
- 長押し閾値のカスタマイズ
setHoldThresh(ms) で長押し判定時間を変更(例:1000msに設定)。
void setup() {
M5.begin();
M5.BtnA.setHoldThresh(1000); // 長押し判定を1秒に設定
}
- 短押しと長押しの競合回避
「長押し後に短押しが誤検出される」問題を防ぐため、wasHold() を先に判定する。
void loop() {
M5.update();
if (M5.BtnA.wasHold()) {
M5.Lcd.println("長押し処理"); // 長押しを優先判定
} else if (M5.BtnA.wasClicked()) {
M5.Lcd.println("短押し処理");
}
}
- 電源ボタン(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() で拾えた。
とりあえず、わかったことをメモ。また、なんかあったら書く。
コメント