ESP32 Bench
Boards: ESP32, S3, C3
Flash and monitor: Web Serial
← All projects

ESP-NOW pair

Two boards talk directly over the Wi-Fi radio, with no router. Each sends a counter and prints what the other sends.

Intermediate20 min115200 baud
Board
Fig. 1. Pins this project uses on the ESP32-DevKitC V4, 38 pin. USB connector at the bottom.

Wiring

Nothing to wire. This one runs on the bare board.

Tested on this board

Not run on this board yet. Treat the wiring and code as a first draft.

Firmware, Arduino sketch for ESP32 Dev Module

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

const char NAME = 'A';  // set to 'B' before flashing the second board
const int CHANNEL = 1;  // both boards must use the same channel
const uint8_t BROADCAST[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

struct Message {
  char from;
  uint32_t count;
};

uint32_t count = 0;

void onReceive(const esp_now_recv_info_t* info, const uint8_t* data, int len) {
  if (len != sizeof(Message)) return;
  Message m;
  memcpy(&m, data, sizeof m);
  if (m.from == NAME) return;
  const uint8_t* a = info->src_addr;
  Serial.printf("rx %c #%lu from %02X:%02X:%02X:%02X:%02X:%02X rssi %d\n",
    m.from, (unsigned long)m.count, a[0], a[1], a[2], a[3], a[4], a[5], info->rx_ctrl->rssi);
}

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  esp_wifi_set_channel(CHANNEL, WIFI_SECOND_CHAN_NONE);

  if (esp_now_init() != ESP_OK) {
    Serial.println("esp-now init failed");
    for (;;) delay(1000);
  }
  esp_now_register_recv_cb(onReceive);

  // Broadcast, so neither board needs the other's MAC address.
  esp_now_peer_info_t peer = {};
  memcpy(peer.peer_addr, BROADCAST, 6);
  peer.channel = CHANNEL;
  peer.ifidx = WIFI_IF_STA;
  peer.encrypt = false;
  esp_now_add_peer(&peer);

  Serial.printf("esp-now ready on channel %d, this board is %c, MAC %s\n", CHANNEL, NAME, WiFi.macAddress().c_str());
}

void loop() {
  Message m = {NAME, ++count};
  esp_err_t r = esp_now_send(BROADCAST, (const uint8_t*)&m, sizeof m);
  Serial.printf("tx %c #%lu %s\n", NAME, (unsigned long)m.count, r == ESP_OK ? "sent" : esp_err_to_name(r));
  delay(2000);
}

Parts

QuantityPartWhere to buy
2×ESP32 dev boards, any mix of ESP32, S3 and C3Buy at Amazon
2×USB cables, or one cable and a USB power supply

Amazon buy links may include an Associates tag, and this site may earn a commission from qualifying Amazon purchases at no extra cost to you. Adafruit links are direct.

Libraries

WiFi (built in), esp_now (built in)

Load it

  1. In the Arduino IDE, install the esp32 board package and pick the board named above the sketch.
  2. Paste the sketch, choose the board's port and upload. Hold BOOT if the upload stalls at Connecting.
  3. Close the IDE's serial monitor, then open the bench here to watch the output.

Field notes

  • Flash the same sketch to both boards, but change NAME to 'B' on the second one.
  • Watch both sides at once: on the Bench page, choose Add a second board and connect one board to each monitor.
  • Broadcasts are not acknowledged, so 'sent' only means the radio queued the message. Seeing it arrive on the other board is the real test.
  • Both boards must be on the same channel. A board that also joins a Wi-Fi network moves to that network's channel, so set CHANNEL to match it.
  • Messages are not encrypted. Do not send anything private this way.

Not tested yet

  • Not tested on hardware yet. Compiles for every board listed with Arduino-ESP32 core 3.3.12.