Getting Started with ESP-NOW (ESP32 with Arduino IDE)

Learn how to use ESP-NOW to exchange data between ESP32 boards programmed with Arduino IDE. ESP-NOW is a connectionless communication protocol developed by Espressif that features short packet transmission. This protocol enables multiple devices to talk to each other in an easy way.

Getting Started with ESP-NOW (ESP32 with Arduino IDE)

We have other tutorials for ESP-NOW with the ESP32:

Arduino IDE

We’ll program the ESP32 board using Arduino IDE, so before proceeding with this tutorial you should have the ESP32 add-on installed in your Arduino IDE. Follow the next guide:

Note: we have a similar guide for the ESP8266 NodeMCU Board: Getting Started with ESP-NOW (ESP8266 NodeMCU with Arduino IDE)

Introducing ESP-NOW

For a video introduction to ESP-NOW protocol, watch the following (try the project featured in this video):

Stating Espressif website, ESP-NOW is a “protocol developed by Espressif, which enables multiple devices to communicate with one another without using Wi-Fi. The protocol is similar to the low-power 2.4GHz wireless connectivity (…) . The pairing between devices is needed prior to their communication. After the pairing is done, the connection is safe and peer-to-peer, with no handshake being required.”

ESP-NOW - ESP32 Logo

This means that after pairing a device with each other, the connection is persistent. In other words, if suddenly one of your boards loses power or resets, when it restarts, it will automatically connect to its peer to continue the communication.

ESP-NOW supports the following features:

  • Encrypted and unencrypted unicast communication;
  • Mixed encrypted and unencrypted peer devices;
  • Up to 250-byte payload can be carried;
  • Sending callback function that can be set to inform the application layer of
    transmission success or failure.

ESP-NOW technology also has the following limitations:

  • Limited encrypted peers. 10 encrypted peers at the most are supported in Station mode; 6 at the most in SoftAP or SoftAP + Station mode;
  • Multiple unencrypted peers are supported, however, their total number should be less than 20, including encrypted peers;
  • Payload is limited to 250 bytes.

In simple words, ESP-NOW is a fast communication protocol that can be used to exchange small messages (up to 250 bytes) between ESP32 boards.

ESP-NOW is very versatile and you can have one-way or two-way communication in different setups.

ESP-NOW One-Way Communication

For example, in one-way communication, you can have scenarios like this:

  • One ESP32 board sending data to another ESP32 board

This configuration is very easy to implement and it is great to send data from one board to the other like sensor readings or ON and OFF commands to control GPIOs.

ESP-NOW One ESP32 board sending data to another ESP32 board

One ESP32 board sending the same or different commands to different ESP32 boards. This configuration is ideal to build something like a remote control. You can have several ESP32 boards around the house that are controlled by one main ESP32 board.

ESP-NOW master ESP32 sending data to multiple ESP32 slaves

This configuration is ideal if you want to collect data from several sensors nodes into one ESP32 board. This can be configured as a web server to display data from all the other boards, for example.

ESP-NOW One ESP32 slave receiving data from multiple masters

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

ESP-NOW Two-Way Communication

With ESP-NOW, each board can be a sender and a receiver at the same time. So, you can establish a two-way communication between boards.

For example, you can have two boards communicating with each other.

ESP-NOW Two-Way Communication between two ESP32 boards

Learn how to: Exchange Sensor Readings with ESP-NOW Two-Way Communication.

You can add more boards to this configuration and have something that looks like a network (all ESP32 boards communicate with each other).

ESP-NOW Communication between multiple ESP32 boards

In summary, ESP-NOW is ideal to build a network in which you can have several ESP32 boards exchanging data with each other.

ESP32: Getting Board MAC Address

To communicate via ESP-NOW, you need to know the MAC Address of the ESP32 receiver. That’s how you know to which device you’ll send the information to.

Each ESP32 has a unique MAC Address and that’s how we identify each board to send data to it using ESP-NOW (learn how to Get and Change the ESP32 MAC Address).

To get your board’s MAC Address, upload the following code.

