ESP32 で Arduino を利用して BLE のアドバタイジング・パケットの送受信を行う

Espressif ESP32 で BLE を central かつ peripheral として動作させることがかなり以前に試したときはうまくいかなかった。しかし、下記の記事を読むとできるようになっているとのことなので試みた。

BLE GATT_Server and GATT_Client at the same time possible?

より正確には、centralとしてadvertising packetを受信すると共に、peripheralとしてadvertising packetを送信するという単純なことだけである。接続をすることも受けることもしない。

PlatformIO IDE for Visual Studio Code で Framework にArduinoを利用し、一部にESP-IDFの関数を利用して開発したが、 advertising packetを受信するのがプログラムでスキャンしているときだけで良ければ一応動作することを確認した。ただし、今回のプログラムでは、常時BLEスキャンをするようにできていない。

常時(電波を発していない場合には可能な限り)BLEスキャンをしてadvertising packetを(できるだけ)収集できるように、Framework として全面的に ESP-IDF を使い、FreeRTOS の機能を使った場合の動作確認を今後行う必要がある。

ハードウェア

開発環境

ESP32 用開発のためには、PlatformIO IDE for VSCode でESP32のプログラム開発 の設定を参照のこと。

BLE の送受信を利用するためにはパーティションテーブルの設定をデフォルトから変更する必要がある。変更方法は、PlatformIO IDE for VSCode におけるESP32 Partition Tableの指定方法 を参照のこと。

プログラム

次のGitHubに備忘録としてPlatform IDE for VSCodeでの開発用ファイルを置いてある。

https://github.com/kunsen-an/BLE_scan_adv_wifi.git

プログラムの主な機能

  • 定期的に BLE  central として、アドバタイジングパケットとRSSIを収集する
  • 定期的に BLE  peripheral として、アドバタイジングパケットを送信する
  • 定期的に WiFi の SSID および RSSI を収集する
  • 収集した情報をAWS IoT に MQTT over Websocket で publish する

aws-mqtt-websocket.cpp

AWS IoT に MQTT over Websocket で送信するためのESP32用コード。

コードの内容については CO2センサーMH-z19の値をAWS IoTに送る を参照。

必要なライブラリなどについては、 AWS IoTにESP32からMQTT over WebSocketでつなぐ を参照。

BLEscan.cpp

次のコードを基にしている。

https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/Arduino/BLE_scan/BLE_scan.ino

setupBLEAdvertise() で BLE のアドバタイジングを開始する。

scanBLE() の中の pBLEScan->start(scanTime) の scanTimeで指定した時間、BLE の advertising packetをスキャンする。

main.cpp

BLEとWiFiの受信した信号の強度(RSSI)を、MQTT でAWS IoT に送るためのメインプログラム。

SSIDなどをそのまま送るとメッセージサイズが大きくなるので、SSIDを整数のIDに変換し、そのIDとSSIDの対応情報とIDとRSSIの配列をパブリッシュするようにしている。SSIDなどの文字列と整数値のID、RSSI値などの対応を管理するためにハッシュマップの構造を利用している。ハッシュマップの要素となる ID、RSSIなどの管理には unordered_map およびhashmap.h の構造を利用している。

MQTTのメッセージサイズを小さくするため、RSSI値は符号を反転して(マイナスの符号を取り除いて)メッセージに含めている。

hashmap.h

整数値のID、RSSI値などを管理するハッシュマップ( unordered_map )の要素の構造を定義している。

wifiManager.cpp

WiFiのSSIDやパスワードをコード内に埋め込むことなくスマホなどから設定可能にする WiFi manager を利用するためのコード。

以下の記事に使い方の例がある。

CO2センサーMH-z19の値をAWS IoTに送る

MH-ET LIVE MiniKit for ESP32 で電波時計の時刻を合わせる

wifiScan.cpp

WiFi のアクセスポイントの SSID をスキャンし、RSSI などの情報を収集する

ライブラリ

動作確認に利用したライブラリのバージョンおよび関係は以下の通り。

Dependency Graph
|-- <SPI> 1.0
|-- <ESP32 BLE Arduino> 0.4.16
|-- <DNSServer> 1.1.0
|   |-- <WiFi> 1.0
|-- <WifiManager> 1.0.0
|   |-- <ESPmDNS> 1.0
|   |   |-- <WiFi> 1.0
|   |-- <WebServer> 1.0
|   |   |-- <FS> 1.0
|   |   |-- <WiFi> 1.0
|   |-- <DNSServer> 1.1.0
|   |   |-- <WiFi> 1.0
|   |-- <WiFi> 1.0
|-- <ArduinoJson> 5.13.2
|-- <ArduinoLog> 1.0.2
|-- <mylan>
|-- <WebServer> 1.0
|   |-- <FS> 1.0
|   |-- <WiFi> 1.0
|-- <WiFi> 1.0
|-- <Paho> 1.0.0
|   |-- <SPI> 1.0
|   |-- <WiFi> 1.0
|-- <WebSockets> 2.1.0
|   |-- <SPI> 1.0
|   |-- <WiFiClientSecure> 1.0
|   |   |-- <WiFi> 1.0
|   |-- <WiFi> 1.0
|-- <aws-mqtt-websockets>
|   |-- <aws-sdk-arduino-ESP32>
|   |   |-- <WiFiClientSecure> 1.0
|   |   |   |-- <WiFi> 1.0
|   |   |-- <WiFi> 1.0
|   |-- <WebSockets> 2.1.0
|   |   |-- <SPI> 1.0
|   |   |-- <WiFiClientSecure> 1.0
|   |   |   |-- <WiFi> 1.0
|   |   |-- <WiFi> 1.0
|-- <PubSubClient> 2.6