Automatic Irrigation System



I developed my automatic Irrigation system using Arduino as a passion project, driven by a deep interest in sustainable living and smart technology. It was more than a technical exercise; it was an opportunity to blend innovation with environmental consciousness. I wanted a practical solution which conserves water, while also simplifying the often tedious task of plant or garden maintenance, ultimately fostering a more sustainable lifestyle. The video shows my passion project, in which i pulled the soil moisture sensor up (to decrease moisture) and the instant i did so, the pump activated, providing water until it was at a good level.
Supplies







Arduino uno r4 wifi board, relay module, soil moisture sensor, dc barrel jack male, jumper wires, water pumps with tubing, crocodile clips with usb a connected, (and a wall adapter to plug into the wall for power) (you'll also need a data transfer cable to upload the code onto the Arduino).
SMS to Arduino


First, with the Arduino, connect it to the soil moisture. connect GND - GND, VCC - 5V, and AOUT to A0. use 3 male male jumper wires.
Relay Module to Arduino


Then connect the Arduino to the relay module. (you'll need the exact kind of relay module I have because other relay modules can cause issues). Using 3 male female jumper wires connect: VCC - VIN, GND - GND, and IN to 2.
This is the most important part. You'll have to upload the following code located underneath to Arduino. You'll have to create a thing on arduino and a dashboard. On your things you'll have to associate your device by following the websites instructions. You'll have to enter your internet details, and add 2 cloud variables. Relay and sensor. for relay:
declaration - boolean - bool relay;
for sensor:
declaration - integer - int sensor;
for sensor put variable update policy on periodically and make it every 1s
Youll have to download the Arduino agent. Then, open sketch. paste the code that's on the bottom and with the data transfer cable connected to your computer and the Arduino, upload the code. the code is located under.
/*
Sketch generated by the Arduino IoT Cloud Thing "Untitled"
https://create.arduino.cc/cloud/things/1ec5753c-648f-41d5-af31-9d5e97d6b133
Arduino IoT Cloud Variables description
The following variables are automatically generated and updated when changes are made to the Thing
int sensor; // This is your moisture level percentage
bool relay; // This is your water pump switch
Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
which are called when their values are changed from the Dashboard.
These functions are generated with the Thing and added at the end of this sketch.
*/
#include "thingProperties.h"
// Pin definitions
#define relayPin 2 // Your relay module IN pin is connected to Arduino Digital Pin 2
// Calibration values for your moisture sensor (from your code)
// dry: 510 means higher analog value for dry
// wet: 210 means lower analog value for wet
#define wet 210
#define dry 510
// Define the moisture thresholds for automatic control
const int MOISTURE_THRESHOLD_ON = 40; // Turn pump ON when moisture is below 40%
const int MOISTURE_THRESHOLD_OFF = 70; // Turn pump OFF when moisture is at or above 70%
// NEW: Define pump operating modes
enum PumpMode {
AUTOMATIC,
MANUAL_OVERRIDE_ON,
MANUAL_OVERRIDE_OFF
};
// NEW: Global variable to track the current operating mode of the pump
PumpMode currentPumpMode = AUTOMATIC; // Default to automatic mode on startup
void setup() {
// Initialize serial communication for debugging
Serial.begin(9600);
// This delay gives the chance to wait for a Serial Monitor without blocking if none is found
delay(1500);
// Configure the relay pin as an output
pinMode(relayPin, OUTPUT);
// Ensure the pump is OFF initially (since your relay is active-LOW, HIGH keeps it off)
digitalWrite(relayPin, HIGH);
// Set the Cloud variable to OFF to match the initial physical state
relay = false;
// Set the initial operating mode
currentPumpMode = AUTOMATIC;
// Defined in thingProperties.h - Initializes Cloud properties
initProperties();
// Connect to Arduino IoT Cloud
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
/*
The following function allows you to obtain more information
related to the state of network and IoT Cloud connection and errors
the higher number the more granular information you’ll get.
The default is 0 (only errors).
Maximum is 4
*/
setDebugMessageLevel(2);
ArduinoCloud.printDebugInfo();
}
void loop() {
ArduinoCloud.update(); // Sync with Arduino IoT Cloud
// --- Read Moisture Sensor ---
int rawSensorValue = analogRead(A0); // Read raw value from analog pin A0
// Convert raw analog reading to a percentage (0-100)
// Your mapping: map(rawSensorValue, dry, wet, 0, 100) -> higher raw value (dry) maps to 0%, lower raw value (wet) maps to 100%
sensor = map(rawSensorValue, dry, wet, 0, 100);
// Ensure the calculated moisture level stays within the valid 0-100% range
sensor = constrain(sensor, 0, 100);
// Print sensor data to Serial Monitor for debugging
Serial.print("Raw Sensor Value: ");
Serial.print(rawSensorValue);
Serial.print(" | Moisture Level: ");
Serial.print(sensor);
Serial.print("% | Pump Mode: ");
switch (currentPumpMode) {
case AUTOMATIC:
Serial.println("AUTOMATIC");
break;
case MANUAL_OVERRIDE_ON:
Serial.println("MANUAL_ON");
break;
case MANUAL_OVERRIDE_OFF:
Serial.println("MANUAL_OFF");
break;
}
// --- Handle Manual Override and Potential Reversion ---
if (currentPumpMode == MANUAL_OVERRIDE_ON) {
// If manually ON, check if it's now wet enough to revert to automatic OFF
if (sensor >= MOISTURE_THRESHOLD_OFF) {
Serial.println("Manual ON override complete: Moisture sufficient. Reverting to auto mode.");
currentPumpMode = AUTOMATIC; // Switch to automatic mode
// CRITICAL: Exit this loop iteration immediately. Let the next loop handle the new automatic state.
delay(500); // Common delay
return; // IMPORTANT: Exit the loop() function to prevent auto logic from running.
}
} else if (currentPumpMode == MANUAL_OVERRIDE_OFF) {
// If manually OFF, check if it's now dry enough to revert to automatic ON
if (sensor < MOISTURE_THRESHOLD_ON) {
Serial.println("Manual OFF override complete: Moisture too low! Reverting to auto mode.");
currentPumpMode = AUTOMATIC; // Switch to automatic mode
// CRITICAL: Exit this loop iteration immediately. Let the next loop handle the new automatic state.
delay(500); // Common delay
return; // IMPORTANT: Exit the loop() function to prevent auto logic from running.
}
}
// If we reach this point, it means:
// 1. currentPumpMode was AUTOMATIC from the start of this loop.
// OR
// 2. currentPumpMode was MANUAL, but conditions for reversion were NOT met (so manual mode persists).
// In this case, we still need to prevent auto logic.
if (currentPumpMode != AUTOMATIC) { // Still in a manual mode (hasn't reverted this cycle)
delay(500); // Common delay
return; // IMPORTANT: Exit the loop() function to prevent auto logic from running.
}
// --- Automatic Control ---
// This block ONLY runs if currentPumpMode is AUTOMATIC at this point.
// This ensures that:
// - If it was AUTOMATIC from the start, auto logic runs.
// - If it was MANUAL and JUST reverted, the 'return' in the manual block was hit, so this block is skipped.
// - If it was MANUAL and did NOT revert, the 'return' right above was hit, so this block is skipped.
if (sensor < MOISTURE_THRESHOLD_ON && relay == false) {
Serial.println("Auto mode: Moisture too low! Turning pump ON.");
digitalWrite(relayPin, LOW); // Turn pump ON
relay = true; // Update Cloud variable to reflect automatic ON
} else if (sensor >= MOISTURE_THRESHOLD_OFF && relay == true) {
Serial.println("Auto mode: Moisture sufficient. Turning pump OFF.");
digitalWrite(relayPin, HIGH); // Turn pump OFF
relay = false; // Update Cloud variable to reflect automatic OFF
}
// Only one delay at the very end if auto logic ran
delay(500);
}
// This function is automatically called by the Arduino IoT Cloud when the 'relay' variable
// is changed from the Dashboard.
void onRelayChange() {
// The 'relay' variable already holds the new state (ON/OFF) from the dashboard.
Serial.print("Manual command received. Water pump state set to: ");
Serial.println(relay ? "ON" : "OFF");
// Apply the manual command directly to the physical relay
if (relay) { // If the dashboard switch is now ON
digitalWrite(relayPin, LOW); // Turn physical pump ON (assuming active-LOW relay)
currentPumpMode = MANUAL_OVERRIDE_ON; // Set mode to manual ON
} else { // If the dashboard switch is now OFF
digitalWrite(relayPin, HIGH); // Turn physical pump OFF
currentPumpMode = MANUAL_OVERRIDE_OFF; // Set mode to manual OFF
}
Serial.println("Manual control mode activated.");
Serial.println("Automatic watering will be suspended until soil conditions revert to auto.");
}
// This function is automatically called by the Arduino IoT Cloud when the 'sensor' variable
// is changed from the Dashboard.
// We are leaving this function empty because the sensor is a read-only input
// for this project, and its value is updated from the device to the cloud,
// not the other way around.
void onSensorChange() {
// Add your code here to act upon Sensor change
// The functionality to read the sensor is handled in loop()
}




after uploading the code we can finish adding the rest of the parts. On the other side of the relay module, youll have to use a screwdriver to open the NO and COM terminals. put the DC barrel male jack into the arduino, and put the red wire of the pump into the NO terminal of the relay module. with the black wire of the pump you'll have to twist the copper wiring around the black wire of the DC barrel jack.
As for the COM section of the relay module, you'll have to put a jumper wire into the terminal, and break off the other side leaving the copper wire exposed. With that copper wire, twirl it around the red wire of the DC barrel jack. Then. connect the crocodile clips to a WALL ADAPTER. DO NOT PLUG THE CROCODILE CLIPS DIRECTLY TO THE WALL - USE A WALL ADAPTER AND CONNECT THE USB END OF IT TO THE WALL ADAPTER AND PLUG IT IN THE WALL. Then, clip the black crocodile clip onto the black wire of the DC barrel jack and clip the red crocodile clip onto the red wire of the DC barrel jack. Plug it in the wall and everything should work.
By the way, I personally extended the water pumps wiring. Using a jumper wire, carefully break off the ends and leave the copper wiring exposed. However for the red water pump, you'll only want to break off one end, and put the plastic part into the no as previously stated. This is not required, but it is helpful.
Open Arduino cloud and create a dashboard. Create a percentage widget and connect it to the sensor, and if you want you can add a graph widget and connect it to the sensor. Test out the sensor to see if it works, when moisture is less then 40 it should turn on by itself and when its over 70 it should stop.