Plant Watering Alert System Easy

Build a plant watering alert system using a soil moisture sensor, buzzer, and LED with ESP32

🔗Goal

Potted plant with soil and gardening tools

Build a system that monitors soil moisture and alerts you when your plant needs watering. When the soil gets too dry, an LED lights up and a buzzer beeps to remind you to water.

Here is how the system works at a high level:

graph LR
    A[Soil Moisture Sensor] -->|Analog signal| B[ESP32]
    B -->|GPIO| C[LED]
    B -->|GPIO| D[Buzzer]
    B -->|Serial| E[Monitor]

The capacitive soil moisture sensor outputs an analog voltage that decreases as the soil dries out. The ESP32 reads this value, compares it to a threshold, and activates the LED and buzzer when watering is needed.

The chart below shows how soil moisture drops over time. Once the reading falls below the threshold, the alert triggers:

Soil moisture decreasing over time until it crosses the dry threshold

🔗Prerequisites

Breadboard with microcontroller, LED, and jumper wires

You will need the following components:

ComponentQtyNotesBuy
ESP32 dev board1Any ESP32 board with ADC pinsAliExpress | Amazon.de .co.uk .com
Capacitive soil moisture sensor v1.21Prefer capacitive over resistive (lasts longer)AliExpress | Amazon.de .co.uk .com
LED (red)1Any standard 5mm LEDAliExpress | Amazon.de .co.uk .com
220 ohm resistor1Current-limiting resistor for the LEDAliExpress | Amazon.de .co.uk .com
Active buzzer13.3V compatibleAliExpress | Amazon.de .co.uk .com
Breadboard1AliExpress | Amazon.de .co.uk .com
Jumper wires~8Male-to-male and male-to-femaleAliExpress | Amazon.de .co.uk .com

Links marked Amazon/AliExpress are affiliate links. We may earn a small commission at no extra cost to you.

The current through the LED is limited by a resistor. For a red LED with a typical forward voltage of $V_f = 2.0\,\text{V}$, the resistor value is calculated using Ohm's law:

$$R = \frac{V_{supply} - V_f}{I} = \frac{3.3 - 2.0}{0.005} = 260\,\Omega$$

A 220 ohm resistor works fine here — the LED will draw about 6 mA, which is bright enough and well within the ESP32 GPIO limit of 12 mA.

🔗Tutorial

Soil moisture sensor probe in the ground

🔗Step 1: Wiring

Connect everything to the ESP32 as shown in the table below:

ComponentPinESP32 Pin
Moisture sensorVCC3.3V
Moisture sensorGNDGND
Moisture sensorAOUTGPIO 34
LED (anode, long leg)GPIO 25 (through 220 ohm resistor)
LED (cathode, short leg)GND
Buzzer (+)GPIO 26
Buzzer (−)GND

GPIO 34 is an input-only pin with ADC support, which makes it a good choice for reading analog sensors.

🔗Step 2: Determine your threshold

The sensor outputs a value between 0 and 4095 (ESP32 has a 12-bit ADC). The mapping depends on your specific sensor, but as a general guide:

Sensor readingSoil condition
3000–4095Dry (needs water)
1500–3000Moist
0–1500Wet / submerged

These values vary between sensors. Use the serial monitor (Step 4) to find the right threshold for your sensor and plant.

The decision logic follows this flow:

graph TD
    A[Read sensor] --> B{Reading > threshold?}
    B -->|Yes: soil is dry| C[Turn on LED]
    C --> D[Beep buzzer]
    D --> E[Wait 1 second]
    B -->|No: soil is moist| F[Turn off LED]
    F --> G[Silence buzzer]
    G --> E
    E --> A

🔗Step 3: Upload the code

#define SENSOR_PIN 34
#define LED_PIN    25
#define BUZZER_PIN 26

// Threshold: readings above this mean the soil is dry.
// Adjust based on your sensor calibration.
#define DRY_THRESHOLD 3000

void setup() {
    Serial.begin(115200);
    pinMode(LED_PIN, OUTPUT);
    pinMode(BUZZER_PIN, OUTPUT);
}

void loop() {
    int moisture = analogRead(SENSOR_PIN);

    Serial.print("Soil moisture: ");
    Serial.println(moisture);

    if (moisture > DRY_THRESHOLD) {
        // Soil is dry — alert!
        digitalWrite(LED_PIN, HIGH);
        digitalWrite(BUZZER_PIN, HIGH);
        delay(500);
        digitalWrite(BUZZER_PIN, LOW);
        delay(500);
    } else {
        // Soil is moist — all good
        digitalWrite(LED_PIN, LOW);
        digitalWrite(BUZZER_PIN, LOW);
        delay(1000);
    }
}

🔗Step 4: Calibrate

  1. Open the Serial Monitor (115200 baud)
  2. Read the value with the sensor in dry air — note this number
  3. Read the value with the sensor in a glass of water — note this number
  4. Place the sensor in your plant's soil and read the value when the soil feels dry to the touch
  5. Set DRY_THRESHOLD to that value

The analog reading maps to a voltage via the ESP32's 12-bit ADC:

$$V_{sensor} = \frac{\text{ADC reading}}{4095} \times 3.3\,\text{V}$$

For example, a reading of 3000 corresponds to $V = \frac{3000}{4095} \times 3.3 \approx 2.42\,\text{V}$.

🔗Common Issues and Solutions

ProblemCauseFix
Reading is always 0Sensor not connected to an ADC-capable pinUse GPIO 32–39 (ADC1). Avoid ADC2 pins (GPIO 0, 2, 4, 12–15, 25–27) when using WiFi
Reading fluctuates wildlyElectrical noise or loose connectionAdd a 100nF capacitor between sensor VCC and GND. Check wiring
Reading doesn't changeSensor not deep enough in soilPush sensor in until the line marking on the PCB
Buzzer won't stopThreshold too lowIncrease DRY_THRESHOLD based on calibration
LED is very dimResistor value too highUse a 220 ohm resistor instead of 1K+
Sensor corrodes quicklyUsing a resistive sensorSwitch to a capacitive sensor (no exposed metal contacts)

Photo credits: Photo by feey on Unsplash. Photo by Bmonster Lab on Pexels. Soil moisture sensor image from Wikimedia Commons (CC0).