M5Stack Chain DualKey買ってみた -3-

 ボタンと電池が内蔵されたS3がほしかっただけなので、CHAINもいらなければ、キーボードとしても用事がない。

 というわけで、ボタンの検出のスケッチを書いてみる。

 前にTHINKLETのアプリをUSB IDを使って起動する仕組みを書いたのだけど、それをそのまま使おう。当時のターゲットはATOMS3 LITE。ボタンは1つで3つのモードをトグルするようになっていたけど、DualKeyはボタンが2つなので、2つのモードの切り替えだけになる。

 こんな感じかな。

 ・Key1 を押すと App A(mode=0) に固定

 ・Key2 を押すと App B(mode=1) に固定

 ・変更後はNVSに保存して再起動し、起動時にそのモードのVID/PIDでUSBを開始

 AIの書いたスケッチ。

 #include <Arduino.h>

 #include "USB.h"

 #include <Preferences.h>

 // --- Chain DualKey ハードウェア定義 ---

 #define PIN_KEY1 0 // Key1 GPIO0

 #define PIN_KEY2 17 // Key2 GPIO17

 Preferences preferences;

 // --- USBプロファイル定義(2モード固定) ---

 #define DEVICE_VID 0x32C8 // FairyDevices

 #define DEVICE_MANUFACTURER "My Company"

 struct USBProfile {

 uint16_t pid;

 const char* productName;

 };

const USBProfile profiles[2] = {

 {0x4001, "Chain DualKey - App A"},

 {0x4002, "Chain DualKey - App B"},

 };

 static int loadMode() {

 preferences.begin("usb-profile", true);

int mode = (int)preferences.getUInt("mode", 0);

 preferences.end();

 return mode & 1;

 }

 static void saveMode(int mode) {

 preferences.begin("usb-profile", false);

 preferences.putUInt("mode", (uint32_t)(mode & 1));

 preferences.end();

 }

 static void applyUSBProfile(int mode) {

const auto& p = profiles[mode & 1];

 USB.VID(DEVICE_VID);

 USB.PID(p.pid);

 USB.manufacturerName(DEVICE_MANUFACTURER);

 USB.productName(p.productName);

 USB.begin();

 Serial.printf("モード %d (%s) で起動しました。\n", mode & 1, p.productName);

 Serial.printf("VID: 0x%04X, PID: 0x%04X\n", DEVICE_VID, p.pid);

 }

 static void switchTo(int nextMode) {

 saveMode(nextMode);

 Serial.printf("モードを %d に設定しました。再起動します。\n", nextMode & 1);

 delay(200);

 ESP.restart();

 }

 // --- デバウンス ---

unsigned long last_debounce_time = 0;
const unsigned long debounce_delay = 50;

 void setup() {

 Serial.begin(115200);

 // ボタン(プルアップ:押下=LOW)

 pinMode(PIN_KEY1, INPUT_PULLUP);

 pinMode(PIN_KEY2, INPUT_PULLUP);

int mode = loadMode();

 applyUSBProfile(mode);

 Serial.println("Key1=App A / Key2=App B に切り替えます。");

 }

 void loop() {

int k1 = digitalRead(PIN_KEY1);
int k2 = digitalRead(PIN_KEY2);

 // どちらか押された(LOW)瞬間を拾う

 if ((k1 == LOW || k2 == LOW) && (millis() - last_debounce_time) > debounce_delay) {

 // 長押し連打防止:離されるまで debounce を更新しない方式

 if (k1 == LOW) {

 Serial.println("Key1: App A へ");

 switchTo(0);

 }

 if (k2 == LOW) {

 Serial.println("Key2: App B へ");

 switchTo(1);

 }

 } else if (k1 == HIGH && k2 == HIGH) {

 // 両方離されたら次の押下を受け付ける

last_debounce_time = millis();

 }

 delay(10);

 }

 Arduinoのライブラリには、ターゲットがDualKeyの設定はなかったので、ATOMS3で設定する。

 キー以外のボタンはないので、ファームウエアの書き込みモードにするのはちょっとめんどくさい。

 ・側面のスイッチを中央(MID)にする

 ・Key1(ストラップ穴から遠い方)を押しっぱなしにする

 ・そのままUSB-CのデータケーブルでPCに接続する

 ・接続できたら Key1を離す

 ・書き込み終わったら電源を入れ直す

 書き込みのコンソールには、以下のように出ているので書いたあとはリセットされているのかも。

 Hard resetting via RTS pin...

 ボード/dev/cu.usbmodem1101は利用できません

 ボード/dev/cu.usbmodem1101は利用できません

 macOSからどう見えるかで動作確認。一応、ボタンを押すと切り替わるようだ。

 あとは、動作に合わせてキーのLEDを光らせたりできるといいかな。面倒なのでやらないけど。

 Androidで紐づけたアプリ2つをボタンで切り替えるのは、当たり前だけど普通にできた。

 100円投げ銭  https://kinneko.booth.pm/items/1963720


オリジナル投稿:
M5Stack Chain DualKey買ってみた -3-|kinneko|pixivFANBOX
https://kinneko.fanbox.cc/posts/11107108