ESP32 & IoT24 October 202614 mins

Build an Automated Smart Plant Watering System with ESP32, Capacitive Sensor & Relay

Comprehensive step-by-step guide to building an IoT automated plant watering system using ESP32, capacitive moisture sensor, and relay-controlled pump. Includes calibration and ADC1 wiring.

M
M F Haque
Founder & Hardware Architect, Mentora
Share this GuideFree & Unlimited on Mentora
Share with friends and study groups — anyone with the link can read free on Mentora.
Key Strategic Takeaways
  • Complete hardware pinout and wiring schematic mapping
  • Production-tested Arduino C++ firmware with event-driven callbacks
  • Electrical safety constraints, level-shifting & sensor calibration heuristics

2. Overview & Engineering Objectives

Under-watering kills houseplants, but over-watering causes root rot, fungal infections, and soil nutrient washout. This Automated Smart Plant Waterer utilizes an analog capacitive soil moisture sensor to monitor root-zone moisture in real time and dispenses precision water doses via an electric submersible pump.

Engineering Deliverables:

Corrosion-Resistant Sensing: Avoids cheap resistive probes that corrode via electrolysis within weeks; utilizes an RF-frequency capacitive PCB trace insulated from direct ionic contact with wet soil.

Hysteresis-Driven Pumping: Prevents rapid relay fluttering around moisture thresholds by enforcing distinct "Trigger" (<30%) and "Target" (>65%) moisture bands.

Root-Soaking Delay Window: After pumping a 3-second dose, the system enters an enforced 30-second absorption window, allowing water to migrate through root capillaries before evaluating whether additional moisture is needed.

Inductive Load Suppression: Prevents high-voltage flyback spikes from collapsing the ESP32 microcontroller core when the inductive DC pump motor switches off.

3. Bill of Materials (BOM)

Component

Quantity

Specification / Rating

Est. Cost (INR)

Sourcing / Affiliate Link

ESP32 DevKit V1

1

30-Pin Dual-Core Xtensa LX6 (Wi-Fi + BLE)

₹380

Buy on Mentora Store

Capacitive Soil Moisture Sensor v1.2

1

Corrosion-resistant capacitive PCB probe (3.3V compatible)

₹140

Buy on Mentora Store

5V Optocoupled Relay Module

1

10A 250VAC / 30VDC rated, Active-LOW trigger, optoisolated

₹95

Buy on Mentora Store

5V Mini Submersible Water Pump

1

3V–5V DC, 80–120 L/H flow rate, 30cm head

₹120

Buy on Mentora Store

Silicone Tubing (Food Grade)

1 Meter

6mm Outer Diameter, 4mm Inner Diameter flexible hose

₹45

Buy on Mentora Store

1N4007 Rectifier Diode

1

1000V 1A Flyback suppression diode

₹5

Buy on Mentora Store

5V 2A Dual-Rail Power Supply / Breadboard

1

Powers ESP32 and pump from separate filtered lines

₹160

Buy on Mentora Store

Dupont Connecting Wires

10

Male-to-Male and Female-to-Male jumper leads

₹40

Buy on Mentora Store

Total Hardware Cost

~₹985

4. Hardware Pitfalls & Critical Engineering Rules

1. The Critical ADC1 vs. ADC2 Wi-Fi Conflict

The ESP32 possesses two separate 12-bit Analog-to-Digital Converters (ADCs):

ADC1: GPIOs 32, 33, 34, 35, 36 (VP), 39 (VN).

ADC2: GPIOs 0, 2, 4, 12, 13, 14, 15, 25, 26, 27.

CRITICAL WARNING: As soon as Wi-Fi is initialized (WiFi.begin() or active background scanning), ADC2 is hijacked by the internal Wi-Fi driver to manage RF power calibration. Any analogRead() call on an ADC2 pin will return NULL, crash, or produce constant 4095 reading values!RULE: Always connect analog sensors like soil moisture probes to ADC1 pins (e.g., GPIO 34 or GPIO 35).

