Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
sanju hannah99
Published

Building a ESP-NOW Network using DHT11

Our project showcases an efficient IoT wireless sensor network with ESP32 and advanced Node-RED visualization.

IntermediateProtip2 hours519
Building a ESP-NOW Network using DHT11

Things used in this project

Hardware components

DHT11 Temperature & Humidity Sensor (4 pins)
DHT11 Temperature & Humidity Sensor (4 pins)
×2
Jumper wires (generic)
Jumper wires (generic)
×2
USB-A to Mini-USB Cable
USB-A to Mini-USB Cable
×3
Solderless Breadboard Half Size
Solderless Breadboard Half Size
×1
Espressif ESP32 Development Board - Developer Edition
Espressif ESP32 Development Board - Developer Edition
×3

Software apps and online services

Arduino IDE
Arduino IDE
MQTT
MQTT
Node-RED
Node-RED

Story

Read more

Schematics

Flow Diagram of Setup

Working Video

Code

Master Code

C/C++
#include <esp_now.h>
#include <WiFi.h>


// Structure to receive data from slave nodes
typedef struct {
  float temperature;
  float humidity;
  bool alert;
} DataPacket;

DataPacket incomingPacket;

// Array to store MAC addresses of slaves
const uint8_t slave1MAC[] = {0x08, 0xB6, 0x1F, 0x28, 0x74, 0xB4};  // Replace with actual MAC of Slave 1
const uint8_t slave2MAC[] = {0xE0, 0x5A, 0x1B, 0x5F, 0x62, 0xD0};  // Replace with actual MAC of Slave 2
// Add more slave MAC addresses as needed

void setup() {
  Serial.begin(115200);



  // Set up ESP-NOW
  WiFi.mode(WIFI_STA);  // ESP-Now requires station mode
  if (esp_now_init() != ESP_OK) {
    Serial.println("ESP-Now initialization failed!");
    return;
  }

  // Register receive callback
  esp_now_register_recv_cb(onDataReceived);

  Serial.println("Master node ready.");
}

void loop() {
  //
}

// Callback for received ESP-NOW data
void onDataReceived(const esp_now_recv_info* recvInfo, const uint8_t *incomingData, int len) {
  memcpy(&incomingPacket, incomingData, sizeof(incomingPacket));

  String sender = identifySender(recvInfo->src_addr);
  Serial.printf("Received Data from %s: Temp = %.1f%°C, Humidity = %.1f%%, Alert = %s\n",
                sender.c_str(),
                incomingPacket.temperature,
                incomingPacket.humidity,
                incomingPacket.alert ? "YES" : "NO");
}

// Identify which slave sent the data based on MAC address
String identifySender(const uint8_t *mac) {
  if (memcmp(mac, slave1MAC, 6) == 0) {
    return "Slave1";
  } else if (memcmp(mac, slave2MAC, 6) == 0) {
    return "Slave2";
  } else {
    return "Unknown Slave";
  }
}

Sensing Node 1 Code

C/C++
#include <esp_now.h>
#include <WiFi.h>
#include <DHT.h>
#include <esp_sleep.h>

#define DHTPIN 4  // Data pin connected to DHT11
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

// Structure for sending ESP-Now data
typedef struct {
  float temperature;
  float humidity;
  bool alert;  // To indicate if the message is an alert
} DataPacket;

DataPacket dataPacket;

// Broadcast address for ESP-Now
uint8_t broadcastAddress[] = {0x08, 0xB6, 0x1F, 0x28, 0x77, 0xF0};

// User-configurable settings
const unsigned long communicationInterval = 3500;  // Communicate every 10 seconds
float tempThresholdHigh = 30.0;  // High-temperature threshold
float tempThresholdLow = 20.0;   // Low-temperature threshold

void setup() {
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);  // Station mode required for ESP-Now
  WiFi.disconnect();    // Disconnect WiFi for ESP-Now use

  // Initialize ESP-Now
  if (esp_now_init() != ESP_OK) {
    Serial.println("ESP-Now initialization failed");
    return;
  }

  // Add broadcast peer
  esp_now_peer_info_t peerInfo = {};
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  // Channel 0 for broadcast
  peerInfo.encrypt = false;

  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add broadcast peer");
    return;
  }

  Serial.println("ESP-Now Slave Ready");

  // Initialize DHT sensor
  dht.begin();
}

