Introduction
Build a smart irrigation system using soil moisture sensors, RTC scheduling, and IoT monitoring to optimize water usage. This comprehensive guide covers everything from design through implementation, testing, and deployment.
Build a smart irrigation system using soil moisture sensors, RTC scheduling, and IoT monitoring to optimize water usage.
Build a smart irrigation system using soil moisture sensors, RTC scheduling, and IoT monitoring to optimize water usage. This comprehensive guide covers everything from design through implementation, testing, and deployment.
Capacitive soil moisture sensors measure soil dielectric constant, which changes with water content. They output an analog voltage: dry soil ~3.0V, saturated soil ~1.5V (values vary by sensor). Calibrate each sensor: read value in completely dry soil (ADC value = Dry_Val), then in water (ADC value = Wet_Val). Convert: moisture% = map(analogRead(A0), Wet_Val, Dry_Val, 100, 0). Install sensors 15cm deep in the root zone of each irrigation zone.
10 components required for this project.
| # | Component | Purpose | Qty |
|---|---|---|---|
| 1 | Arduino Uno | Main controller | x1 |
| 2 | Capacitive Soil Moisture Sensor (v1.2) | Soil moisture level measurement | x4 |
| 3 | 5V Solenoid Valve (1/2" NPT) | Controlling water flow per zone | x4 |
| 4 | DS3231 RTC Module | Time-based watering schedule | x1 |
| 5 | DHT22 Temperature & Humidity Sensor | Weather-based irrigation adjustment | x1 |
| 6 | ESP8266 NodeMCU | IoT monitoring and remote control | x1 |
| 7 | 16x2 LCD with I2C | Local status display | x1 |
| 8 | 12V 2A Power Supply | System and solenoid power | x1 |
| 9 | IRF540N MOSFET | Solenoid valve driver | x4 |
| 10 | Rain Sensor Module | Skip irrigation when raining | x1 |
Follow these 7 steps carefully.
Capacitive soil moisture sensors measure soil dielectric constant, which changes with water content. They output an analog voltage: dry soil ~3.0V, saturated soil ~1.5V (values vary by sensor). Calibrate each sensor: read value in completely dry soil (ADC value = Dry_Val), then in water (ADC value = Wet_Val). Convert: moisture% = map(analogRead(A0), Wet_Val, Dry_Val, 100, 0). Install sensors 15cm deep in the root zone of each irrigation zone.
Solenoid valves draw 200–500mA at 12V — too much for direct Arduino output. Use IRF540N N-channel MOSFET: connect Gate to Arduino digital pin via 220Ω resistor, Source to GND, Drain to solenoid negative terminal. Connect solenoid positive to 12V. Add 1N4007 flyback diode across solenoid terminals (cathode to 12V) to protect MOSFET from back-EMF spike when valve closes. Test: digitalWrite(pin, HIGH) opens valve.
Program multiple watering schedules using DS3231 RTC: Zone 1 (lawn) — daily 6:00 AM, 15 minutes; Zone 2 (garden beds) — Monday/Thursday 7:00 AM, 20 minutes; Zone 3 (pots) — daily 8:00 AM, 5 minutes. Check RTC time each second. Implement season adjustment: multiply watering duration by 0.7 in winter, 1.3 in summer based on month. Skip scheduled watering if soil moisture > 60%.
Connect rain sensor digital output to Arduino input. When rain detected, set a rain_flag. Skip all scheduled irrigation when rain_flag is true. Reset rain_flag when rain sensor reads dry AND soil moisture has had time to equilibrate (wait 2 hours after rain stops before resuming automated schedule). Optionally use weather API via ESP8266: if rain forecasted in next 12 hours, skip morning irrigation.
Program ESP8266 to receive sensor data from Arduino via serial and publish to Blynk or ThingSpeak. Create Blynk dashboard with: 4 moisture gauges (one per zone), manual override buttons for each solenoid, schedule display showing next watering time, temperature/humidity display, rain status indicator, and water volume used today (estimate from valve open time × flow rate). Enable push notifications for watering start/end.
Add a YF-S201 water flow sensor (a hall-effect flow meter) inline with the main supply. It generates 7.5 pulses per liter. Count pulses during each irrigation event: volume_L = pulse_count / 7.5. Log daily/weekly/monthly water usage to ESP8266 flash or cloud. Display water savings compared to fixed-schedule irrigation (typically 30–50% reduction). Calculate water cost savings at your local tariff.
Program multiple fail-safes: maximum single zone runtime (30 minutes regardless of schedule — prevents flooding due to stuck-open solenoid), maximum daily runtime per zone (1 hour), watchdog timer to reset Arduino if program hangs, low-moisture emergency flag (moisture < 20% for critical plants), high-moisture alert (>90% for > 6 hours indicates drainage problem). Log all events to EEPROM with timestamps.
Core code for irrigation.ino:
#include <RTClib.h> RTC_DS3231 rtc; #define ZONES 4 int moisturePins[] = {A0, A1, A2, A3}; int valvePins[] = {4, 5, 6, 7}; int moisture[ZONES]; int schedule[][4] = {{6,0,0,15},{6,0,1,20},{7,0,2,10},{7,0,3,5}}; void readMoisture() { for(int i=0; i<ZONES; i++) { int raw = analogRead(moisturePins[i]); moisture[i] = map(raw, 600, 300, 0, 100); moisture[i] = constrain(moisture[i], 0, 100); } } void runZone(int zone, int minutes) { if(moisture[zone] > 70) { Serial.println("Skip - soil wet"); return; } if(digitalRead(2) == LOW) { Serial.println("Skip - raining"); return; } digitalWrite(valvePins[zone], HIGH); unsigned long start = millis(); while(millis() - start < (unsigned long)minutes * 60000) { if(millis() - start > 1800000) break; } digitalWrite(valvePins[zone], LOW); } void loop() { DateTime now = rtc.now(); readMoisture(); for(auto& s : schedule) { if(now.hour()==s[0] && now.minute()==s[1] && now.second()==0) runZone(s[2], s[3]); } delay(1000); }
Test Automatic Irrigation Controller by verifying each subsystem individually before full integration.
Verify power voltages, check ground connections, use serial monitor for debug.
An interactive simulator will be available here — simulate circuits and run code in-browser without hardware.