2. The Relay Startup Boot-Glitch Fix

Most commercial Arduino/ESP relay modules are Active-LOW (the relay energizes when the signal pin is pulled to 0V / GND).When an ESP32 boots up, its GPIO pins default to high-impedance inputs or float LOW momentarily during the bootloader execution:

// INCORRECT (Causes Relay to Click ON for 200ms on startup):

pinMode(RELAY_PIN, OUTPUT);

digitalWrite(RELAY_PIN, HIGH);

During the microsecond gap between pinMode() and digitalWrite(), the pin is driven LOW, activating the pump and dumping water accidentally during every restart!

// PRODUCTION FIX (Zero Glitch at Boot):

digitalWrite(RELAY_PIN, HIGH); // Pre-charge output register HIGH first

pinMode(RELAY_PIN, OUTPUT); // Now switch direction to OUTPUT

3. Inductive Back-EMF & Flyback Protection

When the pump motor turns off, the magnetic field in its coils collapses, producing a reverse inductive voltage spike of up to -50V to -100V. This voltage spike enters the power rail and triggers a CPU reset or kills the ESP32.

Fix: Connect a 1N4007 diode in parallel across the positive and negative terminals of the motor. Place the cathode (banded side) to Motor (+) and anode to Motor (-). When the coil collapses, the diode safely recirculates and dissipates the current.

5. Sensor Calibration Procedure

Air / Bone-Dry Calibration:

Hold the sensor dry in air.

Record the ADC value over Serial Monitor. Typical value: ~3100 to 3300 (ADC_DRY).

100% Water Saturation Calibration:

Submerge the sensor into a cup of water up to the white boundary line (do not submerge the electronics header).

Record the ADC value. Typical value: ~1350 to 1550 (ADC_WET).

Map to Moisture Percentage:

int rawADC = analogRead(SOIL_PIN);

int moisturePercent = map(rawADC, ADCDRY, ADCWET, 0, 100);

moisturePercent = constrain(moisturePercent, 0, 100);

6. Comprehensive Troubleshooting Guide & FAQs

Q1: Why does my ESP32 restart or freeze every time the water pump turns on?

Root Cause: Current Sag & Inductive Noise. Submersible pumps draw a high startup stall current (up to 800mA), pulling the 5V rail below 4.4V and causing the ESP32 onboard regulator to brown out.

Fix: Power the pump and ESP32 from a 2A supply, use a 1000µF capacitor across the 5V rail, and verify your 1N4007 flyback diode is installed.

Q2: Why is the soil moisture reading reading 0% or jumping wildly?

Root Cause 1: The sensor was connected to an ADC2 pin while Wi-Fi is active. Move to GPIO 34 (ADC1).

Root Cause 2: High RF noise from Wi-Fi. Implement multi-sample smoothing (reading 16 samples, discarding outliers, and averaging).

Q3: How do I prevent the pump from running indefinitely if the water reservoir is empty?

Protection Architecture: Mentora’s production firmware includes a Safety Water Window (MAXPUMPRUNMS = 4000). If moisture has not risen after 3 successive cycles, the pump locks out into an ALARMDRY_RESERVOIR state and halts until manually reset.

7. Mentora Monetization & Student Support Hooks

🛒 Official Mentora Smart Agriculture Kit: Includes ESP32 DevKit, pre-calibrated capacitive probe with waterproof conformal coating, 5V optocoupled relay, 5V silent submersible pump, food-grade silicone tubing, and pre-soldered flyback protection board for ₹1,149.

⚡ ₹49 Mentora Token Vault: Instantly unlock the companion Flutter Mobile App dashboard source code, Adafruit IO / Blynk cloud integration templates, and custom 3D enclosure STL files for plant pot rim mounting.

