Serial over ESP-NOW実装を作成

概要

GitHub - tanakamasayuki/EspNowBus
Contribute to tanakamasayuki/EspNowBus development by creating an account on GitHub.

ESP-NOWの暗号化と自動ピアリングのライブラリに、Serialっぽいクラスを乗せるEspNowSerialを作ってみました。

仕組み

EspNowBusは同じグループ名で接続した端末同士を暗号化したESP-NOWネットワークを構築する機能があります。その機能を利用して、Serial通信を無線化するクラスを作成してみました。

ESP-NOWは1470バイトまでの通信が可能ですが、EspNowBus側のヘッダで6バイト、EspNowSerial側のヘッダが10バイト使ってMTUが1,454ぐらいの通信が可能です。メッセージに送信確認や再送処理はEspNowBusが実施していますので、その上にSerialの文字列を転送する処理を作っています。

EspNowSerial serialHub;
EspNowSerialPort controlSerial;

void setup()
{
  EspNowSerial::Config cfg;
  cfg.groupName = "espnow-serial-demo";
  serialHub.begin(cfg);
  controlSerial.attach(serialHub);
  controlSerial.bindFirstAvailable();
}

利用方法的には上記な感じになります。グループ名を文字列で設定して、同じ文字列同士が自動ペアリングしてシリアルセッションを開きます。serialHubがセッションの管理で、controlSerialが従来のシリアルっぽいクラスとなります。

EspNowBusは同じグループ名は自動でメッシュ上のネットワークを組みますので、2台であれば問題ないのですが、3台以上いるとどれと通信をすればいいのかよくわかりません。

controlSerial.bindFirstAvailable();

上記は最初に接続したセッションを利用する設定になっています。

  // en: Planned policy example: device side does not advertise sessions on its own.
  // ja: 想定ポリシー例: device 側は自分から募集しない。
  cfg.advertise = false;

EspNowBusの接続の制御として、上記の募集を行うかがあります。デフォルトは募集を行うになっているので、接続した端末はフルメッシュになります。サーバー側だけオンにして、端末側をオフにすることで、サーバーに対して端末が接続をする方向にすることができます。

サーバー側では複数のデバイスがみえますので、セッションを選んで利用するか、全部のセッションをループして接続の処理をしてあげます。

スケッチ例

EspNowBus/examples/Serial at main ツキ tanakamasayuki/EspNowBus
Contribute to tanakamasayuki/EspNowBus development by creating an account on GitHub.

上記にあります。

01_BasicPair

void setup()
{
  Serial.begin(115200);
  delay(500);

  EspNowSerial::Config cfg;
  cfg.groupName = "espnow-serial-demo";
  serialHub.begin(cfg));

  controlSerial.attach(serialHub);
  controlSerial.bindFirstAvailable();
}

void loop()
{
  serialHub.poll();

  static uint32_t lastSend = 0;
  if (millis() - lastSend > 2000)
  {
    lastSend = millis();
    uint8_t selfMac[6] = {};
    WiFi.macAddress(selfMac);
    controlSerial.printf("hello from %02X:%02X:%02X:%02X:%02X:%02X\n",
                         selfMac[0], selfMac[1], selfMac[2],
                         selfMac[3], selfMac[4], selfMac[5]);
  }

  while (controlSerial.available() > 0)
  {
    Serial.write(controlSerial.read());
  }
}

2台で動かした例です。両方が募集を出しているので、3台以上動かすと最初に接続したほうとセッションを貼ります。

利用方法は普通のシリアルと変わりません。

02_ControllerBridge

コントローラー側のサンプルとなります。コントローラー側はUSBシリアルとブリッジしており、端末側からのシリアルをESP-NOW経由で送受信可能です。

///list
///use <index>
///help

上記のコマンドだけ特殊処理で、コントローラー側に投げることでセッションを切り替えることが可能です。

03_SilentDevice

controller 側の募集にだけ接続する device 側サンプルです。01_BasicPairとの差は募集をしない設定になっているので、device 端末同士の接続はありません。

04_MultiSessionMonitor

for (size_t i = 0; i < serialHub.sessionCapacity(); ++i)

コントローラー側が全セッションをなめて、ログを収集する場合の例となります。コントローラーからデバイス側への通信は実装していません。

05_ESP32SerialCtlDevice

上記のシリアル経由で操作するライブラリをESP-NOW経由で操作する例です。こちらはデバイス側にいれて、コントローラー側には02_ControllerBridgeをあらかじめ実行させておきます。

まとめ

EspNowBus上にSerial over ESP-NOW実装であるEspNowSerialクラスを作ってみました。用途としてはWiFiが使えないような環境で、簡易的にシリアルを飛ばすときに利用する想定です。

スループット的にはそこまで高くないので実験的な実装ですが、今後もいろいろ実験予定です。

コメント