ESP-NOW Two-Way Communication Between ESP32 Boards

In this guide, we’ll show you how to establish a two-way communication between two ESP32 boards using ESP-NOW communication protocol. As an example, two ESP32 boards will exchange sensor readings (with a range in open field up to 220 meters ~ 722 feet).

ESP-NOW Two-Way Communication Between ESP32 Boards

Watch the Video Introduction

For an introduction to ESP-NOW protocol, you can watch the following video:

If you want to learn more about ESP-NOW, you can read this guide: Getting Started with ESP-NOW (ESP32 with Arduino IDE).

Introducing ESP-NOW

ESP-NOW is a connectionless communication protocol developed by Espressif that features short packet transmission. This protocol enables multiple devices to talk to each other without using Wi-Fi.

ESP-NOW - ESP32 Logo

This is a fast communication protocol that can be used to exchange small messages (up to 250 bytes) between ESP32 boards. ESP-NOW is very versatile and you can have one-way or two-way communication in different arrangements.

In this tutorial, we’ll show you how to establish a two-way communication between two ESP32 boards.

ESP-NOW ESP32 Two-Way Communication Protocol

Note: read our ESP-NOW Getting Started Guide for a complete introduction to ESP-NOW protocol with ESP32.

Project Overview

The following diagram shows a high-level overview of the project we’ll build.

ESP-NOW Two-Way Communication - Send Sensor Readings Between Boards
  • In this project we’ll have two ESP32 boards. Each board is connected to an OLED display and a BME280 sensor;
  • Each board gets temperature, humidity and pressure readings from their corresponding sensors;
  • Each board sends its readings to the other board via ESP-NOW;
  • When a board receives the readings, it displays them on the OLED display;
  • After sending the readings, the board displays on the OLED if the message was successfully delivered;
  • Each board needs to know the other board MAC address in order to send the message.

In this example, we’re using a two-way communication between two boards, but you can add more boards to this setup, and having all boards communicating with each other.

Prerequisites

Before proceeding with this project, make sure you check the following prerequisites.

ESP32 add-on Arduino IDE

We’ll program the ESP32 using Arduino IDE, so before proceeding with this tutorial you should have the ESP32 add-on installed in your Arduino IDE. Follow the next guide:

Install libraries

Install the following libraries in your Arduino IDE. These libraries can be installed through the Arduino Library Manager. Go to Sketch Include LibraryManage Libraries and search for the library name.

Parts Required

For this tutorial you need the following parts:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Getting the Boards MAC Address

To send messages between each board, we need to know their MAC address. Each board has a unique MAC address (learn how to Get and Change the ESP32 MAC Address).

Upload the following code to each of your boards to get their MAC address.

// Complete Instructions to Get and Change ESP MAC Address: https://RandomNerdTutorials.com/get-change-esp32-esp8266-mac-address-arduino/

#include "WiFi.h"
 
void setup(){
  Serial.begin(115200);
  WiFi.mode(WIFI_MODE_STA);
  Serial.println(WiFi.macAddress());
}
 
void loop(){

}

View raw code

After uploading the code, press the RST/EN button, and the MAC address should be displayed on the Serial Monitor.

ESP32 board MAC Address with Arduino IDE Serial Monitor

Write down the MAC address of each board to clearly identify them.

ESP32 board MAC Address label

Schematic Diagram

Wire an OLED display and a BME280 sensor to each ESP32 board. Follow the next schematic diagram.

ESP32 wiring schematic diagram to BME280 sensor and OLED display

You can use the following table as a reference when wiring the BME280 sensor.

BME280ESP32
VIN3.3V
GNDGND
SCLGPIO 22
SDAGPIO 21

You can also follow the next table to wire the OLED display to the ESP32.

OLED DisplayESP32
GNDGND
VCCVIN
SCLGPIO 22
SDAGPIO 21

Learn more about interfacing multiple I2C peripherals with the ESP32.

ESP32 Two-Way Communication ESP-NOW Code

Upload the following code to each of your boards. Before uploading the code, you need to enter the MAC address of the other board (the board you’re sending data to).

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp-now-two-way-communication-esp32/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

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

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

Adafruit_BME280 bme;