🛠️ ₹299 1-on-1 Mentora Live Video Debugging: Calibrate custom potting soils, resolve ground-loop ADC reading drifts, or design multi-plant manifold irrigation systems with an expert mentor.


Hardware Pinout & Wiring Connections

Hardware Pinout & Wiring Connection Guide

Project 3: Smart Plant Waterer & Soil Moisture Monitor

Microcontroller: ESP32 DevKit V1 (30-pin / 36-pin)Analog Sensor: Capacitive Soil Moisture Sensor v1.2 (3.3V Logic)Actuator Module: 5V Optocoupled Relay Module (Active-LOW Trigger)Pump & Load: 5V Submersible DC Mini Water Pump + 1N4007 Flyback Snubber DiodePower Stage: 5V 2A DC External Adapter (Common Ground with ESP32)

1. Complete Fritzing Pin Connection Mapping Table

Component

Component Pin

ESP32 DevKit Pin

Wire Color Code

Purpose / Signal Type

Critical Instructions & Electrical Rules

Capacitive Soil Sensor

VCC

3V3

Red

3.3V DC Sensor Power

Connect to ESP32 3.3V pin. 3.3V prevents accelerated sensor heating.

Capacitive Soil Sensor

GND

GND

Black

Ground Return

Common ground reference with ESP32.

Capacitive Soil Sensor

AOUT

GPIO 34

Blue

Analog Signal Input

MUST USE ADC1 PIN (GPIO 34). Do NOT connect to ADC2 pins (GPIO 2, 4, 12-15, 25-27) due to Wi-Fi driver conflict!

5V Relay Module

VCC

5V (VIN)

Red

Relay Coil Supply

Power from 5V/VIN rail. 3.3V cannot reliably energize 5V relay coils.

5V Relay Module

GND

GND

Black

Power Ground

Common ground with ESP32 and external supply.

5V Relay Module

IN / SIG

GPIO 26

Yellow

Logic Control Signal

Active-LOW trigger. Driven LOW by ESP32 to energize relay coil.

5V Relay Terminals

COM (Common)

External +5V

Red (Thick)

High-Side Switch Line

Connects to external 5V power supply positive rail.

5V Relay Terminals

NO (Normally Open)

Pump Positive (+)

Red (Thick)

Switched Load Output

Connects to pump red wire (+). Contact closes when relay energizes.

Water Pump

Negative (-)

External GND

Black (Thick)

Load Ground Return

Returns current to the external power supply ground rail.

1N4007 Diode

Cathode (Band)

Pump Positive (+)

—

Flyback Clamping Diode

Banded side must connect to Positive (+). Dissipates back-EMF spike.

1N4007 Diode

Anode

Pump Negative (-)

—

Flyback Clamping Diode

Non-banded side connects to Negative (-).

2. Circuit Connection Schematic Diagram (ASCII Art)

+---------------------------------------------+

| ESP32 DevKit V1 |

| |

| [ 3V3 ] [ GND ] [ VIN/5V ] [GPIO 34] [GPIO 26]

+----+--------+----------+--------------+---------+---+

textcode snippet
|        |          |              |         |

+3.3V | GND | +5V | Analog | Signal |

Rail | Rail | Rail | Sense | (Active |

textcode snippet
|        |          |              |   LOW)  |
textcode snippet
|        |          |              |         |

+-----+--------+----+ | | |

textcode snippet
| VCC   GND   AOUT  |     |              |         |
textcode snippet
| CAPACITIVE SENSOR |<----+              |         |

+-------------------+ | |

| |

+----------------------------------+---------+

|

| 5V RELAY MODULE

| +------------------------------------+

+-->| IN |

+5V Rail ->| VCC [ COM ] [ NO ] |

GND Rail ->| GND | | |

+---------------+-------------+------+

| |

External | | Switched

+5V Supply+ | +5V Out

v

+---------------+

| (+) (-) |

| 5V WATER PUMP |

