ソースに絡まるエスカルゴ

貧弱プログラマの外部記憶装置です。

【esp32】M5 Atom LiteでPS3コントローラの値を取得

 ゲーム機のコントローラでマイコンを制御してみたいと思い立ち色々と調べたところ、割と簡単にesp32でPS3のコントローラの値を取得できることがわかったので今回はその備忘録になります。

 また今回の開発環境はWindowsのみになるので注意してください。


 では、始めます。


0:esp32とPS3コントローラの準備
 今回esp32のマイコンとしてAtom Liteを使用しました(※他のesp32系のボードでは本記事のソースコードがそのままでは動かない可能性もあるので注意してください)。

 また前提としてArduino IDEとesp32、Atomを扱える状態にまでしておく必要があります。

 Atom Matrixの方ですが、過去に環境構築してサンプルを動かした記事があるのでそちらを参照してください。


 PS3コントローラ(Bluetooth対応)とPS3コントローラと接続するUSBケーブルを準備します。
 Bluetooth対応PS3コントローラは中古ショップなどで2000円しないぐらいで購入できると思います。

 PS3はモバイルバッテリーなどからは充電できないようで、PCなどのUSBポートから充電するようにしてください。


1:本体のMACアドレスを取得する
 まずはesp32とPS3をペアリングしなければBluetoothでの通信はできないので、esp32のMACアドレスを確認します。

 以下のプログラムをAtom Liteに書き込みます。

・M5Atom_macadrs.ino

#include "M5Atom.h" // 適宜書き換える(今回はM5Atom Lite)

void setup() {
  Serial.begin(115200);
  Serial.println("-----------------------------");
  uint8_t btmac[6];
  esp_read_mac(btmac, ESP_MAC_BT);
  Serial.printf("[Bluetooth] Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", btmac[0], btmac[1], btmac[2], btmac[3], btmac[4], btmac[5]);
}

void loop() {

}


 このスケッチを書き込んでからシリアルモニタを開いてAtom Liteのリセットボタンを押下すると、以下のようにMACアドレスが表示されるのでその値をメモ/コピーしておきます。


2:PS3コントローラにペアリングしたいMACアドレスを書き込む
 PS3のコントローラのペアリングは、コントローラ側に予めペアリング先のMACアドレスを設定しておく必要があります。

 まずは、PC側の書き込みツールをインストールします。

 次のページを開きます。

 赤枠部分をクリックします。

 ダウンロード先を選択してクリックします。ここではUKを選択しました。

 クリックするとダウンロードページが開き、数秒待つと自動的にexeファイルがダウンロードされます。

 ダウンロードしたインストーラを起動し「Next」をクリックします。

 ダウンロード先を指定して「Next」をクリックします。デフォルトのままで問題ないかと思います。

 スタートメニューのショートカットもデフォルトのままで「Next」をクリックします。

 設定確認の画面になるので「Install」をクリックしてインストールを開始します。

 インストールが完了したら「Finish」をクリックします。

 これで書き込むツールのインストールは完了です。

 インストール後、PCとPS3コントローラをUSBケーブルで接続します。

 その状態でWindowsの検索欄に「sixaxis」と入力して出てきた「SixaxisPairTool」を選択してツールを起動させます。

 初回起動時には以下のようにドライバのインストールが始まる場合があるので、しばらく待ちます。

 ドライバのインストール後、以下のような画面になるので「Change Master」と書かれている方に1で確認したMACアドレスを入力し「Update」ボタンをクリックします。

 すると「Current Master」と「Change Master」の値が同じになります。

 これでPS3コントローラへのMACアドレスの書き込みは完了になります。


3:Arduino IDEPS3コントローラのライブラリをインストールする
 次にArduino IDEPS3コントローラのライブラリをインストールします。

 以下のGithubページにアクセスします。

 ページ右上にある「Code」をクリックし、出てきた中にある「Download ZIP」をクリックしてzipファイルをダウンロードします。

 Arduino IDEを開いてメニューの「スケッチ」→「ライブラリをインクルード」→「ZIP形式のライブラリをインストール」を選択します。

 先ほどダウンロードしたzipファイルを指定して「開く」をクリックします。

 これでPS3コントローラをArduinoで扱えるようになりました。


4:Bluetoothのサンプル
 準備ができたので、実際にBluetoothの通信ができるかを確認します。

 Atom Liteに以下のスケッチを書き込みます。

※「Ps3.begin("xx:xx:xx:xx:xx:xx");」のところは各自のMACアドレスに適宜変更してください

・M5Atom_ps3con_test.ino

/**
 * M5Atom Lite PS3 controller
 */
#include "M5Atom.h"
#include <Ps3Controller.h>

const int LED_BRIGHTNESS = 100;

// analogスティックの値を保持する変数
uint8_t b_lx = 0, b_ly = 0, b_rx = 0, b_ry = 0;

void setup() {
  // 本体初期化(UART有効, I2C無効, LED有効)
  M5.begin(true, false, true);
  Ps3.begin("xx:xx:xx:xx:xx:xx");  // M5AtomのMacアドレスに変更

  Serial.begin(115200);
  showMsgLed("Pairing Ready...", 255, 0, 0); // LED赤色

  // ペアリング待ち
  while (!Ps3.isConnected()){
    delay(1000);
  }

  // ペアリングできたらLEDを青に
  showMsgLed("Pairing OK", 0, 0, 255);
}