// REPLACE WITH THE MAC Address of your receiver 
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// Define variables to store BME280 readings to be sent
float temperature;
float humidity;
float pressure;

// Define variables to store incoming readings
float incomingTemp;
float incomingHum;
float incomingPres;

// Variable to store if sending data was successful
String success;

//Structure example to send data
//Must match the receiver structure
typedef struct struct_message {
    float temp;
    float hum;
    float pres;
} struct_message;

// Create a struct_message called BME280Readings to hold sensor readings
struct_message BME280Readings;

// Create a struct_message to hold incoming sensor readings
struct_message incomingReadings;

// Callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  if (status ==0){
    success = "Delivery Success :)";
  }
  else{
    success = "Delivery Fail :(";
  }
}

// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));
  Serial.print("Bytes received: ");
  Serial.println(len);
  incomingTemp = incomingReadings.temp;
  incomingHum = incomingReadings.hum;
  incomingPres = incomingReadings.pres;
}
 
void setup() {
  // Init Serial Monitor
  Serial.begin(115200);

  // Init BME280 sensor
  bool status = bme.begin(0x76);  
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  // Init OLED display
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
 
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // Once ESPNow is successfully Init, we will register for Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  esp_now_peer_info_t peerInfo;
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  // Register for a callback function that will be called when data is received
  esp_now_register_recv_cb(OnDataRecv);
}
 
void loop() {
  getReadings();
 
  // Set values to send
  BME280Readings.temp = temperature;
  BME280Readings.hum = humidity;
  BME280Readings.pres = pressure;

  // Send message via ESP-NOW
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &BME280Readings, sizeof(BME280Readings));
   
  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }
  updateDisplay();
  delay(10000);
}
void getReadings(){
  temperature = bme.readTemperature();
  humidity = bme.readHumidity();
  pressure = (bme.readPressure() / 100.0F);
}

void updateDisplay(){
  // Display Readings on OLED Display
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("INCOMING READINGS");
  display.setCursor(0, 15);
  display.print("Temperature: ");
  display.print(incomingTemp);
  display.cp437(true);
  display.write(248);
  display.print("C");
  display.setCursor(0, 25);
  display.print("Humidity: ");
  display.print(incomingHum);
  display.print("%");
  display.setCursor(0, 35);
  display.print("Pressure: ");
  display.print(incomingPres);
  display.print("hPa");
  display.setCursor(0, 56);
  display.print(success);
  display.display();
  
  // Display Readings in Serial Monitor
  Serial.println("INCOMING READINGS");
  Serial.print("Temperature: ");
  Serial.print(incomingReadings.temp);
  Serial.println(" ºC");
  Serial.print("Humidity: ");
  Serial.print(incomingReadings.hum);
  Serial.println(" %");
  Serial.print("Pressure: ");
  Serial.print(incomingReadings.pres);
  Serial.println(" hPa");
  Serial.println();
}

View raw code

How the code works

We’ve covered in great detail how to interact with the OLED display and with the BME280 sensor in previous tutorials. Here, we’ll just take a look at the relevant parts when it comes to ESP-NOW.

The code is well commented so that you understand what each line of code does.

To use ESP-NOW, you need to include the next libraries.

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

In the next line, insert the MAC address of the receiver board:

uint8_t broadcastAddress[] = {0x30, 0xAE, 0xA4, 0x07, 0x0D, 0x64};

Create variables to store temperature, humidity and pressure readings from the BME280 sensor. These readings will be sent to the other board:

// Define variables to store BME280 readings to be sent
float temperature;
float humidity;
float pressure;

Create variables to store the sensor readings coming from the other board:

// Define variables to store incoming readings
float incomingTemp;
float incomingHum;
float incomingPres;

The following variable will store a success message if the readings are delivered successfully to the other board.

// Variable to store if sending data was successful
String success;

Create a structure that stores humidity, temperature and pressure readings.

typedef struct struct_message {
  float temp;
  float hum;
  float pres;
} struct_message;

Then, you need to create two instances of that structure. One to receive the readings and another to store the readings to be sent.

The BME280Readings will store the readings to be sent.

// Create a struct_message called BME280Readings to hold sensor readings
struct_message BME280Readings;

