はじめに
M5stickにスイッチを繋いで仮想キーボードとか作ったりして遊んでいるのですが、後からつけたスイッチの処理を毎回考えていちいち書いたりコピペしたりするのがめんどくさくなってきました。
本体のボタンはM5.BtnA.wasPressed()とかできるのだから、後つけスイッチでも同じことができたら楽になるんじゃない?というのが今回の趣旨です。
やり方
結論から言うと、Buttonクラスを継承?すればすぐにできました。(※この記事はクラスの継承とかよく分からない素人が書いています)
まずはサンプルコードをご覧ください。
#include <M5StickC.h>
// GPIO 0,26に外部スイッチを繋いでいる場合
#define EX0_BUTTON_PIN 0
#define EX1_BUTTON_PIN 26
Button BtnEX0 = Button(EX0_BUTTON_PIN, true, DEBOUNCE_MS)
Button BtnEX1 = Button(EX1_BUTTON_PIN, true, DEBOUNCE_MS)
void buttonUpdate(void){
BtnEX0.read();
BtnEX1.read();
}
void loop() {
M5.update();
buttonUpdate();
if ( BtnEX0.wasPressed() ) {
// ボタンが押された時の処理
}
if ( BtnEX1.wasPressed() ) {
// ボタンが押された時の処理
}
delay(100);
}
そんなに難しくないですね!
何をやっているのか
まずは公式のButtonはどんな風に処理をやっているのか見てみました。
#define DEBOUNCE_MS 10
Button BtnA = Button(BUTTON_A_PIN, true, DEBOUNCE_MS);
Button BtnB = Button(BUTTON_B_PIN, true, DEBOUNCE_MS);
BtnA BtnB の宣言です。( 100~102行目 )
PIN番号さえ指定してやれば、そんなに難しくなさそうです。
ture とか DEBOUNCE_MSとかありますが、まずは変なところはいじらないでおきます。
次に、「Buttonを使うならM5.update()を忘れるな」と言われるのでupdate()では何をしてるのか見てみます。
void M5Stack::update() {
//ボタンアップデート
BtnA.read();
BtnB.read();
BtnC.read();
//スピーカーアップデート
Speaker.update();
}
お、おう。update()、意外と単純な内容だった。
でもこれなら応用は簡単です。
自分で作ったボタンもループで毎回read()してやればいいという事ですね。
ということでまとめると、上にあげたサンプルコードのような内容になりました。
スイッチを取り付ける時の注意事項
プログラミング上の注意というよりはんだ付けの問題なのですが、スイッチを押したときGPIOがプラスに繋がるかマイナスに繋がるかは大事です。
Buttonクラスは初期化時にINPUT_PULLUPされるからです。
詳しくはこちら。M5stickC - Button.cpp
ものすごくざっくりいうと、Buttonとして宣言するとプラスになるという事です。
ですので、スイッチを押したときGNDに繋がるようにはんだ付けしてやればいいみたいです。
GPIO36 (G36)だけは例外です。GPIO36は「入力専用端子で出力はできません。また、プルアップとプルダウンも利用できませんので注意しましょう」ということなので、GNDに繋ぐことはできません(繋いでも反応しません)。
(lang-ship M5StickC非公式日本語リファレンスより)
これは裏ワザというか間違った使い方だと思いますが、GNDではなく3V3に繋ぐようにすればG36もボタンとして使えます。
ただし動作がほかのボタンと少し違ってきたりします。使用は自己責任で行ってください。
おわりに
これで外部GPIOに接続したスイッチやボタンでも wasPressed()できるようになりました。
スケッチの見通しが良くなっていいね!