How to Make Multiple ESP Talk Via ESP-NOW Using ESP32 and ESP8266
by iamrachelle in Circuits > Arduino
8471 Views, 10 Favorites, 0 Comments
How to Make Multiple ESP Talk Via ESP-NOW Using ESP32 and ESP8266
On my ongoing project, I need multiple ESP to talk with each other without a router. To do this, I'll be using the ESP-NOW to make wireless communicate with each other without a router on the ESP.
Supplies
Get the Board Mac Address
Through ESP-now, ESP devices talk to each other by sending data to their unique address while connected to an internal acces point network made upon intilaizing the esp now. . Thus, determine the MAC address of each device.Attached is my ESP32 and ESP8266 Board Settings
FOR ESP32
#include "WiFi.h" //To access ESP32 WIFI capabilities void setup(){ Serial.begin(115200); Serial.print("ESP32 Board MAC Address: "); Serial.println(WiFi.macAddress()); //prints its MAC Address } void loop(){}
FOR ESP8266
#include <ESP8266WiFi.h> //Library used to access ESP8266 WIFI capabilities void setup(){ Serial.begin(115200); Serial.println(); Serial.print("ESP8266 Board MAC Address: "); Serial.println(WiFi.macAddress()); //prints its MAC Address } void loop(){}
My MAC ADDRESS are:
- ESP32 - 30:AE:A4:F5:03:A4
- ESP8266: A4:CF:12:C7:9C:77
How to Make ESP-NOW Work
Here's an overview on how to make it work:
- Include esp now and wifi libraries
- Save the mac address of the recipient ESP
- Define the data structure of the message send/received
- On the setup, set the wifi to station mode
- Initialize esp_now
- make and register the call back function called after sending and receiving data
- For Esp8266, define its role
- register the peer or recipient esp
- Send data
ESP-NOW FUNCTIONS(ESP32)
esp_now_init(void)
Return:
- ESP_OK : succeed
- ESP_ERR_ESPNOW_INTERNAL : Internal error
Description:
Initialize ESPNOW function
<em><strong>esp_now_register_send_cb(cb)
Returns:
- ESP_OK : succeed
- ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
- ESP_ERR_ESPNOW_INTERNAL : internal error
Parameters:
- cb: callback function name after sending ESPNOW data with this parameters:
- void cb (const uint8_t *mac_addr, esp_now_send_status_t status)
- mac_addr: mac address of receiver
- status:
- 1 = success
- 0 = fail
- void cb (const uint8_t *mac_addr, esp_now_send_status_t status)
Description:
Call the function OnDataSent after sending ESPNOW data
<em><strong>esp_now_add_peerconst esp_now_peer_info_t *peer)
Returns:
- ESP_OK : succeed
- ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
- ESP_ERR_ESPNOW_ARG : invalid argument
- ESP_ERR_ESPNOW_FULL : peer list is full
- ESP_ERR_ESPNOW_NO_MEM : out of memory
- ESP_ERR_ESPNOW_EXIST : peer has existed
Parameters:
- peer :peer information with the following data:
- uint8_t
- peer_addr[ESP_NOW_ETH_ALEN];
ESPNOW peer MAC address that is also the MAC address of station or softap
- peer_addr[ESP_NOW_ETH_ALEN];
- uint8_t lmk[ESP_NOW_KEY_LEN]
- ESPNOW peer local master key that is used to encrypt data
- uint8_t channel
- Wi-Fi channel that peer uses to send/receive ESPNOW data. If the value is 0, use the current channel which station or softap is on. Otherwise, it must be set as the channel that station or softap is on.
- wifi_interface_t ifidx
- Wi-Fi interface that peer uses to send/receive ESPNOW data
- bool encrypt
- ESPNOW data that this peer sends/receives is encrypted or not
- void *priv
- ESPNOW peer private data
- uint8_t
Description:
Add a peer to peer list
<em><strong>esp_now_send(const uint8_t *peer_addr, const uint8_t *data, size_t len)
Returns:
-
ESP_OK : succeed
-
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
-
ESP_ERR_ESPNOW_ARG : invalid argument
-
ESP_ERR_ESPNOW_INTERNAL : internal error
-
ESP_ERR_ESPNOW_NO_MEM : out of memory
-
ESP_ERR_ESPNOW_NOT_FOUND : peer is not found
-
ESP_ERR_ESPNOW_IF : current WiFi interface doesn’t match that of peer
Parameters:
- peer_addr: peer MAC address
- data: data to send
- len: length of data
Description:
Send ESPNOW data. For some cases, this happens:
- If peer_addr is not NULL, send data to the peer whose MAC address matches peer_addr
- If peer_addr is NULL, send data to all of the peers that are added to the peer list
- The maximum length of data must be less than ESP_NOW_MAX_DATA_LEN
- The buffer pointed to by data argument does not need to be valid after esp_now_send returns
<em><strong>esp_now_register_recv_cb(cb)
Returns:
-
ESP_OK : succeed
-
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
-
ESP_ERR_ESPNOW_INTERNAL : internal error
Parameters:
- cb: callback function for receiving ESPNOW data
- void cb (const uint8_t *mac_addr, const uint8_t *data, int data_len)
- mac_addr:
- mac address of receiver
- *data:
- data receive
- data_len
- data byte length
- mac_addr:
- void cb (const uint8_t *mac_addr, const uint8_t *data, int data_len)
Description:
Call the function cb after receiving ESPNOW data
ESP-NOW FUNCTIONS(ESP8266)
FUNCTIONS DESCRIPTION ESP32 ESP8266
int<em> esp_now_init(void)
Returns:
- 1 = success
- 0=fail
Description
Initialize ESPNOW function
int <em><strong>esp_now_set_self_role(u8 role)
Parameters:
- ESP_NOW_ROLE_IDLE: data transmission is not allowed.
- ESP_NOW_ROLE_CONTROLLER: priority is given to Sation interface
- ESP_NOW_ROLE_SLAVE: priority is given to SoftAP interface
- ESP_NOW_ROLE_COMBO: priority is given to SoftAP
interface
Description
Sets the device Role
int <em><strong>esp_now_register_send_cb(cb)
Returns:
- 1 = success
- 0 = fail
Parameters:
- cb: callback function name after sending ESPNOW data with this parameters:
- void cb (const uint8_t *mac_addr, esp_now_send_status_t status)
- mac_addr: mac address of receiver
- status:
- 1 = success
- 0 = fail
- void cb (const uint8_t *mac_addr, esp_now_send_status_t status)
Description
Call the function OnDataSent after sending ESPNOW data
int <em><strong>esp_now_add_peer(u8 *mac_addr, u8 role, u8 channel, u8 *key, u8 key_len)
Returns:
- 1 = success
- 0 = fail
Parameters:
- mac_addr
- mac address of peer
- role
- channel
- If the value is 0, use the current channel which station or softap is on. Otherwise, it must be set as the channel that station or softap is on
- *key
- key for encryption
- key_len
- length of key
Description:
Add a peer to peer list
int <em><strong>esp_now_send(const uint8_t *peer_addr, const uint8_t *data, size_t len)
Returns:
- 1 = Success
- 0 = Fail
Parameters:
- peer_addr: peer MAC address
- data: data to send
- len: length of data
Description:
Send ESPNOW data. For some cases, this happens:
- If peer_addr is not NULL, send data to the peer whose MAC address matches peer_addr
- If peer_addr is NULL, send data to all of the peers that are added to the peer list
- The maximum length of data must be less than ESP_NOW_MAX_DATA_LEN
- The buffer pointed to by data argument does not need to be valid after esp_now_send returns
int<em><strong> esp_now_register_recv_cb(cb)
Returns:
- 1 = Success
- 0 = Fail
Parameters:
- cb: callback function for receiving ESPNOW data
- void cb (const uint8_t *mac_addr, const uint8_t *data, int data_len)
- mac_addr:
- mac address of receiver
- *data:
- data receive
- data_len
- data byte length
- mac_addr:
- void cb (const uint8_t *mac_addr, const uint8_t *data, int data_len)
Description:
Call the function cb after receiving ESPNOW data
One Way Communication(ESP32 As Sender)
The ESP32 sends data to a ESP8266 . with this code. Change the broadcastAddress[] to your corrsponding receiver mac address. Mine was A4:CF:12:C7:9C:77
//Add necessary libraries #include <esp_now.h> //To access the esp now functions #include <WiFi.h> //To Add Wifi Capabilities on ESP32 //save the MAC Address in an array named broadcastAddress; uint8_t broadcastAddress[] = {0xA4, 0xCF, 0x12, 0xC7, 0x9C, 0x77}; //MAC address of my receiver /*define the data types of the multiple variables structured and renamed all of it as struct_message*/ typedef struct struct_message { char a[32]; int b; float c; String d; bool e; } struct_message; // Create a struct_message called myData struct_message myData; // function called when data is sent to print its status 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() { //Set the baud rate for serial communication with ESP Serial.begin(115200); // Set device as a Wi-Fi Station WiFi.mode(WIFI_STA);//Starts the wifi // Init ESP-NOW and returns its status if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } //call the function OnDataSent after sending ESPNOW data esp_now_register_send_cb(OnDataSent); // Register peer esp_now_peer_info_t peerInfo; //initialize and assign the peer information as a pointer to an addres memcpy(peerInfo.peer_addr, broadcastAddress, 6); //copy the value of broadcastAddress with 6 bytes to peerInfo.peer_addr peerInfo.channel = 0; //channel at which the esp talk. 0 means undefined and data will be sent on the current channel. 1-14 are valid channels which is the same with the local device peerInfo.encrypt = false; //not encrypted //Add the device to the paired device list if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } } void loop() { // Set values to send strcpy(myData.a, "THIS IS A CHAR"); //save "THIS IS A CHAR" to variable a of my "data" defined earlier myData.b = random(1,20); //save a random value myData.c = 1.2; //save a float myData.d = "Hello"; //save a string myData.e = false; //save a bool //Send data less than or equal 250 bytes via ESP-NOW and returns its status 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(2000); }
The ESP8266 receives data from the ESP32 using this code.
//Add necessary libraries #include <ESP8266WiFi.h> //To Add Wifi Capabilities on ESP32 #include <espnow.h> //To access the esp now functions /*define the data types of the multiple variables structured and renamed all of it as struct_message*/ typedef struct struct_message { char a[32]; int b; float c; String d; bool e; } struct_message; // Create a variable struct_message called myData struct_message myData; // function called when the data is received and prints it void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) { memcpy(&myData, incomingData, sizeof(myData)); Serial.print("Bytes received: "); Serial.println(len); Serial.print("Char: "); Serial.println(myData.a); Serial.print("Int: "); Serial.println(myData.b); Serial.print("Float: "); Serial.println(myData.c); Serial.print("String: "); Serial.println(myData.d); Serial.print("Bool: "); Serial.println(myData.e); Serial.println(); } void setup() { //Set the baud rate for serial communication with ESP Serial.begin(115200); // Set device as a Wi-Fi Station WiFi.mode(WIFI_STA); //Starts the wifi // Init ESP-NOW and returns its status if (esp_now_init() != 0) { Serial.println("Error initializing ESP-NOW"); return; } esp_now_set_self_role(ESP_NOW_ROLE_SLAVE); //Defines the role of this esp esp_now_register_recv_cb(OnDataRecv); //call the function OnDataRecv after receiving ESPNOW data } void loop() {}
One Way Communication(ESP8266 As Sender)
The ESP8266 sends data to an ESP32 . with this code. Change the broadcastAddress[] to your corrsponding receiver mac address. My esp32 address is 30:AE:A4:F5:03:A4. For other functions for esp8266 go here
//Add necessary libraries #include <ESP8266WiFi.h> //To Add Wifi Capabilities on ESP32 #include <espnow.h> //To access the esp now functions //save the MAC Address in an array named broadcastAddress; uint8_t broadcastAddress[] = {0x30, 0xAE, 0xA4, 0xF5, 0x03, 0xA4}; /*define the data types of the multiple variables structured and renamed all of it as struct_message*/ typedef struct struct_message { char a[32]; int b; float c; String d; bool e; } struct_message; // Create a structured variable called myData struct_message myData; // function called when data is sent and print its status void OnDataSent( uint8_t *mac_addr, uint8_t sendStatus) { Serial.print("\r\nLast Packet Send Status:\t"); Serial.println(sendStatus == 1 ? "Delivery Success" : "Delivery Fail"); } void setup() { //Set the baud rate for serial communication with ESP Serial.begin(115200); // Set device as a Wi-Fi Station WiFi.mode(WIFI_STA);//Starts the wifi // Init ESP-NOW and returns its status if (esp_now_init()) { Serial.println("Error initializing ESP-NOW"); return; } esp_now_register_send_cb(OnDataSent); //call the function OnDataSent after sending ESPNOW data<br> //Add the device to the paired device list if (esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_CONTROLLER, 1, NULL, 0)){ Serial.println("Failed to add peer"); return; } } void loop() { // Set values to send strcpy(myData.a, "THIS IS A CHAR"); //save "THIS IS A CHAR" to variable a of my "data" defined earlier myData.b = random(1,20); //save a random value myData.c = 1.2; //save a float myData.d = "SP8266"; //save a string myData.e = false; //save a bool //Send data less than or equal 250 bytes via ESP-NOW and returns its status int result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); if (esp_now_init() != 0) { Serial.println("Sent with success"); } else { Serial.println("Error sending the data"); } delay(2000); }
The ESP32 receives data from a ESP8266 . with this code. For other functions refere here
//Add necessary libraries #include <esp_now.h> //To access the esp now functions #include <WiFi.h> //To Add Wifi Capabilities on ESP32 /*define the data types of the multiple variables structured and renamed all of it as struct_message*/ typedef struct struct_message { char a[32]; int b; float c; String d; bool e; } struct_message; // Create a variable struct_message called myData struct_message myData; // function called when the data is received and prints it void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) { memcpy(&myData, incomingData, sizeof(myData)); Serial.print("Bytes received: "); Serial.println(len); Serial.print("Char: "); Serial.println(myData.a); Serial.print("Int: "); Serial.println(myData.b); Serial.print("Float: "); Serial.println(myData.c); Serial.print("String: "); Serial.println(myData.d); Serial.print("Bool: "); Serial.println(myData.e); Serial.println(); } void setup() { //Set the baud rate for serial communication with ESP Serial.begin(115200); // Set device as a Wi-Fi Station WiFi.mode(WIFI_STA); //Starts the wifi // Init ESP-NOW and returns its status if (esp_now_init() != 0) { Serial.println("Error initializing ESP-NOW"); return; } esp_now_register_recv_cb(OnDataRecv); //call the function OnDataRecv after receiving ESPNOW data } void loop() {}
TWO WAY COMMUNICATION
The ESP32 sends data on startup to the ESP8266. The ESP8266 prints the received message and then replies of which the ESP32 prints on its serial monitor.
ESP32 CODE
//Add necessary libraries #include <esp_now.h> //To access the esp now functions #include <WiFi.h> //To Add Wifi Capabilities on ESP32 //save the MAC Address in an array named broadcastAddress; uint8_t broadcastAddress[] = {0xA4, 0xCF, 0x12, 0xC7, 0x9C, 0x77}; //MAC address of my receiver /*define the data types of the multiple variables structured and renamed all of it as struct_message*/ typedef struct struct_message { char a[32]; int b; float c; String d; bool e; } struct_message; // Create a struct_message called myData struct_message myData; // function called when data is sent to print its status void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { Serial.print("\r\nLast Packet Send Status:\t"); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail"); if(status!=ESP_NOW_SEND_SUCCESS ){send_data();} } void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) { memcpy(&myData, incomingData, sizeof(myData)); Serial.print("Bytes received: "); Serial.println(len); Serial.print("Char: "); Serial.println(myData.a); Serial.print("Int: "); Serial.println(myData.b); Serial.print("Float: "); Serial.println(myData.c); Serial.print("String: "); Serial.println(myData.d); Serial.print("Bool: "); Serial.println(myData.e); Serial.println(); } void setup() { //Set the baud rate for serial communication with ESP Serial.begin(115200); // Set device as a Wi-Fi Station WiFi.mode(WIFI_STA);//Starts the wifi // Init ESP-NOW and returns its status if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } //call the function OnDataSent after sending ESPNOW data esp_now_register_send_cb(OnDataSent); // Register peer esp_now_peer_info_t peerInfo; //initialize and assign the peer information as a pointer to an addres memcpy(peerInfo.peer_addr, broadcastAddress, 6); //copy the value of broadcastAddress with 6 bytes to peerInfo.peer_addr peerInfo.channel = 0; //channel at which the esp talk. 0 means undefined and data will be sent on the current channel. 1-14 are valid channels which is the same with the local device peerInfo.encrypt = false; //not encrypted //Add the device to the paired device list if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } esp_now_register_recv_cb(OnDataRecv); //call the function OnDataRecv after receiving ESPNOW data send_data(); } void loop() {} void send_data(){ Serial.println("Sending"); // Set values to send strcpy(myData.a, "THIS IS A CHAR"); //save "THIS IS A CHAR" to variable a of my "data" defined earlier myData.b = random(1,20); //save a random value myData.c = 1.2; //save a float myData.d = "ESP32"; //save a string myData.e = false; //save a bool //Send data less than or equal 250 bytes via ESP-NOW and returns its status 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"); } }
ESP8266 CODE
//Add necessary libraries #include <ESP8266WiFi.h> //To Add Wifi Capabilities on ESP32 #include <espnow.h> //To access the esp now functions //save the MAC Address in an array named broadcastAddress; uint8_t broadcastAddress[] = {0x30, 0xAE, 0xA4, 0xF5, 0x03, 0xA4}; /*define the data types of the multiple variables structured and renamed all of it as struct_message*/ typedef struct struct_message { char a[32]; int b; float c; String d; bool e; } struct_message; // Create a variable struct_message called myData struct_message myData; // function called when the data is received and prints it void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) { memcpy(&myData, incomingData, sizeof(myData)); Serial.print("Bytes received: "); Serial.println(len); Serial.print("Char: "); Serial.println(myData.a); Serial.print("Int: "); Serial.println(myData.b); Serial.print("Float: "); Serial.println(myData.c); Serial.print("String: "); Serial.println(myData.d); Serial.print("Bool: "); Serial.println(myData.e); Serial.println(); send_data(); } void OnDataSent( uint8_t *mac_addr, uint8_t sendStatus) { Serial.print("\r\nLast Packet Send Status:\t"); Serial.println(sendStatus == 1 ? "Delivery Success" : "Delivery Fail"); if(sendStatus !=1){ send_data(); } } void send_data(){ // Set values to send strcpy(myData.a, "THIS IS A CHAR"); //save "THIS IS A CHAR" to variable a of my "data" defined earlier myData.b = random(1,20); //save a random value myData.c = 1.2; //save a float myData.d = "ESP8266"; //save a string myData.e = false; //save a bool esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); } void setup() { //Set the baud rate for serial communication with ESP Serial.begin(115200); // Set device as a Wi-Fi Station WiFi.mode(WIFI_STA); //Starts the wifi // Init ESP-NOW and returns its status if (esp_now_init() != 0) { Serial.println("Error initializing ESP-NOW"); return; } if (esp_now_add_peer(broadcastAddress,ESP_NOW_ROLE_SLAVE, 1, NULL, 0)){ Serial.println("Failed to add peer"); return; } esp_now_set_self_role(ESP_NOW_ROLE_COMBO); esp_now_register_send_cb(OnDataSent); esp_now_set_self_role(ESP_NOW_ROLE_COMBO); //Defines the role of this esp esp_now_register_recv_cb(OnDataRecv); //call the function OnDataRecv after receiving ESPNOW data } void loop() {}