void loop() {
  M5.update();  //本体のボタン状態更新

  if (Ps3.data.button.start) { showMsgLed("start", 0xF0, 0xF8, 0xFF); }     // start    :AliceBlue
  if (Ps3.data.button.select){ showMsgLed("select", 0x99, 0x66, 0xCC); }    // select   :Amethyst

  if (Ps3.data.button.l1)    { showMsgLed("button L1", 0xFA, 0xEB, 0xD7); }      // button L1 :AntiqueWhite
  if (Ps3.data.button.l2)    { showMsgLed("button L2", 0xFF, 0x7F, 0x50); }      // button L2 :Coral
  if (Ps3.data.button.l3)    { showMsgLed("analog L3 push", 0x64, 0x95, 0xED); } // analog L3 :CornflowerBlue

  if (Ps3.data.button.r1)    { showMsgLed("button R1", 0x00, 0xFF, 0xFF); }      // button R1 :Aqua
  if (Ps3.data.button.r2)    { showMsgLed("button R2", 0xFF, 0xF8, 0xDC); }      // button R2 :Cornsilk
  if (Ps3.data.button.r3)    { showMsgLed("analog R3 push", 0x00, 0x00, 0x8B); } // analog R3 :DarkBlue

  if (Ps3.data.button.up)   { showMsgLed("up", 0x7F, 0xFF, 0xD4); }         // ↑ :Aquamarine
  if (Ps3.data.button.right){ showMsgLed("right", 0xF0, 0xFF, 0xFF); }      // → :Azure
  if (Ps3.data.button.down) { showMsgLed("down", 0xF5, 0xF5, 0xDC); }       // ↓ :Beige
  if (Ps3.data.button.left) { showMsgLed("left", 0xFF, 0xE4, 0xC4); }       // ← :Bisque

  if (Ps3.data.button.cross)   { showMsgLed("cross", 0x8A, 0x2B, 0xE2); }    // X :BlueViolet
  if (Ps3.data.button.square)  { showMsgLed("square", 0xA5, 0x2A, 0x2A); }   // □ :Brown
  if (Ps3.data.button.triangle){ showMsgLed("triangle", 0xDE, 0xB8, 0x87); } // △ :BurlyWood
  if (Ps3.data.button.circle)  { showMsgLed("circle", 0x5F, 0x9E, 0xA0); }   // 〇 :CadetBlue

//  showAnalog();        // アナログスティックの表示
//  showAccelerometer(); // 加速度の表示

  delay(100);
}

// Serial文字列の送信とLEDの色を変更する関数
void showMsgLed(String s, uint8_t r, uint8_t g, uint8_t b) {
  M5.dis.setBrightness(LED_BRIGHTNESS); // LEDの光量(0-255)
  M5.dis.drawpix(0, getDispColor(r, g, b));
  Serial.println(s);
}

// FastLEDに設定する色を取得する関数
CRGB getDispColor(uint8_t r, uint8_t g, uint8_t b) {
  return (CRGB)((r << 16) | (g << 8) | b);
}

// アナログスティックの値を表示する関数
void showAnalog() {
  uint8_t lx, ly, rx, ry;

  lx = Ps3.data.analog.stick.lx;
  ly = Ps3.data.analog.stick.ly;
  rx = Ps3.data.analog.stick.rx;
  ry = Ps3.data.analog.stick.ry;

  // 値に変化があった場合に表示
  if ((b_lx != lx) || (b_ly != ly) || (b_rx != rx) || (b_ry != ry)) {
    Serial.print("LX=");
    Serial.print(lx);
    Serial.print(", LY=");
    Serial.print(ly);
    Serial.print(", RX=");
    Serial.print(rx);
    Serial.print(", RY=");
    Serial.println(ry);

    // 値を更新
    b_lx = lx;
    b_ly = ly;
    b_rx = rx;
    b_ry = ry;
  }
}


// 加速度を表示する関数
void showAccelerometer() {
  Serial.print("SX=");
  Serial.print(Ps3.data.sensor.accelerometer.x);
  Serial.print(", SY=");
  Serial.print(Ps3.data.sensor.accelerometer.y);
  Serial.print(", SZ=");
  Serial.println(Ps3.data.sensor.accelerometer.z); 
}

 上記スケッチをAtom Liteに書き込んだ後、Atom LiteのLEDが赤色に光ります。その状態でPS3の「PSボタン」を押してペアリングが成功するとAtom LiteのLEDが青色に変化します。

 その状態でPS3コントローラの各ボタンを押すとLEDの色が変化します(中には光の強度の関係で似たような色に見えるものもあります)。

 ちなみにArduino IDEのシリアルモニタを開いた状態で行うと、以下のようにどのボタンを押したかがわかるようにしています。

 またvoid loop( )関数でコメントアウトしているshowAnalog( )、showAccelerometer( )のコメントアウトを外すと、アナログスティックの値とコントローラの加速度の値もシリアルモニタに表示できます。


 以上がAtom LiteでPS3コントローラの値を取得する方法になります。

 参考資料にあるページ様のソースコードを参考にしつつやりましたが、割と簡単にPS3コントローラとのBluetooth通信ができることがわかってよかったです。

 今回はAtom LiteとPS3コントローラでやりましたが、ライブラリ的にはesp32となっているため、他のesp32系のマイコンボードでも同じように通信できると思います(未確認)。

 また検証していませんが、以下のようにPS4コントローラ用ライブラリを公開している方もいるので、PS4コントローラでも同じようなことができるようです。

 ゲーム機のコントローラをesp32で扱えるということは、簡単なラジコンみたいなものも作れそうなので楽しみが広がりますね。


・参考資料