Send Data Wirelessly Between ESP32 Using ESP-NOW

Another wireless protocol developed by Espressif, called ESP-NOW.

Introduction

ESP-NOW is yet another 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 that is often deployed in wireless mouses. So, 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.

Before proceed to the tutorial, please go through following tutorial first:

  1. Dot Matrix Clock With NTP Server Using ESP32
  2. Build Your Own Portable Contactless Temperature Reader

Video

This video shows how to send data wirelessly between 2 units of ESP32 board using ESP-NOW.

Hardware Preparation

This is the list of items used in the video.

The custom PCB is created using CNC on Snapmaker. Below is the list of components used in the PCB.

Schematic and PCB files

If you have Snapmaker, you can download 👉 THIS FILES, and use it for CNC your PCB.

Sample Program

This is Arduino sample program. Before compile, please install following libraries through Library Manager:

  • MD_MAX72XX by majicDesigns Version 3.2.1
  • MD_Parola by majicDesigns Version 3.3.0
  • TFT_eSPI by Bodmer Version 1.4.20
  • MLX90614 Library by Adafruit Version 1.0.1
/*
Tutorial: Build Your Own Portable Contactless Temperature Reader
Hardware:
– TTGO T-Display ESP32
https://my.cytron.io/p-ttgo-t-display-esp32-1.14-display-module-presolder-header?tracking=idris
– MLX90614 Non-Contact Infrared Temperature Sensor
https://my.cytron.io/p-mlx90614-non-contact-infrared-temperature-sensor?tracking=idris
External libraries:
– TFT_eSPI by Bodmer Version 1.4.20
– Adafruit MLX90614 Library by Adafruit Version 1.0.1
Created by:
24 Mar 2020 Idris Zainal Abidin, Cytron Technologies
*/
#include <esp_now.h>
#include <WiFi.h>
#include <TFT_eSPI.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_MLX90614.h>
const byte broadcastAddress[] = {0x30, 0xAE, 0xA4, 0xF6, 0xCD, 0xB8}; // Replace with your ESP board MAC Address
#define ADC_PIN 34
#define VREF 1100
#define BUTTON1 35
#define BUTTON2 0
#define FF17 &FreeSans9pt7b
#define FF21 &FreeSansBold9pt7b
#define ROW1 0,16
#define ROW2 0,38
#define ROW3 0,60
#define ROW4 0,82
#define ROW5 0,104
#define ROW6 0,126
TFT_eSPI tft = TFT_eSPI();
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
float ambientCelsius = 0.0;
float objectCelsius = 0.0;
float objectCelsiusTotal = 0.0;
long prevMillis = 0;
int interval = 1000;
// callback when data is sent
void OnDataSent(const byte *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()
{
pinMode(BUTTON1, INPUT_PULLUP);
pinMode(BUTTON2, INPUT_PULLUP);
Serial.begin(115200);
Serial.println();
Serial.println("Build your own Portable Contactless Temperature Reader for Covid-19");
Serial.println();
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;
}
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
tft.fillRect(0, 0, 240, 43, TFT_DARKGREY);
tft.setFreeFont(FF21);
tft.setTextColor(TFT_BLACK);
tft.setCursor(ROW1);
tft.print(" Portable Contactless");
tft.setCursor(0, 35); // Row 2
tft.print(" Temperature Reader");
tft.setTextColor(TFT_WHITE);
tft.setCursor(ROW3);
tft.print(" Battery:");
tft.setTextColor(TFT_CYAN);
tft.setCursor(ROW4);
tft.print(" < Press button to read >");
tft.setTextColor(TFT_WHITE);
tft.setCursor(ROW5);
tft.print(" Celsius:");
tft.fillRect(0, 112, 240, 23, TFT_MAROON);
tft.setTextColor(TFT_BLACK);
tft.setCursor(0, 128); // Row 6
tft.print(" #Covid19 by Idris");
mlx.begin();
}
void loop()
{
if (millis() – prevMillis > interval) {
int adc = analogRead(ADC_PIN);
float batteryVoltage = ((float)adc/4095.0)*2.0*3.3*(VREF/1000.0);
tft.fillRect(140, 48, 100, 20, TFT_BLACK);
if (batteryVoltage > 4.2) {
tft.setTextColor(TFT_BLUE);
tft.setCursor(140, 60);
tft.print("Charge");
}
else {
batteryVoltage = constrain(batteryVoltage, 3, 4);
float batteryPercent = ((batteryVoltage – 3) / 1) * 100;
if (batteryPercent < 50) {
tft.setTextColor(TFT_RED);
}
else if (batteryPercent < 80) {
tft.setTextColor(TFT_YELLOW);
}
else {
tft.setTextColor(TFT_GREEN);
}
tft.setCursor(150, 60);
tft.print((int)batteryPercent);
tft.print(" %");
}
prevMillis = millis();
}
if (digitalRead(BUTTON2) == LOW) {
objectCelsiusTotal = 0.0;
for (int i = 0; i < 20; i++) {
// ambientCelsius = mlx.readAmbientTempC();
objectCelsius = mlx.readObjectTempC();
objectCelsiusTotal += objectCelsius;
delay(50);
}
objectCelsius = objectCelsiusTotal / 20;
int celsius = objectCelsius;
tft.fillRect(140, 92, 100, 14, TFT_BLACK);
tft.setTextColor(TFT_GREEN);
tft.setCursor(150, 104);
tft.print(objectCelsius);
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &celsius, sizeof(celsius));
if (result == ESP_OK) {
Serial.println("Sent with success");
}
else {
Serial.println("Error sending the data");
}
}
}