The incomingReadings will store the data coming from the other board.

// Create a struct_message to hold incoming sensor readings
struct_message incomingReadings;

Then, we need to create two callback functions. One will be called when data is sent, and another will be called when data is received.

OnDataSent() callback function

The OnDataSent() function will be called when new data is sent. This function simply prints if the message was successfully delivered or not. If the message is delivered successfully, the status variable returns 0, so we can set our success message to “Delivery Success”:

Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
if (status ==0) {
  success = "Delivery Success :)";
}

If the success message returns 1, it means the delivery failed:

else {
  success = "Delivery Fail :(";
}

OnDataRecv() callback function

The OnDataRecv() function will be called when a new packet arrives.

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {

We save the new packet in the incomingReadings structure we’ve created previously:

memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));

We print the message length on the serial monitor. You can only send 250 bytes in each packet.

Serial.print("Bytes received: ");
Serial.println(len);

Then, store the incoming readings in their corresponding variables. To access the temperature variable inside incomingReadings structure, you just need to do call incomingReadings.temp as follows:

incomingTemp = incomingReadings.temp;

The same process is done for the other variables:

incomingHum = incomingReadings.hum;
incomingPres = incomingReadings.pres;

setup()

In the setup(), initialize ESP-NOW.

if (esp_now_init() != ESP_OK) {
  Serial.println("Error initializing ESP-NOW");
  return;
}

Then, register for the OnDataSent callback function.

esp_now_register_send_cb(OnDataSent);

In order to send data to another board, you need to pair it as a peer. The following lines register and add a new peer.

// Register peer
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;

// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){
  Serial.println("Failed to add peer");
  return;
}

Register for the OnDataRecv callback function.

esp_now_register_recv_cb(OnDataRecv);

loop()

In the loop(), we call the getReadings() function that is responsible for getting new temperature readings from the sensor. That function is created after the loop().

After getting new temperature, humidity and pressure readings, we update our BME280Reading structure with those new values:

BME280Readings.temp = temperature;
BME280Readings.hum = humidity;
BME280Readings.pres = pressure;

Then, we can send the BME280Readings structure via ESP-NOW:

// Send message via ESP-NOW
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &BME280Readings, sizeof(BME280Readings));

if (result == ESP_OK) {
  Serial.println("Sent with success");
}
else {
  Serial.println("Error sending the data");
}

Finally, call the updateDisplay() function that will update the OLED display with the readings coming from the other ESP32 board.

updateDisplay();

The loop() is executed every 10 seconds.

That’s pretty much how the code works. You should upload the code to both of your boards. You just need to modify the code with the MAC address of the board you’re sending data to.

Recommended reading: Guide for OLED Display with ESP32 and Guide for BME280 Sensor with ESP32.

Demonstration

After uploading the code to both boards, you should see the OLED displaying the sensor readings from the other board, as well as a success delivery message.

ESP32 ESP-NOW Protocol Exchange Data Demonstration

As you can see, it’s working as expected:

ESP32 ESP-NOW Protocol Exchange Data Demonstration

We tested the communication range between the two boards, and we are able to get a stable communication up to 220 meters (approximately 722 feet) in open field. In this experiment both ESP32 on-board antennas were pointing to each other.

ESP-NOW communication range test with ESP32 boards

Wrapping Up

In this tutorial we’ve shown you how to establish a two-way communication with two ESP32 boards using ESP-NOW. This is a very versatile communication protocol that can be used to send packets with up to 250 bytes. ESP-NOW communication protocol can also be used with ESP8266 boards: Getting Started with ESP-NOW (ESP8266 NodeMCU with Arduino IDE).

As an example, we’ve shown you the interaction between two boards, but you can add many boards to your setup. You just need to know the MAC address of the board you’re sending data to.

We’ll be publishing more tutorials about ESP-NOW, so stay tuned. Additionally, write a comment below saying which tutorial you would like to see with ESP-NOW.

To learn more about the ESP32 board, take a look at our resources:

Thanks for reading.


Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our weekly newsletter!

