ESP32を使って、PS4コントローラとBluetooth接続する:ライブラリ修正編 その1

はじめに

 以前の記事で、ESP32とPS4コントローラのBluetooth接続をしました。コンパイルエラーが多発して結構苦労しました。

 ライブラリに問題があって、そのままだとコンパイルエラーが出てしまうので、海外の方の動画を参考にライブラリに手を加えてエラーを回避していました。GitHub上では、エラーの修正を求めるリクエストがされていますが、一年ほど更新されていません。

 そこで、今回はオリジナルのリポジトリからフォークして、ライブラリに修正を加えました。初GitHubです。このライブラリなら以前のように手を加えなくても使えると思います。新たなエラーが出てくるかもしれませんが…

▼修正を加えたライブラリ

 https://github.com/404background/PS4-esp32

▼以前の記事はこちら

ESP32を使って、PS4コントローラとBluetooth接続する

はじめに  今回はESP32を使って、PS4のコントローラとのBluetooth接続をしました。ロボコンで使っているところを見たことがあります。最近はSwitchのコントローラで操作…

▼PS4のコントローラは、純正品を使っています。

▼秋月電子通商で買ったESP32はこちら

ESP32-DevKitC-VE ESP32-WROVER-E開発ボード 8MB: マイコン関連 秋月電子通商-電子部品・ネット通販 (akizukidenshi.com)

▼Amazonでも販売されています。

すでにインクルードしたライブラリを削除する

 PS4-esp32-masterのライブラリをまだインクルードしたことがない方は大丈夫なのですが、すでにインクルードした方で新しくライブラリをインクルードしたい場合は、既存のものを削除する必要があります。

 環境によってはファイルの場所が違う可能性がありますが、標準ではPC→ユーザー→ユーザー名→ドキュメント→Arduino→librariesPS4-esp32-masterが入っていると思います。これを消去すれば削除できます。

▼Arduino IDEの環境設定の画面。コンパイル時の警告表示を多くしておくと、どこのファイルを参照しているのかなどが表示されるので、デバッグに便利です。

修正箇所一つ目

 前回の記事に載せていた、海外の方のコンパイルエラーを回避する方法をもとに、修正を加えました。ps4_spp.cファイルの修正です。

※Arduino IDEのボードマネージャーにおける、ESP32のバージョンによってはエラーがでる可能性があります。現在調査中です。動作を確認しているのはバージョン1.0.6です。

▼こちらの動画でコンパイルエラーを回避する方法が紹介されています。

 https://youtu.be/dRysvxQfVDw?t=114

▼エラーの一部を引用するとこんな感じです。esp_bt_gap関連のものでエラーが出ます。


PS4-esp32-master\src\ps4_spp.c:87:30: error: 'ESP_BT_CONNECTABLE' undeclared (first use in this function)
     esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);

▼ps4_spp.cの86~90行目です。ここを修正しました。


#if CONFIG_IDF_COMPATIBILITY >= IDF_COMPATIBILITY_MASTER_D9CE0BB
   esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
#elif CONFIG_IDF_COMPATIBILITY >= IDF_COMPATIBILITY_MASTER_21AF1D7
   esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE);
#endif

▼修正したものがこちら


//#if CONFIG_IDF_COMPATIBILITY >= IDF_COMPATIBILITY_MASTER_D9CE0BB
//   esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
//#elif CONFIG_IDF_COMPATIBILITY >= IDF_COMPATIBILITY_MASTER_21AF1D7                
   esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE); 
//#endif

修正箇所二つ目

 二つ目は、過去に使われていたPS4コントローラのプログラムをダウンロードして、コンパイルしたときに出たエラーです。これまで出ていなかったエラーなのですが、急に出てきました。うまくすり抜けていたのかもしれません。

▼エラーを抜粋したものがこちら