// Complete Instructions to Get and Change ESP MAC Address: https://RandomNerdTutorials.com/get-change-esp32-esp8266-mac-address-arduino/

#include "WiFi.h"
 
void setup(){
  Serial.begin(115200);
  WiFi.mode(WIFI_MODE_STA);
  Serial.println(WiFi.macAddress());
}
 
void loop(){

}

View raw code

After uploading the code, open the Serial Monitor at a baud rate of 115200 and press the ESP32 RST/EN button. The MAC address should be printed as follows:

ESP-NOW ESP32 Getting Board MAC Address

Save your board MAC address because you’ll need it to send data to the right board via ESP-NOW.

ESP-NOW One-way Point to Point Communication

To get you started with ESP-NOW wireless communication, we’ll build a simple project that shows how to send a message from one ESP32 to another. One ESP32 will be the “sender” and the other ESP32 will be the “receiver”.

ESP-NOW One-way Point to Point Communication ESP32

We’ll send a structure that contains a variable of type char, int, float, String and boolean. Then, you can modify the structure to send whichever variable types are suitable for your project (like sensor readings, or boolean variables to turn something on or off).

For better understanding we’ll call “sender” to ESP32 #1 and “receiver” to ESP32 #2.

Here’s what we should include in the sender sketch:

  1. Initialize ESP-NOW;
  2. Register a callback function upon sending data – the OnDataSent function will be executed when a message is sent. This can tell us if the message was successfully delivered or not;
  3. Add a peer device (the receiver). For this, you need to know the the receiver MAC address;
  4. Send a message to the peer device.

On the receiver side, the sketch should include:

  1. Initialize ESP-NOW;
  2. Register for a receive callback function (OnDataRecv). This is a function that will be executed when a message is received.
  3. Inside that callback function save the message into a variable to execute any task with that information.

ESP-NOW works with callback functions that are called when a device receives a message or when a message is sent (you get if the message was successfully delivered or if it failed).

ESP-NOW Useful Functions

Here’s a summary of most essential ESP-NOW functions:

Function Name and Description
esp_now_init() Initializes ESP-NOW. You must initialize Wi-Fi before initializing ESP-NOW.
esp_now_add_peer() Call this function to pair a device and pass as argument the peer MAC address.
esp_now_send() Send data with ESP-NOW.
esp_now_register_send_cb() Register a callback function that is triggered upon sending data. When a message is sent, a function is called – this function returns whether the delivery was successful or not.
esp_now_register_rcv_cb() Register a callback function that is triggered upon receiving data. When data is received via ESP-NOW, a function is called.

For more information about these functions read the ESP-NOW documentation at Read the Docs.

ESP32 Sender Sketch (ESP-NOW)

Here’s the code for the ESP32 Sender board. Copy the code to your Arduino IDE, but don’t upload it yet. You need to make a few modifications to make it work for you.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
  
  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 YOUR RECEIVER 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 {
  char a[32];
  int b;
  float c;
  String d;
  bool e;
} struct_message;

// Create a struct_message called myData
struct_message myData;

// 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
  esp_now_peer_info_t peerInfo;
  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
  strcpy(myData.a, "THIS IS A CHAR");
  myData.b = random(1,20);
  myData.c = 1.2;
  myData.d = "Hello";
  myData.e = false;

  // 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(2000);
}

View raw code

How the code works

First, include the esp_now.h and WiFi.h libraries.

#include <esp_now.h>
#include <WiFi.h>

In the next line, you should insert the ESP32 receiver MAC address.

uint8_t broadcastAddress[] = {0x30, 0xAE, 0xA4, 0x07, 0x0D, 0x64};

In our case, the receiver MAC address is: 30:AE:A4:07:0D:64, but you need to replace that variable with your own MAC address.

Then, create a structure that contains the type of data we want to send. We called this structure struct_message and it contains 5 different variable types. You can change this to send whatever variable types you want.

typedef struct struct_message {
  char a[32];
  int b;
  float c;
  String d;
  bool e;
} struct_message;

