Beginners Guide ESP-NOW ESP8266 (NodeMCU) using Arduino Ide

Description

  • ESP-NOW is a wireless communication protocol developed by Espressif Systems for its Wi-Fi chips. 
  • It allows devices to communicate directly with each other without the need for a Wi-Fi access point. 
  • This protocol is based on the 802.11 Wi-Fi standard, but it uses a different networking stack than traditional Wi-Fi. 
  • The Maximum payload allowed is 250 bytes. It communicates faster however with a small payload size.
  • ESP-NOW operates on the 2.4 GHz frequency band same as Wi-Fi, but it does not need to connect to the WiFI network connection.

 

ESP-NOW One-Way Communication

This is a straightforward configuration to set up and is ideal for sending data between boards, such as sensor readings or commands to turn GPIOs on or off.

 

ESP-NOW One to Multiple Board Communication

A single ESP8266 board can send the same or different commands to multiple ESP8266 boards. This configuration is ideal for building a remote control, where a single main board can control multiple devices around the house.

 

ESP-NOW Multiple Board to One Board Communication

This setup is ideal for collecting data from multiple sensor nodes and displaying it on a single web server. For example, we could use this to create a home monitoring system that collects data from temperature, humidity, and motion sensors.

 

ESP-NOW Two-Way Communication

Using ESP-NOW each board can transmit and receive the data at the same time. So, we can establish two-way communication between boards.

 

We can also add more ESP8266 boards to this configuration, which will create a network of devices.

 

ESP-NOW One-way Communication

 

Now here we will take an example of the ESP-Now One way communication with the code.

Before going forward we need to have two ESP8266 boards and know the MAC address of the slave ESP8266.

So first get the MAC address from the below code and note down it.

Getting Board MAC Address

#include "ESP8266WiFi.h"

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

void loop(){}

 

Output

 

ESP NOW Important Functions

esp_now_init() 

This function Initializes ESP-NOW.

 

Returns 

0: Success 

otherwise: Failure

esp_now_set_self_role(role) 

This function is to set the role for ESP NOW

ESP_NOW_ROLE_IDLE        This is the ideal role

ESP_NOW_ROLE_CONTROLLER  This role is for the sender ESP NOW

ESP_NOW_ROLE_SLAVE       This role is for the receiver ESP NOW

ESP_NOW_ROLE_COMBO       This is the combination for both sender and receiver ESP NOW

ESP_NOW_ROLE_MAX         There is no specific role for this

 

esp_now_add_peer(uint8 mac_addr, uint8 role, uint8 channel, uint8 key, uint8 key_len) 

Add an ESP-NOW peer, and store the MAC address of the target device into the ESP-NOW MAC list. 

mac_addr :      MAC address of the device. 

role :               role type of device; see esp_now_role for details. 

channel :        channel of the device. 

key :                 16 bytes key which is needed for ESP-NOW communication. 

key_len :         length of the key, has to be 16 bytes now.

 

Return 

0: Success 

otherwise: Failure

esp_now_send(uint8 mac_address, uint8 data, int len) 

Send data with ESP-NOW.

 

mac_address:    Destination MAC address. If it’s NULL, the packet is sent to all MAC addresses recorded by ESP-NOW otherwise, the packet is sent to the target MAC address only

data:                    data to be sent. int len: data length

len:                     data length

 

Return 

0: Success 

otherwise: Failure

esp_now_register_send_cb() 

Register ESP-NOW send callback. 

 

Return 

0: Success 

otherwise: Failure

esp_now_register_recv_cb() 

Register a callback function that is triggered upon receiving data. When data is received via ESP-NOW, a function is called.

 

Now copy the below code and upload it on the Master device. Before uploading you must have to enter the MAC address of the slave device

uint8_t broadcastAddress[] = {0x84, 0xF3, 0xEB, 0xCA, 0xF8, 0xD3};

Let’s send the “Hello World!” Message every second over ESPNOW.

 

Sender Code

#include <ESP8266WiFi.h>
#include <espnow.h>

// MAC address to broadcast data to
uint8_t broadcastAddress[] = {0x84, 0xF3, 0xEB, 0xCA, 0xF8, 0xD3};