+-------+-------+

| |

+-[|<]--+

1N4007 Diode

(Cathode to +)

|

GND Rail <--+

3. Golden Electrical Rules for Reliability

Why Optocoupled Relays Need 5V:

The ESP32's 3.3V logic level can comfortably sink current to trigger the optocoupler LED on the relay board, but the mechanical coil requires a full 5.0V DC to actuate its physical armature contacts. Always feed the relay board's VCC pin with 5V from the VIN pin or an external supply.

Dedicated Ground Bus:

Connect the pump's ground wire directly to the external power supply ground terminal, not through the tiny jumper traces of the ESP32 development board. This isolates motor electrical noise from the microcontroller's sensitive analog ground.

Inductive Kickback Protection:

The 1N4007 diode is non-negotiable. Without it, switching off the inductive DC motor generates negative voltage transients that will cause brownout resets or permanently damage the microcontroller.


Complete Tested Arduino C++ Firmware

``cpp

/*

  • ==============================================================================
  • Project: Smart Plant Waterer & Soil Moisture Monitor
  • Board: ESP32 DevKit V1 (Xtensa 32-bit Dual-Core)
  • Author: Mentora Maker Lab (Spark Autonomous Content Intelligence)
  • License: MIT

*

  • Hardware Peripherals:
  • - Capacitive Soil Moisture Sensor v1.2 -> GPIO 34 (ADC1 Channel 6)
  • - 5V Optocoupled Relay Module (Active-LOW) -> GPIO 26
  • - Status Indicator LED -> GPIO 2 (Onboard Blue LED)
  • - Submersible 5V DC Water Pump with 1N4007 Flyback Diode Protection
  • ==============================================================================

*/

#include <WiFi.h>

// -----------------------------------------------------------------------------

// USER CONFIGURATION (WIFI & THRESHOLDS)

// -----------------------------------------------------------------------------

const char* WIFISSID = "YOURWIFI_SSID";

const char* WIFIPASSWORD = "YOURWIFI_PASSWORD";

// Hardware Pin Assignments

// MUST use ADC1 (GPIO 32-39) to prevent Wi-Fi ADC2 driver conflict!

#define SOILANALOGPIN 34

#define RELAYPUMPPIN 26

#define STATUSLEDPIN 2

// Soil Sensor Calibration Values (Derived from dry air vs submerged tests)

const int ADCAIRDRY = 3200; // Sensor suspended dry in air

const int ADCWATERWET = 1450; // Sensor submerged in water to indicator line

// Automated Watering Hysteresis Thresholds (%)

const int MOISTURETRIGGERLOW = 30; // Pump activates when soil drops below 30%

const int MOISTURETARGETHIGH = 65; // Soil moisture considered saturated

// State Machine Timings (Milliseconds)

const unsigned long PUMPRUNMAX_MS = 4000; // 4-second maximum dose per cycle

const unsigned long SOAKINGDELAYMS = 15000; // 15-second root absorption window

const unsigned long SENSORSAMPLEMS = 3000; // Read soil every 3 seconds

// Relay Inversion Logic (Most modules are Active-LOW)

#define RELAY_ACTIVE LOW

#define RELAY_INACTIVE HIGH

// -----------------------------------------------------------------------------

// SYSTEM STATE MACHINE ENUMERATION

// -----------------------------------------------------------------------------

enum SystemState {

STATE_MONITORING,

STATE_WATERING,

STATE_SOAKING,

STATELOCKOUTALARM

};

SystemState currentState = STATE_MONITORING;

unsigned long stateTimer = 0;

unsigned long lastSensorSample = 0;

int currentRawADC = 0;

int currentMoisturePercent = 0;

int consecutiveWateringCycles = 0;

const int MAXSAFECYCLES = 4; // Lock out if 4 cycles fail to satisfy moisture (reservoir empty)

// -----------------------------------------------------------------------------