PS4Controller.cpp:47:61: error: format '%x' expects argument of type 'unsigned int*', but argument 3 has type 'uint8_t*  {aka unsigned char*}' [-Werror=format=]
   if (sscanf(mac, ESP_BD_ADDR_STR, ESP_BD_ADDR_HEX_PTR(addr)) != ESP_BD_ADDR_LEN) {

▼PS4Controller.cppファイルのフォーマットにエラーがあるとのことなのですが、GitHubのIssuesでも同じような指摘がされていました。

error: format '%x' expects argument of type 'unsigned int*', but argument has type 'uint8_t* · Issue #10 · aed3/PS4-esp32 · GitHub

 指摘していた方は、このライブラリのベースとなっているesp32-ps3からコードをコピーしてきたと言っています。

▼その一部がこちら


if (sscanf(mac, ESP_BD_ADDR_HEX_STR, ESP_BD_ADDR_HEX_PTR(addr)) != ESP_BD_ADDR_LEN){ log_e("Could not convert %s\n to a MAC address", mac); return false; }

 エラー部分と比較すると、ESP_BD_ADDR_STRではなくESP_BD_ADDR_HEX_STRになっています。つまりここが16進数でないため問題がおきているのではないかと考えて、ESP_BD_ADDR_HEX_STRに変更して、以下の定義を追加しています。これでうまくいきました。

▼PS4Controller.cppに追加した定義


#define ESP_BD_ADDR_HEX_STR "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"

サンプルの追加

 エラーの修正に加えて、使いやすいサンプルを追加しました。

  • GetBluetoothMacAddress

 ESP32のMACアドレスを取得するためのプログラムです。プログラムを書き込んで、シリアルモニターで見ることができます。

 ▼オリジナルはこちら

  https://github.com/un0038998/PS4Controller_ESP32

  • bt_remove_paired_devices

 ESP32のサンプルスケッチとしてArduino IDEに追加されるプログラムです。前回の記事にも寄せられていたのですが、ESP32とPS4コントローラを複数個接続すると、プログラムの書き込みはできるものの接続できないことがあります

 PS4コントローラは接続中にライトが点滅して、接続できたらライトがついたままになるのですが、一瞬接続できたのに切れるという症状がみられました。

 同じような状況になったら、このプログラムで登録しているデバイスを削除してみてください。

▼18行目のREMOVE_BONDED_DEVICESの値を0から1に変更すると削除できます。

//This example code is in the Public Domain (or CC0 licensed, at your option.)
//By Victor Tchistiak - 2019
//
//This example demonstrates reading and removing paired devices stored on the ESP32 flash memory
//Sometimes you may find your ESP32 device could not connect to the remote device despite
//many successful connections earlier. This is most likely a result of client replacing your paired
//device info with new one from other device. The BT clients store connection info for paired devices,
//but it is limited to a few devices only. When new device pairs and number of stored devices is exceeded,
//one of the previously paired devices would be replaced with new one.
//The only remedy is to delete this saved bound device from your device flash memory
//and pair with the other device again.
//
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include"esp_gap_bt_api.h"
#include "esp_err.h"

#define REMOVE_BONDED_DEVICES 0   // <- Set to 0 to view all bonded devices addresses, set to 1 to remove

#define PAIR_MAX_DEVICES 20
uint8_t pairedDeviceBtAddr[PAIR_MAX_DEVICES][6];
char bda_str[18];

bool initBluetooth()
{
  if(!btStart()) {
    Serial.println("Failed to initialize controller");
    return false;
  }
 
  if(esp_bluedroid_init() != ESP_OK) {
    Serial.println("Failed to initialize bluedroid");
    return false;
  }
 
  if(esp_bluedroid_enable() != ESP_OK) {
    Serial.println("Failed to enable bluedroid");
    return false;
  }
  return true;
}

char *bda2str(const uint8_t* bda, char *str, size_t size)
{
  if (bda == NULL || str == NULL || size < 18) {
    return NULL;
  }
  sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
          bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
  return str;
}
 
void setup() {
  Serial.begin(115200);
 
  initBluetooth();
  Serial.print("ESP32 bluetooth address: "); Serial.println(bda2str(esp_bt_dev_get_address(), bda_str, 18));
  // Get the numbers of bonded/paired devices in the BT module
  int count = esp_bt_gap_get_bond_device_num();
  if(!count) {
    Serial.println("No bonded device found.");
  } else {
    Serial.print("Bonded device count: "); Serial.println(count);
    if(PAIR_MAX_DEVICES < count) {
      count = PAIR_MAX_DEVICES; 
      Serial.print("Reset bonded device count: "); Serial.println(count);
    }
    esp_err_t tError =  esp_bt_gap_get_bond_device_list(&count, pairedDeviceBtAddr);
    if(ESP_OK == tError) {
      for(int i = 0; i < count; i++) {
        Serial.print("Found bonded device # "); Serial.print(i); Serial.print(" -> ");
        Serial.println(bda2str(pairedDeviceBtAddr[i], bda_str, 18));     
        if(REMOVE_BONDED_DEVICES) {
          esp_err_t tError = esp_bt_gap_remove_bond_device(pairedDeviceBtAddr[i]);
          if(ESP_OK == tError) {
            Serial.print("Removed bonded device # "); 
          } else {
            Serial.print("Failed to remove bonded device # ");
          }
          Serial.println(i);
        }
      }        
    }
  }
}
 
void loop() {}

最後に

 今回はこれまで使っていたPS4-esp32ライブラリの修正をしましたが、知らないだけでそもそも問題ないライブラリが既に存在しているんじゃないかなと思っています。オリジナルのライブラリはフォークしているリポジトリが現時点で66個もあって、その中にあるかもしれません。

 また、今回修正したライブラリでエラーが起きたようであれば、GitHubでもコメント欄でもいいので、報告していただけると助かります。GitHubを使うのは今回が初めてなので、対応が遅れるかもしれませんが、慣れていこうと思います。

 接続できたという報告でもありがたいです。よろしくお願いします。

 

ESP32を使って、PS4コントローラとBluetooth接続する:ライブラリ修正編 その1” に対して4件のコメントがあります。

  1. 赤羽 より:

    お世話になっています。また、掲載記事大変参考にさせていただいております。
    早速で恐縮ですが、

    bt_remove_paired_devices
    …ESP32とPS4コントローラを複数個接続すると、プログラムの書き込みはできるものの接続できないことがあります。

    →この症状と思われる不具合が解決できません。

    18行目のREMOVE_BONDED_DEVICES

    とありますが、見当たりません
    お手数ですが、もう少し詳細にご教示いただけると助かります。

    お力添えくださいますようお願い申し上げます

    1. 管理人 より:

      コメントありがとうございます。
      bt_remove_paired_devices.inoのコード全文を掲載しておきました。
      私のライブラリをインストールするとArduino IDEのExamplesに追加されるサンプルコードです。GitHubのリポジトリにもあります。
      https://github.com/404background/PS4-esp32/tree/master/examples/bt_remove_paired_devices

      18行目でREMOVE_BONDED_DEVICESが0として定義されています。
      同じ行でコメントアウトされている部分に書かれているのですが、0の場合は登録されたデバイスが表示され、1にすると削除することができます。

      REMOVE_BONDED_DEVICESを1にして実行後、再度接続するための手順を試してみてください。
      接続に関する問題は以前の記事にも寄せられておりますので、ご確認いただけますと幸いです。
      意外と見落としがちなのですが、PS4のコントローラの充電不足ですぐに接続が切れたりします。
      https://404background.com/program/esp32-dualshock4/

  2. より:

    上記のサンプルコードで削除できました。

    スケッチ例 > BluetoothSerial > bt_remove_paired_devices.ino
    とは別物のようでした。

    早々のご対応、感謝いたします。
    ありがとうございました。

    1. 管理人 より:

      確かに、スケッチ例のサンプルだと行数が変わっていますね。
      アップデート等で変更されたのかもしれません。

      こちらこそご確認ありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です