Then, create a new variable of type struct_message that is called myData that will store the variables values.

struct_message myData;

Next, define the OnDataSent() function. This is a callback function that will be executed when a message is sent. In this case, this function simply 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, we register for the OnDataSent() function created previously.

esp_now_register_send_cb(OnDataSent);

After that, we need to pair with another ESP-NOW device to send data. That’s what we do in the next lines:

//Register peer
esp_now_peer_info_t peerInfo;
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 2 seconds (you can change this delay time).

First, we set the variables values as follows:

strcpy(myData.a, "THIS IS A CHAR");
myData.b = random(1,20);
myData.c = 1.2;
myData.d = "Hello";
myData.e = false;

Remember that myData is a structure. Here we assign the values we want to send inside the structure. For example, the first line assigns a char, the second line assigns a random Int number, a Float, a String and a Boolean variable.

We create this kind of structure to show you how to send the most common variable types. You can change the structure to send any other type of data.

Finally, send the message as follows:

esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));

Check if the message was successfully sent:

if (result == ESP_OK) {
  Serial.println("Sent with success");
}
else {
  Serial.println("Error sending the data");
}

The loop() is executed every 2000 milliseconds (2 seconds).

delay(2000);

ESP32 Receiver Sketch (ESP-NOW)

Upload the following code to your ESP32 receiver board.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
  
  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 {
    char a[32];
    int b;
    float c;
    String d;
    bool e;
} struct_message;

// Create a struct_message called myData
struct_message myData;

// callback function that will be executed when data is received
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() {
  // 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() {

}

