ESP-NOW with ESP32: Receive Data from Multiple Boards (many-to-one)

This tutorial shows how to set up an ESP32 board to receive data from multiple ESP32 boards via ESP-NOW communication protocol (many-to-one configuration). This configuration is ideal if you want to collect data from several sensors nodes into one ESP32 board. The boards will be programmed using Arduino IDE.

ESP-NOW with ESP32: Receive Data from Multiple Boards many-to-one

We have other guides related with ESP-NOW that you might be interested in:

Project Overview

This tutorial shows how to setup an ESP32 board to receive data from multiple ESP32 boards via ESP-NOW communication protocol (many-to-one configuration) as shown in the following figure.

ESP-NOW with ESP32 Receive Data from Multiple Boards (many-to-one) Project Overview
  • One ESP32 board acts as a receiver/slave;
  • Multiple ESP32 boards act as senders/masters. We’ve tested this example with 5 ESP32 sender boards and it worked fine. You should be able to add more boards to your setup;
  • The sender board receives an acknowledge message indicating if the message was successfully delivered or not;
  • The ESP32 receiver board receives the messages from all senders and identifies which board sent the message;
  • As an example, we’ll exchange random values between the boards. You should modify this example to send commands or sensor readings (exchange sensor readings using ESP-NOW).

Note: in the ESP-NOW documentation there isn’t such thing as “sender/master” and “receiver/slave”. Every board can be a sender or receiver. However, to keep things clear we’ll use the terms “sender” and “receiver” or “master” and “slave”.

Prerequisites

We’ll program the ESP32 boards using Arduino IDE, so before proceeding with this tutorial, make sure you have these boards installed in your Arduino IDE.

Parts Required

To follow this tutorial, you need multiple ESP32 boards. All ESP32 models should work. We’ve experimented with different models of ESP32 boards and all worked well (ESP32 DOIT board, TTGO T-Journal, ESP32 with OLED board and ESP32-CAM).

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 Receiver Board MAC Address

To send messages via ESP-NOW, you need to know the receiver board’s MAC address. Each board has a unique MAC address (learn how to Get and Change the ESP32 MAC Address).

Upload the following code to your ESP32 receiver board to get is MAC address.

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/get-change-esp32-esp8266-mac-address-arduino/
  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.
*/
#ifdef ESP32
  #include <WiFi.h>
  #include <esp_wifi.h>
#else
  #include <ESP8266WiFi.h>
#endif

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

  Serial.print("ESP Board MAC Address: ");
  #ifdef ESP32
    WiFi.mode(WIFI_STA);
    WiFi.STA.begin();
    uint8_t baseMac[6];
    esp_err_t ret = esp_wifi_get_mac(WIFI_IF_STA, baseMac);
    if (ret == ESP_OK) {
      Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
                    baseMac[0], baseMac[1], baseMac[2],
                    baseMac[3], baseMac[4], baseMac[5]);
    } else {
      Serial.println("Failed to read MAC address");
    }
  #else
    Serial.println(WiFi.macAddress());
  #endif
}
 
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

ESP32 Sender Code (ESP-NOW)

The receiver can identify each sender by its unique MAC address. However, dealing with different MAC addresses on the Receiver side to identify which board sent which message can be tricky.

So, to make things easier, we’ll identify each board with a unique number (id) that starts at 1. If you have three boards, one will have ID number 1, the other number 2, and finally number 3. The ID will be sent to the receiver alongside the other variables.

As an example, we’ll exchange a structure that contains the board id number and two random numbers x and y as shown in the figure below.

ESP-NOW with ESP32 Receive Data from Multiple Boards (many-to-one) Sample Data

Upload the following code to each of your sender boards. Don’t forget to increment the id number for each sender board.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp-now-many-to-one-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>

// REPLACE WITH THE RECEIVER'S MAC Address
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
    int id; // must be unique for each sender board
    int x;
    int y;
} struct_message;

// Create a struct_message called myData
struct_message myData;

// Create peer interface
esp_now_peer_info_t peerInfo;

// 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");
}
 
void setup() {
  // Init Serial Monitor
  Serial.begin(115200);

  // 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
  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;
  }
}
 
void loop() {
  // Set values to send
  myData.id = 1;
  myData.x = random(0,50);
  myData.y = random(0,50);

  // Send message via ESP-NOW
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
   
  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }
  delay(10000);
}

View raw code

How the Code Works

Include the WiFi and esp_now libraries.

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

Insert the receiver’s MAC address on the following line.

uint8_t broadcastAddress[] = {0x30, 0xAE, 0xA4, 0x15, 0xC7, 0xFC};

Then, create a structure that contains the data we want to send. We called this structure struct_message and it contains three integer variables: the board id, x and y. You can change this to send whatever variable types you want (but don’t forget to change that on the receiver side too).

typedef struct struct_message {
  int id; // must be unique for each sender board
  int x;
  int y;
} struct_message;

Create a new variable of type struct_message that is called myData that will store the variables’ values.

struct_message myData;

Create a variable of type esp_now_peer_info_t to store information about the peer.

esp_now_peer_info_t peerInfo;

OnDataSent() callback function

Next, define the OnDataSent() function. This is a callback function that will be executed when a message is sent. In this case, this function prints if the message was successfully delivered or not.

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");
}

