ESP32 UNO - Automatic Irrigation System

Going away for a few days and worried about your plants? Build an automatic irrigation system with the ESP32 Uno and let the soil decide when the water flows. A capacitive soil moisture sensor tells the ESP32 Uno form board how dry the pot is, and a relay switches a 12V pump on or off. You get a small automatic watering setup for a smart garden or a single plant on your desk.

By the end, you can:

  1. Hook up a capacitive moisture probe, a relay module and a 12V water pump
  2. Turn the soil level into a 0 to 4095 number with analogRead()
  3. Pick a dry/wet border value for automatic plant watering
  4. Upload the sketch from Arduino IDE and see the pump react to the soil
ESP32 Uno automatic irrigation system

Components You Need

1×ESP32 Uno-form Board
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×Capacitive Soil Moisture Sensor
1×Relay
1×12V Pump
1×Vinyl Tube
1×12V Power Adapter
1×DC Power Jack
1×Jumper Wires

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Buy Note: Many soil moisture sensors available in the market are unreliable, regardless of their version. We strongly recommend buying the sensor with TLC555I Chip from the DIYables brand using the link provided above. We tested it, and it worked reliably.

How the Sensor, Relay and Pump Work Together

After this part, you know the job of each block in the watering loop.

Part Job in This Project Powered From
Capacitive soil moisture sensor Outputs a voltage on AOUT, a bigger reading means drier soil 3.3V pin
Relay module Acts as a switch that the board opens and closes 5V pin
12V pump Pushes water through the vinyl tube 12V adapter, through the relay contacts
ESP32 Uno Compares the reading with a border value and sets the relay USB Type-C

The board never feeds current to the pump. It only sends a small logic signal to the relay, and the relay contacts carry the 12V.

For a deeper look at each part, open these guides:

Good to know: the ESP32 Uno uses 3.3V logic, so keep every signal that goes into a board pin at 3.3V or lower.

ESP32 Uno Pinout

On the ESP32 Uno, the label printed next to a header (like A0 or D2) is not the number you type in code. Find A0 and D2 in the picture below and note the GPIO behind each one.

ESP32 Uno pinout diagram

How to Connect

When you finish this part, the sensor reads the soil and the relay is ready to start the pump.

The wiring diagram between ESP32 Uno soil moisture sensor Pump

This image is created using Fritzing. Click to enlarge image

Component Pin ESP32 Uno Pin
Soil sensor VCC 3.3V
Soil sensor GND GND
Soil sensor AOUT A0 (GPIO2)
Relay VCC 5V
Relay GND GND
Relay IN D2 (GPIO26)

For the water side, run the 12V adapter through the DC power jack, then through the relay COM and NO terminals to the pump. The pump circuit stays apart from the board pins.

WARNING

A0 is GPIO2, a boot strapping pin of the ESP32 Uno. The chip checks this pin when it starts. If the sensor holds a high voltage on it during power-on or upload, the board may not enter upload mode. If an upload fails, unplug the sensor AOUT wire, upload, then plug it back in.

Good to know: feed the sensor from 3.3V. At 5V its AOUT can go above 3.3V, and ESP32 Uno pins are NOT 5V tolerant.

ESP32 Uno Code

This sketch checks the soil twice per second and switches the pump based on one border value.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-automatic-irrigation-system */ #define RELAY_PIN 26 // D2 (GPIO26) drives the relay IN pin #define MOISTURE_PIN 2 // A0 (GPIO2) reads the sensor AOUT signal #define THRESHOLD 2120 // dry/wet border on the 12-bit scale (0 - 4095), put your own calibrated value here void setup() { Serial.begin(9600); // set the ADC attenuation to 11 dB (up to ~3.3V input) analogSetAttenuation(ADC_11db); pinMode(RELAY_PIN, OUTPUT); } void loop() { int value = analogRead(MOISTURE_PIN); // get the raw moisture level, higher means drier if (value > THRESHOLD) { Serial.print("The soil is DRY => turn pump ON"); digitalWrite(RELAY_PIN, HIGH); } else { Serial.print("The soil is WET => turn pump OFF"); digitalWrite(RELAY_PIN, LOW); } Serial.print(" ("); Serial.print(value); Serial.println(")"); delay(500); }

