The Internet of Things (IoT)
- The promise of IoT lies in everyday objects becoming interconnected, revolutionizing how we interactwith our environment.
- In the realm of IoT, wireless communication plays a crucial role by enabling devices to share datawithout cumbersome cables.
- While Wi-Fi is a popular choice, it can be complex and power-hungry for simpler tasks.
Enter ESP-NOW
- Espressif Systems has addressed this need with ESP-NOW, a fast and efficient protocol specifically designed for direct communication between ESP32 devices.
- It’s perfect for low-power IoT applications where simplicity and speed are paramount. Let’s delve into the intricacies of ESP-NOW communication, focusing on the one-way communication scenario.
Understanding ESP-NOW
What is ESP-NOW?
Functionality:
- Enables multiple ESP32 devices to communicate with each other without using Wi-Fi.
- Similar to low-power 2.4GHz wireless connectivity.
- Requires pairing between devices before communication.
- Connection is safe and peer-to-peer once pairing is done.
- Persistent connection even if a device loses power or resets.
Features:
- Supports encrypted and unencrypted unicast communication.
- Allows mixed encrypted and unencrypted peer devices.
- Up to 250-byte payload can be carried in each message.
- Provides a sending callback function to inform the application layer of transmission success or failure.
Limitations:
- Limited encrypted peers: 10 in Station mode, 6 in SoftAP or SoftAP + Station mode.
- Multiple unencrypted peers supported, but their total number should be less than 20, including encrypted peers.
- Payload is limited to 250 bytes.
Use Cases:
- Fast communication protocol for exchanging small messages (up to 250 bytes) between ESP32 boards.
- Versatile with support for one-way or two-way communication in different setups.
Types of ESP-NOW Communication
ESP-NOW supports various communication types:
One-Way Communication (Our Focus):
Two-Way Communication:
Benefits of ESP-NOW for this Project
Speed and Efficiency:
- Ideal for sending small data packets like button presses.
Low Power Consumption:
- Saves battery life on both sender and receiver.
No Complex Wi-Fi Setup:
- Quick and easy to implement, perfect for beginners.
Connection Diagram
Sender Connection Diagram
Receiver Connection Diagram
Retrieving Your Board’s MAC Address
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_MODE_STA);
Serial.println(WiFi.macAddress());
}
void loop()
{}
- The MAC address will be printed in the Serial Monitor as shown in the image above.
- Make sure to save your board’s MAC address.
- This process ensures that each ESP32 device is uniquely identified, facilitating efficient and targeted communication within an ESP-NOW network.
ESP32 Sender Code
#include <WiFi.h>
#define buttonPin 6
//replace your board mac address
uint8_t broadcastAddress1[] = {0xC8, 0xF0, 0x9E, 0XA6, 0x0A, 0x18};
typedef struct test_struct {
int buttonPress;
} test_struct;
test_struct test;
esp_now_peer_info_t peerInfo;
void DataSent (const uint8_t *mac_addr, esp_now_send_status_t status)
{
Serial.print(” send status:\t”);
Serial.println(status == ESP_NOW_SEND_SUCCESS ? “Delivery Success” : “Delivery
Fail”);
}
void setup()
{
Serial.begin(115200);
pinMode(buttonPin, INPUT_PULLUP);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK)
{
Serial.println(“Error initializing ESP-NOW”);
return;
}
esp_now_register_send_cb(DataSent);
peerInfo.channel = 0;
peerInfo.encrypt = false;
memcpy(peerInfo.peer_addr, broadcastAddress1, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK)
{
Serial.println(“Failed to add peer”);
return;
}
}
void loop()
{
int buttonState = digitalRead(buttonPin);
if (buttonState == LOW)
{
buttonState = digitalRead(buttonPin);
if (buttonState == LOW)
{
test.buttonPress = 1;
}
}
else
{
test.buttonPress = 0;
}
esp_err_t result = esp_now_send(0, (uint8_t *) &test, sizeof(test_struct));
delay(200);
}
Code Explanation
Sender Code
1. Button and Broadcast Address
uint8_t broadcastAddress1[] = {0xC8, 0xF0, 0x9E, 0XA6, 0x0A, 0x18};
2. Data Structure
int buttonPress;
}
test_struct;
test_struct test;
3. ESP-NOW Initialization
if (esp_now_init () != ESP_OK)
{
Serial.println(“Error initializing ESP-NOW”);
return;
}
4. Adding Peer
peerInfo.channel = 0;
peerInfo.encrypt = false;
memcpy(peerInfo.peer_addr, broadcastAddress1, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK)
{
Serial.println(“Failed to add peer”);
return;
}
5. Button State and Data Preparation
if (buttonState == LOW)
{
buttonState = digitalRead(buttonPin);
if (buttonState == LOW)
{
test.buttonPress = 1;
}
}
else
{
test.buttonPress = 0;
}
6. Sending Data
delay(200);
Code Explanation Summary:
- esp_now_init(): Initializes the ESP-NOW library.
- esp_now_register_send_cb(): Registers a callback function to handle the event when data is successfully sent.
- esp_now_add_peer(): Adds the receiver as a peer, specifying the communication channel and encryption status.
- DataSent(): Callback function to print the delivery status of the sent data.
- loop(): Monitors the button state and sends the button press information to the receiver using esp_now_send().
ESP32 Receiver Code
ESP32 Receiver Code
#include <WiFi.h>
#define ledPin 4
typedef struct test_struct {
int buttonPress;
} test_struct;
test_struct myData;
bool ledState = false;
bool lastButtonState = false;
void DataRecv (const uint8_t *mac, const uint8_t *incomingData, int len)
{
memcpy(&myData, incomingData, sizeof(myData));
Serial.print(“buttonPress: “);
uint8_t buttonState = myData.buttonPress;
Serial.println(buttonState);
if (buttonState == 1 && !lastButtonState)
{
ledState = !ledState;
digitalWrite(ledPin, ledState ? HIGH : LOW);
lastButtonState = true;
}
else if (buttonState == 0)
{
lastButtonState = false;
}
}
void setup()
{
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK)
{
Serial.println(“Error initializing ESP-NOW”);
return;
}
esp_now_register_recv_cb(DataRecv);
}
void loop()
{}
Code Explanation
Receiver Code
1. LED and Data Structure
typedef struct test_struct {
int buttonPress;
} test_struct;
test_struct myData;
bool ledState = false;
bool lastButtonState = false;
2. ESP-NOW Initialization
if (esp_now_init() != ESP_OK)
{
Serial.println(“Error initializing ESP-NOW”);
return;
}
3. ledState and lastButtonState
bool lastButtonState = false;
4. OnDataRecv Callback
{
memcpy(&myData, incomingData, sizeof(myData));
Serial.print(“buttonPress: “);
uint8_t buttonState = myData.buttonPress;
Serial.println(buttonState);
if (buttonState == 1 && !lastButtonState)
{
ledState = !ledState;
digitalWrite(ledPin, ledState ? HIGH : LOW);
lastButtonState = true;
}
else if (buttonState == 0)
{
lastButtonState = false;
}
}
Code Explanation Summary:
- esp_now_init(): Initializes the ESP-NOW library.
- esp_now_register_recv_cb(): Registers a callback function to handle the event when data is received.
- DataRecv(): Callback function to process the received data and control the LED based on the button press information.
- loop(): Empty loop, as all functionality is handled in the callback function
Testing ESP-NOW Communication
Upload the code to sender ESP32 board and the receiver ESP32 board.
Open the Serial Monitor for each board.
Serial Monitor 1(Sender):
Serial Monitor 2(Receiver):
In summary, the exploration of ESP-NOW communication with ESP32 highlights its efficiency in one-way IoT communication. Developed by Espressif Systems, ESP-NOW offers a streamlined alternative to Wi-Fi for direct ESP32 device communication. Features like encrypted support, 250-byte payload capacity, and callback functions enhance its versatility. Despite some limitations, ESP-NOW excels in fast, low-power communication.
The provided sender and receiver code examples showcase ESP-NOW’s simplicity for small data transmission. Understanding MAC addresses ensures accurate communication between devices. ESP-NOW’s speed, low power consumption, and easy setup make it an attractive choice for IoT projects, promising seamless device interaction within the Internet of Things ecosystem.