view raw
ESPNow1MLX90614.ino
hosted with ❤ by GitHub

/*
Project: Wireless Display with ESPNow
Board: ESP32 Dev Module
Mac Address: 30:AE:A4:F6:CD:B8
Hardware:
– Node32 Lite
https://my.cytron.io/p-node32-lite-wifi-and-bluetooth-development-kit?tracking=idris
– 4 In 1 MAX7219 Dot Matrix Display Module
https://my.cytron.io/p-4-in-1-max7219-dot-matrix-display-module?tracking=idris
Connections:
ESP32 | Dot Matrix
RAW – VCC
GND – GND
27 – DIN
26 – CS
25 – CLK
External libraries:
– MD_MAX72XX by majicDesigns Version 3.2.1 (Manager)
– MD_Parola by majicDesigns Version 3.3.0 (Manager)
Created by:
24 Mar 2020 Idris Zainal Abidin, Cytron Technologies
*/
#include <esp_now.h>
#include <WiFi.h>
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
//#define HARDWARE_TYPE MD_MAX72XX::ICSTATION_HW
#define MAX_DEVICES 4
#define CLK_PIN 25 // 18 or 25
#define DATA_PIN 27 // 16 or 27
#define CS_PIN 26 // 17 or 26
MD_Parola DotMatrix = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define BUZZER 23
#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_G4 392
#define NOTE_A4 440
#define playReadyMelody() playTone(melody1, melody1Dur, 2)
#define playNote1() playTone(melody2, melody2Dur, 1)
#define playNote2() playTone(melody3, melody3Dur, 1)
#define playBatteryWeak() playTone(melody4, melody1Dur, 2)
int melody1[] = {NOTE_C4, NOTE_G4};
int melody1Dur[] = {12, 8};
int melody2[] = {NOTE_A4};
int melody2Dur[] = {8};
int melody3[] = {NOTE_D4};
int melody3Dur[] = {8};
int melody4[] = {NOTE_G4, NOTE_C4};
int melody4Dur[] = {12, 8};
int celsius;
char textDotMatrix[6];
// callback when data is recv from Master
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *incomingData, int data_len) {
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
memcpy(&celsius, incomingData, sizeof(celsius));
String text = String(celsius) + " °C";
Serial.print("Last Packet Recv from: "); Serial.println(macStr);
Serial.print("Last Packet Recv Data: "); Serial.println(text);
Serial.println(" °C");
sprintf(textDotMatrix, "%d\x90""C", (int)celsius);
DotMatrix.write(textDotMatrix);
playNote1();
}
void setup()
{
Serial.begin(115200);
DotMatrix.begin();
DotMatrix.setIntensity(1);
DotMatrix.setTextAlignment(PA_CENTER);
DotMatrix.print("");
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
DotMatrix.setTextAlignment(PA_CENTER);
DotMatrix.print("Ready");
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_register_recv_cb(OnDataRecv);
playReadyMelody();
}
void loop()
{
}
const int FREQUENCY = 2000;
const int CHANNEL = 0;
const int RESOLUTION = 8;
void playTone(int *melody, int *melodyDur, int notesLength)
{
for (int i = 0; i < notesLength; i++) {
ledcAttachPin(BUZZER, CHANNEL);
int noteDuration = 1000 / melodyDur[i];
ledcWriteTone(CHANNEL, melody[i]);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
ledcDetachPin(BUZZER);
ledcWrite(CHANNEL, 0);
}
}

view raw
ESPNow2DotMatrix.ino
hosted with ❤ by GitHub

Thank You

References:

Thanks for reading this tutorial. If you have any technical inquiries, please post at Cytron Technical Forum.

Please be reminded, this tutorial is prepared for you to try and learn.
You are encouraged to improve the code for better application.

2 thoughts on “Send Data Wirelessly Between ESP32 Using ESP-NOW”

  1. its hard to find esp_now library
    can you please tell me
    where to find library

  2. Can ESP32 become web server (join any WiFi) and doing ESP-NOW communication at same time?

Leave a Comment

Your email address will not be published.

Share this Tutorial

Share on facebook
Share on whatsapp
Share on email
Share on print
Share on twitter
Share on pinterest
Share on facebook
Share on whatsapp
Share on email
Share on print
Share on twitter
Share on pinterest

Latest Tutorial

Raspberry Pi Pico VS Arduino MKRZero
Raspberry Pi Pico VS Teensy LC
A New Challenger in MCU Platform – Raspberry Pi Pico
Raspberry Pi Pico VS Arduino UNO
Raspberry Pi Pico VS micro:bit V2
Scroll to Top