In this guide
Two ESP32 boards can exchange sensor data directly over the air — no Wi-Fi router, no internet connection, no MQTT broker, no cloud account. The protocol that makes this possible is ESP-NOW, Espressif's connectionless 2.4 GHz peer-to-peer protocol. It is the simplest way to build multi-node projects: a sensor node in the field talking to a gateway node next to your laptop, a handheld remote driving a robot, several buttons reporting to one display. This guide explains how ESP-NOW works, walks through a complete sender and receiver build, and covers the gotchas that make a beginner's first ESP-NOW project fail silently.
The problem ESP-NOW solves
Every wireless option you already know comes with baggage:
- Wi-Fi needs infrastructure: a router, credentials, IP configuration. Fine at home, awkward in a demo hall, a field, or an exam lab where you don't control the network.
- Bluetooth/BLE is built for phone-to-device links — pairing friction, short range, and modest throughput for frequent sensor data.
- LoRa reaches kilometres but at very low data rates, needs extra modules, and is overkill for two boards in the same room.
ESP-NOW sits in the gap: fast, no handshake, no router, no pairing dance. Two boards that know each other's MAC address just talk.
How ESP-NOW works
ESP-NOW sends connectionless datagrams on the 2.4 GHz band. There is no association, no IP address, no DHCP — a board transmits, and any peer in range that recognises the sender picks the packet up.
- Peers are identified by MAC address. You add each peer's 6-byte MAC to a peer list on the sender. No discovery, no pairing codes.
- Payloads are small by design: up to 250 bytes. Send readings, commands, and status — not files or images.
- Callbacks report what happened. A send callback tells you whether the packet was acknowledged; a receive callback fires with the raw bytes on arrival.
- Both devices must use the same Wi-Fi channel. This is the number-one silent failure (more below).
- Encryption is optional, using Espressif's PMK/LMK key scheme for projects where the airwaves shouldn't be readable.
- It works ESP32-to-ESP32 and ESP32-to-ESP8266, which is handy when you have a mixed parts bin.
Think of it as passing notes in class: short messages, direct delivery, no post office involved.
Build: a sender and a receiver
You need two ESP32 boards and the Arduino IDE with the ESP32 board package. We'll send a small struct — node ID, temperature, humidity — every two seconds. Replace the dummy values with a real sensor reading once it works.
Step 1 — Get the receiver's MAC address. Upload this once to the board that will receive, open the Serial Monitor, and write the address down:
#include <WiFi.h>
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
Serial.println(WiFi.macAddress());
}
void loop() {}
Step 2 — The sender. Paste the receiver's MAC into receiverMac:
#include <esp_now.h>
#include <WiFi.h>
uint8_t receiverMac[] = {0x24, 0x6F, 0x28, 0xAA, 0xBB, 0xCC};
typedef struct {
float temperature;
float humidity;
int nodeId;
} SensorData;
SensorData data;
void onSent(const uint8_t *mac, esp_now_send_status_t status) {
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Sent OK" : "Send failed");
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
esp_now_init();
esp_now_register_send_cb(onSent);
esp_now_peer_info_t peer = {};
memcpy(peer.peer_addr, receiverMac, 6);
esp_now_add_peer(&peer);
}
void loop() {
data.temperature = 27.5; // replace with your sensor reading
data.humidity = 61.0;
data.nodeId = 1;
esp_now_send(receiverMac, (uint8_t *)&data, sizeof(data));
delay(2000);
}
Step 3 — The receiver:
#include <esp_now.h>
#include <WiFi.h>
typedef struct {
float temperature;
float humidity;
int nodeId;
} SensorData;
void onReceive(const uint8_t *mac, const uint8_t *incoming, int len) {
SensorData data;
memcpy(&data, incoming, sizeof(data));
Serial.print("Node "); Serial.print(data.nodeId);
Serial.print(": "); Serial.print(data.temperature);
Serial.print(" C, "); Serial.print(data.humidity);
Serial.println(" %");
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
esp_now_init();
esp_now_register_recv_cb(onReceive);
}
void loop() {}
Upload the sender to one board and the receiver to the other, open both Serial Monitors, and you should see readings arriving every two seconds.
Step 4 — Make it two-way. Register both callbacks on both boards and add each board as the other's peer. Now either side can initiate — a remote control and its robot, for example.
Step 5 — One-to-many. Add several peers with esp_now_add_peer and loop over them with esp_now_send. One gateway board can collect from a handful of sensor nodes this way (up to 20 peers).
Gotchas that break first projects
- Channel mismatch — the silent killer. Both boards must be on the same Wi-Fi channel or packets vanish without a trace. If either board is also connected to a router as a station, ESP-NOW follows that connection's channel. Simplest rule for beginners: keep both boards off router Wi-Fi while learning ESP-NOW.
- A typo in the MAC address. Double-check every byte. A wrong MAC means packets go nowhere, and the only symptom is the "Send failed" callback.
- Struct mismatch. Both sketches must define the struct identically — same fields, same order, same types. If one side adds a field, the bytes stop lining up and values come out as garbage.
- Payload over 250 bytes. Split larger messages across packets or reconsider whether ESP-NOW is the right transport.
- Forgetting
WiFi.mode(WIFI_STA)beforeesp_now_init(). The radio must be in station mode first. - Weak power on transmit. Radio transmission draws current spikes; a feeble USB port or thin cable causes brownouts and resets exactly when sending. Power the boards properly during development.
Frequently asked questions
ESP-NOW or MQTT?
Different jobs. MQTT needs a broker and an IP network; ESP-NOW needs nothing. The classic student architecture uses both: ESP-NOW for the local hop (sensor nodes to gateway), MQTT for the internet hop (gateway to dashboard).
ESP-NOW or BLE?
BLE for phone-to-device (an app talking to your gadget); ESP-NOW for device-to-device (your gadgets talking to each other).
Can an ESP32 talk to an ESP8266 over ESP-NOW?
Yes. Both chips speak the protocol, so a mixed-parts-bin project works.
What range can I expect?
Roughly what ordinary 2.4 GHz Wi-Fi gives you in the same environment — walls, metal, and crowded spectrum all matter. Always test in the actual room where you'll demo.
Can ESP-NOW reach the internet?
No — there is no IP layer. Use one ESP32 as a gateway: it receives ESP-NOW packets and forwards them over Wi-Fi/MQTT.
Is it secure?
Optional encryption exists via PMK/LMK keys. Treat it as a convenient local link, not a hardened channel — don't send anything you wouldn't want overheard.
Limitations
ESP-NOW is a specialist tool with honest boundaries. The 250-byte payload rules out images, audio, and files. There is no IP, no routing, and no internet — it is a local link only. Delivery is reported by callback, not guaranteed like TCP, so design your messages to be idempotent or retried rather than assuming each one lands. The 2.4 GHz band is shared with Wi-Fi and Bluetooth, so a crowded lab or auditorium can interfere. And 20 peers is plenty for student meshes but not a large network. Within those limits, it is the fastest way to get two boards talking.