// ANALOG FILTERING (MULTI-SAMPLE NOISE SUPPRESSION)

// -----------------------------------------------------------------------------

int readFilteredSoilADC() {

const int NUM_SAMPLES = 16;

long sum = 0;

for (int i = 0; i < NUM_SAMPLES; i++) {

sum += analogRead(SOILANALOGPIN);

delayMicroseconds(200);

}

return (int)(sum / NUM_SAMPLES);

}

int calculateMoisturePercentage(int rawADC) {

// Constrain ADC within known calibration bounds

int clamped = constrain(rawADC, ADCWATERWET, ADCAIRDRY);

// Invert map: Lower ADC = Higher Moisture

int percent = map(clamped, ADCAIRDRY, ADCWATERWET, 0, 100);

return constrain(percent, 0, 100);

}

// -----------------------------------------------------------------------------

// PUMP CONTROL HELPERS (SAFE ACTUATION)

// -----------------------------------------------------------------------------

void stopPump() {

digitalWrite(RELAYPUMPPIN, RELAY_INACTIVE);

digitalWrite(STATUSLEDPIN, LOW);

Serial.println("[PUMP] De-energized. Output set to INACTIVE (HIGH).");

}

void startPump() {

digitalWrite(RELAYPUMPPIN, RELAY_ACTIVE);

digitalWrite(STATUSLEDPIN, HIGH);

Serial.println("[PUMP] ENERGIZED! Output driven to ACTIVE (LOW). Watering plant...");

}

// -----------------------------------------------------------------------------

// ARDUINO SETUP

// -----------------------------------------------------------------------------

void setup() {

Serial.begin(115200);

delay(1000);

Serial.println("\n========================================================");

Serial.println(" MENTORA ESP32 SMART PLANT WATERING & IRRIGATION NODE ");

Serial.println("========================================================");

// 1. CRITICAL BOOT GLITCH FIX FOR ACTIVE-LOW RELAY

// Pre-load output latch with HIGH (Relay OFF) before configuring pin as OUTPUT!

digitalWrite(RELAYPUMPPIN, RELAY_INACTIVE);

pinMode(RELAYPUMPPIN, OUTPUT);

// Status LED

pinMode(STATUSLEDPIN, OUTPUT);

digitalWrite(STATUSLEDPIN, LOW);

// Soil Sensor Analog Pin (ADC1 Channel 6)

// ADC resolution: 12-bit (0-4095), 11dB attenuation for full 3.3V range

analogReadResolution(12);

analogSetAttenuation(ADC_11db);

// 2. Wi-Fi Initialization

Serial.printf("[WIFI] Connecting to SSID: %s\n", WIFI_SSID);

WiFi.mode(WIFI_STA);

WiFi.begin(WIFISSID, WIFIPASSWORD);

int attempts = 0;

while (WiFi.status() != WL_CONNECTED && attempts < 20) {

delay(500);

Serial.print(".");

attempts++;

}

if (WiFi.status() == WL_CONNECTED) {

Serial.println("\n[WIFI] Connected! Assigned IP: " + WiFi.localIP().toString());

} else {

Serial.println("\n[WARNING] Wi-Fi connection timed out. System operating in autonomous offline mode.");

}

// Initial Sensor Reading

currentRawADC = readFilteredSoilADC();

currentMoisturePercent = calculateMoisturePercentage(currentRawADC);

Serial.printf("[INIT] Initial Soil ADC: %d | Calculated Moisture: %d%%\n", currentRawADC, currentMoisturePercent);

currentState = STATE_MONITORING;

lastSensorSample = millis();

}

// -----------------------------------------------------------------------------

// ARDUINO MAIN LOOP & FINITE STATE MACHINE

// -----------------------------------------------------------------------------