Good to know: the line analogSetAttenuation(ADC_11db) widens the input range of the ESP32 Uno analog pin, so it reads the full span from 0V up to about 3.3V. Without a wide range, readings jump to 4095 too soon and the moisture values look wrong.

The border value 2120 is the old 10-bit value of 530, multiplied by 4 for the 12-bit ADC. Treat it as a first guess only, and replace it with your own number after calibration.

Upload and Test

  1. First time with this board? Set it up with ESP32 Uno - Getting Started before you continue.
  2. Build the circuit by following the wiring table above.
  3. Plug in the USB Type-C cable between the ESP32 Uno and your computer.
  4. Select the board in Arduino IDE: pick ESP32 Dev Module and the COM port of the board (CH340).
  5. Measure your border value. Use the calibration part of ESP32 Uno - Soil Moisture Sensor to see the number in dry soil and in wet soil.
  6. Edit the sketch. Write a number between those two readings in the THRESHOLD line.
  7. Open the Serial Monitor and choose 9600 baud.
  8. Press Upload and wait for "Done uploading".
  9. Test it. Hold the sensor in the air (dry), then push it into a glass of damp soil, and read the lines:
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
New Line
9600 baud
The soil is DRY => turn pump ON (3012) The soil is DRY => turn pump ON (2987) The soil is DRY => turn pump ON (2531) The soil is WET => turn pump OFF (1904) The soil is WET => turn pump OFF (1588) The soil is WET => turn pump OFF (1562) The soil is WET => turn pump OFF (1575)
Ln 11, Col 1
ESP32 Dev Module on COM15
2
  1. Pro tip: put the pump in a bucket and aim the tube back into the same bucket for the first run. You can watch many on/off cycles without flooding your table.

Video Tutorial

See the ESP32 Uno build in action in the video below.

Code Explanation

After this part, you can read each line of the sketch and change it with confidence.

Code Part What It Does
RELAY_PIN 26 and MOISTURE_PIN 2 Name the GPIOs behind D2 and A0
THRESHOLD 2120 Sets the border between dry and wet soil
analogSetAttenuation(ADC_11db) Lets the analog pin read up to about 3.3V
analogRead(MOISTURE_PIN) Gets the moisture level as a number from 0 to 4095
value > THRESHOLD Dry soil sets the relay HIGH, wet soil sets it LOW
delay(500) Waits half a second before the next check

The result is a simple loop: read, compare, switch the pump, print the state with the raw number, and repeat.

ESP32 Uno vs UNO R4 for This Project

Moving this watering project from the UNO R4 to the ESP32 Uno changes the pin numbers, the ADC scale and one setup line.

Item Arduino UNO R4 ESP32 Uno
Logic voltage 5V 3.3V
Relay pin in code 2 26 (D2 header)
Sensor pin in code A0 2 (A0 header)
ADC range 0 to 1023 0 to 4095
Threshold start value 530 2120
Extra setup line none analogSetAttenuation(ADC_11db)
Arduino IDE board Arduino UNO R4 WiFi ESP32 Dev Module

The wires go to the same header spots, so the same wiring diagram works. Just power the sensor from 3.3V instead of 5V, and calibrate again because the numbers are on a new scale.

Go Wireless: Check Your Plants from Your Phone

After this part, you have an idea for watching the soil without a USB cable.

The ESP32 Uno has WiFi and Bluetooth built in. You can send the moisture number to a phone page and see it as a live chart or a gauge. You can also add an ON/OFF button to start the pump by hand when you want extra water.

Note that A0 (GPIO2) is an ADC2 pin, and ADC2 cannot be read while WiFi is on. For a WiFi version, move the sensor AOUT to A2 to A5 or GPIO32/33 and change MOISTURE_PIN. Bluetooth does not have this limit.

Troubleshooting

