Uncategorized

ESP32 Smart Garden: Auto-Watering System with Soil Moisture Sensor

ESP32 DevKitC V4 Development Board

The Problem

Your plants keep dying because you forget to water them. Or you water too much and the roots rot. You need a system that knows when your plants are actually thirsty — and waters them automatically.

With an ESP32, a soil moisture sensor, and a relay, you can build a fully automatic smart garden that:

  • Monitors soil moisture 24/7
  • Waters your plants when they need it (not on a fixed schedule)
  • Sends you alerts when the water tank is empty

What You’ll Build

An ESP32-powered auto-watering system that reads soil moisture every hour and triggers a water pump when the soil gets dry. Optional: connect to WiFi for remote monitoring via MQTT.

Difficulty: Beginner  |  Time: 45 minutes  |  Cost: ~$35 in parts

Hardware Required (Bill of Materials)

Part Model Qty Price Buy
Microcontroller ESP32 DevKitC V4 1 $13.49 View Product
Soil Moisture Sensor Capacitive Soil Moisture v1.2 1 $4.49 View Product
Relay Module 2-Channel 5V Relay 1 $5.24 View Product
Display 0.96″ OLED SSD1306 1 $5.99 View Product
Breadboard 830-point 1 $4.49 View Product
Jumper Wires M-M 40pcs 1 $2.99 View Product

You’ll also need a mini water pump (5V, ~$3 from any hardware store) and silicone tubing. Connect the pump’s positive wire through the relay.

Step 1: Wiring

ESP32 ↔ Soil Moisture Sensor

Sensor Pin ESP32 Pin Note
VCC 3V3 Power
GND GND Ground
AOUT GPIO 34 Analog output (ADC1_CH6)

ESP32 ↔ Relay Module

Relay Pin ESP32 Pin Note
VCC 5V/VIN Power
GND GND Ground
IN1 GPIO 26 Relay control signal

ESP32 ↔ OLED Display

OLED Pin ESP32 Pin Note
VCC 3V3 Power
GND GND Ground
SDA GPIO 21 I2C Data
SCL GPIO 22 I2C Clock

Important: Connect the water pump through the relay’s NO (Normally Open) terminal and COM terminal. The relay acts as a switch — when GPIO 26 goes LOW, the pump turns ON.

Step 2: Calibration

Before automating, you need to find your soil’s “dry” and “wet” values:

  1. Insert the sensor into dry soil → note the analog reading (e.g., 3200)
  2. Insert into wet soil → note the reading (e.g., 1400)
  3. Calculate the threshold — below this value = wet enough, above = needs water
DRY_VALUE = 3200   (your reading in dry soil)
WET_VALUE = 1400   (your reading in wet soil)
THRESHOLD = 2500   (trigger watering above this)

Step 3: Upload the Code

#include <Wire.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// --- Pins ---
#define SOIL_PIN 34
#define PUMP_PIN 26

// --- Calibration (change these!) ---
const int DRY_VALUE = 3200;
const int WET_VALUE = 1400;
const int THRESHOLD = 2500;

const unsigned long CHECK_INTERVAL = 3600000;
const unsigned long PUMP_DURATION = 5000;
unsigned long lastCheck = 0;

void displayReading(int raw, int percent) {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Smart Garden");
  display.drawLine(0, 10, 128, 10, SSD1306_WHITE);
  display.setCursor(0, 20);
  display.printf("Moisture: %d%%", percent);
  display.setCursor(0, 35);
  if (percent < 40) {
    display.println("Status: DRY");
    display.println("Pump: ACTIVE");
  } else {
    display.println("Status: OK");
    display.println("Pump: OFF");
  }
  display.setCursor(0, 55);
  display.printf("Raw: %d", raw);
  display.display();
}

void setup() {
  Serial.begin(115200);
  pinMode(PUMP_PIN, OUTPUT);
  digitalWrite(PUMP_PIN, HIGH);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("OLED not found!");
  }
  display.clearDisplay();
  display.display();
}

void loop() {
  if (millis() - lastCheck >= CHECK_INTERVAL || lastCheck == 0) {
    lastCheck = millis();
    int raw = analogRead(SOIL_PIN);
    int percent = map(raw, DRY_VALUE, WET_VALUE, 0, 100);
    percent = constrain(percent, 0, 100);
    Serial.printf("Soil: %d%% (raw: %d)n", percent, raw);
    displayReading(raw, percent);
    if (percent < 40) {
      Serial.println("Soil is dry! Watering...");
      digitalWrite(PUMP_PIN, LOW);
      delay(PUMP_DURATION);
      digitalWrite(PUMP_PIN, HIGH);
      Serial.println("Watering complete.");
    }
  }
}

Step 4: Deploy

  1. Insert the capacitive soil moisture sensor into your plant pot
  2. Connect the water pump to a water container with tubing leading to the plant
  3. Power the ESP32 via USB or 18650 battery shield
  4. The OLED display shows live moisture percentage and pump status
  5. Every hour, the system checks soil moisture and waters automatically

Why Capacitive Sensors Are Better

This system uses a capacitive soil moisture sensor (not a resistive one). Resistive sensors have exposed metal probes that corrode in wet soil within weeks. Capacitive sensors seal the electronics behind a protective layer — they last for years without degradation.

Going Further

  • Add WiFi + MQTT — Forward moisture data to your phone (combine with the MQTT tutorial)
  • Add multiple sensors — Use a multiplexer (CD4051BE) to monitor multiple plants with one ESP32
  • Add a water level sensor — Alert when your water tank is running low
  • Home Assistant integration — Control the pump from your smart home dashboard
  • Solar power — Add a 5V solar panel + 18650 battery shield for permanent outdoor deployment

Leave a Reply

Your email address will not be published. Required fields are marked *