Community project

ESP32 Circuit Design

ESP32
Photo of ESP32 Circuit Design
Generated with AI

Angelo Jake Sevilla

Published October 19, 2026

This project builds an automated watering system controlled by an ESP32 microcontroller. The system monitors water temperature using a DS18B20 sensor and activates a 12V submersible pump when conditions are met, with manual override buttons for immediate control. The pump is driven by an IRLZ44N MOSFET for safe switching, protected by a 1N4007 diode against voltage spikes.

The guide provides a complete wiring diagram showing how to connect the temperature probe, control buttons, and pump circuit to the ESP32. Assembly steps walk through configuring the buck converter, building the MOSFET switch stage, and integrating all components. Firmware is included to handle temperature monitoring, button debouncing, and automatic or manual pump activation.

Wiring diagram

Gather all the parts

QtyComponent
1

DS18B20

Digital temperature sensor using OneWire protocol

1

12V DC Submersible Mini Water Pump

Two-wire brushed DC submersible water pump for small irrigation or circulation projects. It is an external load and must be driven through a relay, MOSFET, or motor driver; do not connect directly to an MCU GPIO.

1

IRLZ44N Logic-Level N-Channel MOSFET

Logic-level N-channel MOSFET commonly used as a low-side switch for DC loads from 3.3V or 5V microcontroller GPIO. Use a gate resistor, a gate pulldown, and a flyback diode for inductive loads.

1

1N4007 Diode

General-purpose silicon rectifier diode in DO-204AL (DO-41) axial through-hole package. Rated 1A average forward current and 1000V peak reverse voltage (VRRM). Forward voltage drop ~0.7V at typical load (up to 1.1V at full 1A). Used here in series with LM7805 Vout for reverse polarity protection: anode to LM7805 output, cathode to 5V rail, resulting in ~4.3V on the output rail. Not suitable for high-frequency switching (reverse recovery ~2µs–30µs); intended for DC or 50/60Hz rectification only.

1

12V Barrel-Jack Adapter

12 V / 2 A wall adapter with a 5.5 mm / 2.1 mm barrel jack. Used to power motor drivers, LED strips, or boards that need a higher rail.

1

24v Buck Converter

LM2596-based adjustable step-down buck converter module. Commonly used to regulate a higher battery rail, such as a 2S 18650 pack, down to 5V for Arduino logic. It is a regulator, not a charger or battery protection board.

1

Push Button

Momentary push button switch

1

Push Button

Momentary push button switch

1

4.7 kΩ Resistor

4.7 kΩ

A small resistor that keeps the temperature sensor’s data wire at a reliable high level.

1

220 Ω Resistor

220 Ω

A small resistor that protects the ESP32 output while it controls the pump switch.

1

10 kΩ Resistor

10 kΩ

A resistor that holds the pump switch off while the ESP32 is starting up.

Assemble it in 6 steps

1. Set the 5 V converter before joining the ESP32

With the ESP32 unplugged, connect the 12 V adapter’s positive lead to buck_5v VIN+ and its negative lead to buck_5v VIN-. Use a multimeter and turn the small adjuster on the converter until VOUT+ to VOUT- measures 5.0 V. Connect buck_5v VOUT+ to the ESP32 VIN/5V pin and buck_5v VOUT- to an ESP32 GND pin.

  • Keep the 12 V pump wires separate from the thin sensor wires so electrical noise is less likely to affect readings.
  • Do not connect the converter to the ESP32 until its output is 5.0 V — a higher setting can damage the ESP32.
  • Unplug the 12 V adapter while moving any wires.

2. Wire the temperature probe

Connect temp_sensor VCC to ESP32 3V3 (power), GND to ESP32 GND (ground), and DATA to GPIO4 (temperature signal). Put sensor_pullup, the 4.7 kΩ resistor, between the same DATA connection and ESP32 3V3; resistors have no direction.

  • Put only the metal probe into the water. Keep the cable joint and the ESP32 dry.
  • Do not connect the sensor VCC to the 12 V pump supply — that can damage the sensor.

