Page 1 of 1

ESPNOW Slower than expected RTT (Round Trip Time)

Posted: Wed Apr 03, 2019 1:14 am
by leonyuhanov
I have been testing RTT times on 2 ESP32 modules & have it down to an average of 6000 micro seconds (6 mili seconds).

Source for TX: https://github.com/leonyuhanov/ESP32_ES ... r/espnowv1
Source for RX: https://github.com/leonyuhanov/ESP32_ES ... r/espnowv2

-The TX Module sends a 250Byte ESPNOW packet to the RX module
-The TX Module waits for a reply from the RX module & calculates the Time (in uS).

The RTT is way to long or I'm missing something... On the ESP8266 RTT for the same size packet is under 1000 micros on average.
On the ESP32 (using the Arduino SDK) RTT is 2ms worse!
I started testing this using the IDF SDK and thought id get better times.

I suspect that on the ESP8266 the send data function does not wait for an ACK from the receiver before returning an OK.
I think on the ESP32 IDF SDK, the espnow send data function returns OK only when an ACK from the receiver has been revived, BUT i have no way to test or prove this

Has anyone had any experience with this?
PS I have opened a case https://github.com/espressif/esp-idf/issues/3238

Re: ESPNOW Slower than expected RTT (Round Trip Time)

Posted: Wed May 15, 2019 8:56 pm
by plajjd
I believe the default ESP-NOW bit rate is 1 Mbps. A 250 byte packet would take 2 ms just to send it over the air. So round trip that is a full 4 ms (just in "air" time).

We are starting to experiment with increasing the ESP-NOW bit rate in order to reduce round-trip time, and are seeing large improvements.

Does anyone have experience actually doing this for a product?

Is there a recommended "maximum bit rate" to use with ESP-NOW?

Re: ESPNOW Slower than expected RTT (Round Trip Time)

Posted: Wed May 15, 2019 11:18 pm
by leonyuhanov
I believe the default ESP-NOW bit rate is 1 Mbps.
Where is this documented?
We are starting to experiment with increasing the ESP-NOW bit rate
How are you doing that? Can you elaborate?

Re: ESPNOW Slower than expected RTT (Round Trip Time)

Posted: Thu May 16, 2019 4:08 pm
by plajjd
Unfortunately, the documentation is quite limited. And we have only tested this in the lab - we have not commited to changing the bit rate in production yet.

Here is what I know:

In `esp_wifi_internal.h` there is:

Code: Select all

/**
  * @brief  enable or disable transmitting WiFi MAC frame with fixed rate
  *
  * @attention 1. If fixed rate is enabled, both management and data frame are transmitted with fixed rate
  * @attention 2. Make sure that the receiver is able to receive the frame with the fixed rate if you want the frame to be received
  *
  * @param  ifx : wifi interface
  * @param  en : false - disable, true - enable
  * @param  rate : PHY rate
  *
  * @return
  *    - ERR_OK  : succeed
  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
  *    - ESP_ERR_WIFI_NOT_STARTED: WiFi was not started by esp_wifi_start
  *    - ESP_ERR_WIFI_IF : invalid WiFi interface
  *    - ESP_ERR_INVALID_ARG : invalid rate
  *    - ESP_ERR_NOT_SUPPORTED : do not support to set fixed rate if TX AMPDU is enabled
  */
esp_err_t esp_wifi_internal_set_fix_rate(wifi_interface_t ifx, bool en, wifi_phy_rate_t rate);
In `esp_wifi_types.h` there is a list of data rate #defines:

Code: Select all

/**
  * @brief WiFi PHY rate encodings
  *
  */
