聞きかじりめも

主にC++やメディア処理技術などに関して気付いたことを書いていきます.ここが俺のメモ帳だ!

複数のM5StackでESP-NOW双方向通信を試す

 

 

最近,お仕事でM5Stackを扱う機会がありました.私はこれまでマイコンといえばSTM32Arduino(とその互換機)を扱ったことがありますが,M5Stackを扱ってみて電子工作がどんどん便利になっていることを実感しています.以前の記事Digisparkを扱った時もその小ささと扱いやすさに感動したものですが,M5Stackは本当に凄いです.

今回は,4個のM5StackESP-NOWで無線接続し,マスター・スレーブの関係を起動後に指定できるようにします.

M5Stackとは

 

M5Stack Basic

M5Stack Basic

  • スイッチサイエンス
Amazon

 

深圳のスタートアップ企業M5Stack社が発売する,オールインワンマイコンとでもいうべきArduino互換のマイコンです.個人的にRasberryPiを初めて知った時と同じくらい革命的です.

驚くべきは入出力系が一通り揃っていることで,Basicグレードですら,モニター,スイッチ入力,スピーカー,6軸モーションセンサ,SDカードが備わっており,更にバッテリーが標準搭載なのでスタンドアロンで動きます.Wifi/Bluetooth接続も可能なのでIoT開発にも使いやすいです.従って,基本的な動作確認とデバッグM5Stack本体だけで完結できます.単純なprintfデバッグならシリアルモニタすら不要です.

拡張性も高く,様々なモジュールを積み上げるように接続できるようになっています.専用ユニバーサル基板によって,自分で独自のモジュールを開発することもできます.更に,上位機種ではLEGO互換の固定穴やGrove端子が用意されているものもあり,マインドストームとの連携も考えられています.

何より,基板むき出しじゃない点が非常にクールです.専用拡張モジュールを使う限りは,ハウジングを自分で用意する必要すらありません.

開発環境も,Arduino IDEが使えるほか,UIFlowというWebベースのビジュアルプログラミング環境が用意されています.後者については私は試していませんが,見た目はScratchのようですので学習用にも最適ではないでしょうか.

 

余談ですが,M5Stack社の社長は元々は企業の電気エンジニアで,組み込みシステム開発する際に毎回同じ入出力モジュールを組み立てるのが煩わしく感じたことから,元々必要なものがすべて備わっているマイコンがあれば売れると考えて独立したそうです.至れり尽くせりの出来栄えは現場を知っているからこそでしょうか.M5Stack英語圏よりも日本での売れ行きが特に良いそうで,日本の組み込みエンジニアの層の厚さと嗅覚の鋭さを感じさせますね.怪しい中華デバイスも日本人なら漢字から何となく意味が分かるからなんだろうか…?

今回やりたいこと

1台のPCと大量のマイコンを無線シリアル接続したいのですが,Bluetoothで何個もCOMポートを開けたくありませんし,そもそもBluetooth7台までしか接続できません*1.そこで,1個のマイコンをハブ(マスター)にして,その下に複数台のマイコン(スレーブ)を接続する方式にしようとしています.

ただ,マスター用・スレーブ用のプログラムをわざわざ別々に用意するのは億劫ですよね?私は怠惰で粗雑なので,同じ見た目のM5Stackのどれがマスターでどれがスレーブかなどと管理できる気がしませんし,したくありません.*2同じプログラムを全てのマイコンに書き込むようにして,どれがマスターでどれがスレーブかなんて後で自由に決めたいのです.どのM5StackにもPCとの無線通信手段があるのに,ハブ用に1個余計にマイコンを使うのも馬鹿らしいですし.

幸いにもM5StackにはESP32マイコンが使われていますので,この用途に最適なESP-NOWという通信方式が使えます.*3これはBluetoothとは別の通信規格なのでPC-マスター間の通信に干渉しません.また,双方向通信が可能で,本質的にマスターとスレーブを区別しない通信方式ですので,誰でもマスターになれます.*4

 

ということで,今回は起動後に一定の手順を踏んでマスター・スレーブを動的に決定するシステムを試作しました.

構成

M5Stack FIRE ×4台

なぜFIREにしたのか?というと,バッテリー拡張モジュールが標準装備なので長時間動作が期待できるからです.その代わり,GPIOへのアクセスが多少悪くなってしまいます.

M5Stack FIRE

M5Stack FIRE

  • スイッチサイエンス
Amazon

 

結果

ソースはGitHubを参照.

github.com

 


www.youtube.com

動画にはなっていませんが,PCとBluetooth接続もできています.やったね!

ソースコードのフロー