3. Add the two control buttons

Connect one leg of start_button to GPIO18 (start signal) and its other leg to GND (ground). Connect one leg of stop_button to GPIO19 (stop signal) and its other leg to GND (ground). The code uses the ESP32’s internal pull-up, so each button works by joining its GPIO to ground when pressed.

  • Place the buttons across the breadboard’s centre gap so their four legs are not accidentally all joined together.

4. Build the pump switch

Connect gate_resistor, the 220 Ω resistor, from GPIO23 (control signal) to pump_mosfet GATE. Connect gate_pulldown, the 10 kΩ resistor, from that GATE connection to GND (keeps the pump off at startup). Connect pump_mosfet SOURCE to the shared 12 V adapter negative/GND and connect DRAIN to water_pump PUMP-.

  • For a bare IRLZ44N with the writing facing you and legs downward, the usual left-to-right pins are Gate, Drain, Source; check the marking or datasheet for the exact part before powering it.
  • The ESP32 ground, converter negative, and 12 V adapter negative must all join together — without this shared return, the pump switch will not work reliably.

5. Connect the pump and its protection diode

Connect water_pump PUMP+ to the 12 V adapter positive lead. Connect flyback_diode across the pump: its striped Cathode end goes to PUMP+ (12 V), and its unstriped Anode end goes to PUMP- / the MOSFET DRAIN connection. Attach the flexible tubing and nozzle firmly to the pump outlet, then put the pump into the water tray.

  • Secure the tubing with a tie or clamp so it cannot spray the breadboard.
  • The diode stripe must face the pump’s positive 12 V wire — reversing it makes a short circuit when power is connected.
  • Keep all breadboard electronics above and away from the water tray; spilled water can cause a short circuit.

6. Mount and test the finished unit

Fix the ESP32, breadboard, and converter on the foam board above the tray. Plug in the ESP32 by USB for programming, then connect the 12 V adapter. Press START to allow pumping only when the probe reads 30 °C or warmer; press STOP to turn the pump off immediately.

  • Test the pump nozzle over an empty container before aiming it at plants or equipment.
  • Do not run the submersible pump dry unless its own instructions explicitly allow it — it can overheat or fail.

Review all connections

1. Connections between "supply_12v" and "ESP32"

Functionsupply_12vESP32
power+12V → 24v Buck Converter VIN+EXT
power+12V → 12V DC Submersible Mini Water Pump PUMP+EXT
groundGND → 24v Buck Converter VIN-EXT
groundGND → IRLZ44N Logic-Level N-Channel MOSFET SOURCEEXT

2. Connections between "buck_5v" and "ESP32"

Functionbuck_5vESP32
powerVOUT+VIN
groundVOUT-GND

3. Connections between "temp_sensor" and "ESP32"

Functiontemp_sensorESP32
powerVCC3V3
groundGNDGND
dataDATAGPIO 4

4. Connections between "sensor_pullup" and "ESP32"

Functionsensor_pullupESP32
powerEnd A3V3
dataEnd B → DS18B20 DATAEXT

5. Connections between "start_button" and "ESP32"

Functionstart_buttonESP32
groundGNDGND
digitalSIGNALGPIO 18

6. Connections between "stop_button" and "ESP32"

Functionstop_buttonESP32
groundGNDGND
digitalSIGNALGPIO 19

7. Connections between "gate_resistor" and "ESP32"

Functiongate_resistorESP32
dataEnd AGPIO 23
dataEnd B → IRLZ44N Logic-Level N-Channel MOSFET GATEEXT

8. Connections between "gate_pulldown" and "ESP32"

Functiongate_pulldownESP32
dataEnd A → IRLZ44N Logic-Level N-Channel MOSFET GATEEXT
groundEnd BGND

9. Connections between "pump_mosfet" and "ESP32"

