
XIAO ESP32C3でワイヤレスマクロキーボードを作ろう
作ったもの


使ったもの
はじめに
以前↓の記事で似たようなものを作ったんですが、こちらは有線のため少し使い勝手が悪いと感じたので、今回はBluetoothで接続できるものを作成しようと思います。
また、前回は勉強がてらキーマトリックス回路を作成して作ってたんですが、ピンに収まるボタン数であればそんなことする必要も無いので、そこもシンプルに作成していこうと思います。
ドキュメント
セットアップ方法に関してはドキュメントのセットアップ項目をご覧ください。
セットアップ完了後にPCと接続してもArduino IDEのポートに表示されない場合がありますが、その場合はドキュメントのよくある質問項目にもありますが、接続した状態でRestボタンを押すことでポートに表示され書き込むことができるようになるはずです。



こんな感じでUSB表示のものが出ます。環境やデバイスによって表示のされ方違うかもですが、
ちなみに自分用のメモですが、特にデバイス接続してないでも出てるものは仮想シリアルポートみたいです。
注意点
今回作るものでは #include <BleKeyboard.h>というライブラリを使用します。
これがesp32のverとの影響からか最新(3.0.0以上)のものを使用しているとこのようなエラーが出るみたいなんですよね。(記事作成時点2025/2/16)
note: no known conversion for argument 1 from 'std::string' {aka 'std::__cxx11::basic_string<char>'} to 'String'
なので、2.0.17(ver2で一番新しいもの)を使用してください。
2.0.17でならコンパイルでエラーが出なくなります。

まぁ最新verでも書き込みさせる方法はあるかもなんですが、あまりそこは詳しく無いのでとりあえずな感じです。
BleKeyboard以外で何か作ろうとした時3.0.0以上じゃないとダメみたいなものがあれば、結構厄介になるかもです。
あとちなみに、↓画像の赤枠のものがwifiやらBluetoothのアンテナになるので紛失しないように注意を(最初何か分からず必要ないと思って捨てるとこだった)

回路図

前述しましたとおり、今回はシンプルなものなので単純にピンとボタンを繋げただけです。画像だとArduinoになってるのはご了承ください。
コード
#include <BleKeyboard.h>
#include <esp_sleep.h>
BleKeyboard bleKeyboard;
const int numPins = 3;
int pins[numPins] = { 2, 6, 8 }; // GPIO 2と6と8にボタンを接続
int pinStates[numPins]; // ボタンの状態を記録
unsigned long lastActivityTime = 0; // 最後にボタンが押された時刻を記録
const unsigned long inactivityThreshold = 60000; // 1分(60000ミリ秒)操作がない場合にスリープするよう設定
void setup() {
for (int i = 0; i < numPins; i++) {
pinMode(pins[i], INPUT_PULLUP);
}
// BLEキーボードの初期化
bleKeyboard.begin();
// GPIO2が LOW(ボタンが押された状態)になるとESP32をスリープ解除
esp_deep_sleep_enable_gpio_wakeup(BIT(2), ESP_GPIO_WAKEUP_GPIO_LOW);
}
void loop() {
if (bleKeyboard.isConnected()) {
for (int i = 0; i < numPins; i++) {
pinStates[i] = digitalRead(pins[i]); // 各ピンの状態を取得
if (pinStates[i] == LOW) { // ボタンが押された場合
lastActivityTime = millis(); // 最後のアクティビティ時間を更新
switch (pins[i]) {
case 2:
bleKeyboard.press(KEY_RIGHT_ARROW);
break;
case 6:
bleKeyboard.press(KEY_LEFT_ARROW);
break;
case 8:
bleKeyboard.press(KEY_RETURN);
break;
}
// 50ms のデバウンス処理(誤動作防止)
delay(50);
// ボタンが押されている間はループして待機
while (digitalRead(pins[i]) == LOW) {
delay(10);
}
// ボタンが離されたらキーをリリース
bleKeyboard.releaseAll();
}
}
}
// 一定時間(1分間)操作がなかった場合、ディープスリープモードに入る
if (millis() - lastActivityTime > inactivityThreshold) {
delay(1000); // 少し待ってからスリープ
esp_deep_sleep_start(); // ディープスリープに入る
}
}
全体的にはこんな感じになります。
コード内にもコメントありますが、重要そうな部分を解説していこうと思います。
1. ライブラリのインクルード
#include <BleKeyboard.h>
#include <esp_sleep.h>
BleKeyboard.h は ESP32をBLEキーボードとして機能させるライブラリ
esp_sleep.h は ディープスリープ機能を利用するためのライブラリ
2. オブジェクトと変数の定義
BleKeyboard bleKeyboard;
bleKeyboard オブジェクトを作成し、BLEキーボードの機能を使用できるようにする。
3. setup() 関数
bleKeyboard.begin();
BLEキーボード機能を開始(PCやスマホと接続する準備)
esp_deep_sleep_enable_gpio_wakeup(BIT(2), ESP_GPIO_WAKEUP_GPIO_LOW);
ディープスリープモードの時、特定のボタンやスイッチ(GPIOピン)を押すと自動で起動するように設定
注意点
理由は分からないんですが、下記のようなエラーが出る時があります。
sleep: gpio 20 is an invalid deep sleep wakeup IO
これはディープスリープのウェイクアップ用GPIOとして無効なピンを指定していることを示しているみたいです。
これが出た時自分はピンをBIT(D0)と指定していました。
ピン配置の画像を見てもD0はGPIO20では無いはずなのですが、どうもBIT(D0) が GPIO20 に解釈されてしまっているみたいです。
他の作ったものはD0の書き方で動いたので、物によって差異があるのかも..?
なのでもしこういうのが出たらそのピンはウェイクアップピンとして使えないかもなので、大人しく別のところを指定しましょう。
まぁそもそもピン指定をGPIOの番号でやれば出ないかもです。
4. loop() 関数
if (bleKeyboard.isConnected()) {}
BLEキーボードが PCやスマホに接続されているときのみ処理を実行
if (pinStates[i] == LOW) {
lastActivityTime = millis(); // 最後のアクティビティ時間を更新
ボタンが押されたら 現在の時間(ミリ秒)を lastActivityTime に記録
5. スリープ判定
if (millis() - lastActivityTime > inactivityThreshold) {
delay(1000); // 少し待ってからスリープ
esp_deep_sleep_start(); // ディープスリープに入る
}
最後のアクティビティから1分以上経過したらスリープ
少し待ってからディープスリープに入る
終わりに
とまぁこんな流れで処理が行われています。
スリープ解除ボタンの設定は複数でできればなんですが、多分できないっぽいんですよね。全然調べてないですが。。
スリープモードに入る時間の調整はinactivityThresholdの値変更すればいいので、バッテリーとの兼ね合いでですね。
前にXIAO ESP32C3のバッテリー駆動時間の記事も書いたのでもし参考になればこちらもどうぞ。
あと一応こちらにも回路図とコードが見れるサンプルも置いています。
ただ、もちろんこのシュミレーターで何か動作ができるわけでは無くこの記事内に書かれていないものもないので特段見る必要もないと思いますが、よければこちらも参考に。
終