Skip to content
Buy 10+ on select items — save 10% auto-applied
Free US shipping on orders $35+
Order by 3pm ET — ships same-day from the US
Skip to main content

ESP32 ESP-NOW: Send DHT11 Data to OLED | ShillehTek

September 13, 2026 11 views

ESP32 ESP-NOW: Send DHT11 Data to OLED | ShillehTek
Project

Build an ESP32 ESP-NOW sender and receiver to broadcast DHT11 temperature and humidity to an SSD1306 OLED with no router, using parts from ShillehTek.

45 min Intermediate6 parts

Project Overview

ESP-NOW on ESP32 with a DHT11 sensor and SSD1306 OLED: In this project, two ESP32 boards exchange sensor data over ESP-NOW so you can send temperature and humidity without a router, Wi-Fi password, or IP networking. One ESP32 reads a DHT11 and broadcasts a small data packet every two seconds, and a second ESP32 receives it and displays the values on an I2C OLED.

ESP-NOW is Espressif's peer-to-peer radio protocol. The two boards talk directly to each other by MAC address, with a round trip of a few milliseconds, which works well for a remote sensor reporting to a display across the house, a wireless button, or a robot remote.

  • Time: ~45 minutes
  • Skill level: Intermediate
  • What you will build: A sender/receiver pair exchanging a typed data struct over ESP-NOW, with a MAC-address lookup step and delivery feedback.
Two ESP32 development boards communicating over ESP-NOW for wireless sensor data transfer
Board to board, radio to radio, no router in the loop.

Parts List

From ShillehTek

External

  • Two USB-C cables (you will have both boards plugged in at once during setup)

Note: ESP-NOW packets are limited to 250 bytes and are sent as raw bytes, so both boards must agree on the exact same struct layout. Define the struct once, copy it verbatim into both sketches, and you can send numbers, flags, and short strings in a single packet.

Step-by-Step Guide

Step 1 - Wire Both Boards

Goal: A sensor on one board, a display on the other.

What to do: Wire the sender ESP32 to the DHT11: VCC to 3V3, GND to GND, DATA to GPIO 4. Wire the receiver ESP32 to the OLED: VCC to 3V3, GND to GND, SDA to GPIO 21, SCL to GPIO 22.

Label the boards "S" (sender) and "R" (receiver) with tape so you do not mix them up while uploading code and reading Serial output.

Expected result: Two ESP32 boards, each with one peripheral connected.

Step 2 - Find the Receiver's MAC Address

Goal: Get the receiver MAC address that the sender needs for ESP-NOW.

What to do: Upload the receiver sketch first (from Step 3). Open Serial Monitor at 115200 baud and copy the printed MAC address (for example: 24:6F:28:AA:BB:CC).

Convert the six bytes into hex values and paste them into the sender sketch RECEIVER_MAC array as 0x24, 0x6F, and so on.

Expected result: The receiver's MAC address is written into the sender code.

Step 3 - Upload the Sketches

Goal: Send DHT11 readings over ESP-NOW and show them on the SSD1306 OLED.

What to do: Upload the receiver code first and note its MAC address. Then edit the sender code with that MAC address and upload the sender.

Code:

// ================= SENDER (ESP32 + DHT11) =================
#include <WiFi.h>
#include <esp_now.h>
#include <DHT.h>

uint8_t RECEIVER_MAC[] = {0x24, 0x6F, 0x28, 0xAA, 0xBB, 0xCC};   // from Step 2
DHT dht(4, DHT11);

typedef struct { int id; float tempC; float hum; unsigned long count; } Packet;
Packet pkt;

void setup() {
  Serial.begin(115200);
  dht.begin();
  WiFi.mode(WIFI_STA);                              // ESP-NOW needs the radio in station mode
  if (esp_now_init() != ESP_OK) { Serial.println("ESP-NOW init failed"); while (true); }
  esp_now_peer_info_t peer = {};
  memcpy(peer.peer_addr, RECEIVER_MAC, 6);
  peer.channel = 0; peer.encrypt = false;
  esp_now_add_peer(&peer);
}

