ESP-NOW on ESP32: The Complete 2026 Guide to Wireless Communication Without Wi-Fi
If you've ever needed two ESP32 boards to talk to each other but didn't want the hassle of setting up a Wi-Fi router, a broker, or even an internet connection — ESP-NOW is probably the answer you've been searching for. I ran into this exact problem while building a mesh of battery-powered soil sensors scattered across a garden with no router coverage. MQTT over Wi-Fi was draining batteries in days. Switching to ESP-NOW stretched that to months.
This guide walks through exactly how ESP-NOW works, how to pair boards, send real sensor data, broadcast to multiple receivers at once, and fix the connection issues that trip up almost everyone the first time they try it.
What Is ESP-NOW, Really?
ESP-NOW is a connectionless wireless protocol developed by Espressif that lets ESP32 (and ESP8266) boards exchange small packets of data directly over Wi-Fi's 2.4 GHz radio — without ever joining a Wi-Fi network. There's no router, no IP address, no handshake delay. One board just sends, and the other receives, using MAC addresses instead of network credentials.
That single design choice is what makes it so useful for embedded projects:
- Latency — packets typically arrive in under 2 milliseconds
- Range — around 200 meters line-of-sight with the default antenna, further with external antennas
- Power draw — dramatically lower than standard Wi-Fi because there's no association or DHCP overhead
- Payload limit — up to 250 bytes per packet, enough for sensor readings, commands, or short status updates
Compare that to Wi-Fi + MQTT, where a board might spend 300–800ms just associating with an access point before it can send a single reading. If you're running on a coin cell or a small LiPo, that difference decides whether your project lasts a week or a year.
When ESP-NOW Makes Sense (and When It Doesn't)
ESP-NOW isn't a replacement for Wi-Fi in every case. It shines when:
- You need multiple ESP32 boards to communicate directly, with no internet requirement
- Battery life matters more than internet connectivity
- You want near-instant response, like a remote control or wireless doorbell
- You're building a local sensor mesh (soil moisture, temperature nodes, motion sensors)
It's the wrong tool when you need to push data to the cloud, view a dashboard from your phone over the internet, or integrate with Home Assistant remotely — for those, you'd pair ESP-NOW with a "gateway" board that also runs Wi-Fi and forwards the data to MQTT (I'll show a way to do both in the FAQ section below).
Requirements Before You Start
- Two or more ESP32 boards (any variant — including ESP32-S3 and ESP32-C6)
- Arduino IDE with the ESP32 board package installed
- USB cables for flashing
- Each board's MAC address (we'll pull this with code, no guessing needed)
Step 1: Find Each Board's MAC Address
Every ESP32 has a unique MAC address baked in, and ESP-NOW uses this instead of an IP to route packets. Flash this sketch to each board first:
#include <WiFi.h>
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
Serial.print("MAC Address: ");
Serial.println(WiFi.macAddress());
}
void loop() {}Open the Serial Monitor at 115200 baud and note the address — you'll need it for the sender sketch. Label your boards physically with tape; it saves a lot of confusion once you have three or four in play.
Step 2: Program the Sender
This example sends a simulated sensor reading (swap in real values from a DHT22 or soil sensor later) to a specific receiver's MAC address.
#include <esp_now.h>
#include <WiFi.h>
// Replace with the receiver's MAC address
uint8_t receiverAddress[] = {0x24, 0x6F, 0x28, 0xAB, 0xCD, 0xEF};
typedef struct SensorPacket {
float temperature;
float humidity;
int nodeID;
} SensorPacket;
SensorPacket packet;
esp_now_peer_info_t peerInfo;
void onDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Delivery status: ");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Failed");
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init failed");
return;
}
esp_now_register_send_cb(onDataSent);
memcpy(peerInfo.peer_addr, receiverAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
}
void loop() {
packet.temperature = 24.5;
packet.humidity = 61.2;
packet.nodeID = 1;
esp_now_send(receiverAddress, (uint8_t *) &packet, sizeof(packet));
delay(5000);
}Step 3: Program the Receiver
#include <esp_now.h>
#include <WiFi.h>
typedef struct SensorPacket {
float temperature;
float humidity;
int nodeID;
} SensorPacket;
SensorPacket incoming;
void onDataRecv(const esp_now_recv_info_t *info, const uint8_t *data, int len) {
memcpy(&incoming, data, sizeof(incoming));
Serial.printf("Node %d -> Temp: %.1f C, Humidity: %.1f%%\n",
incoming.nodeID, incoming.temperature, incoming.humidity);
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init failed");
return;
}
esp_now_register_recv_cb(onDataRecv);
}
void loop() {}Flash the receiver, open its Serial Monitor, then power the sender. You should see the readings arrive within a few milliseconds of the sender waking up.
Broadcasting to Multiple Boards at Once
If you want one board to send to every node in range (rather than a specific MAC address), use the broadcast address instead:
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};Every ESP-NOW receiver listening on the same Wi-Fi channel will pick up the packet. This is the pattern I use for a "wake all nodes" command in the garden sensor mesh — one broadcast tells every sleeping node to report in early if rain is detected.
Common Problems and How to Fix Them
Packets aren't arriving at all
Almost always a channel mismatch. ESP-NOW peers must be on the same Wi-Fi channel. If your router later assigns a different channel during a Wi-Fi reconnect, ESP-NOW communication silently breaks. Lock the channel explicitly with esp_wifi_set_channel() on both boards.
"Failed to add peer" error
This usually means esp_now_init() failed silently earlier, or you're trying to add the same peer twice. Add a check that removes an existing peer before re-adding it.
Works on the bench, fails at range ESP-NOW inherits the same 2.4 GHz limitations as Wi-Fi — walls, metal enclosures, and microwave interference all cut range. Moving the antenna away from metal project boxes typically recovers most of the lost distance.
Data looks corrupted Double-check that the struct definition is byte-for-byte identical on both sender and receiver. Even a reordered field will misalign the memory copy and produce garbage values.
ESP-NOW vs Wi-Fi vs Bluetooth: Quick Comparison
| Feature | ESP-NOW | Wi-Fi (MQTT) | Bluetooth BLE |
|---|---|---|---|
| Setup complexity | Low | Medium–High | Medium |
| Latency | ~1-2ms | 100-800ms | 20-50ms |
| Power draw | Very low | High | Low |
| Internet access | No | Yes | No |
| Max range | ~200m | Router-dependent | ~10-50m |
| Best for | Sensor meshes, remotes | Cloud dashboards | Phone pairing |
Wrapping Up
ESP-NOW is one of those protocols that feels almost too simple once it clicks — no routers, no credentials, no reconnect logic, just boards talking directly to each other in milliseconds. For sensor networks, remote triggers, and any project where battery life matters more than internet access, it's worth learning before you reach for Wi-Fi by default. If you want to go further, the natural next step is combining ESP-NOW with a single "gateway" ESP32 that stays on Wi-Fi and forwards everything to MQTT or Home Assistant — a project I'll be covering in a future guide.
Frequently Asked Questions
Can ESP-NOW and Wi-Fi run on the same board at the same time? Yes. A board can stay connected to a Wi-Fi network while also sending and receiving ESP-NOW packets, as long as both use the same channel. This is exactly how a gateway node works — it collects ESP-NOW data from sensor nodes and republishes it to the cloud over Wi-Fi.
How many ESP-NOW peers can one ESP32 handle? Up to 20 peers by default (6 of which can be encrypted), which is more than enough for most home sensor networks.
Does ESP-NOW work between an ESP32 and an ESP8266? Yes, the two chips are cross-compatible with ESP-NOW, though payload structures and library syntax differ slightly, so test both directions carefully.
Is ESP-NOW secure? It supports optional CCMP encryption for up to 6 peers. For anything beyond a hobby sensor network, enable encryption rather than relying on the default open transmission.
If you're exploring this niche because you're also thinking about building a content site around a passionate hobby and turning it into real income, it's worth looking at how other niche creators approach monetization outside of ads and affiliate links. petlifehacks.page breaks down practical ways people are earning from niche websites — worth a look if that's part of your goal too.