本プログラムは以下のように動作します.

  1. 電源投入後,ESP-NOWを初期化する.

  2. 初期設定のため,ブロードキャスト用のPeer情報を登録し,初期設定用のコールバック関数を登録する.

  3. 初期設定モードに入る.この時点で,どれがマスターでどれがスレーブかは決まっていない.

    1. ボタンをクリックした瞬間に,誰もマスターになっていない場合は,自分がマスターであるとすべてのデバイスに宣言(ブロードキャスト)する.その際,自分のMACアドレスをマスターのMACアドレスとして記録する.

    2. マスター宣言を受信したら,送信者のMACアドレスをマスターとして記録する.自分はスレーブIDの確定していないスレーブであると認識し,IDカウンターを0とする.

    3. ボタンをクリックした瞬間に,誰かがマスターになっていて,自分のスレーブIDが確定していない場合は,自分がスレーブであると宣言する.その際,スレーブIDIDカウンターの値=nとし,n番目のスレーブとして自分のMACアドレスを記録する.その後,IDカウンターを進める.

    4. スレーブ宣言を受信したら,送信者のMACアドレスをn=スレーブID)番目のスレーブとして記録し,IDカウンターを進める.

    5. 以上の手続きを進め,IDカウンターが既定のスレーブ数に達した場合,初期設定モードを抜ける.

  4. 初期設定用のコールバック関数登録を解除し,設定完了後のコールバック関数を再登録する.

  5. 自身がマスターの場合,認識したスレーブのMACアドレスを含むPeer情報を登録する.逆に自分がスレーブの場合,認識したマスターのMACアドレスを含むPeer情報を登録する.

  6. Bluetoothシリアルポートを開ける.
  7. 以上で初期設定が完了するので,setup()を抜け,loop()に入る.

    1. テスト用に,押したボタンの種類に応じて,特定のIDのスレーブに文字列を送信する.
    2. あるいは,Bluetooth接続したPCのシリアルモニタから数字が送られてくると,該当のデバイスの表示を変更する.

 

解説

※番号は上のフローと対応しています.

  1. ESP-NOWは内部的にWiFiの機能を借用しています.WiFiモジュールを起動し,disconnectした後にesp_now_init()のコマンドを入れることで,ESP-NOW用に初期化することができます.
  2. ESP-NOWでは,FF:FF:FF:FF:FF:FFに送信することですべてのESP-NOW通信中のデバイスに送信することができます.初期設定では全員が全員に自分の情報を教えあう必要があるため,ブロードキャスト用にPeer情報を登録しています.
  3. 全体としての動作は,最初にボタンをクリックしたM5Stackがマスターになり,ボタンを押した順にスレーブ1,スレーブ2,…と決定していくことになります(動画参照).初期設定ループを進めると,マスターのMACアドレスと各IDのスレーブのMACアドレスを全てのデバイスが(自分のMACアドレスも含めて)知っている状態になります.
  4. コールバック関数を付け替えることで,初期設定時の通信挙動と設定完了後の通信挙動を変えることができます.
  5. マスターもスレーブも,MACアドレス以外は設定を共通にしています.Peer設定は色々な設定項目があるようですが,今のところよく分かっていません.(「現在のチャンネル」とは…?)
  6. 自分のMACアドレス下2桁を使って固有のデバイス名を作成しています.ペアリング完了後はPC側のCOMポートが開きっぱなしになるので,別の機体をマスターにしたい場合はペアリングの解除をしてから初期設定するといいと思います.
  7. ここでは自分がマスターかスレーブかによらず,特定IDのスレーブに送信を試みる,という動作をさせています.自分がスレーブであればマスターの分しかPeer設定をしていないので,確実に送信失敗します.そのため,スレーブのボタンを押しても誰にも送信されない動作が実現できている,というわけです.本当は自分がマスターの時に限ってボタン読み込みするような挙動の方が望ましいと思います.

その他

  • MyUtility.hには,主にモニター上部に電池残量や自分の属性を表示させるための機能が含まれています.今回はこの解説は省きますが,この記事が参考になると思います.
  • 2021/10/21時点ではこのプログラムには致命的な欠陥があり,稀に意図せず落ちる場合があります.また,2個以上のM5Stackのボタンを同時押ししても落ちます.
    • これは,ループ内とコールバック関数内の両方にモニター画面を更新する命令が含まれているためです.ループ内のLCD描画命令の最中にコールバックが呼ばれてしまうことで,LCDへの命令が二重に発生し強制終了してしまうようです.回避する一つの手段はコールバック内にのみ描画命令を書くことなどが考えられますが,正直不明です…
  • ブログへのアップ用にMACアドレスの上位5桁をマスクする機能を搭載しています.

 

*1:Bluetooth4.0から用意された Bluetooth Low Energy (BLE) 規格なら接続台数に規格上の制約はありません.M5StackBLEを使えますが,BLEのライブラリはちょっと難しかったので今回はパスしました.何より,PCCOMポートが大量に開く状況は避けられません.

*2:ラベルシールを貼るという管理手段もありますが,見た目のスマートさを劇的に低下させます.そのうえ,「やっぱりこっちのM5をマスターにしたい」「スレーブ①をスレーブ②に変えたい」となった時に,ラベルの貼り換え&プログラムの書き換えという虚無しかない手間が発生します.

*3:ESP-NOWIEEE802.11規格をベースに独自拡張された通信方式です.WiFiと共通の機能を一部使うことになるため,ESP-NOW通信中にWiFiを使うときには注意が必要ですこちらの記事が詳しいです.

*4:本来,ESP-NOWでは送信側をコントローラ,受信側をスレーブと呼びます.今回はマルチスレーブ環境ですが,センサ群が一つのハブに情報を集積させる,IoTによくある場合はマルチコントローラ環境ということになります.このとき,マスター/スレーブ構成という文脈での「マスター」が,ESP-NOWの文脈では「スレーブ」と呼ばれることになります.この通り非常にややこしいので,本文ではマスター/スレーブ構成の文脈での呼称に統一しています.