typedef enum {
    WIFI_PHY_RATE_1M_L      = 0x00, /**< 1 Mbps with long preamble */
    WIFI_PHY_RATE_2M_L      = 0x01, /**< 2 Mbps with long preamble */
    WIFI_PHY_RATE_5M_L      = 0x02, /**< 5.5 Mbps with long preamble */
    WIFI_PHY_RATE_11M_L     = 0x03, /**< 11 Mbps with long preamble */
    WIFI_PHY_RATE_2M_S      = 0x05, /**< 2 Mbps with short preamble */
    WIFI_PHY_RATE_5M_S      = 0x06, /**< 5.5 Mbps with short preamble */
    WIFI_PHY_RATE_11M_S     = 0x07, /**< 11 Mbps with short preamble */
    WIFI_PHY_RATE_48M       = 0x08, /**< 48 Mbps */
    WIFI_PHY_RATE_24M       = 0x09, /**< 24 Mbps */
    WIFI_PHY_RATE_12M       = 0x0A, /**< 12 Mbps */
    WIFI_PHY_RATE_6M        = 0x0B, /**< 6 Mbps */
    WIFI_PHY_RATE_54M       = 0x0C, /**< 54 Mbps */
    WIFI_PHY_RATE_36M       = 0x0D, /**< 36 Mbps */
    WIFI_PHY_RATE_18M       = 0x0E, /**< 18 Mbps */
    WIFI_PHY_RATE_9M        = 0x0F, /**< 9 Mbps */
    WIFI_PHY_RATE_MCS0_LGI  = 0x10, /**< MCS0 with long GI, 6.5 Mbps for 20MHz, 13.5 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS1_LGI  = 0x11, /**< MCS1 with long GI, 13 Mbps for 20MHz, 27 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS2_LGI  = 0x12, /**< MCS2 with long GI, 19.5 Mbps for 20MHz, 40.5 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS3_LGI  = 0x13, /**< MCS3 with long GI, 26 Mbps for 20MHz, 54 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS4_LGI  = 0x14, /**< MCS4 with long GI, 39 Mbps for 20MHz, 81 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS5_LGI  = 0x15, /**< MCS5 with long GI, 52 Mbps for 20MHz, 108 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS6_LGI  = 0x16, /**< MCS6 with long GI, 58.5 Mbps for 20MHz, 121.5 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS7_LGI  = 0x17, /**< MCS7 with long GI, 65 Mbps for 20MHz, 135 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS0_SGI  = 0x18, /**< MCS0 with short GI, 7.2 Mbps for 20MHz, 15 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS1_SGI  = 0x19, /**< MCS1 with short GI, 14.4 Mbps for 20MHz, 30 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS2_SGI  = 0x1A, /**< MCS2 with short GI, 21.7 Mbps for 20MHz, 45 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS3_SGI  = 0x1B, /**< MCS3 with short GI, 28.9 Mbps for 20MHz, 60 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS4_SGI  = 0x1C, /**< MCS4 with short GI, 43.3 Mbps for 20MHz, 90 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS5_SGI  = 0x1D, /**< MCS5 with short GI, 57.8 Mbps for 20MHz, 120 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS6_SGI  = 0x1E, /**< MCS6 with short GI, 65 Mbps for 20MHz, 135 Mbps for 40MHz */
    WIFI_PHY_RATE_MCS7_SGI  = 0x1F, /**< MCS7 with short GI, 72.2 Mbps for 20MHz, 150 Mbps for 40MHz */
    WIFI_PHY_RATE_LORA_250K = 0x29, /**< 250 Kbps */
    WIFI_PHY_RATE_LORA_500K = 0x2A, /**< 500 Kbps */
    WIFI_PHY_RATE_MAX,
} wifi_phy_rate_t;
When we call the function with these data rate settings, it seems to make the change - and dramatically changes round trip time.

Also, here is an article discussing the feature:
https://hackaday.io/project/161896-linu ... ementation

I think there is a page in the ESP IDF docs about this, but can't find it at the moment...

Re: ESPNOW Slower than expected RTT (Round Trip Time)

Posted: Fri May 17, 2019 12:49 am
by leonyuhanov
How did you compile this function?

Code: Select all

error: implicit declaration of function 'esp_wifi_internal_set_fix_rate' [-Werror=implicit-function-declaration]
esp_wifi_internal_set_fix_rate(ESPNOW_WIFI_IF, 1, WIFI_PHY_RATE_MCS7_SGI);
This seems to be a set of functions that we can not use?
Can you elaborate?

Re: ESPNOW Slower than expected RTT (Round Trip Time)

Posted: Fri May 17, 2019 1:17 am
by leonyuhanov
Ok I was able to get this working
You need to
include:

Code: Select all

#include "esp_private/wifi.h"
and disable AMPDU TX and RX via menuconfig:

Code: Select all

DISABLE BOTH Components => Wi-Fi => "WiFi AMPDU TX" & "WiFi AMPDU RX"
Only then does it compile and enable the set rates!

Successfully got it down to 689Micros!!

Code: Select all

Current sendCount       996     RTT     689 microseconds

Re: ESPNOW Slower than expected RTT (Round Trip Time)

Posted: Fri May 17, 2019 2:47 pm
by plajjd
Awesome!

I am interested in the result of your further testing. We are also excited to have the higher performance, but am concerned that it may reduce reliability...

Phil.

Re: ESPNOW Slower than expected RTT (Round Trip Time)

Posted: Thu Feb 22, 2024 11:26 am
by jkingdon
Is this still working for anyone? I'm seeing minimum round trip times of about 6ms with 250 byte payload with no observable impact from calling esp_wifi_internal_set_fix_rate after disabling ampdu. I found issue https://github.com/espressif/esp-idf/issues/3238 which has one similar report of fix_rate not working. I also noticed a comment in the api docs:

* @attention 3. Not support to set fix rate for espnow and 80211_tx

I have the call wrapped in ESP_ERROR_CHECK and have tried moving it earlier in the start up sequence. If called before wifi_start I see the expected failure.

Ok, I should have tried a little bit harder. The internal API must have been superseded, using

ESP_ERROR_CHECK( esp_wifi_config_espnow_rate(ESP_IF_WIFI_STA, WIFI_PHY_RATE_54M) );

works and reduces the round trip time. It generates a warning that it is itself deprecated, so I'll need to figure out the replacement call next.