Wi-Fi接続に対応したい
Azure IoTに接続するアプリを作ったのですが、有線LANで接続するものしかなかったのでWi-Fiでも接続したいと思い、手元にあったESP32を使用することにしました。
ESP32自体でもArduino IDEやIDFを使って単体でソフトを作ることができますが、TOPPERSのRTOSはESP32のCPU(Xtensa)には移植されていませんので、直接ESP32でTOPPERSを動作させることは現状出来ません。
そこで、ESP32のファームウェアとして提供されているATコマンドファームウェアを使い、外部CPUからのWi-Fi接続を実現することにしました。
TOPPERS BASE PLATFORM
TOPPERSプロジェクトでは、組込み技術者養成用の教育コンテンツを提供していて、そのコンテンツで使用するソフトウェアプラットフォームとして、TOPPERS BASE PLATFORMというのを提供しています。
そのTOPPERS BASE PLATFORMに含まれるサンプルアプリにEPSのATコマンドをシリアルコンソールを通して、手打ちで確認できるサンプルアプリがあります。
これを改造し簡単なATコマンドパーサーを追加し、Wi-Fi接続とTCPの接続が関数呼び出しで実現できるようにしました。
TOPPERS BASE PLATFORMは下記からダウンロードできます。
https://www.toppers.jp/edu-baseplatform.html
ESP-WROOM-02シールド向けサンプルアプリ
ESPのATコマンド手打ちアプリのパスは、上記のサイトからダウンロードしたasp_baseplatformv1.4.1_051120.tar.gz
では、NOCLEO-F401RE向けのサンプルアプリで、下記のフォルダにあります。
asp\OBJ\STM32F401NUCLEO_GCC\espshield
このフォルダにあるesptest.c
のヘッダーコメントに書いてありますが、ESP-WROOM-02シールド向けのコードになっているようです。
シリアルを接続するピンなどは、このシールドに合わせてあるようです。
余談ですが、TOPPERS BASE PLATFORMのリリースでは文字コードに「EUC-JP」が使われているので、「UTF-8」変換して使っています。
シリアルコンソール
TOPPERS BASE PLATFORMではシリアルコンソール(モニター)が実装されていて、このサンプルアプリでATコマンドを入力すると、ESP32へコマンドが転送され、応答が表示されます。
ESP32のATコマンドはここにあるように、AT+GMR
のように入力し、改行コードもCRLF
を使用しますが、シリアルコンソール経由では、下記のように入力し、形式が違っているので注意が必要です。改行コードもLF
のままです。
mon> AT GMR
AT+GMR
ver ...
初めのAT
+スペースまでが、シリアルコンソールのコマンドで、引数としてGMR
を渡しています。ESP32にはAT+GMR
が渡されるようになっています。
ESP32のATコマンドを試してみるには便利ですが、通信ソフトを組み込みたいときには機能が足りません。
ATコマンドパーサーの追加
TOPPERS BASE PLATFORMのサンプルアプリでは、ATコマンドの仲介をするだけのコードしかないので、ATコマンドの応答を読み取り、Wi-Fiの接続状態やTCPの接続状態を遷移させるような処理を実装を追加しました。
ESP32と接続したシリアルからの入力を処理するメインタスクと、入力コマンドを処理するモニタタスクの2つがあり、リングバッファを介して繋がっています。
この改造では、ESP32からのシリアル入力をユーザーへの表示ではなくATコマンドの解析処理をするコマンドパーサーに渡して、応答を処理します。
一方ユーザーからのコマンド入力で、Wi-Fi接続やTCP接続を行うので、ATコマンドを発行する側はモニタタスクになります。
ATコマンド発行を含むコマンドは、以下のようなコマンドがあります。
mon> device wifi ssid password
mon> device csgen mqtt scopeid deviceid key
mon> device setcs connection_string
mon> device iot
2つのタスク間のデータのやり取りにはタスク間通信が必要で、データはリングバッファで、通知はデータキューを使っています。
改造部分を含むソースコードは下記のサイトにあります。
https://dev.toppers.jp/trac_user/contrib/wiki/azure_iot_hub_riscv
ATコマンドパーサーとAzure IoT SDK for Cを繋ぐ
ATコマンドを使ったTCP接続を行うアプリとして、Azure IoT接続サンプルアプリを使います。
ATコマンドパーサーは自前で作ったものなので、Azure IoT SDK for C には繋がるコードはありません。
GR-LYCHEEというmbed対応基板のもESP32が付いていて、それを使った経験から、mbed向けのコードから改造することにしました。
TCP接続の実装部分のファイルsocketio_mbed_os5.c
を元に、socketio_esp_at.c
を作って、関数名のプリフィックスtcpsocketconnection
をesp_at_socket
にリネーム、このファイルから呼ばれる下記の関数をATコマンドパーサーのファイルesp_at_socket.c
に実装しました。
関数名 | 実装内容 |
---|---|
esp_at_socket_create |
TCP接続用の領域確保 |
esp_at_socket_destroy |
TCP接続用の領域解放 |
esp_at_socket_connect |
AT+CIPSTART コマンド発行し、応答があるまで待機 |
esp_at_socket_close |
AT+CIPCLOSE コマンド発行、応答があるまで待機 |
esp_at_socket_set_blocking |
設定を保存 |
esp_at_socket_receive |
バッファにデータがある場合は読み込む、バッファにはESPからのシリアル受信時にデータが入る |
esp_at_socket_send |
AT+CIPSEND コマンド発行、応答があるまで待機 |
詳しくはAzure IoT SDK for Cのポーティングガイドを見てください。
https://github.com/Azure/azure-c-shared-utility/blob/master/devdoc/porting_guide.md
SSL/TLS
クラウドサービスにはSSL/TLSも必要です。ESP32のATコマンドでもSSL/TLS接続ができますが、ESP32と本体側CPUとはシリアルで通信しているので、簡単に読み取られてしまいます。
セキュリティを考えて本体側CPUにSSL/TLS通信部分をを実装し、それにwolfSSLを使っています。Azure IoT SDK for Cにも対応するコードが入っているのですぐに使えます。また、セキュリティ意識の高いAzure Sphereでも使われているので、安心かと思います。クローズドソースの商用向けには有償なようですが、GPLを組み込んでもいい公開用のサンプルアプリなら問題ないです。
動作確認したデバイス
実際にESP32とシリアル接続したデバイスは、STマイクロの「NUCLEO F401RE」と「NUCLEO F767ZI」、Sipeed社のRISC-Vボード「Maix Bit」です。
ESP32のピン
NUCLEO F401RE
- GND ⇔ GND
- D8 ⇔ U2 RXD
- D2 ⇔ U2 TXD
NUCLEO F767ZI
- GND ⇔ GND
- TX D1 ⇔ U2 RXD
- RX D0 ⇔ U2 TXD
Maix Bit
- GND ⇔ GND
- 6 ⇔ U2 RXD
- 7 ⇔ U2 TXD
その他
また、Azure IoT Centralに接続するまでの動画もありますので、参考になればうれしいです。
https://www.youtube.com/watch?v=EAdgV0TPsZY