setup()

In the setup(), initialize the serial monitor for debugging purposes:

Serial.begin(115200);

Set the device as a Wi-Fi station:

WiFi.mode(WIFI_STA);

Initialize ESP-NOW:

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

After successfully initializing ESP-NOW, register the callback function that will be called when a message is sent. In this case, register for the OnDataSent() function created previously.

esp_now_register_send_cb(OnDataSent);

Add peer device

To send data to another board (the receiver), you need to pair it as a peer. The following lines register and add a new peer.

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;
}

loop()

In the loop(), we’ll send a message via ESP-NOW every 10 seconds (you can change this delay time).

Assign a value to each variable.

myData.id = 1;
myData.x = random(0,50);
myData.y = random(0,50);

Don’t forget to change the id for each sender board.

Remember that myData is a structure. Here assign the values that you want to send inside the structure. In this case, we’re just sending the id and random values x and y. In a practical application these should be replaced with commands or sensor readings, for example.

Send ESP-NOW message

Finally, send the message via ESP-NOW.

// Send message via ESP-NOW
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
 
if (result == ESP_OK) {
  Serial.println("Sent with success");
}
else {
  Serial.println("Error sending the data");
}

ESP32 Receiver Code (ESP-NOW)

Upload the following code to your ESP32 receiver board. The code is prepared to receive data from three different boards. You can easily modify the code to receive data from a different number of boards.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp-now-many-to-one-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>

// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
  int id;
  int x;
  int y;
}struct_message;

// Create a struct_message called myData
struct_message myData;

// Create a structure to hold the readings from each board
struct_message board1;
struct_message board2;
struct_message board3;

// Create an array with all the structures
struct_message boardsStruct[3] = {board1, board2, board3};

// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac_addr, const uint8_t *incomingData, int len) {
  char macStr[18];
  Serial.print("Packet received from: ");
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.println(macStr);
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.printf("Board ID %u: %u bytes\n", myData.id, len);
  // Update the structures with the new incoming data
  boardsStruct[myData.id-1].x = myData.x;
  boardsStruct[myData.id-1].y = myData.y;
  Serial.printf("x value: %d \n", boardsStruct[myData.id-1].x);
  Serial.printf("y value: %d \n", boardsStruct[myData.id-1].y);
  Serial.println();
}
 
void setup() {
  //Initialize Serial Monitor
  Serial.begin(115200);
  
  //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 recv CB to
  // get recv packer info
  esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));
}
 
void loop() {
  // Acess the variables for each board
  /*int board1X = boardsStruct[0].x;
  int board1Y = boardsStruct[0].y;
  int board2X = boardsStruct[1].x;
  int board2Y = boardsStruct[1].y;
  int board3X = boardsStruct[2].x;
  int board3Y = boardsStruct[2].y;*/

  delay(10000);  
}

View raw code

How the Code Works

Similarly to the sender, start by including the libraries:

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

Create a structure to receive the data. This structure should be the same defined in the sender sketch.

typedef struct struct_message {
  int id;
  int x;
  int y;
} struct_message;

Create a struct_message variable called myData that will hold the data received.

struct_message myData;

Then, create a struct_message variable for each board, so that we can assign the received data to the corresponding board. Here we’re creating structures for three sender boards. If you have more sender boards, you need to create more structures.

struct_message board1;
struct_message board2;
struct_message board3;

Create an array that contains all the board structures. If you’re using a different number of boards you need to change that.

struct_message boardsStruct[3] = {board1, board2, board3};

onDataRecv()

Create a callback function that is called when the ESP32 receives the data via ESP-NOW. The function is called onDataRecv() and should accept several parameters as follows:

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

Get the board MAC address:

char macStr[18];
Serial.print("Packet received from: ");
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
         mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.println(macStr);

Copy the content of the incomingData data variable into the myData variable.

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

Now, the myData structure contains several variables with the values sent by one of the ESP32 senders. We can identify which board send the packet by its ID: myData.id.

This way, we can assign the values received to the corresponding boards on the boardsStruct array:

boardsStruct[myData.id-1].x = myData.x;
boardsStruct[myData.id-1].y = myData.y;

For example, imagine you receive a packet from board with id 2. The value of myData.id, is 2.

So, you want to update the values of the board2 structure. The board2 structure is the element with index 1 on the boardsStruct array. That’s why we subtract 1, because arrays in C have 0 indexing. It may help if you take a look at the following image.

setup()

In the setup(), initialize the Serial Monitor.

Serial.begin(115200);

Set the device as a Wi-Fi Station.

WiFi.mode(WIFI_STA);

Initialize ESP-NOW:

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

Register for a callback function that will be called when data is received. In this case, we register for the OnDataRecv() function that was created previously.

esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));

The following lines commented on the loop exemplify what you need to do if you want to access the variables of each board structure. For example, to access the x value of board1:

int board1X = boardsStruct[0].x;

Demonstration

Upload the sender code to each of your sender boards. Don’t forget to give a different ID to each board.

Upload the receiver code to the ESP32 receiver board. Don’t forget to modify the structure to match the number of sender boards.

On the senders’ Serial Monitor, you should get a “Delivery Success” message if the messages are delivered correctly.