Functionpump_mosfetESP32
dataDRAIN → 12V DC Submersible Mini Water Pump PUMP-EXT

10. Connections between "flyback_diode" and "ESP32"

Functionflyback_diodeESP32
powerAnode → IRLZ44N Logic-Level N-Channel MOSFET DRAINEXT
powerCathode → 12V DC Submersible Mini Water Pump PUMP+EXT

Deploy the firmware

#include <OneWire.h>
#include <DallasTemperature.h>

const int TEMP_DATA_PIN = 4;
const int START_BUTTON_PIN = 18;
const int STOP_BUTTON_PIN = 19;
const int PUMP_GATE_PIN = 23;
const float PUMP_ON_TEMPERATURE_C = 30.0f;
const unsigned long SENSOR_INTERVAL_MS = 1000;
const unsigned long DEBOUNCE_MS = 40;

OneWire oneWire(TEMP_DATA_PIN);
DallasTemperature temperatureSensor(&oneWire);

bool automaticWateringEnabled = false;
bool pumpIsOn = false;
bool lastStartReading = HIGH;
bool lastStopReading = HIGH;
unsigned long lastStartChangeMs = 0;
unsigned long lastStopChangeMs = 0;
unsigned long lastSensorReadMs = 0;
float lastTemperatureC = DEVICE_DISCONNECTED_C;

void setPump(bool shouldRun) {
  if (pumpIsOn == shouldRun) return;
  pumpIsOn = shouldRun;
  digitalWrite(PUMP_GATE_PIN, pumpIsOn ? HIGH : LOW);
  Serial.println(pumpIsOn ? "Pump ON" : "Pump OFF");
}

bool pressedOnce(int pin, bool &lastReading, unsigned long &lastChangeMs) {
  bool reading = digitalRead(pin);
  if (reading != lastReading) {
    lastChangeMs = millis();
    lastReading = reading;
  }
  if (reading == LOW && millis() - lastChangeMs >= DEBOUNCE_MS) {
    while (digitalRead(pin) == LOW) delay(1);
    lastReading = HIGH;
    return true;
  }
  return false;
}

void readTemperatureAndControlPump() {
  temperatureSensor.requestTemperatures();
  float temperatureC = temperatureSensor.getTempCByIndex(0);
  if (temperatureC == DEVICE_DISCONNECTED_C) {
    Serial.println("Temperature sensor not found; pump kept off.");
    setPump(false);
    return;
  }

  if (temperatureC != lastTemperatureC) {
    lastTemperatureC = temperatureC;
    Serial.print("Water temperature: ");
    Serial.print(temperatureC, 1);
    Serial.println(" C");
  }
  setPump(automaticWateringEnabled && temperatureC >= PUMP_ON_TEMPERATURE_C);
}

void setup() {
  Serial.begin(115200);
  pinMode(PUMP_GATE_PIN, OUTPUT);
  digitalWrite(PUMP_GATE_PIN, LOW);
  pinMode(START_BUTTON_PIN, INPUT_PULLUP);
  pinMode(STOP_BUTTON_PIN, INPUT_PULLUP);
  temperatureSensor.begin();
  Serial.println("Pump controller ready. START enables automatic pumping at 30 C; STOP turns it off.");
}

void loop() {
  if (pressedOnce(START_BUTTON_PIN, lastStartReading, lastStartChangeMs)) {
    automaticWateringEnabled = true;
    Serial.println("Automatic pump control enabled.");
    readTemperatureAndControlPump();
  }

  if (pressedOnce(STOP_BUTTON_PIN, lastStopReading, lastStopChangeMs)) {
    automaticWateringEnabled = false;
    setPump(false);
    Serial.println("Automatic pump control disabled.");
  }

  if (millis() - lastSensorReadMs >= SENSOR_INTERVAL_MS) {
    lastSensorReadMs = millis();
    readTemperatureAndControlPump();
  }
  delay(1);
}

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik