ESP-NOWの送信速度検証

概要

ESP-NOWは通信速度がデフォルトで1Mbpsに設定されています。速度を変更しつつ、どの程度時間が変わるのかを検証してみました。

検証に利用したコード

#include <esp_now.h>
#include <esp_wifi.h>
#include <WiFi.h>

esp_now_peer_info_t slave;
QueueHandle_t xQueueMailbox;

void onDataSent(const uint8_t* mac_addr, esp_now_send_status_t status) {
  xQueueSend(xQueueMailbox, nullptr, 0);
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("================================================");

  xQueueMailbox = xQueueCreate(1, (size_t)0);

  WiFi.mode(WIFI_STA);
  esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE);
  Serial.print("STA MAC: ");
  Serial.println(WiFi.macAddress());
  Serial.print("STA CHANNEL ");
  Serial.println(WiFi.channel());
  WiFi.disconnect();
  esp_now_init();
  esp_wifi_config_espnow_rate(WIFI_IF_STA, WIFI_PHY_RATE_54M);
  esp_now_register_send_cb(onDataSent);

  for (int i = 0; i < 6; ++i) {
    slave.peer_addr[i] = (uint8_t)0xff;
  }
  esp_err_t addStatus = esp_now_add_peer(&slave);
}

void loop() {
  uint8_t data[250] = {};
  size_t sizeList[] = { 1, 50, 100, 150, 200, 250 };
  //size_t sizeList[] = { 1, 250 };
  static size_t size = 0;
  static uint8_t speed = 0;
  char* speedList[] = {
    "WIFI_PHY_RATE_1M_L",
    "WIFI_PHY_RATE_2M_L",
    "WIFI_PHY_RATE_5M_L",
    "WIFI_PHY_RATE_11M_L",
    "",
    "WIFI_PHY_RATE_2M_S",
    "WIFI_PHY_RATE_5M_S",
    "WIFI_PHY_RATE_11M_S",
    "WIFI_PHY_RATE_48M",
    "WIFI_PHY_RATE_24M",
    "WIFI_PHY_RATE_12M",
    "WIFI_PHY_RATE_6M",
    "WIFI_PHY_RATE_54M",
    "WIFI_PHY_RATE_36M",
    "WIFI_PHY_RATE_18M",
    "WIFI_PHY_RATE_9M",
    ""
  };
  int count = 1000;
  unsigned long time = 0;
  unsigned long minTime = 9999999;
  unsigned long maxTime = 0;
  esp_wifi_config_espnow_rate(WIFI_IF_STA, (wifi_phy_rate_t)speed);
  for (int i = 0; i < count; i++) {
    unsigned long startTime = micros();
    esp_err_t result = esp_now_send(slave.peer_addr, data, sizeList[size]);
    xQueueReceive(xQueueMailbox, nullptr, portMAX_DELAY);
    unsigned long oneTime = micros() - startTime;
    time += oneTime;
    minTime = min(minTime, oneTime);
    maxTime = max(maxTime, oneTime);
  }
  Serial.printf("speed = %s(0x%02x), count = %d, size = %d, time = %d, time/count = %d, minTime = %d, maxTime = %d\n", speedList[speed], speed, count, sizeList[size], time, time / count, minTime, maxTime);
  if (sizeList[size] == 250) {
    size = 0;
    speed++;
    if (speed == 0x10) {
      while (1) {
        delay(1);
      }
    }
  } else {
    size++;
  }
  delay(100);
}

速度と送信長を変更しつつ1000回送信するプログラムです。送信完了するとコールバック関数が呼ばれるのでキューを使って、送信完了待ちをしています。

送信先はブロードキャストのff:ff:ff:ff:ff:ffですので、送信は投げっぱなしで受信確認はしていません。

速度1Mbpsで送信長別の送信時間

送信長(バイト)平均送信時間(us)最小送信時間(us)最大送信時間(us)
18847545,434
501,2821,1554,675
1001,7191,5455,293
1502,1441,9555,571
2002,5712,3498,714
2502,9752,7519,114

ESP-NOWは1バイトから250バイトまでのデータを送信できるので、送信長別に送信にかかった速度を計測しています。単位はμ秒になります。概ね送信長に比例して送信時間が伸びています。最小の1バイトでは1ミリ秒弱、最長の250バイトで3ミリ秒弱かかっています。

特記事項として、ESP-NOWは送信しっぱなしなのですが、送信時間にばらつきがあります。最大のところをみてみると5ミリ秒から9ミリ秒程度送信にかかっている場合があります。このへんは周りの電波状況等に応じて変わってくるところだと思います。

速度別1バイト送信

速度平均送信時間(us)最小送信時間(us)最大送信時間(us)
WIFI_PHY_RATE_54M(0x0c)3142283,825
WIFI_PHY_RATE_36M(0x0d)3212323,984
WIFI_PHY_RATE_48M(0x08)3242373,930
WIFI_PHY_RATE_24M(0x09)3352434,957
WIFI_PHY_RATE_18M(0x0e)3432444,040
WIFI_PHY_RATE_12M(0x0a)3492523,939
WIFI_PHY_RATE_9M(0x0f)3492652,988
WIFI_PHY_RATE_6M(0x0b)3802843,968
WIFI_PHY_RATE_11M_S(0x07)4473384,030
WIFI_PHY_RATE_5M_S(0x06)4623694,408
WIFI_PHY_RATE_11M_L(0x03)5354374,106
WIFI_PHY_RATE_5M_L(0x02)5714654,192
WIFI_PHY_RATE_2M_S(0x05)5904824,263
WIFI_PHY_RATE_2M_L(0x01)7015775,623
WIFI_PHY_RATE_1M_L(0x00)8847545,434

送信長を最小の1バイトに固定して、通信速度を変更した例になります。1Mbpsから54Mbpsまで選択が可能ですが、速度の比と比べると送信時間の差はあまりありません。そして最大送信時間は4ミリ秒程度であまり変わっていません。

速度別250バイト送信

速度平均送信時間(us)最小送信時間(us)最大送信時間(us)
WIFI_PHY_RATE_54M(0x0c)3622784,238
WIFI_PHY_RATE_48M(0x08)3712873,871
WIFI_PHY_RATE_36M(0x0d)3873063,905
WIFI_PHY_RATE_24M(0x09)4403225,701
WIFI_PHY_RATE_18M(0x0e)4413653,802
WIFI_PHY_RATE_12M(0x0a)5464424,243
WIFI_PHY_RATE_9M(0x0f)5854883,853
WIFI_PHY_RATE_11M_S(0x07)6195214,013
WIFI_PHY_RATE_11M_L(0x03)7316204,462
WIFI_PHY_RATE_6M(0x0b)7406304,306
WIFI_PHY_RATE_5M_S(0x06)8867445,971
WIFI_PHY_RATE_5M_L(0x02)9948389,826
WIFI_PHY_RATE_2M_S(0x05)1,6471,4815,103
WIFI_PHY_RATE_2M_L(0x01)1,7551,5735,350
WIFI_PHY_RATE_1M_L(0x00)2,9752,7519,114

最長の250バイトを送信する場合には速度の設定で時間に差ができています。

LとS?

2Mと5Mと11MにはLとSがあり、Sの方が少し早いです。

無線LAN - IEEE802.11フレームフォーマット
無線LAN(WLAN)について解説。

上記の説明がわかりやすかったのですが、PLCPプリアンブルのデータの違いによります。その無線パケットの通信速度を渡すためのデータで、ここは低速で通信され、実際のデータ部分は指定した速度で高速通信するような形になっていました。

そしてロングとショートがあり、ショートの方が通信速度も早いようです。ただし、ロングの標準的で、オプションとしてショートがある関係性のようです。

まとめ

受信や速度に応じて消費電力や距離なども調べたかったですが現在準備中のarduino-esp32の3系(ESP-IDF5.1系)でESP-NOWまわりの関数群がガラッと変わっていましたので新しいバージョンがでたら検証しなおしてみたいと思います。

コメント