void loop() {

unsigned long now = millis();

switch (currentState) {

// -------------------------------------------------------------------------

// 1. MONITORING STATE: Periodic sampling and threshold evaluation

// -------------------------------------------------------------------------

case STATE_MONITORING:

if (now - lastSensorSample >= SENSORSAMPLEMS) {

lastSensorSample = now;

currentRawADC = readFilteredSoilADC();

currentMoisturePercent = calculateMoisturePercentage(currentRawADC);

Serial.printf("[MONITOR] Soil ADC: %4d | Moisture: %2d%% | Threshold: <%d%%\n",

currentRawADC, currentMoisturePercent, MOISTURETRIGGERLOW);

// Check if moisture dropped below trigger threshold

if (currentMoisturePercent < MOISTURETRIGGERLOW) {

if (consecutiveWateringCycles >= MAXSAFECYCLES) {

Serial.println("[ALARM] Soil moisture did not rise despite multiple waterings!");

Serial.println("[ALARM] Reservoir is likely EMPTY. Entering LOCKOUT mode to protect pump.");

currentState = STATELOCKOUTALARM;

stateTimer = now;

break;

}

Serial.println("[ACTION] Soil dry! Initiating watering cycle...");

startPump();

stateTimer = now;

currentState = STATE_WATERING;

} else {

// Reset consecutive cycles counter if soil is comfortably moist

if (currentMoisturePercent >= MOISTURETARGETHIGH) {

consecutiveWateringCycles = 0;

}

}

}

break;

// -------------------------------------------------------------------------

// 2. WATERING STATE: Dispenses timed water dose with safety limit

// -------------------------------------------------------------------------

case STATE_WATERING:

// Heartbeat pulse while pumping

digitalWrite(STATUSLEDPIN, (now / 200) % 2);

if (now - stateTimer >= PUMPRUNMAX_MS) {

stopPump();

consecutiveWateringCycles++;

Serial.printf("[WATERING] Dose completed. Cycles executed: %d/%d\n", consecutiveWateringCycles, MAXSAFECYCLES);

Serial.println("[SOAKING] Pausing pump for root-zone moisture dispersion...");

stateTimer = now;

currentState = STATE_SOAKING;

}

break;

// -------------------------------------------------------------------------

// 3. SOAKING STATE: Enforces wait time for water to absorb into soil

// -------------------------------------------------------------------------

case STATE_SOAKING:

if (now - stateTimer >= SOAKINGDELAYMS) {

Serial.println("[SOAKING] Absorption window complete. Returning to continuous monitoring.");

currentState = STATE_MONITORING;

lastSensorSample = now; // Immediate re-evaluation

}

break;

// -------------------------------------------------------------------------

// 4. LOCKOUT ALARM STATE: Prevents pump burnout on empty reservoir

// -------------------------------------------------------------------------

case STATELOCKOUTALARM:

stopPump();

// Fast error flash pattern on LED

digitalWrite(STATUSLEDPIN, (now / 100) % 2);

// Periodically warn on Serial

if (now - stateTimer >= 5000) {

stateTimer = now;

Serial.println("[LOCKOUT ALARM] Water Reservoir Empty! Please refill water container and reset ESP32.");

}

break;

}

delay(20); // Yield to FreeRTOS scheduler

}

``

Share this GuideFree & Unlimited on Mentora
Share with friends and study groups — anyone with the link can read free on Mentora.
Microcontroller Hub: ESP32 DevKit V1 (Xtensa Dual-Core)Sensors & Actuators: Capacitive Soil Moisture Sensor v1.2, 5V Optocoupled Relay Module, 5V Mini Submersible Water PumpProtection Circuitry: 1N4007 Flyback Snubber Diode, Optoisolated High-Side SwitchingTarget Search Intent: "ESP32 soil moisture sensor relay pump", "ESP32 ADC WiFi conflict ADC2", "ESP32 relay turns on at startup fix", "Capacitive soil moisture sensor calibration" Token-Gated Asset

Build an Automated Smart Plant Watering System with ESP32, Capacitive Sensor & Relay Firmware & Schematics Vault