ESP-NOW Sending Packets Delivery Success ESP32 Serial Monitor

On the receiver board, you should be receiving the packets from all the other boards. In this test, we were receiving data from 5 different boards.

ESP-NOW Receive Data from Multiple Boards ESP32 Serial Monitor

Wrapping Up

In this tutorial, you’ve learned how to set up an ESP32 to receive data from multiple ESP32 boards using ESP-NOW (many-to-one configuration).

As an example, we’ve exchanged random numbers. In a real application, those can be replaced with actual sensor readings or commands. This is ideal if you want to collect data from several sensor nodes. You can take this project further and create a web server on the receiver board to displays the received messages.

To use Wi-Fi to create a web server and use ESP-NOW simultaneously, you need to set up the ESP32 both as a Wi-Fi station and access point. Additionally, you need to set a different Wi-Fi channel: one for ESP-NOW and the other for the station. You can follow the next tutorial:

We have other tutorials related with ESP-NOW that you may like:

Learn more about ESP32 with our resources:

Thanks for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Recommended Resources

Build a Home Automation System from Scratch » With Raspberry Pi, ESP8266, Arduino, and Node-RED.

Home Automation using ESP8266 eBook and video course » Build IoT and home automation projects.

Arduino Step-by-Step Projects » Build 25 Arduino projects with our course, even with no prior experience!

What to Read Next…


Enjoyed this project? Stay updated by subscribing our newsletter!