// Message to send
char msg[] = "Hello World!";

// Callback function to handle data send status
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.print("\r\nDelivery Status: ");
  Serial.println(sendStatus == 0 ? "Delivered Successfully" : "Delivery Fail");
}
 
void setup() {
  Serial.begin(115200);

  // Set WiFi mode to Station mode
  WiFi.mode(WIFI_STA);
 
  // Initialize ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // Set the role of this device as a controller
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
 
  // Register callback for data send status
  esp_now_register_send_cb(OnDataSent);
 
  // Add a peer (slave) with the specified broadcast address
  esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}
 
void loop() {
  // Send the message to the specified broadcast address
  esp_now_send(broadcastAddress, (uint8_t *) &msg, sizeof(msg));
 
  // Delay for 2 seconds before sending the next message
  delay(2000);
}

 

Output 

 

Understand the code

Add ESP8266WiFi.h and espnow.h libraries.

#include <ESP8266WiFi.h>
#include <espnow.h>

Now add the MAC address of receiver ESP32

Our MAC address is 84:F3:EB:CA:F8:D3

uint8_t broadcastAddress[] = {0x84, 0xF3, 0xEB, 0xCA, 0xF8, 0xD3};

now send the below message in character array to the slave device

char msg[] = "Hello World!";

OnDataSent() is a callback function that will be executed when a message is sent. We will print the Delivery Status via this function.

void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.print("\r\nDelivery Status: ");
  Serial.println(sendStatus == 0 ? "Deliverd Successfully" : "Delivery Fail");
}

In the setup function, 

Initialize the serial monitor 

Serial.begin(115200);

Set ESP32 in a Wi-Fi station Mode:

WiFi.mode(WIFI_STA);

Initialize ESP-NOW:

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

Set the ESP8266 role as a controller, to send data to other devices in the network

esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);

Now, register the callback function that will be called when a message is sent.

esp_now_register_send_cb(OnDataSent);

Pair with the slave device to send the data 

esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_CONTROLLER, 1, NULL, 0);

The arguments for esp_now_add_peer are:

esp_now_add_peer (mac address, role, wi-fi channel, key, key length)

 

In the loop function

Here we’ll send the message (Hello Word!) every second.

esp_now_send(broadcastAddress,(uint8_t *) &msg, sizeof(msg));

Wait for one second

delay(1000);

 

Now copy the below code and upload it on the Slave (Receiver) device and check the result on the serial monitor.

Receiver Code

#include <ESP8266WiFi.h>
#include <espnow.h>

// Structure to hold the received message
typedef struct struct_message {
    char a[32];
} struct_message;

// Create an instance of the struct_message
struct_message myData;

// Callback function to handle received data
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
  // Copy the incoming data to the myData structure
  memcpy(&myData, incomingData, sizeof(myData));
 
  // Print the received message
  Serial.println(myData.a);
}

void setup() {
  //Initialize the serial monitor
  Serial.begin(115200);

  // Set WiFi mode to Station mode
  WiFi.mode(WIFI_STA);
 
  // Initialize ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // Set the role of this device as a slave
  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
 
  // Register callback for received data
  esp_now_register_recv_cb(OnDataRecv);
}
 
void loop() {}

 

Output

 

Understand the code

Similarly to the sender, start by including the libraries:

#include <ESP8266WiFi.h>
#include <espnow.h>

Here we have created a structure to receive the data.

typedef struct struct_message {
  char a[32];
} struct_message;

Create a struct_message variable called myData.

struct_message myData;

Create a callback function that will be called when the ESP32 receives the data via ESP-NOW. In this function, we print the received data.

void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) 

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

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

Now print the received data, on a serial monitor.

Serial.println(myData.a);

 

In the setup function

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() != 0) {
  Serial.println("Error initializing ESP-NOW");
  return;
}

Set the ESP8266 role as a slave, to receive the data from other device in the network

esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);

Now, register the callback function that will be called when a message is sent.

esp_now_register_send_cb(OnDataSent);

Components Used

NodeMCU
NodeMCUNodeMCU
1

Downloads

ESP_Now_Master Download
ESP_Now_Slave Download
Ad