ESP-NOW Two-way communication

Description

  • As we know the 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. 
  • Using ESP-NOW each board can transmit and receive the data at the same time. So, you can establish two-way communication between two boards.
  • We will use the DHT11 sensor for the first ESP32 and BMP180 for the second ESP32 for two-way communication.
  • We will read the pressure and altitude from BMP180 at the same time, temperature, and humidity from the DHT11 sensor and exchange the data between them.

 

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

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

Getting Board MAC Address

#include "WiFi.h"

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

void loop(){}

 

Output

Connection Diagram of DHT11 with ESP32

Connection Diagram of DHT11 with ESP32

 

BMP180 Hardware Connection with ESP32

BMP180 Hardware Connection with ESP32

 

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

uint8_t broadcastAddress[] = {0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };

ESP Now: ESP32 with DHT11 Sensor Code

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

DHT dht;
float BMP180_Pres;
float BMP180_Alt;

uint8_t broadcastAddress[] = {0x30, 0xC6, 0xF7, 0x23, 0x34, 0x44};
String success;

typedef struct struct_message {
    float temp;
    float hum;
    float pres;
    float alt;
} struct_message;

struct_message DHT11_data;
struct_message BMP180_data;
esp_now_peer_info_t peerInfo;

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nDelivery Status: ");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Deliverd Successfully" : "Delivery Fail");
  if (status ==0){
    success = "Delivery Success :)";
  }
  else{
    success = "Delivery Fail :(";
  }
}

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&BMP180_data, incomingData, sizeof(BMP180_data));
  BMP180_Pres = BMP180_data.pres;
  BMP180_Alt = BMP180_data.alt;
}
 
void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  dht.setup(0);                 /*Connect the DHT11's data pin to GPIO0*/
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  esp_now_register_send_cb(OnDataSent);
 
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0; 
  peerInfo.encrypt = false;
       
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  esp_now_register_recv_cb(OnDataRecv);
}
 
void loop() {
  DHT11_data.temp = dht.getTemperature(); /*Get the Temperature value*/
  DHT11_data.hum = dht.getHumidity();       /*Get the Humidity value*/

  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &DHT11_data, sizeof(DHT11_data));
   
  if (result == ESP_OK) {
    Serial.println("Sent Successfullt");
  }
  else {
    Serial.println("Getiing Error while sending the data");
  }

  Serial.print("Pressure: ");
  Serial.print(BMP180_data.pres);
  Serial.println(" Pa");
  Serial.print("Altitude: ");
  Serial.print(BMP180_data.alt);
  Serial.println(" Meters");
  Serial.println();

  delay(3000);
}

 

  • Now upload the code. (While uploading the code make sure your ESP32 board is in the boot mode.)
  • After uploading the code open the serial monitor and set the baud rate to 115200 then reset the ESP32 board and check the IP address as shown in the below image

 

Output 

 

Understand the code

Add esp_now.h, DHT.h, and WiFi.h libraries.

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

Create the object as below

DHT dht;

Now add the MAC address of receiver ESP32

Our MAC address is 30:C6:F7:23:34:44

uint8_t broadcastAddress[] = {0x30, 0xC6, 0xF7, 0x23, 0x34, 0x44};

Here we are created a structure to send and receive the data.

typedef struct struct_message {
    float temp;
    float hum;
    float pres;
    float alt;
} struct_message;

Create a struct_message variable called DHT11_data and BMP180_data.

struct_message DHT11_data;
struct_message BMP180_data;

esp_now_peer_info_t is a variable to store information of peers.

esp_now_peer_info_t peerInfo;

 

Important Function: Callback function when ESP32 send the data

OnDataSent() is a callback function that will be executed when a message is sent. 

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nDelivery Status: ");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Deliverd Successfully" : "Delivery Fail");
  if (status ==0){
    success = "Delivery Success :)";
  }
  else{
   success = "Delivery Fail :(";
  }
}

 

Important Function: Callback function when ESP32 receives the data

Create a callback function that will be called when the ESP32 receives the data via ESP-NOW

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&BMP180_data, incomingData, sizeof(BMP180_data));
  BMP180_Pres = BMP180_data.pres;
  BMP180_Alt = BMP180_data.alt;
}

 

In the setup function

initialize the serial monitor 

Serial.begin(115200);

set the GPIO 0 pin as a data communication Pin.

dht.setup(0);

Set ESP32 in a Wi-Fi station Mode:

WiFi.mode(WIFI_STA);

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

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

esp_now_register_send_cb(OnDataSent);

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

memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK){
  Serial.println("Failed to add peer");
  return;
}

 

In the loop function

Get the temperature and humidity reading from DHT11 and store it.

DHT11_data.temp = dht.getTemperature(); /*Get the Temperature value*/
DHT11_data.hum = dht.getHumidity();       /*Get the Humidity value*/

Here we’ll send the temperature and humidity every three seconds.

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

Check the message status was successfully sent or not

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

Here print the received pressure and altitude on serial monitor

  Serial.print("Pressure: ");
 Serial.print(BMP180_data.pres);
 Serial.println(" Pa");
 Serial.print("Altitude: ");
 Serial.print(BMP180_data.alt);
 Serial.println(" Meters");
  Serial.println();