View raw code

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 {
  char a[32];
  int b;
  float c;
  String d;
  bool e;
} 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. The function is called onDataRecv() and should accept several parameters as follows:

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {

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

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

Now, the myData structure contains several variables inside with the values sent by the sender ESP32. To access variable a, for example, we just need to call myData.a.

In this example, we simply print the received data, but in a practical application you can print the data on a display, for example.

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

In the setup(), intialize 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(OnDataRecv);

Testing ESP-NOW Communication

Upload the sender sketch to the sender ESP32 board and the receiver sketch to the receiver ESP32 board.

Now, open two Arduino IDE windows. One for the receiver, and another for the sender. Open the Serial Monitor for each board. It should be a different COM port for each board.

This is what you should get on the sender side.

Testing ESP-NOW Communication ESP32 with Arduino IDE Sender

And this is what you should get on the receiver side. Note that the Int variable changes between each reading received (because we set it to a random number in the sender side).

Testing ESP-NOW Communication ESP32 with Arduino IDE Receiver

We tested the communication range between the two boards, and we are able to get a stable communication up to 220 meters (approximately 722 feet) in open field. In this experiment both ESP32 on-board antennas were pointing to each other.

ESP-NOW communication range test ESP32

Wrapping Up

We tried to keep our examples as simple as possible so that you better understand how everything works. There are more ESP-NOW related functions that can be useful in your projects, like: managing peers, deleting peers, scanning for slave devices, etc… For a complete example, in your Arduino IDE, you can go to File > Examples > ESP32 > ESPNow and choose one of the example sketches.

We hope you’ve found this introduction to ESP-NOW useful. As a simple getting started example, we’ve shown you how to send data as a a structure from one ESP32 to another. The idea is to replace the structure values by sensor readings or GPIO states, for example.

Additionally, with ESP-NOW, each board can be a sender and receiver at the same time, and one board can send data to multiple boards and also receive data from multiple boards. These topics will be covered in future tutorials, so stay tuned.

We also have a tutorial about ESP-NOW with the ESP8266: Getting Started with ESP-NOW (ESP8266 NodeMCU with Arduino IDE).

To learn more about the ESP32 board, make sure you take a look at our resources:

Thanks for reading.



Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our weekly newsletter!

98 thoughts on “Getting Started with ESP-NOW (ESP32 with Arduino IDE)”

  1. Great, we don’t need a WIFI_AP anymore 🙂
    For now, I’m challenging a light handshake protocol between slave and master.
    For my application, the slave must decide the duration of sleep for the master(s). The idea is synchronize all ESP32.

    Reply
  2. hello,
    a simple question: yiu tyitlet this post esp-now-esp32…, but if i’m right the protocol works on esp8266 too: is this correct? is there any difference between esp32 and esp8266?
    regards

    Reply
    • Hi.
      You’re right, ESP-NOW also works with ESP8266.
      However, I haven’t tested this code with the ESP8266. Probably there are some changes that need to be made to make it compatible.
      We’ll write a guide about ESP-NOW with ESP8266 – but we still don’t know when.
      Regards,
      Sara

      Reply
      • can we have both ESP NOW and Wifi running simultaneously? I want to have an esp acting like a slave, receive the message from esp now, and then send it into an MQTT queue via wifi, is this possible?

        Reply
        • Yes.
          It is possible.
          But the ESP32 needs to be set as a wi-fi station and access point at the same time.
          You need to use different wi-fi channels. One for ESP-NOW and other to connect to Wi-Fi.
          I’ll be publishing a tutorial about combining ESP-NOW with Wi-Fi in the next weeks.
          So, stay tuned.
          Regards.
          Sara

          Reply
        • Hi JF,
          It is possible to use an ESP32 to receive the data and send it to the web. I don’t know exactly what you want to do, but I modified the code of this excellent post of this blog and made a project which builts an web server which publishes all the data received by the ESP-NOW protocol.

          This project is available here: https://github.com/dualvim/ESP32CAM_ESPNOW_Sensors_WebServer

          It uses an ESP32, an ESP32-CAM and some sensors.

          I hope that it will help you.
          For Sara and Rui, feel free to use it, once all the code are only modifications based on tons of code that I learned here in the blog. It is yours actually!

          Reply
          • Thanks for sharing that 😀
            We’ll write a tutorial using some of the concepts you address in that project.
            Thank you.
            Regards,
            Sara

  3. With respect to your “ESP32 LoRa Sensor Monitoring with Web Server” project could ESP-NOW be used to setup multiple remotes talking to a single ESP32 server?

    Reply
  4. How about ESP32 to ESP8266 so I can use all of those old 8266 I have? Maybe you could provide a summary of alternative 32 to 8266 networking at this current time in the product development cycle.
    Looking forward to your future developments on this product…

    Reply
    • Hi.
      ESP-NOW communication protocol also works with the ESP8266.
      However, at the moment, I haven’t tested these examples with the ESP8266. So, I don’t know if both boards can use the same code or not.
      Regards,
      Sara

      Reply
    • I have modified the code and now it is working just fine below is the code i used…And the sender is ESP32 while the receiver is ESP8266(nodeMcu).

      extern “C” {
      #include
      #include “user_interface.h”
      }
      #include

      // Structure example to receive data
      // Must match the sender structure
      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;

      // callback function that will be executed when data is received
      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() {
      // Initialize Serial Monitor
      Serial.begin(115200);

      // Set device as a Wi-Fi Station
      WiFi.mode(WIFI_STA);

      // Init ESP-NOW
      if (esp_now_init() == 0)
      {
      Serial.println(“ESP NOW initialised. . .”);
      }
      else
      {
      Serial.println(“ESP NOW not initialised. . .”);
      ESP.restart();
      delay(1);
      }

      // Once ESPNow is successfully Init, we will register for recv CB to
      // get recv packer info
      esp_now_register_recv_cb(OnDataRecv);
      }
      void loop() {}

      Reply
  5. Hi Sara,
    The source code of the ‘Sender module’ (ESP_NOW_Sender.ino) should be fixed, it is different from the code in the explanations bollow of it.

    Despite this detail, excelent post! I didn’t know this resource and I’m testing it here.
    Congratulations!

    Reply
  6. I definitely want to work with this method. It looks so interesting, and the fact it will reply back is amazing. Random Nerds has the best learning site that I am aware of. I have learned more in a month here, than I have learned in a year from any other site.
    Thank you!!
    Bob D

    Reply
    • Hi Bob.
      Yes, ESP-NOW is a great method to exchange data between boards. And you know if the message was successfully delivered or not.
      Thanks for your nice words.
      Regards,
      Sara

      Reply
  7. Really interesting! A new capability for longer range remote control.
    Definitely one of your best tutorials. The amount of first class info you freely share is admirable.

    Reply
  8. Wow, I am very excited about this, it is what I have been looking for to set up networks in my home and on my RV to use when we are on the road seeing our great nation.

    Do you have any idea how much modification it would take to add an M5Stick-c to the network, since it is based on an ESP32, has the built in color screen, and the environmental hat is available for it, using the same chip for reading temp and humidity?

    Perhaps the Heltec ESP32 could be included as well, with it’s built in OLED screen. Just thoughts, this does look extremely useful, thank you so much for the write up and effort put into this project, it could have life changing consequences.

    Reply
    • Hi Jerry.
      Thank you for your nice words.
      The M5Stick-c can be programmed using Arduino IDE, and it uses the ESP32 chip, so you can use the code with that board.
      Then, you just need to know the connections between the peripherals and the board and search for examples that interface those peripherals (the sensors and the display).
      Regards,
      Sara

      Reply
    • I am currently running a Heltec Wireless Stick Lite as the sender with ESP NOW to an M5 Stick C as a receiver with the LCD screen showing data. It works great!! The M5 Stick C has far better reception with its on board antenna. The Heltec board needed a small (3″) wire attached to the 3D on board antenna to get better reception. I needed the Heltec board at the sending end as the M5 didnt have enough pins for my application. Other than that , I prefer the M5 over the Heltec for ease of use.

      Reply
  9. I tested ESP NOW with this example and it is very impressive. In my distance tests from outdoors, through two walls to the receiver indoors, I was able to get 40 meters. It is a great alternative to LoRa for point – point closer range communication. Now to get analog sensor readings from sender to receiver …

    Reply
  10. Great post — as usual. 😉

    One thing that concerns me though is the use of 2.4GHz channels. That is, I can see how useful this can be in a field or an open space (as in the picture above) where no WiFi hubs are present. However, if we use the ESP NOW in a home, it will conflict with the current WiFi hub — competing and forcing ‘everybody’ to every-now-and-then drop packages due to collisions. Also, since ESP NOW likely doesn’t have functionalities to auto switch channels, MIMO, etc… the use of the same IEEE802 channels can be a real problem to the current hubs/devices.
    I am saying this because I have noticed in the past that the simple presence of an ESP closer to my home WiFi hub has affected the WiFi hub’s performance — likely, in this case, due to the ‘cheap’ antennas and hardware of the ESPs in general that cause a spread of the channel spectrum (eg. channel 11 in a simple 802.11b/n going, in frequency/spectrum, way over channels 8, 9, 10… 12, 13 14…)

    Reply
  11. It looks to me that it works by sending and receiving low level wireless data frames which I presume are analogous to raw (wired) ethernet frames. That makes me think the station limits are artifacts of the library rather than something baked into the hardware? It also makes me wonder if multi station broadcast would in fact work (with ff:ff:ff:ff:ff:ff as the target address)?

    Reply
      • Hello Sara,

        Is it possible to make a two way communication between multiple ESP32 without setting the MAC addresses and just use FF:FF:FF:FF:FF:FF. Using the confirm message to carry a few data?

        Reply
        • Hi.
          Yes, you can use FF to exchange data between your boards.
          What do you mean by “confirm message to carry a few data?”
          Regards,
          Sara

          Reply
    • You can also use NULL, as in:

      esp_now_send(NULL, (uint8_t *) &myData, sizeof(myData))

      The package will than be sent to all peers added with esp_now_add_peer.

      Reply
  12. Hi sara thanks a lot. And this tutorial is very interesting and very useful for me. Appreciate and thanks again.

    Reply
  13. Hi Sara and Rui
    Just a few days ago I was looking for information on this type of communication between modules. It only works between modules or you can also use the Master with ESP NOW and connect to the Wifi and dump the data on a server or in the cloud? .. Good job … and also beautiful beaches to test the connection distance. ..Thank you

    Reply
    • Hi Carlos.
      Yes, you can use ESP-NOW and Wi-Fi in the same board, in theory.
      However, I didn’t get it working yet. There should be some trick to make it work properly. But, we’re working on that and we’ll publish a tutorial about that subject when we get it working.
      Regards,
      Sara

      P.S. Portugal has a 1,794 km coastline with beautiful beaches. It’s worth a visit, if you have the opportunity, specially the south.
      Regards,
      Sara

      Reply
      • Hi Rui and Sara,
        I figure out hou to connect the ESP32 to the internet and use the ESP-NOW.

        It is a little Akward and I’m really tired, but if you’re interested in my solution, just tell me. I’ll try to upload and share as soon as possible!

        Reply
        • Hi Eduardo.
          If you have that project ready, then share a link to the project GitHub page.
          I’d love to see how you did it. But don’t be in a rush, we have time.
          Regards,
          Sara

          Reply
          • Hi Eduardo.
            Great project! I’ve seen your GitHub page. Very well explained. Thanks for sharing it with us!
            Unfortunately, I was not able to see the project running on that link today 4th February.
            Regards,
            Sara

  14. Hi Sara,

    Great article! But I have a few things to clarify. First, there are several references to using the sender callback function to “know if the message was received,” but, since this is a connectionless protocol, (no “ACK”), the sender can only say that the message was successfully sent. It has no way to know if the message was received, unless the receiver becomes a sender and sends back an “ACK” message. I think that should be clarified in your article.
    Also, in one of your replies, you said that it’s possible to use “ff-ff-ff-ff” as a MAC address to send to multiple receivers… But, in the intro, the article stated that “broadcast is not possible.” Is that because the senders cannot decode and match the “ff-ff-ff-ff” to their own MAC address?
    Also one question: with regards to “registering the sender & receiver,” it seems that all that entails is putting the receiver’s MAC address in the code – – is that correct?
    (But, I’ve forgotten if you need to put the sender’s MAC address in the receiver’s code. If not, I don’t really see how it’s “registering” like when we’re linking two Bluetooth devices. It’s just putting the destination address in the packet, like any other transmission.)
    Thanks again for all the fine (actually awesome) articles!

    Reply
    • Hi Jeff.
      Thanks for your comment.
      I’m not sure if I know how to answer all the questions.
      In the espressif documentation, it says “Call esp_now_send() to send ESP-NOW data and esp_now_register_send_cb to register sending callback function. It will return ESP_NOW_SEND_SUCCESS in sending callback function if the data is received successfully on the MAC layer.” https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/network/esp_now.html#send-esp-now-data But, you’re right, because “t is not guaranteed that application layer can receive the data. ”

      Yes, you can use the FF MAC address to send to all devices and it works. However, in the espressif ESP-NOW “datasheet” they said it doesn’t support broadcast mode: https://www.espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf But, maybe this is outdated. I’ll update our article about broadcasting.

      To send a message to a device, you just need to put the receiver MAC address on your code and you don’t need to put the sender MAC address on the receiver code.

      I think that what I’m saying is correct, but tell me if I’m wrong.

      Thanks for your comment.
      Regards,
      Sara

      Reply
  15. Hi Sara,
    very often you refer to address 192.168.4.1 an it works.
    My default addreess of the router is 192.168.1.1

    Which is the reference to the first address?
    Thanks

    Renzo

    Reply
  16. renzo, 192.168.4.1 is the default (gateway address) of the ESP when it is in AP mode. Some applications use 192.168.4.1 to host a web page from which you enter your own home network credentials. The famous ESP-Link bridge application does just that.

    Your default address of 192.168.1.1 is usually the gateway address of your router, it does vary with different routers and some use 192.168.1.254.

    I hope that helps

    Reply
  17. I am using two M5 Stick C , which has an ESP32 Pico chipset. I discovered the above code to get the MAC address doesn’t work on this device.
    I found one that does.

    #include “WiFi.h”

    void setup(){

    Serial.begin(115200);
    delay(500);

    Serial.println();
    Serial.print(“MAC: “);
    Serial.println(WiFi.macAddress());

    }

    void loop(){}

    Hope this helps anyone using M5 Stick C. ( great device by the way)

    Reply
  18. Thank U Rui and Sara,
    I made this project with 100% of success!!!
    Compliments for explanations, videos, pictures and your HUGE patience, availability and endurance

    A hug from Italy
    Renzo (Bologna)

    Reply
  19. “…Additionally, with ESP-NOW, each board can be a sender and receiver at the same time, and one board can send data to multiple boards and also receive data from multiple boards. These topics will be covered in future tutorials, so stay tuned.”

    Hey Rui and Sara: promise me U’ll write soon these “future tutorials” !!!
    Another hug from Italy
    Renzo (Bologna)

    Reply
  20. Hi Sara,
    the idea of JD to make an application in which the slave must decide the duration of sleep for the master(s) is very good.

    But how to do it? As far as I know it is impossible to awake from sleep an ESP8266 with a Wifi signal because simply it can’t receive any signal during sleep.

    Thanks
    Renzo Giurini

    Reply
    • Hi.
      Yes, that’s right.
      But I don’t know the application of his project. Maybe he wants to set up a new sleep time when the ESP32 wakes up from sleep. So, the next time it goes to sleep, it is for a different period of time. I don’t know, I’m just guessing 😀
      Regards,
      Sara

      Reply
  21. I used the sender-sketch for a esp8266 ans the receiver-sketch for a esp32. And both are communicating. A strange thing is that the value “Hello” for the string is not printed in the serial monitor.
    I used the sketches from getting started with ESP-now (one way communication).
    So it is working, yet the stringvalue is not known in the receiver.
    Strange?

    Reply
    • Hi Bert.
      Yes, that’s weird.
      What version of Arduino IDE are you using?
      If it doesn’t work, a workaround is to send the message as a CHAR.
      Regards,
      Sara

      Reply
  22. Sorry, I pressed the Post button too early.
    It is said above in the comments, I should get the library while I installed the ESP8266 boards onto IDE. I did that but the compiler throws me “esp_now.h: No such file or directory” error, so it seems that this is not so.
    I don’t have any ESP32 boards so I did not include them.

    Reply
  23. Hi,
    I’ve made an Arduino IDEe installation from scratch. IDE version is 1.8.12. Then I installed software for ESP8266 Community version 2.6.3 (from the link provided in your tutorial). Compiler still cannot find the esp_now.h.

    Just to see if the same thing happens for ESP32 boards, I installed software esp32 Espresiff Systems version 1.0.4 (also from the link in your corresponding tutorial). I choosed one of ESP32 boards as target and my sketch compiles OK.

    The board for which I am trying to use with ESP-Now is Wemos D1 mini. Is it possible that this board doesn’t support ESP-Now??

    Reply
      • Hi,
        well, I do have an esp2866 board selected. I managed to start web server and also a client with my settings. Just to compile the script, the board doesn’t have to be physically available, so I’ve selected some Adafruit and SparkFun boards – and experienced the same issue —

        Reply
  24. Thanks for this amazing tutorial, I have a little request, would you do a tutorial to how to work with ESP-MESH protocol ? Thanks for you contribution!!

    Reply
    • Hi Jairo.
      Thanks for the suggestion.
      I’ve been thinking about that subject for a while.
      It’s definitely in my to-do list. However, I still don’t know when it will be released. I haven’t started yet.
      Regards,
      Sara

      Reply
  25. Thanks for this great tutorial! I’ve been searching for many hours on the net to find one clean and working code like yours. So thank you!
    I would have a question that I cannot find an answer to yet.
    If I want to send the data shared in my esp-now set-up on a database meaning is it possible to switch the last esp which receives all the data to send them over the internet ?
    Is it possible or I must go with the esp-mesh protocol to do that ?
    Thank you for your time.
    jF

    Reply
    • Hi.
      Yes, you can do that.
      You need to set that ESP32 as a station and access point simultaneously for that to work.
      Regards,
      Sara

      Reply
  26. Hi,

    I want to ask. Can I use different type of ESP32 to do this? I’m using TTGO32-LoRa (as Receiver) and ESP Wroom32 (as Sender). But I didn’t receive anything.

    Thanks.

    Reply
    • Hi.
      It should work with other boards. Because they all have the ESP32 chip.
      I tried with different ESP32 board models, but not those you are mentioning, and it worked fine.
      Regards,
      Sara

      Reply
  27. Fantastic as usual!

    Can I just say, perhaps I read things differently, but I found the following line a bit confusing… “register the callback function that will be called when a message is sent.”

    I find it easier to understand worded thus… “register the callback function that will be called AFTER a message is sent.”

    Reply
  28. Hey, ive got a Problem, the Sender alway says:
    -“Last Packet Send Status: Delivery Fail”
    -“Sent with success”
    and the reciever doesnt get anything….

    Reply
    • Hi Nils.
      That means the sender was able to send the message, but the receiver didn’t get the message.
      Double-check that you’ve properly typed the receiver’s MAC address and that the receiver is relatively close to the sender (so that you’re sure it is not something related to distance).
      Regards,
      Sara

      Reply
  29. Dear Sara can we use esp now with ESP01 since it’s a low cost drive and some time no need to use ESP8266 node mcu or ESP32

    Reply
    • Hi.
      I haven’t experimented with ESP-01.
      But I think it should work. You have to experiment and see what you get.
      Regards,
      Sara

      Reply
  30. Hey guys,
    Great work, as usual.

    Is it possible to put the sender to sleep (light or deep) and have the receiver wake it up somehow to send data, with like a request or something? The sender will be a battery operated device.

    Thanks!

    Reply
    • Hi.
      I don’t know how to do that, and I don’t think it is possible (someone correct me if I’m wrong).
      You can wake up the ESP32 using an external wake-up (via physical GPIO) or have a timer wake-up. So, I don’t think you can wake it up using Wi-Fi or ESP-NOW.
      Regards,
      Sara

      Reply
  31. I m loving this ballistic learning curve I am on, I look at these tutorials and I get them working learning by my errors as I go.

    Then I get these stupid ideas like “I can use the ‘8266 one to many ESP-NOW’ with the ‘ds18b20 code’ and add the ‘oled display’ together “

    And yes I can but boy it’s not easy!

    I am trying to create separate temperature sensors with local displays that I will 3d print enclosures for later. These I will place around my home and garden and have all the data sent back to another that can display ALL the data.

    It’s not going well but thats all part of learning isn’t it. I keep getting tangled as I am finding that simple things like libraries can trip each other up if placed in certain orders.

    I am currently struggling to get the oled to display anything from within the code and although I can get the temperature (as float) across I cant then use it.

    It’s great because it time I go back to your other tutorials I learn a different approach, I am really enjoying the frustration of it

    Cheers Clive

    Reply
  32. Hi Clive,
    I agree totally; I am going back now and starting fresh on an ESP Now tutorial that uses combo mode. I will add the DSS1306 displays, and some code that will track value of a switch condition.
    It is a play on another project I completed, so I know it will work. I just want to re-enforce what I have been learning here at RN by repeating the same concept…but slightly different so I can learn more.
    The good news is I received 5 more WeMos D1, and 3 more ESP8266 modules to experiment with.

    Reply
  33. This is a great page to start with ESP-NOW. I love the community surrounding “RandomNerdTutorials”.
    My hands are burning with new projects in mind.

    Reply
  34. hi Sara
    I´m doing test with esp-now.
    Do you have the code for two ways comunication?
    Is it too different to the one way comunication code?

    regrats and thanks!

    Reply

Leave a Reply to Clive Cancel reply

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.