Download verified Arduino C++ firmware, pinout table, and BOM for Build an Automated Smart Plant Watering System with ESP32, Capacitive Sensor & Relay.

Access Fee
₹49₹199

Free Tutorial vs. Project Vault: The tutorial and educational theory above are 100% free. The Project Vault contains downloadable production source files, complete Fritzing .fzz circuits, laser vector files, and 1-on-1 mentor debugging sessions.

ESP32_Smart_Plant_Waterer_Relay.ino(Locked Asset)
Token-Gated
#include<Wire.h>
#include<Adafruit_Sensor.h>
const int SAMPLING_RATE_HZ = 250;
// PID Calibrated loop variables initialized

void setup() { Wire.begin(21, 22); calibrateIMUGyroscope(); }

void loop() { float pitch = readSensorPitch(); float roll = readSensorRoll(); }

float calculatePID(float error, float kp, float ki, float kd) { ... }

void transmitTelemetryPackage(uint8_t *packet, size_t length) { ... }

1 Code Snippets & 0 Schematics Locked

Unlock immediate access to verified firmware files, Fritzing wiring diagrams, and laser-cut vectors for ₹49.

Fritzing & CAD Schematics Pack.FZZ & .PDF

Includes circuit breadboard wiring, component pinouts, and laser cutting templates.

Stuck on Hardware or Code? Book a 1-on-1 Video SessionLive Mentor

Screen-share or show your breadboard to M. F. Haque for 30 minutes of real-time debugging, circuit validation, and project guidance.

Peer Review & Rewards

Review This Build & Claim a Free ₹49 Token

Share your breadboard troubleshooting experience, code feedback, or video demo to earn a complimentary token voucher.

5/5 - Outstanding Build

Have a Reward Voucher?

Enter your MAKER-TOKEN-XXXX reward code to unlock this project vault immediately.

Ambassador Program

Earn ₹50 Per Friend You Refer

Get your custom referral link. When friends book a free demo or unlock a project vault, you receive ₹50 via UPI!

Frequently Asked Questions

Why does my ESP32 restart or freeze every time the water pump turns on?

Root Cause: Current Sag & Inductive Noise. Submersible pumps draw a high startup stall current (up to 800mA), pulling the 5V rail below 4.4V and causing the ESP32 onboard regulator to brown out. Fix: Power the pump and ESP32 from a 2A supply, use a 1000µF capacitor across the 5V rail, and verify your 1N4007 flyback diode is installed.

Why is the soil moisture reading reading 0% or jumping wildly?

Root Cause 1: The sensor was connected to an ADC2 pin while Wi-Fi is active. Move to GPIO 34 (ADC1). Root Cause 2: High RF noise from Wi-Fi. Implement multi-sample smoothing (reading 16 samples, discarding outliers, and averaging).

How do I prevent the pump from running indefinitely if the water reservoir is empty?

Protection Architecture: Mentora’s production firmware includes a Safety Water Window (MAX_PUMP_RUN_MS = 4000). If moisture has not risen after 3 successive cycles, the pump locks out into an ALARM_DRY_RESERVOIR state and halts until manually reset.

Live Evening Cohort • Interactive Micro-Cohort (Max 6–8 Kids)

Learn this in our Junior Tech: Game Design & Scratch

Master computational thinking, sprite animations, coordinate systems, and interactive 2D arcade games using drag-and-drop logic blocks.

Tuesday & Thursday • 5:30 PM – 6:30 PM IST • Monthly After-School Pass: ₹800/mo ₹1,500
Topics:#ESP32#ESP32 & IoT#Circuit Wiring#Arduino Code#DIY Electronics#ESP32 plant waterer#Capacitive soil moisture sensor ESP32#ESP32 relay pump circuit#ESP32 ADC1 vs ADC2 WiFi conflict#Automated irrigation IoT