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:
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.

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”.
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.
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!
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.

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

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

Copyright ©2025. All Rights Reserved Emblab THE RAVE INNOVATION