99 thoughts on “ESP-NOW Two-Way Communication Between ESP32 Boards”

  1. Hi Rui,

    Great write up! But I am having a lot of issues compiling the code; the error is with the library. For some reason the Arduino IDE is unable to find it. I did install all of the board libraries for esp32, esp12 and esp8266. I am able to run their example sketches without any issues. I tried this on 3 different Window PC’s without much luck. Any help is welcome. Abrigado!

    Reply
      • Hi Sara,

        I get the following error when compiling the ESP_Now_Les_Example_1 sketch

        exit status 1
        esp_now.h: No such file or directory

        Thanks for helping me out!! 🙂

        Brett

        Reply
        • Hi.
          The esp_now.h file is installed by default.
          So, make sure you have an ESP32 board selected in the Boards menu and that the ESP32 boards are properly installed.
          Also, can you run the example sketch in File > Examples > ESP32 > ESPNow?
          Regards,
          Sara

          Reply
          • Hi Sara,
            I found espnow.h is for the ESP8266, and esp_now.h is for the ESP32.
            I have been taking notes as I make mistakes…and find solutions.
            With esp8266 also make sure to add:
            WiFi.mode(WIFI_STA);
            WiFi.disconnect(); // it will improve signal responses.

  2. Can you still use any of the Wi-Fi modes while using ESP-NOW?
    How can this configuration share their data with the outside world?

    Reply
  3. Hi Rui,
    This method of communication between ESP32 boards is very interesting.
    I built an arduino based audio controller, for my whole home audio system.
    I want to add control from a second station in another room, and upgrade to either an ESP32 or ESP8266.
    After seeing this system, I think it could be adapted to do what I need.
    I want it to display the current Mode in both rooms, yet allow the source selection, power off commands to be updated from either location.
    I will set up this project as a start, so I can go through the code step by step.
    Thank you, and Sara, so much for all the great tutorials!

    Reply
  4. Hi Sara and Rui,
    Great tutorial.
    As I saw in the comments in the tutorial for the “ESP-NOW One-Way communication”, it is possible to use the ESP-NOW with Wi-Fi (it is possible right?).

    And about the ESP32-CAM, does the ESP-NOW works well with it? I’m thinking in building an web server in the ESP32-CAM and this server receives the data os temperature, pressure, umidity from another ESP32, via ESP-NOW.

    Reply
  5. It is not quite the same. I saw it long time ago, and it is in the Master slave configuration.
    What Rui did here is like ESP-NOW combo mode, when each of the boards can talk when he want and is not master slave. Both are equal.

    “https://www.espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf” , page 2.7, table 2-1

    Reply
  6. Assuming i do not have sensors and no float data, if a replace float with double , can i send 8 bytes to the other end ?
    Or better,
    float replaced with double
    float replaced with double
    float replaced with double
    so in this case i can send 24 bytes from one board to other.
    I am new to that, so correct me if i am wrong.

    Reply
  7. I just found this 15 minutes ago and now it’s up and running! I just happened to get some BME280 (s) and some OLED (s) last week.

    Reply
  8. I do not know what is wrong on my side but both of the boards they display on the port monitor that they do not find BME280.
    I am surprised because they are just 4 wire.
    The power is OK 3.3V
    Also the display is completely blank/black.
    I put for the display 5V from USB as power.
    Any suggestion.

    Reply
  9. I am at the end of the rope.
    1.I am using a breakout from sparkfun for BME280:
    SparkFun Atmospheric Sensor Breakout – BME280-SEN-13676
    The address is by default 0x77 (default, ‘1’ side) – The same like in
    Adafruit library:
    #define BME280_ADDRESS (0x77) // Primary I2C Address
    I tried the simple BME test sketch from
    “ESP32 with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity)”
    and all the time i get the same error:
    “Could not find a valid BME280 sensor, check wiring!”
    On the Adafruit Feather board : “Assembled Adafruit HUZZAH32 – ESP32 Feather Board – with Stacking Headers”
    SCL pin is pin 11 on the battery side and
    SDA is pin 12.
    I have two identical boards and i exclude possibility to be both of them bad.
    Can anybody give me a suggestion because i do not see any one now.

    Reply
    • Hi Ion,
      I suggest you to try a different sensor. In my case, I didn’t have a BME280 and used other I²C sensors… or better, with analog or one-wire sensors.

      One question: The I²C pins in the Adafruit boards follows a different numeration? In all my ESP32 boards the SCL pin is the 22 and the SDA is the 21… this is the other suggestion that I can tell you right now…. I’m not as good as Rui or Sara!

      Reply
      • Thank you Eduardo. I will try tomorrow with different sensors if i get them in time. For pinout, i just follow the Adafruit pinout table, not the numbers, like here
        “https://learn.adafruit.com/adafruit-huzzah32-esp32-feather/pinouts”

        Reply
        • I never used this board.
          Now I understand when you said that used pins 11 and 12.
          Well, I’ll try to find some free time in this next days and try to organize and document what I built this weekend. I built a project using I²C sensors a ESP32 and a ESP32-CAM. After organizing it I can upload the project to my github, if someone is interested.

          Reply
    • Hi Ion.
      The SDA and SCL pins of the Huzzah 32 are: GPIO 23 (SDA) and GPIO 22 (SCL)
      By default, our code uses GPIO 21 (SDA) and GPIO 22 (SCL). So, this might be the problem.
      I suggest that you run an I2C scanner sketch to see if your board is able to find the sensor. The sketch is this: https://randomnerdtutorials.com/esp32-esp8266-i2c-lcd-arduino-ide/
      If it doesn’t detect any sensor on the I2C pins, you need to add a few lines of code so that it uses other I2C pins.

      To use other I2C pins, in the setup() add the following:
      I2CBME.begin(23, 23, 400000);

      Then, initialize the sensor as follows:
      if (!bme.begin(0x76, &I2CBME)) {
      Serial.println(“Could not find a valid BME280 sensor, check wiring!”);
      while (1);
      }

      This should solve the problem.

      Also, this tutorial might be useful: https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/

      Let me know the results.
      Regards,
      Sara

      Reply
      • Hello Sara,
        First i got an error that i have too many wifi. I tried each one at the time, but no luck. I deleted all. and of course i get
        “WiFi.h: No such file or directory”
        Which one to download again and use ?
        Thank you

        Reply
      • The scanner found the bme280 at address 77, for both of them.
        How about the I2C address for display?
        What is the brand and model of display you used ?
        More news tomorrow as i just bought 2 new NodeMCU from Amazon canada with delivery today.
        The I2C is on port GPIO 21 and 22.

        Reply
  10. Hello Sara,
    I will do the test immediately.
    is it for sure
    I2CBME.begin(23, 23, 400000);
    because above you said it use pins 22,23 .
    “The SDA and SCL pins of the Huzzah 32 are: GPIO 23 (SDA) and GPIO 22 (SCL)”

    Reply
  11. I made it to work with only one BME280
    In the sketch where i do not have BME, i just comment the “while” line like here
    ” // while (1); ”
    Now i have communication on both directions and i wait to get the parts and put them on the breadboard.
    One side display on the port monitor the temperature and Hum and Press from the other side like here
    13:30:50.317 -> Last Packet Send Status: Delivery Success
    13:30:50.317 -> INCOMING READINGS
    13:30:50.317 -> Temperature: 25.60 �C
    13:30:50.317 -> Humidity: 38.87 %
    13:30:50.317 -> Pressure: 987.90 hPa
    13:30:58.316 ->
    13:30:58.316 -> Bytes received: 12
    13:31:00.315 -> Sent with success

    And the other monitor, does not have info about the value of temp,hum, or pressure and display
    13:32:58.428 -> INCOMING READINGS
    13:32:58.428 -> Temperature: 0.00 �C
    13:32:58.428 -> Humidity: 0.00 %
    13:32:58.428 -> Pressure: 0.00 hPa
    13:33:00.362 ->
    13:33:00.362 -> Bytes received: 12
    13:33:08.426 -> Sent with success
    13:33:08.426 ->
    13:33:08.426 -> Last Packet Send Status: Delivery Success

    I want to Thank You in particular to Sara for patience to babysit me.
    I will update tomorrow when i have all the parts.
    Thank you ALL.

    Reply
      • Interesting. I have to look closer to it even though it looks big.
        I did a thermostat one time and i used MCP7940N.
        But of course i did my own PCB and i put it on the same board with the display, and BME680.

        Reply
        • You took the IC MCP7940N and built your own PCB with battery? Congratulations! It really looks great!

          The ZS-042 may look big, but is because the battery which powers it. It is a CR2032 battery (3V, 2cm of diammeter). The dimensions of the module is 2cm x 4cm.

          Also, the ZS-042 is a very nice module to use. It is I²C powered too. Of course the DS3231 don’t have all the features of the MCP7940N, but it solves my problems here!

          God luck Ion!

          Reply
          • If you write me at [email protected] i can send you a pdf print of the board.
            I do all my boards and i am happy to do them how i want, not having a pcb designer doing it 5 times until i am happy.
            Some times, i do small changes and it take me few hours and i am done.

  12. I have a question. I put an extra row on the display after pressure to display the lenght of the bytes received.
    Like here
    display.print(“Bytes Received: “);
    display.print(“len”);
    But here of course is just printing len
    I tried as a variable like is defined here
    Serial.print(“Bytes received: “);
    Serial.println(len);
    Then i wrote on the display

    display.print(“Bytes Received: “);
    display.print(len);
    and i got an error
    ESP-NOW_LEFT:177:17: error: ‘len’ was not declared in this scope
    display.print(len);
    ^
    exit status 1
    ‘len’ was not declared in this scope
    What should i write to display the number of bytes received ?
    Thank you

    Reply
    • Hi Ion.
      When you print “len”, it is a String. So, it will output exactly that “len”.
      What is happening is that the variable len is defined locally inside the OnDataRecv() function. When you define a variable locally, you can’t access it anywhere else in the code except where it was defined.
      You need to create a global variable that can be accessed anywhere in the code. Usually, variables created outside functions are global.
      To do that, you can for example: create a variable called messageLength before the setup(), for example:
      int messageLength;
      Then, inside the OnDataRecv() function update the messageLength variable to match the bytes received. You can add the following line:
      messageLength = len;
      Now, you can use the messageLength variable to display the number of bytes received:
      display.print(“Bytes Received: “);
      display.print(messageLength);
      I hope this helps.
      Regards,
      Sara

      Reply
  13. Yes I like the project a lot .What would be nice is a real time graph for the readings done on the biggest color Tiff display you can get. Have the reading and background in different colors. And maybe add some graphics. Just a thought. Thanks for the projects.

    Rainman…….

    Reply
  14. hi! can someone help me solve my problem.
    i used similar sensor and got this message from serial monitor : “Sent with success
    Last Packet Send Status: Delivery Fail”

    is it sent or not? I open the serial monitor of the received ESP32 but nothing in the monitor. so it didnt received any data?

    Reply
    • Hi Josephine.
      That means that the command to send the message was successfully executed but the other board didn’t receive the package.
      It can be due to:
      – you didn’t inserted the receiver MAC address or you’ve inserted it wrong;
      – the receiver structure doesn’t match the sender structure
      – you’ve forgotten to upload the receiver code to the other board.
      I hope this helps.
      Regards,
      Sara

      Reply
  15. Hi,

    I am planning to do a project named wireless call buttons. This project has two main devices. One is Button(esp32) and another one is receiver(esp32). The buttons are going to implement in patient rooms in a hospital. The receiver kept in one corner. When the patient press button, the receiver has to receive message from the specific button.

    May i know is this possible with ESP, because every floor in hospital has more than 10 rooms and the distance between Room No:10(button10) and receiver will be 200 meters. It may not line of sight also. In my case we should not use internet.

    ESP-Now i can use, but my doubt is how 200 meters is possible in this case?

    Reply
    • Hi.
      You have to experiment. But I’m not sure if it is possible to get a distance of 200 meters inside a building with walls and obstacles – seems very unlikely.
      But you really have to try it to figure it out.
      Regards,
      Sara

      Reply
  16. Maybe you can use a repeater.
    Put a receiver at room No:5, collect data from all 10 rooms and resend it to nurse station – your main receiver. It is unlikely that all the 10 buttons will be pressed in the same time, I mean, same fraction of second and make a collision on the traffic. On the repeater i suggest to have a ESP to receive data, a PIC or whatever processor to store it, and a second ESP to send it further. In this way you have a receiver ESP and a transmitter ESP. You can explore the options. Do not forget, but in the hospitals everything must be redundant. Is like planes or space shuttle. If one line fail, MUST be a second to instantly replace it and keep working.
    If the patient in room 8 press the button to call the nurse because he feel ill and needs assistance, that message MUST go to nurse station.

    Reply
    • Complementing Ion Gheorghe’s idea, wouldn’t it be nice for Yuvaraj create a Wi-Fi web server with one ESP32 and the others (doesn’t need to be a ESP32, can be a ESP8266, PIC or something cheaper) and when a button in one device is pressed the web server shows to the nurse the exactly device wich pressed the button. To solve the redundancy issue pointed by Ion, the device with the pacient sends the signal continually untill the moment that the nurse do something in the web server to tell to the pacient’s device that he/she received the message (in ESP-NOW, there is a risk of the nurse’s device receive the message but he/she don’t see it because is busy with another pacient). Also, the Wi-Fi repeaters suggested by Ion probably will work better in this sittuation.

      Of course, this suggestion is just a guessing that came in to my mind, built over I imagined whe I read Yuvaraj’s comment.

      Reply
      • Excelente idea Eduardo.
        Of course at nurse station we can get an output of the receiving ESP to drive also a buzzer or similar.
        The nurse might be busy surfing the net, chatting on the phone, having a coffee, or …..
        BUT, whatever you put in a hospital, be sure it is 1000000% reliable.
        The patients and hospitals will not hesitate to sue you for smallest issue.
        The system also must pass Safety Approval.
        I wanted to propose to a hospital in Toronto a wireless thermostat .
        Yes, a dummy thermostat but with a lot of benefits and energy saving for hospital. The safety tests i had to pass, was so expensive that i just renounced. They told me that temperature in some of the rooms is critical, and constantly recorded, and they cannot afford to use whatever system and lose some patients, medicines or similars.

        Reply
        • Yes, Ion is more right impossible…
          The best suggestion for you, Yuvaraj, is first test your idea in a different space and after beig sure that you figured out in your mins all the suing possibilities (or at least almost, because human creativity is something really to beat) I believe that you can suggest this project for your superiors.

          Well thought Ion!

          Reply
  17. Hi , i have a specific question , i have 100 points(esp8266) that have a button, this button is in deepsleep mode, when the people press the button this button send a data via espnow and go to deepsleep mode, the esp32 that receive the data can support 100 call button ? not all the 100 buttons are pressed at the same time , if this possible or i need maximun 10 call buttons ?

    can i register one button send data and after disconect this peer to de server (espnow esp32)…

    thanks

    Reply
    • Hi.
      If all buttons are in deep sleep mode and only the “receiver” is awake, I think you shouldn’t have problems with all the buttons.
      It should also work for your scenario, if you simply use the 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF MAC address. All receivers that are awake will receive the message – in your case, it’s just one.
      But as I haven’t experimented with so many devices, I can’t really tell what happens with all those buttons.
      Regards,
      Sara

      Reply
    • Hello Paolo,
      What i see:
      1-Buttons are not registered anywhere. As long as as you tell them where to send data – MAC – they do not care how many they are, nor the receiver knows in advance, and you can have in my opinion 1000s.
      2-You said, that not every button is pressed in the same time. This is a very fine statement. Button 1 is pressed now, and button 2 is pressed a fraction of second after.
      So while the server is busy receiving data from button 1, data from button 2 is lost.
      This involve your creativity in coding. Each message sent must have the MAC of sender. The receiver, must acknowledge the sender back that the message arrived in full.
      The sender button does not have to go to sleep, or permit another press until he get the response that his first message was received OK. If the receiver button does not get the acknowledge reply in let’s say 100 ms, it has to resend the message.
      100ms it is a pure imaginary value. By trying with one button only, you can find out the total time until you get the response, and replace the 100 ms.
      So, the transmitter button, will resend the message until it receive the acknowledge that the message was received.
      Here it is the BIG picture of 100 buttons or more.
      Imagine an army of messages at the gate of receiver , trying to be received by the server.
      Of course, one by one in time will be received, and finally the last one is in. But during all that period, all the buttons waiting a reply, will not respond to eventual users, nor sleep.
      BUT your purpose of the buttons is to send SUCCESSFULLY a message to server.
      Try to imagine …..

      Reply
  18. Hey guys, thanks a lot for your explanation!

    In my case i have one ds18b20 sensor connectedto one board and i have another board sending the measurement interval and resolution to this board in order to perform the measurements following the interval and resolution that it has received.

    My problem is that when i send the interval and resolution to the second board it only works correctly when both boards are close. When they are a bit more far away, it only receives the interval, instead, it doesn’t update the resolution values.
    I send the data like you the temp, hum, pres.

    Is it possible that due to the distance, it only receives a part of the message correctly (interval) and lose the resolution part? I thought that if the message reached the destination, reached the whole message.

    I calculate that interval reachs up to 18 m, instead, interval and resolution values only reach up to 12 m.

    I don’t know if you, Rui and Sara or someone have faced this kind of problems, but i would thank a lot your help.

    I’m looking forward to hearing from you!

    Reply
    • Hi.
      That issue is very strange. It seems that due to the distance, it doesn’t receive the whole message.
      Maybe you can try sending different messages. One with the interval and other with the resolution one after the other and see if that solves the problem.
      Regards,
      Sara

      Reply
      • Hi Sara. But if both messages come from the same board, how can i identify them as an interval message and resolution message?

        Normally i identified the message by the MAC of the board coming from. But in this case both messages come from the same board, so both have the same MAC.

        Thank you!

        Reply
        • Hi.
          You can send the messages as a string, in which the interval message starts with an i and the resolution message starts with an r: for example
          “i20”
          “r1250”
          Then, on the receiver, you can split the strings to get only the number. Then, you can convert them to int or float or other variable type is more suitable.
          This is just a suggestion.
          Regards,
          Sara

          Reply
    • Further to my request above do we have a tutorial on using ESP NOW between ESP32 and ESP8266. sure it will be of value to many. Cheers

      Reply
      • Hi.
        No, I don’t have that specific project.
        But what you have to do for the ESP8266 is to combine a sender and receiver ESP8266 code on the same sketch.
        Regards,
        Sara

        Reply
  19. Hey,
    I am trying to create a Wi-Fi mesh using esp32 where one esp32 node (AP) is connected to a webserver (as demonstrated in your tutorials) and the other esp32 nodes communicate with each other using esp-now ( 2 way communication). My question is how do i Incorporate the client-server and peer to peer infrastructure in one to complete a mesh.
    I am also trying to generate hops between esp32 incase one is out of range of the AP. I’d appreciate your help.

    Thanks

    Reply
    • Hi.
      To do that, you need to define a Wi-Fi channel for the access point and a different wi-fi channel for ESP-NOW.
      We’ll be publishing a project with Wi-Fi + ESP-NOW soon, so stay tuned.
      Regards,
      Sara

      Reply
  20. hi im using espnow on 2 * esp32s, one as a master sending data and 1 as a slave recieving data, I have seen examples where a master can send to many slaves. is there any examples of a slave recieving sensor details from more than 1 master. maybe in a closed mesh network??
    board 1 data send >>>
    board 2 data send >>>
    board 3 data recieve <<<<<< from board 1 and board 2?????

    Reply
  21. HI,
    Working with this code from the beginning, I now have bidirectional comms sent over ESP-NOW. But I am only in the beginning of my code. One ESP32 has a couple of DS18B20s, and it sends indoor and outdoor temperatures to it’s local display, and the remote ESP32’s display too. (GREAT! BTW!!). I created a new struct for information of switch (button) states on the return from the remote, That data will eventually act as remote control switches for functions on the local. The switches are readable on the local, so the rest will be trivial, but I came to a question because I would like to save space.

    Why do you have local variables as well as a struct for the data? My guess is because then you can use one struct to transmit either way. Is this the case? And, since I am using different data and 2 structs, then I should be able to omit the local global variables and just use the struct variables throughout the code, (since the structs are global) correct? Or am I missing something?

    Thanks,
    Dave K

    Reply

Leave a Reply to Eduardo Alvim Cancel reply

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.