Problem Possible Cause Solution
No COM port appears in Arduino IDE CH340 driver is missing or the USB cable is charge-only Install the CH340 driver and use a USB cable that carries data
Upload stops at "Failed to connect" or "Waiting for download" The board did not enter upload mode Hold the BOOT button while the upload starts
Board does not boot or upload with the sensor connected A0 is GPIO2, a boot strapping pin, and the sensor pulls it the wrong way Unplug the AOUT wire while uploading, then reconnect it
Relay clicks but no water flows The 12V adapter is off, or the pump is on the NC terminal Check the adapter and move the pump wire to NO
Pump never stops Border value is too low for your soil Print dry and wet numbers and choose a value in the middle
Pump never starts Border value is too high or the AOUT wire is loose Check the A0 (GPIO2) wire and lower THRESHOLD
Reading is stuck at 4095 Sensor runs on 5V or the attenuation line was removed Power the sensor from 3.3V and keep analogSetAttenuation(ADC_11db)
Pump turns on when the soil is wet The relay module is active LOW Swap HIGH and LOW in both digitalWrite() lines
Text in the Serial Monitor is garbled Baud rate does not match Choose 9600 baud

FAQ

How does a capacitive soil moisture sensor measure water?

It acts like a small capacitor. Wet soil changes its capacitance, and the module turns that into a voltage on AOUT. Because no metal touches the soil, it does not rust like the cheap two-prong sensors.

Which number means dry soil and which means wet soil?

With this sensor, a higher reading means drier soil. On the ESP32 Uno, dry air often reads near 3000 and wet soil near 1500, but every sensor and soil type is a bit different, so measure your own.

Is it safe to run the 12V pump from the ESP32 Uno 5V pin?

No. The pump needs 12V and much more current than the board can give. Power it from the 12V adapter and let the relay switch it. The board only drives the relay input.

Will a 5V relay module work with a 3.3V control signal?

Most relay modules with a transistor input switch fine from a 3.3V signal while the coil runs on 5V. If yours does not click, try a relay module made for 3.3V control.

Why is the border value 2120 and not 530?

The ESP32 Uno ADC is 12-bit and returns 0 to 4095, which is four times the 0 to 1023 range of the UNO R4. So 530 becomes about 2120. Still, calibrate it, since the sensor also runs on 3.3V here.

What is the analogSetAttenuation(ADC_11db) line in setup() for?

This call opens the ESP32 Uno analog input up to roughly 3.3V, and that span is spread over the numbers 0 to 4095. Leave it out and the input window gets narrow, so the number tops out long before the soil is truly dry. The UNO R4 sketch has no such line, because only this chip family needs it. Make sure the AOUT voltage never goes over 3.3V.

Can I read the sensor on A0 if I add WiFi to this project?

No. A0 (GPIO2) and A1 (GPIO4) are ADC2 pins, and ADC2 cannot be read while WiFi is on. Move the sensor to A2 to A5 (GPIO35, 34, 36, 39) or GPIO32/33 and change MOISTURE_PIN in the code.

How do I stop the relay from clicking on and off near the border value?

Use two values instead of one: start the pump above a dry value and stop it only below a lower wet value. You can also keep the pump on for a fixed time once it starts.

Can I water two plant pots with separate sensors?

Yes. Add a second sensor on another analog pin and a second relay on another digital pin, then copy the if/else block for the new pair. For the extra sensor, A2 or A3 (GPIO35, GPIO34) work well because they are input-only ADC1 pins.

Do I need a special USB driver for this board?

The ESP32 Uno uses a CH340 USB-to-serial chip. Windows often installs it by itself, but if no COM port shows up, install the CH340 driver once.

What if my project needs more pins than the Uno headers give?

The ESP32 Uno has a few extra holes near the power header: GPIO32 and GPIO33 (I/O, PWM, analog on ADC1, so they also work while WiFi is on) and GPIO15 (I/O, PWM, analog on ADC2). Solder pin headers to them and write the GPIO number in your code. For a WiFi garden with more soil sensors, GPIO32/33 are the best choice. Two warnings: GPIO15 and GPIO0 (the IO0 pin at the unused Uno NC position) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code, so use GPIO32/33 first. Never use the six holes under the digital header (SD0 to SD3, CMD, CLK = GPIO6 to GPIO11); they are wired to the flash chip and using them crashes the board.

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!