Device to Device Communication with ESP-NOW

Learn how to use the ESP-NOW protocol to send data between ESP based boards.

Introduction

ESP-NOW is a wireless communication protocol developed by Espressif, the company behind the ESP32 microcontroller (MCU). Since the Arduino Nano ESP32 is equipped with that MCU it also supports the ESP-NOW protocol out of the box. It's designed for efficient and low-latency communication between devices, capable of sending up to 250 bytes.

Hardware Requirements

ESP-NOW is supported on the following microcontrollers:

You need two boards or more to communicate via ESP-NOW. Minimum one sender and one receiver.

How It Works

Communication Protocol

ESP-NOW operates as a peer-to-peer (P2P) protocol, meaning it allows direct communication between two ESP8266 or ESP32 devices without the need for a central server or access point, e.g. a Wi-Fi® router. Each ESP device has a unique MAC address which is used to identify the receiving board.

ESP-NOW can be set up in different ways:

One-way communication: In one-way communication mode, one device (the sender) can send data to another device (the receiver) without expecting a response. This mode is often used for scenarios where one device provides data or commands to another device, such as remote sensor readings or control commands.

Two-way communication: In two-way communication mode, both devices can exchange data bidirectionally. This mode enables a back-and-forth exchange of information between the devices, allowing for more interactive and responsive communication. It's suitable for applications where devices need to send and receive data from each other, such as remote control systems or interactive IoT devices.

ESP-NOW Communication
ESP-NOW Communication

Protocol Stack

ESP-NOW operates primarily at the data-link layer of the OSI model. In contrast to traditional networking protocols that involve multiple layers, ESP-NOW condenses the communication stack, streamlining the process. By reducing the protocol stack to a single layer, ESP-NOW eliminates the need for complex packet headers and unpackers on each layer. This simplicity results in quicker response times, reducing delays caused by packet loss in congested networks.

TCP/IP and ESP-NOW Protocol Stack
TCP/IP and ESP-NOW Protocol Stack

Lightweight Design

The protocol minimizes communication overhead, making it more efficient for resource-constrained devices. It also doesn’t perform handshakes as devices are preconfigured to allow for faster data transmission and reduced power consumption.

Limited Data Quantities

ESP-NOW is useful when transmitting smaller amounts of data (max 250 bytes). It utilizes action frames for communication. Action frames are specialized data frames that contain information about the action being performed. These frames allow ESP-NOW devices to efficiently exchange data without the overhead associated with more generic data frames.

Action Frames
Action Frames

Low Latency

As a result of the limited data quantities and its lightweight design ESP-NOW introduces a low latency, which means that devices can quickly exchange data making it suitable for remote controlling other devices, e.g. a radio car.

Limitations

Limited Range

ESP-NOW has a limited signal range, typically around 220 meters under ideal conditions. The actual range can vary depending on factors like environmental interference, antenna design, and obstacles in the communication path.

Interference

Like other wireless communication technologies operating in the 2.4 GHz band, ESP-NOW can be susceptible to interference from other devices and Wi-Fi networks. It's essential to choose communication channels carefully to minimize interference and ensure reliable communication.

No Network Infrastructure

ESP-NOW is designed for point-to-point and point-to-multipoint communication but doesn't provide the infrastructure for building complex network topologies. If your application requires a network with multiple interconnected devices or Internet connectivity, you may need to complement ESP-NOW with additional networking solutions.

Limited Data Payload

ESP-NOW is optimized for transmitting smaller amounts of data, with a maximum payload of around 250 bytes. If your application requires high-bandwidth data transfer or large file exchanges, other services such as the Arduino Cloud might be more suitable.

Security Considerations

While ESP-NOW offers some level of data privacy, it may not be as secure as other communication protocols like HTTPS or MQTT with robust encryption. If your project involves sensitive data, consider implementing additional security measures to protect against eavesdropping and unauthorized access.

No Message Acknowledgment

ESP-NOW does not provide built-in acknowledgment mechanisms for confirming successful message delivery. If message reliability is crucial for your application, you'll need to implement your own acknowledgment and error-handling mechanisms.

Compatibility

ESP-NOW is primarily designed for use with ESP8266 and ESP32 microcontrollers. While it can be compatible with other ESP32-based devices, it may not work seamlessly with other non-ESP platforms. Compatibility should be considered when designing a system with multiple types of devices.

Arduino Cloud

Arduino provides their own service for handling wireless communication called Arduino Cloud. You can read more about it here.

While the Arduino Cloud offers similar features to the ESP-NOW protocols they are vastly different and should be used for specific use cases. Check the comparison table below for more information.

Arduino CloudESP-NOW
RangeDepends on Internet connectivity, suitable for global reach.Approx. 220 m.
SecuritySecure communication with encryption and authentication.Basic security, may need additional measures.
DelayNetwork-related delays due to Internet communication.Low latency for local communication.
Data SizeUnlimited data (min. Entry plan)max 250 bytes.
Device CompatibilityCompatible with various Arduino boards and IoT devices.Primarily used with ESP8266 and ESP32 microcontrollers.
ProtocolUses MQTT for communication.Uses a custom ESP-NOW protocol.
Power ConsumptionMay consume more power, especially when connected to the internet.Known for low power consumption.
Data ProcessingAllows for Cloud-based data processing and analytics.Primarily for direct device-to-device communication.
Use CasesIoT projects requiring global connectivity and Cloud-based data management.Applications needing low-latency, local communication.