118 thoughts on “ESP-NOW with ESP32: Receive Data from Multiple Boards (many-to-one)”

      • I tried this a few months ago but it didn’t go well. I had stopped. I don’t know enough to understand everything. I can’t do that either. I have a small “thinking” handicap. My hamlet has been very bad for years and I write too many mistakes. Google tranlate is a friend of mine. haha
        So I am curious about Julli Esp8266 version.
        Thank you for all your beautiful work.

        Reply
  1. Hi Rui, great tutorial again I will try it soon 😉
    I was wondering if it would be possible to synchronize all boards to go to deep sleep in between communications (say sleep 15 minutes, everyone wakes up and sends sensor readings to the receiver, everyone sleep again). Would you have an option for that (maybe synchronizing time between boards)? The goal being to save battery when constant sensor readings are not required. Thanks again for all these great tutorials which are clearly explained!

    Reply
    • Hi Oli.
      Thanks for your comment.
      I was thinking that to make all boards go sleep at the same time, the receiver board could send a command at the same time to all boards, so that they know it is time to go to sleep.
      The boards would receive the message approximately at the same time (maybe a few seconds of difference). This would be one of the easiest solutions in this scenario. However, I’m sure there should be a more “precise” way to do that.
      Regards,
      Sara

      Reply
      • Hi
        it is a solution but not very convenient. The boards sleep mode should be independent and random in time.

        Thanks a lot Sara,

        Reply
        • Good day,
          I would like to ask if you happened to come up with a more elegant solution so as not to shift the time.
          Thank you

          Reply
  2. Hi Sara, thank you for this work !
    In the first sketch intended to get the MAC address, there is no #define ESP32 on top
    Is it defined implicitely by the IDE when we select an ESP32 card ?

    Reply
  3. Hi Sara!
    Question on the topic ESP32. I recently found out that there is an “old” and “new” version of the ESP32 module. Are there any fundamental differences in the programming of these modules in ARDUINO IDE?

    Reply
  4. If something follows a fixed scheme it is pre-destinated to be done by a computer.
    Mac-adresses and writing code is such a thing. So I wrote a function that prints out the mac-adress in a way that produces the code-line for defining the mac-adress with all details except the variable-name

    here it is:
    void PrintWiFiMacAdress()
    {
    char MacAdr_AoC[18]; //suffix _AoC for easier remembering variable-type is ArrayOfChar
    char HexByteDigits[3];

    for (uint8_t i = 0; i < 18; i = i + 1)
    {
    MacAdr_AoC[i] = WiFi.macAddress()[i];
    }
    MacAdr_AoC[17] = 0; // zero to terminate the string
    Serial.print(“ESP Board Wifi.macAddress: “);
    Serial.println(MacAdr_AoC);

    Serial.println();
    Serial.println(“copy the line below and replace the ‘#’ with variablename of your choice”);
    Serial.println();
    Serial.print(“uint8_t #[] = { “);
    for (uint8_t i = 0; i < 16; i = i + 3)
    {
    HexByteDigits[0] = MacAdr_AoC[i];
    HexByteDigits[1] = MacAdr_AoC[i+1];
    HexByteDigits[2] = 0; // zero for terminating the string
    Serial.print(“0x”);
    Serial.print(HexByteDigits);
    if (i < 14) Serial.print(“, “);
    }
    Serial.println(” };”);
    Serial.println();
    }

    So you simply add the function to your code
    and insert the line

    PrintWiFiMacAdress();

    into the setup-function
    when booting the device prints
    something similar to

    copy the line below and replace the ‘#’ with variablename of your choice

    uint8_t #[] = { 0x5C, 0xCF, 0x7F, 0x00, 0xD2, 0x9C };

    with the mac-adress of the device running this code.

    Remember THIS mac-adress must be used in the RECEIVING device

    It is just a few lines of code so you can keep it inside your code and always have
    the mac-adress handy through serial-output without the need to load another code.

    I’m using array of chars in this code because variable-Type “String” is dangerous to use.

    best regards

    Stefan

    Reply
  5. hm this comment-function eliminates spaces that were used to format the code.

    @Rui & Sara, is this something that could be changed in this comment-software?
    best regards

    Stefan

    Reply
  6. Regarding the comment by Oli, I am, at the moment, doing what he suggests with two boards one sending, one receiving. The ‘sender’ wakes up every 15 minutes and sends date from a BME280 to the ‘receiver’. This works really well so I guess it would work with multiple senders, I’ll try it when I get chance. The receiver sits there constantly running waiting for a message so it is mains powered. I want to find a way to measure the battery voltage on the sender (units) using minimum current so a resistor divider to the on board ADC isn’t ideal unless it is switched with an output pin.

    Reply
  7. To clarify my last post, I ran this sketch :
    #ifdef ESP32
    String msg = “ESP32!”;
    #endif
    #ifdef ESP8266
    String msg = “ESP8266!”;
    #endif

    void setup() {
    Serial.begin(115200);
    Serial.println(msg);
    }

    void loop() {
    }
    With an ESP32, result is ESP32!
    With an ESP8266, result is ESP8266!
    Then the IDE processes the user sketch, and inserts, among other things, the right #include ESPxx on top of the code submitted to the compiler
    I do not know if there is a way to see this processed code ?
    Alain

    Reply
  8. Hi Sara Id like to know if wifi connection can be used to send data to server while espnow is working to collect data from other esp32?.

    Reply
    • Hi Marcos.
      Yes.
      You need to set the ESP32 as a wi-fi station and access point at the same time.
      You also need to set the ESP-NOW to use channel 2.
      We’ll be publishing a ESP-NOW + Web Server project this week. The ESP32 receives data from other boards and displays the readings on a web server.
      So, stay tuned.
      Regards,
      Sara

      Reply
  9. Hello, First thank you for all the information shared with everyone.
    I tried to do with the esp826 the programming that you did with the esp32 (several esp32 which send data to an Esp32, in fact temperature and humidity as well as the ID of the board). There is a part of the code where I hang, it is the structure. I managed to display the id but the temperature and humidity is 0. On the other hand with an esp8266 can send to another esp8266 the id., Temperature and humidity without problem. So I send you the transmitter and receiver program. the transmitter is an esp01 and the receiver is a wemos d1 r1. I also send you the result received from the receiver on the serial port.

    p.s excuse my english
    transmiter
    (…)

    Reply
    • Hi Michel,
      If you want assistance sharing your code is a must.
      From what you describe – if I look into my RGB-LED enlighted glas-sphere I can see something through the fog like

      The structures of sender and receiver deviate from each other
      you are using a variable of type String in the structure (very bad idea)
      the memcopy-command copies too less bytes
      the send_ESP_Now-message sends too less bytes

      This comment-section is not well suited for such discussions and support.
      Sorry Rui and Sara: if you keep this simple comment-function I will repeat to suggest asking the questions in the arduino-forum.

      here is the link to the right sub-forum
      https://forum.arduino.cc/index.php?board=4.0

      best regards Stefan

      Reply
  10. Hi there, I have managed to get this project working following your excellent guide, however when I change the typedef struct to String & float I get an unexpected result in the output of the receiver ESP32. i.e.
    // Set values to send
    myData.id = 1;
    myData.x = “Hello”;
    myData.y = 50.1;

    Packet received from: fc:f5:c4:01:c0:60
    Board ID 1: 20 bytes
    x value: 1073483784
    y value: -1073741824

    It works OK in your “Introduction” tutorial but not in the “many to one” project
    Can you have a look at this and let me know what I’m missing in the code.
    Many thanks
    Ian

    Reply
  11. Resolved, in the “Serial.printf(“x value: %d \n”, boardsStruct[myData.id-1].x);” line of the receiver code the printf format specifier needs to be changed to match the desired output. In my case I changed %d (signed decimal integer) to %f (decimal floating point).
    Regards
    Ian

    Reply
    • Hi.
      I don’t need to install any library.
      It is included when you install the ESP32 boards in the ARduino IDE.
      When compiling the code make sure you have an ESP32 board selected in Tools>Board.
      Regards,
      Sara

      Reply
  12. Hi Sara,
    Can I use ESP-NOW to send data from one ESP8266 and one ESP32 to an ESP8266 (receiver) ? I have that need. It should work because the commands are all the same regardless of bard type, are they not?
    Please let me know.
    Thank you
    Mike

    Reply
  13. Hi, I try to use your code, but I don’t have sucess.
    I use the exacly code for the Receiver and I changed the myData.id (I use 1, 2 and 3) for the Sender and change too the MAC andress (I use the MAC andress the Receiver)
    I am using 4 esp 32 (1 Receiver and 3 Sender )
    There are other part of code to change?

    Reply
  14. Respected Sara Santo , You have done great work. Still I have one doubt regarding Multiple transmitters and single receiver that>>>>>> I am getting the data from all transmitters with their ID. But want to receive data sequentially. How to obtain data coming from 3 transmitter sequentially? Thanks.

    Reply
    • Hi.
      To be honest, I’m not sure how to do that.
      Maybe when the first board sends information to the receiver, it should also send something to the second board to trigger it.
      There should be another way to synchronize the boards more efficiently, but I don’t know how to do that.
      If you find a better way, please share.
      Regards,
      Sara

      Reply
  15. Hi Sara,

    I want to thank you for all the shared knowledge, it has been very helpful in my project. My problem was generated when trying to receive information from 8 slaves at the same time, since it was possible to update information from 4 of them and inconsistently, so I had to program a way in which the master requested information from a slave to the time. I don’t know if the problem is because all the information is not processed or if I have to configure another channel to receive the information in parallel and if it were, I don’t know how to do it.

    Reply
  16. Hi Rui and Sara,
    Thank you for all information and the shared knowledge. I have one question for project one to many with ESP now protocol. Can “receiver” take message from “senders” with different struct_message?
    We create many struct_message at receiver but how we can see the ID before copy the content of the incomingData data variable into the correct myData variable?

    Reply
  17. HI
    I am hoping to use a few ESP01s modules to capture temp from either BME280 or BS18D20 sensors on a Beehive. I want to use them as they are extremly small. I hope to power them with a disc battery. Could I use them in a ESP NOW many to one with a dev module and the one.
    Would this work do you think?

    Reply
  18. Great Tutorials! just curious if i can use this along side MQTT. is there any particular configurations I will need to do in other to achieve this because if am not mistaken the MQTT uses the “Access point” mode for wifi configurations while the EspNOW uses the “station mode”?

    Reply
  19. Hi Sara. Great Tutorials.
    In your code you define the delay like this: delay(10000);
    Is it possible to define: delay(10); ?

    Reply
    • Hi.
      Yes. It will send messages every 10 milliseconds. I don’t know if it will be able to catch all the messages.
      Regards,
      Sara

      Reply
  20. Hi.
    Great Tutorials. It works well, or it did a month ago.
    Now I get the error: E (1384) ESPNOW: Peer interface is invalid
    What happened?

    Reply
  21. Hi,
    I have a question: What will happen when the process time, in the OnDataRecv of the receiver, is longer then the rate of messages arrival from 20 sending stations? will messages be lost? be queued ? will the sender be notified that the receiver is busy?
    Thanks

    Reply
  22. Hello,
    I noticed a problem in a String field in struct_message: If the data in the field contains a space (“Hello World”) the field arrives corrupted to the server (if the data is only “Hello” it arrives correctly). Can somebody trys to recreate the scenario and verifies it? or am I doing something wrong?
    Thanks

    Reply
  23. Hi Sara,

    I tried the codes, but on the receivers side no message is received. I took broadcast Address FF.. at the senders side. Any suggestions, whats wrong?

    kind regards
    Rainer

    Reply
  24. Hi Sara 🙂 !

    Can you help me please, Im trying to use as a slave a ESP-CAM but i didn’t manage to do it. Is there any extra configuration to upload the code?

    Best Regards
    Mateo López

    Reply
  25. Hi Sara

    Can you help me please, Im trying to set a ESPCAM as a slave but I can’t. Is there any extra setup ?

    Regards 🙂
    Mateo

    Reply
  26. Really? in this post says “We’ve experimented with different models of ESP32 boards and all worked well (ESP32 DOIT board, TTGO T-Journal, ESP32 with OLED board and ESP32-CAM).” but thank you very much i will keep it trying.

    🙂 Thank you, please ignore my last sms i though this comment wasn’t published.

    Reply
  27. Hello Rui and Sara,
    Thank you for sharing this interesting tutorial.
    I have successifully tried to repeat it at my home, but i woul like to add something.
    I tried to send data of Temperature and Humidity collected by two devices to a database using post.
    Unfortunately i noticed that i am able to collect the results of both, but when it comes to connect to WiFi for sending post data i fail to connect.
    Do you know if there are some triks to overcome this issue?
    Thank you very much
    Regards
    Manuel

    Reply
      • I have Tried to use the Wifi connection you used in the bme280 tutorial, where data are sent to SQL database using blue host service. Unfortumately when i try to connect to Wifi it is not working.

        Reply
  28. Brilliant work guys!!
    Question: In the “many-to-one” code, I have come across a problem receiving char* data in the boardsStruct[myData.id-1].ch. I wonder if you could suggest a fix?
    on the Master side: I have variable type: char ch [10];
    In the values to send: strcpy(myData.ch, “Hello”);
    On the Slave side:
    Also variable type: char ch[10];
    but boardsStruct[myData.id-1].ch = myData.ch; Will not compile. error: invalid array assignment
    But, if I do Serial.printf(“Characters: %s\n”, myData.ch); it works and I get “Characters: Hello”
    That would be fine, except I would really like to make the boardsStruct work so I can receive data from multiple Masters. I have tried using the variable type char* but it displays ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮ on the Slave side when printing as a string (%s). Any ideas?

    Reply
  29. I think I have found the solution to my problem –
    On the slave side:
    strcpy (boardsStruct [myData.id-1].ch, (myData.ch));
    Serial.printf(“myChars: %s \n”, boardsStruct[myData.id-1].ch);

    Output: myChars: Hello

    Reply
  30. Hi, I am using three esp32 boards which all have mpu6050s. I am trying to get the receiver board to calculate the differences in the angles between the other two sender boards. The problem that I’m experiencing is that I cannot seem to simply subtract the variables in my main loop. the output of this does not give me the correct integer outputs. As you will see when I try to subtract the -9 and the -1 from each other, I simply get a +9 as a result. These are the x-values coming in from my other two sender boards.

    I have copied the code for the receiver board and the serial output results.
    P.S. thanking you in advance

    *****This is the receiver board code*********
    /*********
    Rui Santos
    Complete project details at https://RandomNerdTutorials.com/esp-now-many-to-one-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>

    // Structure example to receive data
    // Must match the sender structure
    typedef struct struct_message {
    int id;
    int x;
    int y;
    }struct_message;

    // Create a struct_message called myData
    struct_message myData;

    uint8_t board1X ;
    uint8_t board1Y ;
    uint8_t board2X ;
    uint8_t board2Y ;
    uint8_t boardsX_difference;
    uint8_t boardsY_difference;
    // Create a structure to hold the readings from each board
    struct_message board1;
    struct_message board2;
    //struct_message board3;

    // Create an array with all the structures
    struct_message boardsStruct[2] = {board1, board2};

    // callback function that will be executed when data is received
    void OnDataRecv(const uint8_t * mac_addr, const uint8_t *incomingData, int len) {
    char macStr[18];
    Serial.print(“Packet received from: “);
    snprintf(macStr, sizeof(macStr), “%02x:%02x:”, mac_addr[0], mac_addr[1]);
    //, mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
    Serial.println(macStr); //%02x:%02x:%02x:%02x
    memcpy(&myData, incomingData, sizeof(myData));
    Serial.printf(“Board ID %u: %u bytes\n”, myData.id, len);
    // Update the structures with the new incoming data
    boardsStruct[myData.id-1].x = myData.x;
    boardsStruct[myData.id-1].y = myData.y;
    Serial.printf(“x value: %d \n”, boardsStruct[myData.id-1].x);
    Serial.printf(“y value: %d \n”, boardsStruct[myData.id-1].y);
    Serial.println();

    }

    void setup() {
    //Initialize Serial Monitor
    Serial.begin(115200);

    //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 recv CB to
    // get recv packer info
    esp_now_register_recv_cb(OnDataRecv);
    }

    void loop() {
    // Acess the variables for each board
    int board1X = boardsStruct[0].x;
    int board1Y = boardsStruct[0].y;
    int board2X = boardsStruct[1].x;
    int board2Y = boardsStruct[1].y;

    int boardsX_difference= board1X-board2X ;
    int boardsY_difference= board1Y-board2Y;

    Serial.println(“boardsX_difference”);
    Serial.println(boardsX_difference);

    Serial.println(“boardsY_difference”);
    Serial.println(boardsY_difference);
    delay(2000);
    }

    *********This is my serial output**************
    Packet received from: 7c:9e:
    Board ID 2: 12 bytes
    x value: -9
    y value: 0

    Packet received from: 94:b9:
    Board ID 3: 12 bytes
    x value: -1
    y value: 0

    boardsX_difference
    9
    boardsY_difference
    0

    Reply
  31. so i looked at this code (esp32) and esp8266 many to one implementation. And now i have a question are these two libraries different? espnow.h and esp_now.h or the same.
    When i try to flash code with esp_now it says ERROR.

    Reply
  32. Hi Sara, is it possible to put the ‘Send-to-many’ code and ‘Receive-from-many’ code in one board? I mean in one board it can receive from many boards also can send to many board.

    Reply
  33. Hello, thank you for your effort,
    i have a question , as i see the receiver can work with multiple senders with the same structure data
    Can the master receive different structure data ?

    Reply
  34. Hi,
    congratulations for your article.
    I have a doubt. My use case is: I have multiple master sending information to one sclave.
    My masters are ESP01 and my sclave is ESP32.
    I am having problem when try to use key to encrypt the message. Have you checked this feature?
    The main part of the code:
    esp_now_add_peer(mac,role,channel,key,size) –> when KEY is NULL, everything is OK. when KEY has value, the receiver (esp32) doesn’t receive anything.
    Thanks in advance.

    Reply
  35. Hi,
    Having a bit of weird issue that I can’t seem to figure out. I have 4 nodes sending to 1 receiver in broadcast mode, and I have noticed when more than 2 of the nodes are switched on, a latency of around 100ms is introduced to the system. I first thought this was to do with the receiver having to read more packets, but after some testing it seems as though the nodes are interfering with each other, as even when I made the receiver only listen to 1 node, the system would still get latency just by having the other nodes switched on nearby. Is there anything that can be done about this latency? or is it just part of the system that “more nodes in 1 area = more latency”?

    Thanks!

    Reply
    • Ok never mind sorry. I realised that only 2 of the nodes that had the same code slowed down, but the other 2 have the same latency no matter if everything is switched on or off. I uploaded their code to the other nodes and the problem went away, but it seems to be a part of the code that has nothing to do with the ESP-NOW that seems to effect it. Like it’s literally 2 lines declaring analog pins for a sensor that I remove from the code and that seems to trigger the latency. very strange behaviour, hopefully I will figure out why.

      Reply
  36. Hi all,
    Thanks for the great tutorials!
    I have multiple boards (let’s call them slaves) sending sensor acquisitions to one single board (let’s call it master) once every hour with ESP-now.
    When the slaves go to deep sleep the wake-up time it’s not very accurate and I fear on the long run I will lose the syncronization. I don’t need an accurate syncro, I just need that the time at which the slave boards send their acquisition is roughly the same (1 minute difference max).
    I was thiking that the master might send a self adjusting “timer” to the slaves to make them wake up together. Is that feasible? I fear that if the master sends messages to the slaves it might end up losing some of the data sent by the slaves themselves.
    I read somewhere that the max number of communication that ESP-NOW can handle is 20, but what does that mean?
    Does it mean that one board can send to a maximum of 20 boards or does it mean that one board can receive from a maximum of 20?
    Or is it a sum e.g a single board can send to 10 and receive from 10?
    Furthermore I would like a clarification on how I should choose the channel when adding multiple peers.
    Thaks again for your tutorials, I am learning a lot.

    Reply
  37. I am planning to build a system og ESP32 like descibed here.
    The sensors are temperature measuring. The sensors Will be placed in different buildings.
    But I allready have a wifi network covering all buildings.
    My question:
    Will the system work on the existing wifi network?

    Reply
    • Hi.
      I’m not sure that I understood your question.
      But, ESP-NOW doesn’t use the Wi-Fi network to communicate.
      Those are two different protocols.
      Regards,
      Sara

      Reply
  38. Hello Sara,
    Is it possible to use the ESP Now method to send data from multiple platforms (sensors) to a receiver that is setup as websocket server so that I am able to access to all sensor data via internet? Or how can this be done? Thank you.

    Reply
  39. Hi Sara Santos can you please tell me is same thing possible with BLE esp32(many to one communication) if yes can you please guide me with some reference. For my project I need many to one commuincation using ble.

    Reply
  40. I am sending data from a transmitter to a single receiver using ESP-NOW. At the receiver side, i am serial printing the received data at a baud rate of 115200.
    everything works fine. I have observed one thing.
    The problem is when i switch off the power at the transmitter side, it takes around a second to have a no data at the receiver serial monitor. I know that the buffer gets be cleared till it stops showing any data at the receiver

    I have tried sending a voltage value of 3.3V (3300mV) from the Tx,which comes around 3299 in the receiver side, But when the Tx power is turned off, the last 2-3 values come as 31xx, 29xx etc, which is never expected as the values sent from the Tx are always 3299.

    Can you tell me why this is happening and how to get rid of this.

    Thanks in advance.

    Reply
  41. Excellent material presented in a very good way.
    The ESP-NOW protocol is definitely useful, but I see examples mainly for getting information from senders, not for automating a process…
    Suppose there are several senders 200-300 meters from the receiver. Each one of them is connected to a sensor and a relay. Is it possible for a receiver, receiving data from the senders, to return an instruction to each of them to turn on or off a relay, based on the readings of the sensor connected to each of them? All this through ESP-NOW protocol and let’s say…LoRa Network.

    Reply
  42. Hey Sara,
    Thanks for this nice elaborating tutorial, but I am not able to download this “esp_now” library.
    Could please guide to download it?

    Reply
  43. Gentlman

    when I use loop section.
    void loop() {
    // Acess the variables for each board
    int board1X = boardsStruct[0].x;
    int board1Y = boardsStruct[0].y;
    int board2X = boardsStruct[1].x;
    int board2Y = boardsStruct[1].y;
    int board3X = boardsStruct[2].x;
    int board3Y = boardsStruct[2].y;

    delay(10000);
    }
    I get below error, it’s appreciate that you can let me know what’s the problem. thanks
    Compilation error: unused variable ‘board1X’ [-Werror=unused-variable]

    Reply
  44. Thank you for all the great articles!
    In the many to one example, I replaced the struct x,y variables with float variables to work with temp/ humidity readings from 2 sht45 sensors. And in the receiver sketch I printed results on a ssd1306 oled. Everything displays, but the display alternates the readings. How do you get readings from different sensors on different lines without the readings alternating. Would like to have 4 lines temp1/hum1/temp2 /hum2, without them alternating. Thank you

    Reply
    • Hi.
      Make sure you display each reading on a different place of the OLED display.
      Set the cursor in different positions before writing to the display.

      For example:
      display.setCursor(0, 10);
      display.println("FIRST SENSOR");
      display.setCursor(0, 20);
      display.println("SECOND SENSOR");
      display.setCursor(0, 30);
      display.println("THIRD SENSOR");
      display.display();

      You can learn more about displaying text on the oled display here:https://randomnerdtutorials.com/esp32-ssd1306-oled-display-arduino-ide/

      I hope this helps.
      Regards,
      Sara

      Reply
      • Wow
        Thank you for such a quick response.
        That is how I had it written basically, but it would alternate the display between id 1 and id 2 of the sender boards. Hope I’m making sense.
        display.clearDisplay();
        display.setTextSize(2);
        display.setTextColor(WHITE);
        display.setCursor(0,0);
        display.print(“TEMP”);
        display.print(myData.id);
        display.setCursor (40,0);
        display.print(myData.a);
        display.setCursor (0,16);
        display.print(“HUM”);
        display.print(myData.id);
        display.setCursor (40,16);
        display.print(myData.b);
        display.setCursor(0,32);
        display.print(“TEMP”);
        display.print(myData.id);
        display.setCursor (40,32);
        display.print(myData.a);
        display.setCursor (0,48);
        display.print(“HUM”);
        display.print(myData.id);
        display.setCursor (40,48);
        display.print(myData.b);
        display.display();

        Reply
        • Hi again.
          I’m sorry, but I didn’t understand…
          Do you want to show only data from id 1 for like three seconds, and then only data from id 2, and so on…?
          Regards,
          Sara

          Reply
          • Hello Sara
            Thanks for the reply back. Would like to show both id 1and id 2 to remain on the oled screen constantly but with updated temp/hum readings to be updated every 10 seconds that the sender sketch is set at. Kind of like the Esp now Web server example where only the temp/hum readings are being updated, but the id names never change.Thank you

          • Hello Sara
            Where should I put the ssd1306 display code in the many to one receiver example. The loop, setup, or under the serial print section of the code. The Esp32 doesn’t like it if I try any of them.

  45. Hello sara, i want to ask you about esp now, i have two senders and one receiver, each sender have same data structure, but different name, for example we will using the name for temperature data from the first sender is “Temperature Inside” that will appear in serial monitor of the receiver, and temperature data from the second sender is “Temperature Outside” that will appear in serial monitor of the receiver, how do i make this possible? i really need your help, thank you

    Reply
  46. Hi Sara. I use de code of many to one slave. I put (float y) for temperature decimals …
    But I cant receive de correct data. What I making wrong???

    Reply
  47. Hi Sara. I use this code for my ESP32 Wroom32. I compile the sender and all is OK. But when compile the receiver-slave and apearing the following error.

    exit status 1

    Compilation error: invalid conversion from ‘void ()(const uint8_t, const uint8_t*, int)’ {aka ‘void ()(const unsigned char, const unsigned char*, int)’} to ‘esp_now_recv_cb_t’ {aka ‘void ()(const esp_now_recv_info, const unsigned char*, int)’} [-fpermissive]

    I change the esp32 by a esp8266 and the code for this.No problem with this.
    I dont change nothing of your code.
    What its wrong?…
    Thanks

    Reply
    • Carlo I had the same issue and now solved I’ve solved ,
      I was using in arduino ide the board definition 3.0.0 -rc that seems to be not compatible with the intruction format “esp_now_register_recv_cb(OnDataRecv);”.
      I’ve installed the version 2.0.14 and now is working.

      Should be great update the code for the new board version or place an allert in the comments.

      Reply
  48. Hello,
    SUBJECT: Many to One Code
    Your comment for the code below…
    “Next, define the OnDataSent() function. This is a callback function that will be executed when a message is sent. In this case, this function prints if the message was successfully delivered or not.”
    Your code….
    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”);
    }
    My Question…
    In the void OnDataSent command, is this ” *mac_addr” the address of the Sender or the Receiver?

    I am confused between the placement of the Sender address and the Receiver. Where
    should each addresss go?

    Thank you for all the great articles!

    Reply
  49. Hi Rui and Sara, thanks for this tutorial it’s a great method to get a network of data loggers sending to Single node! the one question i have however is do you have a recommendation for synchronising the data on the receiving end? on my setup, even if i power all transmitters simultaneously, i get the messages in an incorrect order which isn’t ideal as it writes to a monitor dashboard in Node-Red…

    basically is there a way to force the Serial out of the receiver to put the messages in order 1,2,3,…n?

    Reply
    • as an example, when i do the many to one version; i will often get the readings in an incorrect order… i thought the data structure would force them to come out on receiver as board1, board 2, board 3.

      However it seems kind of random, one time if i boot them up (all at same time because power hub being used) i’ll get like: board2, board3, board1… is there a way to force them into ascending order based on the id?

      Reply
  50. Hi Sara. I use this code for my ESP32-C3 mini .
    No problem when i compile the sender but with the receive I’ve the same error mentioned by Carlos in November , see some post above :

    exit status 1

    Compilation error: invalid conversion from ‘void ()(const uint8_t, const uint8_t*, int)’ {aka ‘void ()(const unsigned char, const unsigned char*, int)’} to ‘esp_now_recv_cb_t’ {aka ‘void ()(const esp_now_recv_info, const unsigned char*, int)’} [-fpermissive]

    Have you idea if there is any issues with such levels of libraries ?
    Thanks Roberto

    Reply
  51. Hi
    Basically i want, to Disable receiving data from sender for some time,
    will try using , >> esp_now_unregister_recv_cb()
    but its not working

    Reply
  52. Hi Sara
    How would I send different Data from the Master to the Slave, using struct or typedef? master 1 would send [ id, x, y ] but master 2 would send [ id, speed, temp, x, y, ] and master 3 would send [ id, x, y, hight, time ]. Maybe a struct array or something? I don’t see the use of sending the same Data from 3 different places, But different Data would be very useful. Can this be done?
    Thanks Shelley

    Reply

Leave a Comment

Download Our Free eBooks and Resources

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