void loop() {
  // Wait a little before reading sensor data
  delay(500);  // Wait for the sensor to stabilize

  // Retry mechanism for reading sensor data
  const int maxRetries = 5;  // Max retries before failing
  int retries = 0;
  
  while (retries < maxRetries) {
    dataPacket.temperature = dht.readTemperature();
    dataPacket.humidity = dht.readHumidity();
    
    // Check if the readings are valid
    if (!isnan(dataPacket.temperature) && !isnan(dataPacket.humidity)) {
      // Successfully read data
      break;
    }
    
    retries++;
    Serial.println("Retrying to read from DHT11...");
    delay(1000);  // Wait a little before retrying
  }

  if (retries == maxRetries) {
    Serial.println("Failed to read from DHT sensor!");
    enterDeepSleep();
    return;
  }

  // Check for alerts (temperature threshold)
    // Default: no alert
  if (dataPacket.temperature > tempThresholdHigh || dataPacket.temperature < tempThresholdLow) {
    dataPacket.alert = true;
  } else {
    dataPacket.alert = false;
  }

  // Send data via ESP-Now
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *)&dataPacket, sizeof(dataPacket));

  if (result == ESP_OK) {
    if (dataPacket.alert) {
      Serial.printf("ALERT sent: Temp = %.1f°C\n", dataPacket.temperature);
    } else {
      Serial.printf("Data sent from sensing node 1: Temp = %.1f°C, Humidity = %.1f%%\n", 
                    dataPacket.temperature, dataPacket.humidity);
    }
  } else {
    Serial.println("Failed to send data");
  }

  // Enter deep sleep
  enterDeepSleep();
}

void enterDeepSleep() {
  // Wake up after communication interval
  esp_sleep_enable_timer_wakeup(communicationInterval * 2000);  // Convert ms to µs
  Serial.println("Entering deep sleep...");
  esp_deep_sleep_start();
}

Sensing Node 2 Code

C/C++
#include <esp_now.h>
#include <WiFi.h>
#include <DHT.h>
#include <esp_sleep.h>

#define DHTPIN 17  // Data pin connected to DHT11
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

// Structure for sending ESP-Now data
typedef struct {
  float temperature;
  float humidity;
  bool alert;  // To indicate if the message is an alert
} DataPacket;

DataPacket dataPacket;

// Broadcast address for ESP-Now
uint8_t broadcastAddress[] = {0x08, 0xB6, 0x1F, 0x28, 0x77, 0xF0};

// User-configurable settings
const unsigned long communicationInterval = 3500;  // Communicate every 10 seconds
float tempThresholdHigh = 30.0;  // High-temperature threshold
float tempThresholdLow = 20.0;   // Low-temperature threshold

void setup() {
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);  // Station mode required for ESP-Now
  WiFi.disconnect();    // Disconnect WiFi for ESP-Now use

  // Initialize ESP-Now
  if (esp_now_init() != ESP_OK) {
    Serial.println("ESP-Now initialization failed");
    return;
  }

  // Add broadcast peer
  esp_now_peer_info_t peerInfo = {};
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  // Channel 0 for broadcast
  peerInfo.encrypt = false;

  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add broadcast peer");
    return;
  }

  Serial.println("ESP-Now Slave Ready");

  // Initialize DHT sensor
  dht.begin();
}

void loop() {
  // Wait a little before reading sensor data
  delay(500);  // Wait for the sensor to stabilize

  // Retry mechanism for reading sensor data
  const int maxRetries = 5;  // Max retries before failing
  int retries = 0;
  
  while (retries < maxRetries) {
    dataPacket.temperature = dht.readTemperature();
    dataPacket.humidity = dht.readHumidity();
    
    // Check if the readings are valid
    if (!isnan(dataPacket.temperature) && !isnan(dataPacket.humidity)) {
      // Successfully read data
      break;
    }
    
    retries++;
    Serial.println("Retrying to read from DHT11...");
    delay(1000);  // Wait a little before retrying
  }

  if (retries == maxRetries) {
    Serial.println("Failed to read from DHT sensor!");
    enterDeepSleep();
    return;
  }

  // Check for alerts (temperature threshold)
    // Default: no alert
  if (dataPacket.temperature > tempThresholdHigh || dataPacket.temperature < tempThresholdLow) {
    dataPacket.alert = true;
  } else {
    dataPacket.alert = false;
  }

  // Send data via ESP-Now
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *)&dataPacket, sizeof(dataPacket));

  if (result == ESP_OK) {
    if (dataPacket.alert) {
      Serial.printf("ALERT sent: Temp = %.1f°C\n", dataPacket.temperature);
    } else {
      Serial.printf("Data sent from sensing node 2: Temp = %.1f°C, Humidity = %.1f%%\n", 
                    dataPacket.temperature, dataPacket.humidity);
    }
  } else {
    Serial.println("Failed to send data");
  }

  // Enter deep sleep
  enterDeepSleep();
}

