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.
We have other guides related with ESP-NOW that you might be interested in:
- Getting Started with ESP-NOW (ESP32 with Arduino IDE)
- ESP-NOW Two-Way Communication Between ESP32 Boards
- ESP-NOW with ESP32: Send Data to Multiple Boards (one-to-many)
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.
- 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(){
}
After uploading the code, press the RST/EN button, and the MAC address should be displayed on the 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.
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);
}
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);
}
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.
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.
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:
- Getting Started with ESP-NOW (ESP32 with Arduino IDE)
- ESP-NOW Two-Way Communication Between ESP32 Boards
- ESP-NOW with ESP32: Send Data to Multiple Boards (one-to-many)
- Getting Started with ESP-NOW (ESP8266 NodeMCU with Arduino IDE)
Learn more about ESP32 with our resources:
Thanks for reading.
Hello Rui.
Are you going to do this for the esp8266 to ?
That would be very nice. Thanks in advance.
Bert Heideveld
Hi Bert.
Yes, we can experiment this scenario for the ESP8266.
Note that this code doesn’t work for the ESP8266. But with some modifications you can make it work.
Take a look at the functions used for the ESP8266 in this tutorial: https://randomnerdtutorials.com/esp-now-esp8266-nodemcu-arduino-ide/
Then, I’m sure you’ll be able to came up with a similar scenario but for the ESP8266.
Thank you for your comment.
Regards,
Sara
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.
sorry hamlet is memory
Hi Bert.
We’ll may came up with a similar tutorial for the ESP8266 in a near future.
So, stay tuned. Subscribe to our newsletter if you haven’t already to be notified of the project.
Keep working on your projects, it is good to keep your brain active. 🙂
Regards,
Sara
Thank you
I also await to see this implementation on the 8266. (I’ve got a dozen 8266 to use up somehow. 🙂 Thanks.
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!
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
Hi
it is a solution but not very convenient. The boards sleep mode should be independent and random in time.
Thanks a lot Sara,
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
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 ?
Yes.
Thank you Sara and Rui!
Please keep up the excellent work. Your tutorials are the highlight of my mailbox.
You’re welcome. Thanks for reading!
very good Rui. but how can I get around it, to receive data from 100 devices for example?
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?
Hi.
As long as they have an ESP32 chip, the programming should be the same.
Regards,
Sara
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
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
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.
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
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?.
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
Well done to you both…
Thanks to you I have the system up and running with three temp sensors!
Keep up the excellent work.
I don’t, but we’ll publish something like that in a near future.
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
(…)
Hi.
You can follow this tutorial for better guidance: https://randomnerdtutorials.com/esp-now-many-to-one-esp32/
Regards,
Sara
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
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
Did you change the type structure on the receiver side too?
Regards,
Sara
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
Hi Sara
I can’t work out how to get the esp_now.h library uploaded to my Arduino IDE. Are you able to assist?
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
Hi Sarah can you tell me if ESP12F can be used as a transmitter thank you for your work and a window into the world of ESP
Hi.
Yes, I think it can.
Regards,
Sara
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
Yes this works. Only condition is to send to the right MAC-adress or to use the broadcasting-“MAC-Adresse” which is FF:FF:FF:FF:FF:FF
For ESP8266 and EPS32 you need different libraries and there are different commands for the setup-process. to configue ESP-NOW
best regards Stefan
Hi.
You can do that.
But the commands are slightly different for each board.
See the ESP8266 ESP-NOW tutorial:
https://randomnerdtutorials.com/esp-now-two-way-communication-esp8266-nodemcu/
Regards,
Sara
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?
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.
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
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.
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?
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?
Hi.
First, check if the ESP01 modules work with a simple ESP-NOW example: https://randomnerdtutorials.com/esp-now-esp8266-nodemcu-arduino-ide/
If they work, it is probably that those will work in a many-to-one configuration.
I haven’t tested ESPNOW with ESP-01 boards.
Regards,
Sara
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”?
Hi Sara. Great Tutorials.
In your code you define the delay like this: delay(10000);
Is it possible to define: delay(10); ?
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
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?
Hi.
Can you try the following?
cut this line from the setup():
esp_now_peer_info_t peerInfo;
And past it before the loop() and before the setup().
Does it work?
If this solves your issue, we need to update our code.
Regards,
Sara
Hi Sara.
Thank you very much, it works 😀
Great!
I’ll update the code.
Regards,
Sara
Hi Sara, I had the same issue in the broadcast tutorial code (https://randomnerdtutorials.com/esp-now-one-to-many-esp32-esp8266/) and doing this fix helped me there as well. Just wanted to let you know in case you want to update that tutorial as well. 🙂
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
Hi! Did you solve your question? I am facing the same issue.
Best regards
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
Hi.
You should send a char variable instead of a string.
See this example that sends a structure with a char variable: https://raw.githubusercontent.com/RuiSantosdotme/Random-Nerd-Tutorials/master/Projects/ESP32/ESP_NOW/ESP_NOW_Sender.ino
Regards,
Sara
could you please give the receiver code as well ? I’m having trouble to get the char variable on the receiver :/
Thanks Sara. I will change the code.
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
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
Hi.
I’m not sure. I never tried ESP-NOW with the ESP32-CMA. But it should be similar to a regular ESP32 board.
Regards,
Sara
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
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.
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
Hi.
Without further info, it is very difficult to find out what might be wrong.
Regards,
Sara
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.
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?
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
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
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.
Hi.
espnow.h and esp_now.h are different.
Regards,
Sara
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.
Hi.
Yes. You can do that.
Regards,
Sara
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 ?
Hi.
The structure must be the same.
Regards,
Sara
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.
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!
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.
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.
Amazing Thanks a lot!
randomnerdtutorials is my favorite webpage in the world
Thank you so much for supporting our work.
Regards,
Sara
Hello Sara,
I am going to build this setup with ESP32.
One question:
Can I link the ESP32 wia my existingwifi Network ?
Hi.
Do you mean connecting your ESP32 to the internet?
Yes, you can do that.
It might be useful taking a look at the following: https://randomnerdtutorials.com/esp8266-esp-now-wi-fi-web-server/
Regards,
Sara
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?
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
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.
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.
Hi
How can I add button with led this program?
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.
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.
Yes. All of that is possible.
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?
Hi.
The esp_now library is included by default on the ESP32 core.
Just make sure you have an ESP32 board selected in Tools > Board before compiling the code.
If you’re using an ESP8266 board, note that it uses a different library espnow.h and not esp_now.h: https://randomnerdtutorials.com/esp-now-many-to-one-esp8266-nodemcu/
Regards,
Sara
Thanks for the early reply. Thumbs up for you.
Hi
How many Master-Sender can be Communicate with one slave-Reciver ?, any limitation ?
Hi
How to start or Stop Communication from Receiver-Slave Side ? in main Loop
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]
Great tutorial, i was wondering if would be to use interrupts when data is sent and received?
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
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
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();
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
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.
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
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???
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
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.
It is now updated and compatible with 3.0.0.
Regards,
Sara
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!
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?
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?
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
Hi
How Deseble data receiving ?
will try using , >> esp_now_unregister_recv_cb()
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
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