Cirkit Designer LogoCirkit DesignerYour all-in-one circuit design IDE Launch Cirkit Designer App

ESP32-Based Smart Irrigation System with Soil Moisture Sensing and Wi-Fi Connectivity

View and Edit Project In Cirkit DesignerImage of ESP32-Based Smart Irrigation System with Soil Moisture Sensing and Wi-Fi Connectivity

Circuit Documentation

Summary

This circuit is designed to monitor soil moisture levels and control a water pump based on the moisture data. It also measures temperature and humidity using a DHT11 sensor. The system is controlled by an ESP32 microcontroller, which is capable of Wi-Fi connectivity to send sensor data to a server. The circuit includes a relay module to control the water pump, soil moisture sensor, DHT11 sensor, and multiple LEDs to indicate the status of the sensors and the relay. Power is supplied by two 5V batteries.

Component List

Soil Moisture Sensor

Water Pump

DHT11 Humidity and Temperature Sensor

LEDs (Red)

Resistors

ESP32

5V Batteries

1 Channel 5V Relay Module

Wiring Details

Soil Moisture Sensor

Water Pump

DHT11 Humidity and Temperature Sensor

LEDs (Red)

Resistors

ESP32

5V Batteries

1 Channel 5V Relay Module

Documented Code

#include <DHT.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <EEPROM.h>

// Pin definitions for sensors and relay
#define SOIL_MOISTURE_PIN 4   // Soil Moisture Sensor on GPIO 4
#define DHT_PIN 5             // DHT11 Sensor on GPIO 5
#define RELAY_PIN 18          // Relay Module for Water Pump on GPIO 18
#define DHT_TYPE DHT11        // DHT Sensor Type

// LED pin definitions
#define LED_SOIL_MOISTURE_PIN 25 // LED for Soil Moisture Sensor on GPIO 25
#define LED_DHT_PIN 27           // LED for DHT11 Sensor on GPIO 27
#define LED_RELAY_PIN 32         // LED for Relay Module on GPIO 32
#define LED_ERROR_PIN 33         // LED for error indication on GPIO 33

// DHT sensor instance
DHT dht(DHT_PIN, DHT_TYPE);

// Variables for Wi-Fi credentials (use secure storage or environment variables in real scenarios)
String ssid;
String password;

String serverUrl = "https://yourserver.com/api/sensor-data"; // Use HTTPS for secure communication (configurable)

// Variables for adaptive threshold adjustment
int soilMoistureThreshold = 300;          // Default threshold for soil moisture
int soilMoistureReadings[10];             // Array to store soil moisture readings
int soilMoistureAverage = 0;              // Average soil moisture value
int previousReading = 0;                  // Previous reading for comparison
unsigned long lastThresholdUpdate = 0;    // Time of last threshold update
const unsigned long thresholdUpdateInterval = 60000; // Update threshold every minute (60 seconds)

// Variables for non-blocking soil moisture threshold adjustment
unsigned long thresholdReadMillis = 0; // Store the time of the last read
int thresholdReadIndex = 0; // To track the number of readings taken

// Variables for non-blocking LED feedback
unsigned long lastErrorBlinkTime = 0;
unsigned long lastDHTErrorBlinkTime = 0;
unsigned long errorBlinkInterval = 500; // Time interval for LED blinking
bool ledState = false; // LED state for blink control

// Setup function
void setup() {
  Serial.begin(115200);

  // Initialize pins
  pinMode(SOIL_MOISTURE_PIN, INPUT);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(LED_SOIL_MOISTURE_PIN, OUTPUT);
  pinMode(LED_DHT_PIN, OUTPUT);
  pinMode(LED_RELAY_PIN, OUTPUT);
  pinMode(LED_ERROR_PIN, OUTPUT); // Initialize error LED

  // Initialize DHT sensor
  dht.begin();

  // Initialize EEPROM for secure storage
  EEPROM.begin(512);
  loadWiFiCredentials(); // Load Wi-Fi credentials from EEPROM

  // Initialize Wi-Fi connection
  connectToWiFi();

  // Initialize threshold update logic
  lastThresholdUpdate = millis(); // Set the last update time to the current time
}

// Loop function
void loop() {
  unsigned long currentMillis = millis();

  // Update soil moisture threshold every minute
  if (currentMillis - lastThresholdUpdate >= thresholdUpdateInterval) {
    calculateThreshold(); // Directly call calculateThreshold() without redundancy
    lastThresholdUpdate = currentMillis; // Update threshold only every minute
  }

  // Read sensors and control system
  readSensors();

  // Blink error LED if Wi-Fi is not connected
  if (WiFi.status() != WL_CONNECTED) {
    blinkLED(LED_ERROR_PIN, lastErrorBlinkTime, 1); // Pattern 1 for Wi-Fi error
  }
}

// --- Modularized Sensor Reading Function ---
void readSensors() {
  int soilMoistureValue = readSoilMoisture();
  float humidity, temperature;
  bool dhtError = readDHT(humidity, temperature);

  // Print sensor values to Serial Monitor
  Serial.print("Soil Moisture: "); Serial.println(soilMoistureValue);
  Serial.print("Humidity: "); Serial.print(humidity);
  Serial.print(" %   Temperature: "); Serial.println(temperature);

  // Control water pump based on soil moisture value
  controlWaterPump(soilMoistureValue);

  // Control LEDs based on sensor values
  controlLEDs(soilMoistureValue);

  // Blink DHT error LED if there's a sensor reading error
  if (dhtError) {
    blinkLED(LED_DHT_PIN, lastDHTErrorBlinkTime, 2); // Pattern 2 for DHT error
  }

  // Send sensor data to server
  sendDataToServer(soilMoistureValue, temperature, humidity);
}

// --- Modularized Soil Moisture Reading ---
int readSoilMoisture() {
  return analogRead(SOIL_MOISTURE_PIN);
}

// --- Modularized DHT Reading ---
bool readDHT(float &humidity, float &temperature) {
  humidity = dht.readHumidity();
  temperature = dht.readTemperature();

  if (isnan(humidity) || isnan(temperature)) {
    Serial.println("Error: Could not read DHT sensor data.");
    return true;  // Return error flag
  }
  return false; // No error
}

// --- Modularized Control Functions ---
void controlWaterPump(int soilMoistureValue) {
  if (soilMoistureValue < soilMoistureThreshold) { 
    digitalWrite(RELAY_PIN, HIGH); // Turn on water pump
    digitalWrite(LED_RELAY_PIN, HIGH); // Turn on Relay LED
  } else {
    digitalWrite(RELAY_PIN, LOW); // Turn off water pump
    digitalWrite(LED_RELAY_PIN, LOW); // Turn off Relay LED
  }
}

void controlLEDs(int soilMoistureValue) {
  if (soilMoistureValue < soilMoistureThreshold) {
    digitalWrite