void enterDeepSleep() {
  // Wake up after communication interval
  esp_sleep_enable_timer_wakeup(communicationInterval * 2000);  // Convert ms to µs
  Serial.println("Entering deep sleep...");
  esp_deep_sleep_start();
}

Python Client code

Python
import serial
import paho.mqtt.client as mqtt
import re

# Configure serial port
SERIAL_PORT = "COM9"  # Replace with the correct COM port for your ESP32
BAUD_RATE = 115200

# MQTT Configuration
MQTT_BROKER = "broker.mqtt.cool"  # Replace with your broker
MQTT_PORT = 1883
MQTT_TOPIC_TEMP_SLAVE1 = "esp/now/slave1/temp"
MQTT_TOPIC_HUM_SLAVE1 = "esp/now/slave1/humidity"
MQTT_TOPIC_TEMP_SLAVE2 = "esp/now/slave2/temp"
MQTT_TOPIC_HUM_SLAVE2 = "esp/now/slave2/humidity"

# Initialize serial and MQTT client
ser = serial.Serial(SERIAL_PORT, BAUD_RATE)
mqtt_client = mqtt.Client()

def on_connect(client, userdata, flags, rc):
    if rc == 0:
        print("Connected to MQTT broker")
    else:
        print(f"Failed to connect, return code {rc}")

mqtt_client.on_connect = on_connect
mqtt_client.connect(MQTT_BROKER, MQTT_PORT, 60)

mqtt_client.loop_start()

# Regular expression to match data format
data_regex = r"Received Data from Slave(\d+): Temp = ([\d.]+)°C, Humidity = ([\d.]+)%, Alert = (.*)"

try:
    while True:
        if ser.in_waiting > 0:
            line = ser.readline().decode('utf-8').strip()
            print(f"Received: {line}")

            # Match the data using regex
            match = re.match(data_regex, line)

            if match:
                slave_id = match.group(1)  # Slave number (1 or 2)
                temperature = float(match.group(2))  # Temperature value
                humidity = float(match.group(3))  # Humidity value

                # Depending on the slave id, publish temperature and humidity to corresponding topics
                if slave_id == "1":
                    mqtt_client.publish(MQTT_TOPIC_TEMP_SLAVE1, temperature)
                    print(f"Published to {MQTT_TOPIC_TEMP_SLAVE1}: {temperature}")
                    
                    mqtt_client.publish(MQTT_TOPIC_HUM_SLAVE1, humidity)
                    print(f"Published to {MQTT_TOPIC_HUM_SLAVE1}: {humidity}")
                elif slave_id == "2":
                    mqtt_client.publish(MQTT_TOPIC_TEMP_SLAVE2, temperature)
                    print(f"Published to {MQTT_TOPIC_TEMP_SLAVE2}: {temperature}")
                    
                    mqtt_client.publish(MQTT_TOPIC_HUM_SLAVE2, humidity)
                    print(f"Published to {MQTT_TOPIC_HUM_SLAVE2}: {humidity}")
                else:
                    print(f"Invalid slave ID: {slave_id}")
            else:
                print(f"Invalid data format: {line}")

except KeyboardInterrupt:
    print("Exiting...")
finally:
    ser.close()
    mqtt_client.loop_stop()
    mqtt_client.disconnect()

Github

Credits

sanju hannah99
1 project • 0 followers
Contact
Thanks to Manoj Raveendran.

Comments

Please log in or sign up to comment.