ESP32において、BLEを使って特定のキャラクタリスティックにSSIDとパスワードを書き込むことで、Wi-Fi設定が簡単にできました。
Bluetooth Classic(Bluetoothシリアル)とWi-Fiを同時に使うと、どちらを先に begin()
しても同時に有効になった時点でBluetoothがしにます。
(2020年7月末・Arduino core for the ESP32 development v1.0.4時点)
と書いておきながら、よっぽど自力で実装してみたいというわけでなければ "ESP32 Smart Config" の利用をおすすめします。
前提条件
同上に加え "ESP32 Sketch Data Upload" が利用できること
www.mgo-tec.comBLEの基礎知識(サービス・キャラクタリスティックなどの理解)
わかりやすくて以下おすすめです。
jellyware.jpArduino core for the ESP32 を GitHubからインストールする
(訂)Bluetooth Classicを使う場合の話なので以下は必要ないです(いちおう残しておく)
通常、Arduino IDE のボードマネージャからESP32開発用の環境を用意することが多いですが、現時点(2020年7月)ではボードマネージャ経由のビルドではonData
などのコールバック関数を利用することができません。
そのためgitから直接Developmentビルドを持ってきて利用します。
以下の "Using Arduino IDE with the development repository" 項目から自分の環境(OS)に合った方法で「Arduino core for the ESP32」をインストールしてください。
サンプルコード
自作の Store
クラスを使い、SPIFFS上で設定を読み書きできるようにしているところが基本です。
BLEのキャラクタリスティックにアクセスされたときのコールバックを使い、設定値の読み取りや書き込みを行っています。
スケッチ書き込みをする前に
ツール → "Partition Scheme" を "Huge APP (3MB No OTA/1MB SPIFFS)" に設定してください。
"ESP32 Sketch Data Upload" を実行して、SPIFFSを初期化してください。
ダイアログが出ますがそのままOKをクリックします。
使い方
BLEのセントラル側となる端末が必要です。
最も手軽に使う具体例としては、スマホに「BLE Scanner」アプリをインストールして使うのがよいです。
アプリを起動したら、それっぽい端末が表示されるので接続します。
カスタムサービスを開くと、Wi-Fi接続状態確認(READ, NOTIFY)、SSID読み書き(READ)、パスワード書き込み(WRITE)の各キャラクタリスティックが表示されるので、画像手順通りに設定します。最終的に、状態確認のキャラクタリスティックを呼んだときにIPアドレスが表示されるようになっていれば接続成功です。
各キャラクタリスティックにはUUIDが割り振られていますが、これは独自の設定UIを持つBLEアプリを作ったときに「このUUIDを持つキャラクタリスティックはSSIDを書き込むところ」などのように認識して操作することができる「キー」となりうるものです。ここでは簡易的に使えればよいのでまだセントラルアプリ側は作りませんが、Web Bluetooth APIとかでそのうちさくっと作れればいいなと思っています。
なお、この上記のスクリーンショットを撮ったときにはM5Cameraを使っていたのですが、 "flash read err, 1000" というSPIFFSが利用できなくなるエラーで書き込みができなかったため、接続表示まで至っていません。(もちろん別のESP32でちゃんと使えることは確認しています)
ここから技術メモ
基本的にはWi-FiとBluetoothの同時使用はシビア
どうやら電波周りの回路が同じものを使っているため、プログラム的に重複するっぽいです。
arduino-esp32 で BLE 接続中に WiFi.begin() すると BLE が切断されるぽいんだけど、同時使用に制限あったっけ?
— こばさん (@wakwak_koba) July 16, 2019
混信防止で BLE を停止させたりとか??
ちなみにしばらくすると BLE 再接続する。
(再接続は私の Fork ライブラリ側で実現してる)
最初はBluetooth Classicによるシリアル通信で対話的にSSIDやパスワードを設定しようとしたんですが、試行錯誤ののちに冒頭の結論となり諦めました。
Bluetooth Classic では同時使用オプション SW_COEXIST_ENABLE
はあまり意味ないかも
SW_COEXIST_ENABLE
というコンパイルオプションを変更したらなんかよさそうかも? な情報がありました。
このオプションが設定できる実体は、Macの場合 ~/Documents/Arduino/hardware/espressif/esp32/tools/sdk/sdkconfig
であるようです。
見てみると、値はすでに y
となっており、有効フラグとなっています。WiFiとBluetoothを同時使用するときのマネジメントをソフトウェア制御優先で行う? ようですが、 n
にしても挙動はあまり変わらず、詳細不明でした。
Bluetoothライブラリだけで1MB近くプログラムメモリを消費するため、Partition Scheme(メモリマップ)を変更する必要がある
通常状態だとプログラムに1.2MB、SPIFFSに1.5MB、残りはOTA(ネットワーク経由でプログラム書き込み)、のようなメモリ割り当てになっています。
Bluetooth関係のヘッダファイルをインクルードするとコンパイル後に間違いなく1MB超えるので、OTAを無効にした以下のようなメモリ割り当てに変更しないと書き込みできません。
WiFi.status()
は WL_CONNECTED
かどうかだけ見ればよい
WiFi.status()
が返す値は8種類定義されています。
ただし、存在しないSSIDを指定しても WL_DISCONNECTED
になるなど、返却値に基づいたデバッグメッセージを表示してもあまり意味がありませんでした。
ユーザプログラム内でハンドリングしないが細かい状況が知りたい場合は、Core Debug Level: "Warn" 以上でコンパイル&書き込みしてシリアルモニタで確認すると良いと思います。
あまり関係ないハマりポイント:ボード選択でESP32が2つあった件
最初、BluetoothSerialの onData
が、ちゃんとライブラリのコード内に存在しているのに、何回コンパイルしても 'class BluetoothSerial' has no member named 'onData'
というエラーが出て困り果ててました。
試行錯誤したところ、最近のIDEのアップデートでいつのまにか新しくなっていたボード選択部分にESP32ファミリーを示す大分類が2種類あることに気付き、これを「(in sketchbook)」という表記のある中のESP32モジュールを選択してコンパイルを行ったらすんなりと成功しました。
ボードマネージャ経由のライブラリとGitHub直のライブラリで重複してるような気もしましたがそうでもなく……
この重複表記、ご存知の方いらっしゃったらぜひ教えてください。