TOPPERS BASE PLATFORMを改造してESP32をATコマンドで使ってみる


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を作って、関数名のプリフィックスtcpsocketconnectionesp_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