• Home
  • Robotics
  • 3D Printing
  • Web
  • Microcontrollers
  • Frameworks
  • Protocols
  • Other
  • Explore knowledge
  • Loading graph.
    Depth
    …
    … visible
  • Home
  • Robotics
  • 3D Printing
  • Web
  • Microcontrollers
  • Frameworks
  • Protocols
  • Other
Tools
    Pages
    • Microcontrollers
      • ESP32
        • C3 Dev Kit M1
        • Datasheets
        • Debug
        • ESP-Mesh
        • ESP-Now
        • ESP32 C3 DevKit M1
        • ESP32 D1 Mini
        • ESP32-C3 0.42 Oled
        • FireBeetle
        • M5 Atom Lite
        • M5 Stick C Plus
        • m5 stick V
        • Round Display
        • S2 Saola 1
        • Software
        • Thermostat Control
        • Timer Cam OV3660
        • TTGO T-Display
        • TTGO T5-EPaper
        • Wall Display
        • Waveshare S3 3.5 Inch display
      • nRF52
        • nRF52832 UART dongle
        • nRF52840 USB dongle
        • Simple Mesh SensorTag
        • Thread SensorTag
        • Trick Tracker
        • UWB DWM1001 dev
        • UWB DWM3001 cdk
      • nRF53
        • thingy53
      • Risc-V
      • STM32
        • Black Pill
        • Blue Pill
        • Dev EBox F407
    Pages
    • Microcontrollers
      • ESP32
        • C3 Dev Kit M1
        • Datasheets
        • Debug
        • ESP-Mesh
        • ESP-Now
        • ESP32 C3 DevKit M1
        • ESP32 D1 Mini
        • ESP32-C3 0.42 Oled
        • FireBeetle
        • M5 Atom Lite
        • M5 Stick C Plus
        • m5 stick V
        • Round Display
        • S2 Saola 1
        • Software
        • Thermostat Control
        • Timer Cam OV3660
        • TTGO T-Display
        • TTGO T5-EPaper
        • Wall Display
        • Waveshare S3 3.5 Inch display
      • nRF52
        • nRF52832 UART dongle
        • nRF52840 USB dongle
        • Simple Mesh SensorTag
        • Thread SensorTag
        • Trick Tracker
        • UWB DWM1001 dev
        • UWB DWM3001 cdk
      • nRF53
        • thingy53
      • Risc-V
      • STM32
        • Black Pill
        • Blue Pill
        • Dev EBox F407
    Home/Microcontrollers/ESP32/esp-now
    Metadata
    description
    An ESP-Now wrapper library is created and used in a Broadcast and Gateway examples. The ESP-Now Broadcast had 100% RX success with another ESP-Now only device, but the ESP-Now to wifi gateway had only 25% RX success rate
    date
    2021-02-25

    Relates to

    ESP-Mesh Wrapper

    Overview

    Github

    Github repo

    ESP-Now reference

    docs.espressif esp-now

    Status

    Caution

    As we can see in the details of the logs below, running an ESP-Now gateway through wifi, results in dropping the reception success rate from 100% to 25%, therefore, a serial ESP-Now gateway would be recommended and not a Wifi one.

    Examples

    Broadcast

    In this example, a 5 sec loop is sending an ESP-Now broadcast message then keeps listening the rest of the time.
    esp32_iot 09_esp_now_broadcast
    Broadcast 'main.cpp'
    C++
    #include <Arduino.h>
    #include <ArduinoJson.h>
    #include <WiFi.h>
    #include <MQTT.h>
    
    #include <ConfigUtils.h>
    #include <EspNowWrapper.h>
    #include <ESPStringUtils.h>
    
    DynamicJsonDocument config(5*1024);//5 KB
    DynamicJsonDocument secret(1*1024);//1 KB
    MQTTClient mqtt(1*1024);
    WiFiClient wifi;//needed to stay on global scope
    NowApp espnow;
    
    uint32_t cycle_count = 0;
    
    //https://esp32.com/viewtopic.php?t=12992
    
    void meshMessage(String &payload,String from){
      Serial.printf("RX> from(%s) => [%s]\n",from.c_str(),payload.c_str());
      mqtt.publish("espnow/"+from,payload);
    }
    
    void setup() {
      
      Serial.begin(115200);
      timelog("Boot ready");
    
      load_json(config,"/config.json");
      load_json(secret,"/secret.json");
      timelog("config loaded");
    
      WiFi.mode(WIFI_MODE_STA);
      timelog("config loaded");
    
      espnow.start(config,secret);
      espnow.onMessage(meshMessage);
    
      espnow.set_channel(config["wifi"]["channel"]);
    
      timelog("setup() done");
    
    }
    
    void loop() {
      cycle_count++;
      Serial.printf("\n\n");
      timelog("loop start cycle ("+String(cycle_count)+")");
      espnow.print_info();
      espnow.broadcast("Hello Everyone ("+String(cycle_count)+")");
      delay(5000);
    }

    Note

    In this example, we notice in the log below a broadcast from an ESP-Now only device is received by another ESP-Now only device with 100% success. This success is due to the receiving device listening most of the time except when transmitting. A higher frequency can reveal misses on collision times.

    Broadcast startup 'main.cpp'
    Log
    rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:2
    load:0x3fff0018,len:4
    load:0x3fff001c,len:1044
    load:0x40078000,len:8896
    load:0x40080400,len:5828
    entry 0x400806ac
    36 : Boot ready
    150 : config loaded
    
    Brownout detector was triggered
    
    ets Jun  8 2016 00:22:57
    
    rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:2
    load:0x3fff0018,len:4
    load:0x3fff001c,len:1044
    load:0x40078000,len:8896
    load:0x40080400,len:5828
    entry 0x400806ac
    37 : Boot ready
    150 : config loaded
    234 : wifi mode set
    236 : setup() done
    send => (ff:ff:ff:ff:ff:ff) 'Good Morning Everyone (0)'
    237 : initial broadcast() done
    
    
    237 : loop start cycle (1)
     Version=1;  channel=1;  peers=1 encrypted=0;   send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (1)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    Log of Two boradcasters receivers

    first instance

    Log
    540465 : loop start cycle (109)
     Version=1;  channel=8;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (109)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    RX> from(10:52:1c:68:e8:84) => [Hello Everyone (20)]
    
    545466 : loop start cycle (110)
     Version=1;  channel=8;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (110)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    RX> from(10:52:1c:68:e8:84) => [Hello Everyone (21)]

    second instance

    Log
    540465 : loop start cycle (109)
     Version=1;  channel=8;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (109)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    RX> from(10:52:1c:68:e8:84) => [Hello Everyone (20)]
    
    
    545466 : loop start cycle (110)
     Version=1;  channel=8;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (110)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    RX> from(10:52:1c:68:e8:84) => [Hello Everyone (21)]

    MQTT Wifi Gateway

    In this example, a gateway is listening to ESP-Now, once a message is received, it is relayed to an MQTT broquer through wifi. This Gateway example is run with another device running the Broadcast example.

    esp32_iot 10_esp_now_mqtt_gateway

    Caution

    Although the implementation is successfull, we can notice in the log below that the success rate is only 25%. The issue that the Gateway is skipping reception during parallel wifi activity.

    Wifi Gateway 'main.cpp'
    C++
    #include <Arduino.h>
    #include <ArduinoJson.h>
    #include <WiFi.h>
    #include <MQTT.h>
    
    #include <ConfigUtils.h>
    #include <EspNowWrapper.h>
    #include <ESPStringUtils.h>
    
    DynamicJsonDocument config(5*1024);//5 KB
    DynamicJsonDocument secret(1*1024);//1 KB
    MQTTClient mqtt(1*1024);
    WiFiClient wifi;//needed to stay on global scope
    NowApp espnow;
    
    uint32_t cycle_count = 0;
    
    //https://esp32.com/viewtopic.php?t=12992
    
    void meshMessage(String &payload,String from){
      Serial.printf("RX> from(%s) => [%s]\n",from.c_str(),payload.c_str());
      mqtt.publish("espnow/"+from,payload);
    }
    
    void setup() {
      
      Serial.begin(115200);
      timelog("Boot ready");
    
      load_json(config,"/config.json");
      load_json(secret,"/secret.json");
      timelog("config loaded");
    
      WiFi.mode(WIFI_MODE_STA);
      timelog("config loaded");
    
      espnow.start(config,secret);
      espnow.onMessage(meshMessage);
    
      espnow.set_channel(config["wifi"]["channel"]);
    
      timelog("setup() done");
    
    }
    
    void loop() {
      cycle_count++;
      Serial.printf("\n\n");
      timelog("loop start cycle ("+String(cycle_count)+")");
      espnow.print_info();
      espnow.broadcast("Hello Everyone ("+String(cycle_count)+")");
      delay(5000);
    }
    Broadcaster log
    Log
    rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:2
    load:0x3fff0018,len:4
    load:0x3fff001c,len:1044
    load:0x40078000,len:8896
    load:0x40080400,len:5828
    entry 0x400806ac
    36 : Boot ready
    151 : config loaded
    358 : config loaded
    361 : setup() done
    
    
    361 : loop start cycle (1)
     Version=1;  channel=5;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (1)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    
    
    5365 : loop start cycle (2)
     Version=1;  channel=5;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (2)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    
    
    10366 : loop start cycle (3)
     Version=1;  channel=5;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (3)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    
    
    15367 : loop start cycle (4)
     Version=1;  channel=5;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (4)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    
    
    20368 : loop start cycle (5)
     Version=1;  channel=5;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (5)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    
    
    25369 : loop start cycle (6)
     Version=1;  channel=5;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (6)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    
    
    30370 : loop start cycle (7)
     Version=1;  channel=5;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (7)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    
    
    35371 : loop start cycle (8)
     Version=1;  channel=5;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (8)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    
    
    40372 : loop start cycle (9)
     Version=1;  channel=5;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (9)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    
    
    45373 : loop start cycle (10)
     Version=1;  channel=5;  peers=1 encrypted=0;
    send => (ff:ff:ff:ff:ff:ff) 'Hello Everyone (10)'
      send_cb> Sent data to ff:ff:ff:ff:ff:ff, status: 0
    Gateway log
    Log
    272534 : loop start cycle (55)
    5
    
    277538 : loop start cycle (56)
    5RX> from(10:52:1c:68:e8:84) => [Hello Everyone (3)]
    
    
    282542 : loop start cycle (57)
    5
    
    287546 : loop start cycle (58)
    5
    
    292550 : loop start cycle (59)
    5RX> from(10:52:1c:68:e8:84) => [Hello Everyone (6)]
    
    
    297554 : loop start cycle (60)
    5
    
    302558 : loop start cycle (61)
    5
    
    307562 : loop start cycle (62)
    5
    
    312566 : loop start cycle (63)
    5RX> from(10:52:1c:68:e8:84) => [Hello Everyone (10)]
    
    
    317570 : loop start cycle (64)
    5
    
    322574 : loop start cycle (65)
    5
    
    327578 : loop start cycle (66)
    5

    MQTT Explorer showing both topics received from the gateway:

    • the gateway itself with its mac address

    • the one related from the ESP-Now broadcaster device with the broadcaster mac address

    image-esp-now_mqtt_gateway.png
    ×
    espnow_mqtt_gateway.ino

    FAQ - Discussion

    If you need support, want to ask a question or suggest an idea, you can join the discussion on the forum
    Home Smart Mesh - Discussions
    Can I ran an ESP-Now wifi gateway ?

    No, because relaying messages through wifi drops reception success from almost 100% to 25%. It is possible to remediate to this through retries but this will harm the power consumption of end devices which might be the first motivation to use ESP-Now. Therefore, it is recommended that the Gateway forwards messages to another device through a serial uart to maximize ESP-Now listening time.

    Is it possible for a device to identify its ESP-Now peers ?
    • No, given the ESP-Now API Reference, it looks like that it is a low level point to point messaging including broadcast, but not more. Therefore it's only based on mac addresses and does not have a higher level management. If it's needed to discover devices without entering their mac manually as a peer list, then it's probably better to look for ESP-Mesh which is intended to manage a fleet of devices. This ESP-Mesh-Wrapper is a wrapper for Arduino framework to make usage ESP-Mesh easier.
    • but I'm not really much satisfied with the custom protocols ideas, the ESP is at its best with wifi, when it comes to 2.4 GHz mesh solutions, why use a custom one while Standards exist like zigbee and Thread.

    Can ESP-Now solve the 'Provisioning' Problem or make it easier ?
    • No, the provisioning dilemma is unfortunately common to all protocols and is a Home Automation Nightmare : "Provisioning / Pairing / Joining / Configuring".

    Let's first have a look on other protocols deal with provisioning :

    • Zigbee : Is the worst I've ever seen, as the state is not visible to the user shared between a device and a server, if a device goes offline it still thinks it's paired, to overcome temporary network shortage, and if you want it to join a new network you need to actively be playing around with it to figure out how each device has a different way to be reset and then enable pairing on the gateway...

    • Wifi : has a secred that each device has to know, but how can you give that secret, the own hotspot is not easy, as you need a webserver and manual entry, there are some protocols designed to make that easier :

    • DDP Device Provisioning Protocol

    • SmartConfig : this is another example, you can read more about Unified Provisioning on the Espressif website

    Now, we might find wifi inconvenient for two reasons, provisioning and also range which is very limited compared to mesh networks that have repeaters.

    • Custom RF : e.g. the same here applies for ESP-NOW or any other custom mesh such as the SimpleMesh which is as it's names suggest simple, but also stable. Changing the battery is not more complex than changing the battery. The way I solved the configuration issue there, is by an automated script run after attaching a devices with the debugger, it reads the serial number, which has an associated short id coming from a config file. That short id will be used in radio packets as unique ID, I could also assign a master key for encryption, but I did not need security as it is only about light and temperature values, no control.

    So when it comes to ESP-Now, you also need to configure each of them to give them the security with "esp_now_set_pmk()" if you do not want everyone using your devices to spy on each other. The problem gets bigger if you want to give your devices to a user that has to use it securely on his network with a unique pmk and that user does not want to be flashing and messing with a configuration.

    To summarize, there's no way around a "provisioning" process whatever protocol you use unless you need no security, nor networks isolation, or can flash the secret uniquely for each device, which is also a sort of provisioning. And not mentioning the provisioning that needs an internet connection to synchronise with a backend and user account.

    ← PreviousESP32 C3 DevKit M1Next →ESP-Mesh
    On this page
    • Relates to
    • Overview
      • Github
      • ESP-Now reference
      • Status
    • Examples
      • Broadcast
      • MQTT Wifi Gateway
    • FAQ - Discussion
    Open page ×