void loop() {
  pkt.id = 1;
  pkt.tempC = dht.readTemperature();
  pkt.hum   = dht.readHumidity();
  pkt.count++;
  esp_err_t r = esp_now_send(RECEIVER_MAC, (uint8_t*)&pkt, sizeof(pkt));
  Serial.printf("packet %lu: %.1f C  %.0f %%  -> %s\n", pkt.count, pkt.tempC, pkt.hum,
                r == ESP_OK ? "queued" : "send error");
  delay(2000);
}

// ================= RECEIVER (ESP32 + OLED) =================
#include <WiFi.h>
#include <esp_now.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 oled(128, 64, &Wire, -1);
typedef struct { int id; float tempC; float hum; unsigned long count; } Packet;   // identical struct
Packet pkt;
volatile bool fresh = false;

// ESP32 Arduino core 3.x signature (core 2.x: const uint8_t *mac, const uint8_t *data, int len)
void onRecv(const esp_now_recv_info_t *info, const uint8_t *data, int len) {
  if (len == sizeof(pkt)) { memcpy(&pkt, data, sizeof(pkt)); fresh = true; }
}

void setup() {
  Serial.begin(115200);
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  oled.setTextColor(SSD1306_WHITE);
  WiFi.mode(WIFI_STA);
  Serial.print("Receiver MAC: "); Serial.println(WiFi.macAddress());   // paste into the sender
  esp_now_init();
  esp_now_register_recv_cb(onRecv);
}

void loop() {
  if (!fresh) return;                               // draw in loop(), not inside the callback
  fresh = false;
  oled.clearDisplay();
  oled.setTextSize(1); oled.setCursor(0, 0);  oled.printf("node %d   pkt %lu", pkt.id, pkt.count);
  oled.setTextSize(2); oled.setCursor(0, 20); oled.printf("%.1f C", pkt.tempC);
  oled.setCursor(0, 44);                      oled.printf("%.0f %%", pkt.hum);
  oled.display();
}

Expected result: The sender prints queued every two seconds, and the OLED updates with temperature, humidity, and a packet counter that increments each update.

Step 4 - Test the Range

Goal: Understand reliable indoor and outdoor range for your environment.

What to do: Power the sender from a USB power bank and walk it away from the receiver. Indoors through a wall or two you will typically get 30-50 m; outdoors with line of sight, well over 100 m.

Watch the packet counter on the OLED. Gaps in numbering indicate dropped packets, which is a practical range indicator.

Expected result: A realistic sense of ESP-NOW reach based on your space.

Step 5 - Scale It Up

Goal: Extend the pattern to multiple nodes and low-power senders.

What to do: Give each sender a different pkt.id and add them as peers on the receiver (or let them send; the receiver accepts any peer that sends to its MAC). Use the broadcast address FF:FF:FF:FF:FF:FF to reach every board in range at once.

For battery-powered nodes, combine ESP-NOW with deep sleep: wake, read, send one packet (a few milliseconds of radio time), then sleep for ten minutes.

Expected result: A sensor network with no router, no cloud dependency, and no monthly bill.

Conclusion

You built an ESP-NOW link between two ESP32 boards where one reads a DHT11 sensor and the other updates an SSD1306 I2C OLED. The core workflow is consistent for most projects: define a shared struct, learn the receiver MAC address, and send raw bytes over ESP-NOW.

Want the exact parts used in this build? Grab them from ShillehTek.com. If you want help customizing this project or building something for your product, check out our IoT consulting services.

Credits

All photos and images in this tutorial are credited to Pradeep (CETECH) on Hackster.io. The original guide by Pradeep served as the reference for this ShillehTek version. We thank him for his excellent work in the maker community.

Parts for this build

Everything used in this tutorial. Uncheck what you already have.

4 of 6 in stock
0 parts selected $0.00