Wait for three second

delay(3000);

Now copy the below code and upload it on the second device and check the result on the serial monitor.

Before uploading make sure you have updated your MAC address
uint8_t broadcastAddress[] = {0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };

 

ESP Now: ESP32 with BMP180 Sensor Code

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

Adafruit_BMP085 bmp;
float DHT11_Temp;
float DHT11_Hum;

uint8_t broadcastAddress[] = {0x24, 0x0A, 0xC4, 0x59, 0xBB, 0x50};
String success;

typedef struct struct_message {
    float temp;
    float hum;
    float pres;
    float alt;
} struct_message;

struct_message DHT11_data;
struct_message BMP180_data;
esp_now_peer_info_t peerInfo;

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nDelivery Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Successfully" : "Delivery Fail");
  if (status ==0){
    success = "Delivery Success :)";
  }
  else{
    success = "Delivery Fail :(";
  }
}

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&DHT11_data, incomingData, sizeof(DHT11_data));
  DHT11_Temp = DHT11_data.temp;
  DHT11_Hum = DHT11_data.temp;
}
 
void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

  if (!bmp.begin()) {
      Serial.println("Could not find a valid BMP085 sensor, check wiring!");
      while (1) {}
  }
 
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  esp_now_register_send_cb(OnDataSent);
 
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0; 
  peerInfo.encrypt = false;
       
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  esp_now_register_recv_cb(OnDataRecv);
}
 
void loop() {
  BMP180_data.pres = bmp.readPressure();
  BMP180_data.alt = bmp.readAltitude();

  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &BMP180_data, sizeof(BMP180_data));
   
  if (result == ESP_OK) {
    Serial.println("Sent Successfully");
  }
  else {
    Serial.println("Error sending the data");
  }

  Serial.print("Temperature: ");
  Serial.print(DHT11_data.temp);
  Serial.println(" ºC");
  Serial.print("Humidity: ");
  Serial.print(DHT11_data.hum);
  Serial.println(" %");
  Serial.println();

  delay(3000);
}

 

  • Now upload the code. (While uploading the code make sure your ESP32 board is in the boot mode.)
  • After uploading the code open the serial monitor and set the baud rate to 115200 then reset the ESP32 board and check the IP address as shown in the below image

 

Output

 

Understand the code

Add esp_now.h, DHT.h, and WiFi.h libraries.

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

Now add the MAC address of receiver ESP32

Our MAC address is 30:C6:F7:23:34:44

uint8_t broadcastAddress[] = {0x30, 0xC6, 0xF7, 0x23, 0x34, 0x44};

Here we are created a structure to send and receive the data.

typedef struct struct_message {
    float temp;
    float hum;
    float pres;
    float alt;
} struct_message;

Create a struct_message variable called DHT11_data and BMP180_data.

struct_message DHT11_data;
struct_message BMP180_data;

esp_now_peer_info_t is a variable to store information of peers.

esp_now_peer_info_t peerInfo;

OnDataSent() is a callback function that will be executed when a message is sent. 

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nDelivery Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Successfully" : "Delivery Fail");
  if (status ==0){
    success = "Delivery Success :)";
  }
  else{
    success = "Delivery Fail :(";
  }
}

Create a callback function that will be called when the ESP32 receives the data via ESP-NOW. 

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&DHT11_data, incomingData, sizeof(DHT11_data));
  DHT11_Temp = DHT11_data.temp;
  DHT11_Hum = DHT11_data.temp;
}

 

In the setup function 

initialize the serial monitor 

Serial.begin(115200);

Now, we have used an if condition to check if the module is connected or not using begin() function.

  if (!bmp.begin()) {
      Serial.println("Could not find a valid BMP085 sensor, check wiring!");
      while (1) {}
  }

Set ESP32 is a Wi-Fi station Mode:

WiFi.mode(WIFI_STA);

Initialize ESP-NOW:

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

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

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:

memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK){
  Serial.println("Failed to add peer");
  return;
}

 

In the loop function

Get the pressure and altitude reading from BMP sensor and store it.

BMP180_data.pres = bmp.readPressure();
BMP180_data.alt = bmp.readAltitude();

Now send the temperature and humidity readings to other ESP32 boars.

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

If readings send successfully then print Sent with success or Error sending the data.

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

Print the received temperature and Humidity on the serial monitor

Serial.print("Temperature: ");
Serial.print(DHT11_data.temp);
Serial.println(" ºC");
Serial.print("Humidity: ");
Serial.print(DHT11_data.hum);
Serial.println(" %");
Serial.println();

Wait for three second

delay(3000);

Components Used

ESP32 WROOM
WiFi Development Tools - 802.11 ESP32 General Development Kit, embeds ESP32-WROOM-32E, 4MB flash.
2
DHT11
DHT11 is a single wire digital humidity and temperature sensor, which gives relative humidity in percentage and temperature in degree Celsius.
1
BMP180 Digital Pressure sensor
BMP180 is an ultra low power, high precision barometric pressure sensor with I2C serial interface.
1

Downloads

ESP_Now_Master Download
ESP_Now_Slave Download
Ad