ESP32-C3をXBOXコントローラーから操作する

マイコン/Arduino

今回はXBOXのコントローラーからESP32-C3を操作する方法を紹介します。

WiiリモコンをESP32で利用する方法は以前紹介していますので次の記事をご参照ください。

Bluepad32

Bluepad32というライブラリを使用します。様々なゲームコントローラーと様々なマイコンの組み合わせで使用することができ、使い方も簡単です。

Bluetoothの問題

一口にBluetoothといっても、大きく分けてBluetooth BR/EDR(いわゆるClassic)とBLEの2種類があり基本的には互換性がなく別のものだと考えてよいです。

マイコン側の対応で言えば、ESP32はBR/EDRとBLEの両対応ですが、ESP32-C3やESP32-S3はBLEのみの対応です。一方、コントローラー側を見ると、WiiリモコンやPS5のコントローラーはBR/EDRのみ対応、XBOXのコントローラーはBLEのみの対応です。

FAQ - Bluepad32
A Bluetooth controller

今回はBLEに対応しているESP32-C3とXBOXコントローラーを使用した例を紹介します。

Bluetooth BR/EDRとBLEについては私も詳細は説明できません。気になる方は各自調べてみてください。

使い方

1:ボードマネージャの追加

ArduinoIDEで、[ファイル]-[環境設定]を開き、[追加のボードマネージャーのURL]に以下のアドレスを追加してください。

https://raw.githubusercontent.com/ricardoquesada/esp32-arduino-lib-builder/master/bluepad32_files/package_esp32_bluepad32_index.json

ESP32C3とXBOXコントローラーを接続する方法

2:ボードの追加

[ツール]-[ボード]-[ボードマネージャ]を開いてください。検索ボックスに”bluepad32″と入力して、ヒットしたものをインストールしてください。

ESP32C3とXBOXコントローラーを接続する方法ESP32C3とXBOXコントローラーを接続する方法

3:ボードの設定

[ツール]-[ボード]-[ESP32 Arduino+Bluepad32]の中から自分で使用するボードを選択してください。

今回はXIAOのESP32C3を使用して動作確認を行いました。

 

4:スケッチ

動作確認用のスケッチを以下に掲載します。といっても、ライブラリに標準で付属しているサンプルから不要な部分を削り、少し手直ししただけのものです。

シリアル通信から、コントローラー側で押されたキーを確認できるようにしてあります。

#include <Bluepad32.h>
ControllerPtr myControllers[BP32_MAX_GAMEPADS];

void onConnectedController(ControllerPtr ctl) {
 bool foundEmptySlot = false;
 for (int i = 0; i < BP32_MAX_GAMEPADS; i++) {
 if (myControllers[i] == nullptr) {
  Serial.printf("CALLBACK: Controller is connected, index=%d\n", i);
  ControllerProperties properties = ctl->getProperties();
  Serial.printf("Controller model: %s, VID=0x%04x, PID=0x%04x\n", ctl->getModelName().c_str(), properties.vendor_id, properties.product_id);
  myControllers[i] = ctl;
  foundEmptySlot = true;
  break;
  }
 }
 if (!foundEmptySlot) {
  Serial.println("CALLBACK: Controller connected, but could not found empty slot");
 }
}

void onDisconnectedController(ControllerPtr ctl) {
 bool foundController = false;

 for (int i = 0; i < BP32_MAX_GAMEPADS; i++){
  if (myControllers[i] == ctl){
   Serial.printf("CALLBACK: Controller disconnected from index=%d\n", i);
   myControllers[i] = nullptr;
   foundController = true;
   break;
  }
 }
 if (!foundController) {
   Serial.println("CALLBACK: Controller disconnected, but not found in myControllers");
 }
}
void processGamepad(ControllerPtr ctl) {
 //ABXY BUTTONS
 if (ctl->a()) Serial.printf("A\n");
 if (ctl->b()) Serial.printf("B\n");
 if (ctl->x()) Serial.printf("X\n");
 if (ctl->y()) Serial.printf("Y\n");
 if (ctl->l1()) Serial.printf("L1\n");
 if (ctl->r1()) Serial.printf("R1\n");
 if (ctl->l2()) Serial.printf("L2\n");//トリガーL
 if (ctl->r2()) Serial.printf("R2\n");//トリガーR

 //DPAD
 if (ctl->dpad()& DPAD_UP) Serial.printf("UP\n");
 if (ctl->dpad()& DPAD_DOWN) Serial.printf("DOWN\n");
 if (ctl->dpad()& DPAD_LEFT) Serial.printf("LEFT\n");
 if (ctl->dpad()& DPAD_RIGHT) Serial.printf("RIGHT\n");

 //MISCボタン
 if (ctl->miscButtons()& MISC_BUTTON_SYSTEM) Serial.printf("XBOX\n");
 if (ctl->miscButtons()& MISC_BUTTON_BACK) Serial.printf("BACK\n");
 if (ctl->miscButtons()& MISC_BUTTON_HOME) Serial.printf("HOME\n");

 //アナログ入力
 Serial.printf("L:(%4d,%4d) R:(%4d,%4d) TRIG:(%4d,%4d)\n",
 ctl->axisX(), ctl->axisY(),
 ctl->axisRX(), ctl->axisRY(),
 ctl->brake(), ctl->throttle());
}

void processControllers() {
 for (auto myController : myControllers) {
  if (myController && myController->isConnected() && myController->hasData()) {
   if (myController->isGamepad()) {
    processGamepad(myController);
   }
   else {
    Serial.println("Unsupported controller");
   }
  }
 }
}

// Arduino setup function. Runs in CPU 1
void setup() {
 Serial.begin(115200);
 Serial.printf("Firmware: %s\n", BP32.firmwareVersion());
 const uint8_t* addr = BP32.localBdAddress();
 Serial.printf("BD Addr: %2X:%2X:%2X:%2X:%2X:%2X\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);

 // Setup the Bluepad32 callbacks
 BP32.setup(&onConnectedController, &onDisconnectedController);
 BP32.forgetBluetoothKeys();
}

// Arduino loop function. Runs in CPU 1.
void loop() {
 bool dataUpdated = BP32.update();
 if (dataUpdated) processControllers();
 delay(10);
}

5:使い方

上記スケッチが書き込まれたマイコンに電源を接続した状態でコントローラー側の電源を入れれば、自動的に接続されます。(XBOXボタンが白点滅から白点灯になれば接続完了)

この状態でシリアルモニタを確認すれば、コントローラーの押されたボタンに応じて返答が確認できるはずです。

上記手順で接続できない場合、ペアリングボタン長押しで接続できます。また、初出時ESP32開発ボードで接続できないと書いたのですが、この手順で無事に接続・動作確認できました。

まとめ

ESP32-C3とXBOXコントローラーを接続する方法を紹介しました。ESP32-C3は価格が安く、使いやすいサイズのマイコンですがBLEにしか対応していないため、接続できるコントローラーはXBOXのコントローラーのみです。

なお、BR/EDRとBLEに両対応しているはずのESP32開発ボードでも動作を確認したのですがXBOXコントローラーと接続できませんでした。この点については引き続き検証して、わかり次第追記します。

 

 

 

 

コメント