Check out the different Arduino Cloud plans here.

Code

Below you can find examples for sending and receiving data via the ESP-NOW protocol. You first need to identify the MAC address of your receiving board to let the sender know where to send the data. To identify the MAC address of your board upload the following code:

1// Complete Instructions to Get and Change ESP MAC Address: https://RandomNerdTutorials.com/get-change-esp32-esp8266-mac-address-arduino/
2
3#include "WiFi.h"
4
5void setup(){
6 Serial.begin(115200);
7 WiFi.mode(WIFI_MODE_STA);
8 Serial.println(WiFi.macAddress());
9}
10
11void loop(){
12
13}

Sender Sketch

1/*
2 Rui Santos
3 Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files.
7
8 The above copyright notice and this permission notice shall be included in all
9 copies or substantial portions of the Software.
10*/
11
12#include <esp_now.h>
13#include <WiFi.h>
14
15// REPLACE WITH YOUR RECEIVER MAC Address
16uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
17
18// Structure example to send data
19// Must match the receiver structure
20typedef struct struct_message {
21 char a[32];
22 int b;
23 float c;
24 bool d;
25} struct_message;
26
27// Create a struct_message called myData
28struct_message myData;
29
30esp_now_peer_info_t peerInfo;
31
32// callback when data is sent
33void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
34 Serial.print("\r\nLast Packet Send Status:\t");
35 Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
36}
37
38void setup() {
39 // Init Serial Monitor
40 Serial.begin(115200);
41
42 // Set device as a Wi-Fi Station
43 WiFi.mode(WIFI_STA);
44
45 // Init ESP-NOW
46 if (esp_now_init() != ESP_OK) {
47 Serial.println("Error initializing ESP-NOW");
48 return;
49 }
50
51 // Once ESPNow is successfully Init, we will register for Send CB to
52 // get the status of Transmitted packet
53 esp_now_register_send_cb(OnDataSent);
54
55 // Register peer
56 memcpy(peerInfo.peer_addr, broadcastAddress, 6);
57 peerInfo.channel = 0;
58 peerInfo.encrypt = false;
59
60 // Add peer
61 if (esp_now_add_peer(&peerInfo) != ESP_OK){
62 Serial.println("Failed to add peer");
63 return;
64 }
65}
66
67void loop() {
68 // Set values to send
69 strcpy(myData.a, "THIS IS A CHAR");
70 myData.b = random(1,20);
71 myData.c = 1.2;
72 myData.d = false;
73
74 // Send message via ESP-NOW
75 esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
76
77 if (result == ESP_OK) {
78 Serial.println("Sent with success");
79 }
80 else {
81 Serial.println("Error sending the data");
82 }
83 delay(2000);
84}

Receiver Sketch

1/*
2 Rui Santos
3 Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files.
7
8 The above copyright notice and this permission notice shall be included in all
9 copies or substantial portions of the Software.
10*/
11
12#include <esp_now.h>
13#include <WiFi.h>
14
15// Structure example to receive data
16// Must match the sender structure
17typedef struct struct_message {
18 char a[32];
19 int b;
20 float c;
21 bool d;
22} struct_message;
23
24// Create a struct_message called myData
25struct_message myData;
26
27// callback function that will be executed when data is received
28void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
29 memcpy(&myData, incomingData, sizeof(myData));
30 Serial.print("Bytes received: ");
31 Serial.println(len);
32 Serial.print("Char: ");
33 Serial.println(myData.a);
34 Serial.print("Int: ");
35 Serial.println(myData.b);
36 Serial.print("Float: ");
37 Serial.println(myData.c);
38 Serial.print("Bool: ");
39 Serial.println(myData.d);
40 Serial.println();
41}
42
43void setup() {
44 // Initialize Serial Monitor
45 Serial.begin(115200);
46
47 // Set device as a Wi-Fi Station
48 WiFi.mode(WIFI_STA);
49
50 // Init ESP-NOW
51 if (esp_now_init() != ESP_OK) {
52 Serial.println("Error initializing ESP-NOW");
53 return;
54 }
55
56 // Once ESPNow is successfully Init, we will register for recv CB to
57 // get recv packer info
58 esp_now_register_recv_cb(OnDataRecv);
59}
60
61void loop() {
62
63}

Read More

For a more detailed explanation on how the code works check out the article at randomnerdtutorials.com.

You can also read more about the

esp_now
library over at https://docs.espressif.com/.

Summary

In this article we covered the basics of the ESP-NOW protocol and how it works. We also provided example code serving as a starting point for your project. Overall, ESP-NOW is a powerful communication protocol for local and low-latency applications, particularly when using ESP8266 and ESP32 microcontrollers.

However, it comes with certain limitations that you should be aware of when designing projects.

Suggest changes

The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything wrong, you can edit this page here.

License

The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.