ESP32でNucleo(STM32)を簡単にWiFi対応に
無線モジュールESP32(ESP32-WROOM-32)を使用してSTM32をWiFi対応にする方法を解説します。大人気のESP32モジュールですが、ESP32自体をマイコンとして操作する解説が多く他のマイコンを簡単にWiFi化する情報が少ない状況で比較的簡単にシリアル通信のATコマンドによるリモート操作を実現してみました。
目次
無線モジュールESP32
組み込みシステムをIoT化するのにまず思い浮かべるものが無線モジュールを使ったWiFi化です。さまざまな無線モジュールがあるなかで、シリアル通信を介してWiFiが使用できるものとして電子工作でよく使われるESP32-WROOM-32をSTM32マイコンに組み込んでWiFi化することにします。
ESP32はWiFiやBluetoothに対応した無線モジュールですがそれ自体が高性能のマイコンで、電子工作で人気があるArduinoの開発環境を使ってプログラミングできるものです。ここではArduinoには関与せず、無線化モジュールとして扱うことにします。
無線モジュールESP32を使用してNucleoボード(STM32マイコン)をWiFiのIoT対応にする方法を解説します。大人気のESP32モジュール(ESP32-WROOM-32)ですが、ESP32自体をArduino開発環境でマイコンとして操作する解説が多く他のマイコンシステムを簡単にWiFi化する情報が少ない状況で比較的簡単にSTM32のWiFi化を実現して端的にまとめてみました。
いろいろ調べた結果、無線化モジュールとして使用する場合はシリアルUART通信で「ATコマンド」を送ってモジュールのモード設定したり、データを取得すればよいことがわかりました。ESP32は購入した直後にはこのATコマンドを使用することはできず、ファームウェア(ATコマンド用)を書き込む必要があります。
このファームウェアをPCからシリアルUART通信でモジュールに書き込むのですが、始めて扱う場合はUSBシリアル変換モジュールが搭載されたESP32-DevKitCを使うことをおすすめします。このボードではマイクロUSBポートから電源が供給でき、USBバスパワー5VをESP32用供給電源3.3Vに変換するレギュレータも搭載されているので気軽に使えて便利です。
ATコマンド用ファームウェア
ATコマンドを使用すればシリアルUART通信でPCやマイコンからESP32をコントロールしてWiFi通信できることがわかりました。ESP32モジュールでATコマンドを使うことができるようにするために以下の手順によってATコマンド対応にします。
- ATコマンド用ファームウェアをダウンロード
- ファームウェアをフラッシュ書き込みツールで書き込み(マイクロUSB UART0ポート)
- PCのターミナルソフトでATコマンドの動作確認(USB-UART変換ケーブル UART2ポート)
ATコマンド用ファームウェアのダウンロードからATコマンドの動作確認までの手順詳細の解説につきましては当サイトの趣旨からそれますので割愛します。インターネットで「ESP32 ATコマンド」などの検索で十分な情報が得られますので参考して実施してください。
ESP32-DevKitCではPCのUSBポートとシリアルUART通信でデータ通信を行うためにESP32-DevKitC内部のシリアル変換ICを利用します。このICはSILICON LAB社の「CP2102」が実装されていますので制御するためのドライバが必要です。はじめてESP32-DevKitCとPCをUSBケーブルで接続したときにUSBポートが認識されない場合はこちらでOSにあった「Download for xxxx」の欄から「VCPダウンロード」を選択しダウンロードおよびインストールをしておいて下さい。
ESP32には他にUART1(ピン/ソケットSD2 RX /SD3 TX)があるのですが、デフォルトではこれらの端子にSPI通信が割与えられているので使用しません。
ESP32-WROOM-32のUART通信のデフォルト設定
ファームウェア転送用 USART0:RXD0 RX/TXD0 TX
ATコマンド用 USART2:IO16 RX/IO17 TX
Baud rate:115200bps / Data siza:8/ Parity:None/ Stop bits:1
ATコマンド用ファームウェアを転送するとPCからATコマンドでESP32と通信できるようになります。注意点は、ESP32のUART0はファームウェア転送など書き込み用でATコマンドの送受信はできないことです。ATコマンドはUART2にUSB-UART変換ケーブルを介してやり取りします。
PCターミナルは慣れたものを使ってもらってよいのですが、このサイトでは「TeraTerm」を使っています。シリアル通信の設定をEPS32のでデフォルト(Baud rate:115200bps / Data siza:8/ Parity:None/ Stop bits:1)に設定し、「設定」-「端末」での改行コードの送信はCR+LFとしてリターンキーを打つとコードCRとLFが送信されるようにしてください。また、ローカルエコーにチェックを入れると打ち込んだ文字が返されるので気になる人はチェックを外してください。
PCのシリアル通信設定を行ったターミナルソフトでコマンド"AT"を送ったときに"OK"の応答が得られれば成功です。
ESP32のシリアルUART通信をデフォルト値から変更することができます。コマンドAT+UART_CUR?で現在の通信設定が応答されます。変更するには例えばコマンドAT+UART_DEF=9600,8,1,0,0のようにパラメータを与えます。詳細は英文ですがESP32のATコマンド取説(ESP32 AT Instruction Set)に記載しています。
注意:誤った数値を設定すると以後通信できなくなる恐れがありますので気をつけてください。
STA(ステーション)モード
まず、事始めにESP32をSTA(ステーション)モードとしてWiFiに設定することにします。STA(ステーション)モードは無線ルーター(DHCPサーバー)からIPアドレスを割り当てられた端末として機能させるモードです。ここでは192.168.3.19のIPのアドレスが与えられたものとしています。
PCでターミナルソフトを起動させてください。USBシリアル変換ケーブルをPCに接続していると仮想シリアルポート(下記の場合はCOM4)が認識されてますので選択します。
ファームウェアを書き込んだときに使用したESP32-DevKitCに搭載のUSBのポートではありません。
これからターミナルから主要なATコマンドをESP32に送り込んでモードを書き込んだり、応答を確認したりします。まず、コマンドAT+GMRを送ってみてください。ESP32のATファームウェアバージョンが応答されます。
次にESP32をSTAモードにするためにコマンドAT+CWMODE=1を送ります。”1”がSTAモードです。
ESP32がSTA(ステーション)モードになったのでネットワークに参加するためにコマンドAT+CWJAP="SSID","PASSWORD"を送信してください。SSIDとPASSWORDは使用している無線ルーターに合わせてSSID名と暗号キーを入力してください。
”WIFI CONNECTED"の応答があったら、無線ルーターにつながりました(LANに参加)。割り振られたアドレス状況を確認するために、コマンドAT+CIFSRを送信するとIPアドレスとMACアドレスが応答されます。
ここでPCのコマンドプロンプトで割り当てられたIPアドレスが有効であることをpingコマンドを実行して接続確認をしてみます。コマンドプロンプトはWindowsのスタートメニューの「Windows システムツール」内の「コマンドプロンプト」を選択するかメニュー検索でcmd.exeと入力すると表示されます。
pingコマンドのあとに割り振られたIPアドレスを"ping 192.168.3.19"のように入力して、アドレスが有効でネットワークに接続できると下記のような応答が返ってきます。これはルーター経由でPCとESP32が接続していることを意味しています。このようにネットワークに接続が開通している状態を「pingが通る」といいます。コマンドpingは機器の接続状況を確認するのによく使われます。
STAモード設定まとめ
- コマンドAT+CWMODE=1でSTAモードに設定
- コマンドAT+CWJAP="SSID","PASSWORD"でWiFi設定
AP(アクセスポイント)モード
STAモードでは家庭などにある無線ルーターをアクセスポイントしたネットワークに端末として参加するモードでした。今度はESP32自体がアクセスポイントとなるAP(アクセスポイント)モードの設定をしてみましょう。
このモードでは家庭や職場などのWiFiが使えない状況でもESP32自体がアクセスポイントのマスターとして他のクラアントネットワーク機器にIPアドレスを割り振るDHCPサーバーの役割をしています。
STAモード設定と同様にPCでターミナルソフトを起動させてから、まず現在のモードの確認をするためにコマンドAT+CWMODE?を送ります。応答が"1"であったらSTAモード、"2"であったらAPモードです。(確認だけのコマンド)
ESP32をAPモードにするためにはコマンドAT+CWMODE=2を送ります。”2”がAPモードでESP32ではsoftAPモードと読んでいます。
APモードのアクセスポイントSSID名および暗号キー等(任意)を設定します。コマンドAT+CWSAP="ESP32","12345678",5,3は順にSSID名、暗号キー、無線LANチャネルそして暗号種別です。
最後の暗号種別は3はWPA2_PSKです。他、0:open/1:WPA_PSK/4:WPA_WPA2_PSKです。
暗号キーは暗号種別のルールに従ってください。WPA2_PSK指定時に暗号キーが8文字未満であるとエラーになります。
割り振られたアドレス状況を確認するために、コマンドAT+CIFSRを送信するとIPアドレスとMACアドレスが応答されますのでネットワークIDとしてのIPアドレスが確認できます。
これまでの設定で新しいESP32によるWiFiアクセスポイント(SSID:ESP32)が作成できましたので、PCを"ESP32"に接続しましょう。作成した暗号キーを入力すれば接続できるはずですが、失敗するようでしたら一旦 アクセスポイント"ESP32"を削除して、もう一度試してください。
WiFiアクセスポイントESP32に接続できましたら、コマンドプロンプトでpingが通っているかを確認してみましょう。下記の応答が返ってきたら接続は成功です。
WiFiアクセスポイントESP32からPCへ割り振られたIPアドレスを確認するためにはコマンドプロンプトでコマンドipconfigを実行してください。下記のように自分のIPアドレス情報が返ってきます。ESP32がDHCPサーバーとしてクライアントであるPCへIPアドレスを割り振ったことがわかります。
AP(アクセスポイント)モード設定まとめ
- コマンドAT+CWMODE=2でAPモードに設定
- コマンドAT+CWSAP="ESP32","12345678",5,3でWiFi設定
TCPサーバーにしたESP32とPCとの通信
これまではESP32をSTAモードもしくはAPモードに設定してクライアントあるいはサーバーとして立場の同じLAN(デフォルトゲートウェイが同じ)で他の機器(PCなど)と通信できる無線LAN環境を構成してきました。
この状態ではpingが通って互いに同じネットワーク上にあることが確認できただけでまだ互いにLAN内の通信はできません。ESP32の通信をするためには通信をする上でのサーバーとクライアントの関係を構築する必要があります。
ここではEPS32をTCPサーバーとして構成し、同じLAN内のPCやスマホをクライアントとしてターミナルソフトから無線でアクセスするシステムを作り、LANで基本であるTCP通信をするための設定を解説していきます。
TCP通信ができるようになると、例えば、PCのターミナルソフトでIPアドレスととポートを指定するとシリアル通信のように文字列のやり取りができるようになります。
システムの構成はこれまでと基本的には同じなのですが、ATコマンドをシリアル通信でESP32とやり取りするPCとLAN内のネットワーククライアントとしたPCとは明示的にわけています。実際は共用してもかまいません。
TCPサーバー設定
TCPサーバーに設定する場合ははじめに複数のコネクションに対応できるモード(マルチコネクションモード)に設定します。コマンドAT+CIPMUX=1の"1":マルチコネクション、"0":シングルコネクションモード。ESP32はデフォルトがシングルコネクションモードですのでこのコマンドを必ず実行します。
コマンドAT+CIPSERVER=1,50000でTCPサーバーを生成します。1つ目の値が"1"でサーバー生成、"0"でサーバー削除です。2つ目の値はTCPサーバーのポート番号です。「OK」の応答でTCPサーバーは起動しました。クライアント側の接続待ち状態になります。
PC等のクライアント側でターミナルソフトを起動して、ホスト(TCPサーバーのIPアドレスとポート番号を指定してサーバー側に接続します。
ターミナル上部にTCPサーバー側のIPアドレスが表示されますと接続成功です。
さっそくターミナルからTCPサーバー側へ文字列を送信してみましょう。”depfields”の9文字を入力してEnterキーを押すと、改行コードを含めて11文字を送信したことになります。この例ではターミナルをローカルエコーに設定していますので入力した文字が現れています。
TCPサーバー側ではクライアント側からの文字を受信すると"+IPD,0,11:depfields"と表示されます。+IPDは受信データであることを示し、コネクションIDが0に文字列と改行コードを含んだ合計11文字を受信したことを意味しています。
つぎにTCPサーバー側のATコマンド操作ターミナルから文字列を送信してみます。AT+CIPSEND=0,11はコネクションIDが0のリンクに対して11文字を送信するコマンドです。改行コード2文字を含んだ9文字のデータを送る場合のものです。コマンドが受理されると”OK”が返されて、>のプロンプトが表示されて入力待ちになっています。
送信する文字は大文字で"DEPFIELDS"としてリターンを押すと文字列はターミナル側へ送信されます。改行コードあわせて11文字です。Recv 11bytesと表示されたあとにSEND OKの応答があれば送信成功です。
クライアント側のターミナルでは送られた文字列"DEPFIELDS"が表示されているはずです。
TCPサーバー設定まとめ
- コマンドAT+CIPMUX=1でマルチコネクション設定とする
(TCPサーバーの場合はマルチコネクションであること) - コマンドAT+CIPSERVER=1,xxxxでTCPサーバー ポートxxxxを生成する
今回はESP32をPCからATコマンドで操作してTCPサーバーにしてからTCPクライアントのPCとの通信をおこないました。次はいよいよPCの代わりにマイコンがATコマンドを操作してESP32をTCPサーバーに設定してクライアントのPCやスマホから無線操作するシステムに挑戦します。
そのまえに、ESP32をTCPクライアントにする場合もありますので解説しておきます。クラウド上のサーバーにアクセスする場合などに使用します。
TCPクライアント設定
ESP32をTCPクライアントに設定することができます。通信プロトコルにおいてTCPソケット通信よりさらに上位のHTTPプロトコルを使用したHTTPサーバーにアクセスしてWEB上のブラウザから操作するアプリの場合はこちらを使います。
TCPクライアントに設定する場合は単一のコネクションに対応できるモード(シングルコネクションモード)に設定します。コマンドAT+CIPMUX=0の"0":マルチコネクション、"0":シングルコネクションモード。ESP32はデフォルトがシングルコネクションモードです。
コマンドAT+CIPSTART="TCP","xxx.xxx.xxx.xxx",80でTCPクライアントを生成します。1つ目がプロトコルを2つ目はWEB上のHTTPサーバアドレス、3つ目がそのポート番号です。「OK」の応答でTCPクライアントは起動しました。
シングルコネクションモードの場合は透過モードというものが使用でき、ATコマンドによらず通常のシリアル通信のようなやりとりができるようになります。これには"AT+CIPMODE=1"を実行しておきます。
以後、文字列送信のために"AT+CIPSEND"を送ると透過モードになるのでHTMLコードでWEBサーバとやり取りできるようになります。"+++"を受信すると透過モードは終了します。
TCPクライアント設定まとめ
- コマンドAT+CIPMUX=0でシングルコネクション設定とする
(TCPクライアントの場合はシングルコネクションであること) - コマンドAT+CIPSTART="TCP","xxx.xxx.xxx.xxx",80でTCPクライアントを生成する
- コマンドAT+CIPMODE=1で透過モード に設定する
マイコンとESP32との接続
ESP32にATコマンド用ファームウェアを転送してPCとATコマンドで通信できるようになった段階で、今度はPCの代わりにマイコンとの通信に挑戦です。
PCのターミナルからではATコマンドを送ってESP32との通信はできるようになりましたが、他の実行環境であるマイコンからATコマンドをやりとりして、例えばターミナルのTCP通信ポートを開くところまではどうすればよいのでしょうか。
これもわかってしまえば簡単ですが、種を明かせばPCのターミナルで行っているのと同じようにATコマンドそのものを文字列としてシリアル通信で送受信させればよいだけのことです。
ここではATコマンドのうちで主要なものを一部を取り上げて通信ポートを開いてデータのやりとりができるところまでを解説します。
マイコンプログラムによるTCPサーバー開通までの手順
ESP32をATコマンドでSTAモードかAPモードに設定して無線LAN環境のpingを通すまでは運転モードの設定がフラッシュに書き込まれますのでどの環境でも共通です。
マイコンを使った場合はコネクションモードの設定からマイコンのプログラムで自動化するイメージです。
マイコンでESP32をATコマンドでTCPサーバーに設定してから無限ループ内でデータを一秒ごとに端末に送って表示させるサンプルです。
PCでシリアル通信のターミナルソフトから設定するのと基本的には同じなのですが、マイコンプログラムでATコマンド操作を自動化するには注意すべきポイントがあります。
ターミナルから手動でATコマンドを実行させると正常に動作するのに同じ手順をマイコンプログラムで行うと問題が起こる場合があります。
これはコマンド実行のための十分な応答の時間等がないために正常に動作できないでいることが原因であると考えられます。特に、プログラム起動後にはじめに実行したATコマンド転送で文字化けしていた問題があり、以降のコマンドが有効にならなかったことがありました。
これを防ぐためにATコマンドの前後で十分に待ち時間を入れさらに念の為にはじめのコマンドに限ってフェールセーフのために2度実行し確実に問題を回避すると正常に動作するようになりました。
初めてATコマンドをマイコンプログラムで実行する場合にはまず、TCPサーバーが確実に起動し、ターミナルプログラムでアクセスしたいIPアドレスとポートを指定してTCP通信が開通するまでを目指してください。
アプリ内での文字列送信のポイント
TCPサーバーにアクセスできポートが開通したらとりあえず一つの関門突破です。次は、アプリケーション内での文字列のやり取りです。
文字列を送信するには直前にコマンドAT+CIPSEND=0,5を改行コード\r\nを付加して実行するといわゆる送信待機状態になります。そこで送りたい文字列を文字列送信関数(ここではUASART3_SendString関数)を実行させて送信実行します。
シリアル通信のように送信したい文字列を送ってターミナルに表示させる簡単なことだけでもツボを押さえていなければなかなか安定して実現できません。筆者の経験では初めて文字列送信を扱ってシリアル通信のばあいと同様な結果を得るまでまる一日以上試行錯誤しました。
文字列の送信を安定させるためのツボはわかってしまえば何でもないことですが、不安定であった原因は送信文字列の文字数が一定でなかったことです。アプリケーション内で演算した変動する数値を文字列に変換してからターミナルへの送信であったため、桁数が不安定であったことが原因です。
マイコンプログラムでなくPCのシリアル通信のターミナルソフトから手動で文字数がずれた場合のコマンドを送ってみてください。表示はかなり不安定となるのが確認できます。
問題解決のために、数値の桁数に関わらず例えば最大3桁の数字を送りたい場合に文字変換して3文字に固定する関数(digit_conv関数)を自作してからは安定した表示ができるようになりました。
文字列送信のポイント
- 文字列送信直前に文字数を指定したコマンドAT+CIPSEND=0,xを実行しておく。
- 文字列送信関数(ここではUSART3_Send_String関数)で実際に送信する文字数と厳密に一致させること。
アプリ内での文字列受信のポイント
PC、スマホなどのターミナルソフトから文字列を受信してコマンドやデータとして扱うことで、マイコンをリモートコントロールできるようになります。
ターミナルソフトで例えば文字列”command"を入力するとESP32は "+IPD,0,9:command"の文字列を応答として返すのでマイコン側では":"以下 の"command"を抽出してからアプリでコマンドやデータとして処理します。
ESP32をTCPサーバーに設定すると、リモートのクライアント端末からターミナルソフトで文字列のやりとりができるようになりますのでシリアル通信のように扱えるようになります。マイコンの無線化やIoTの第一歩と言えるでしょう。TCP通信はインターネットのウェブブラウザから操作するWEBサーバーの基礎的なものですのでまずは使いこなしてください。