Digital ChallengeArduino × Processing
P5Project module

Automatic Irrigation System

A plant that waters itself — sensing, deciding and acting.

Measure soil moisture with a capacitive sensor, switch a water pump through a relay, and combine both into a closed-loop automatic irrigation system with a live Processing dashboard.

4 × 45 min difficultyPhysicsBiologyEnvironmental ScienceComputer Science
Automatic Irrigation System
RelaysThreshold logicHysteresisClosed-loop controlTwo-way serial
01Before you start

What you’ll learn

By the end of this module you can…
  • 1Explain how a capacitive soil moisture sensor works and why it does not corrode.
  • 2Explain what a relay is and why it is needed to switch a pump.
  • 3Use threshold logic to make automatic decisions in code.
  • 4Control an actuator manually from Processing and automatically from Arduino.
  • 5Improve a control system with hysteresis to prevent rapid on/off switching.
Key vocabulary
Capacitive sensor
Measures how well the soil stores electric charge (permittivity) — water changes this a lot.
Permittivity
How strongly a material responds to an electric field. Water ≈ 80, dry soil ≈ 4.
Relay
An electrically operated switch: a small signal from Arduino switches a separate, more powerful circuit.
Active-LOW
A module that switches ON when its input is LOW (common for relay boards).
Threshold
A limit value at which the system changes its decision.
Hysteresis
Using two thresholds (switch on at one, off at another) so the system does not flicker.
Closed loop
A system that measures the result of its own action and corrects itself.
02Kit list

Required equipment

ComponentQtyPurpose
Arduino Uno1Microcontroller
Capacitive soil moisture sensor v1.21Soil moisture measurement
Relay module (5 V)1Pump switching
Small submersible water pump (3–6 V)1Watering
Battery box / external supply matching the pump1Power for the pump
Silicone hose (50 cm)1Water delivery
Breadboard + jumper wires1 setComponent connection
USB cable + Processing IDE1Connection & visualization
03Theory

Theoretical Background

Components: pump, hose, relay, capacitive sensor, battery box, wires.
Components: pump, hose, relay, capacitive sensor, battery box, wires.

How does the soil moisture sensor work?

The capacitive sensor outputs an analog voltage that decreases as moisture increases. Dry soil → high value (~1023 in air, ~600+ in dry soil). Wet soil → low value (~300). Its electrodes are covered, so unlike resistive sensors it does not corrode over time.

Physics
Wet soil has a much higher permittivity than dry soil. This changes the capacitance of the sensor and therefore its output voltage.

The relay module

A relay is an electrically operated switch. A tiny 5 V signal from Arduino controls a separate pump circuit that would be too powerful for an Arduino pin. Many relay boards are active-LOW: input LOW → switch closes → pump ON; input HIGH → pump OFF. Always check your module!

Water + electricity safety
Use only low-voltage batteries or adapters (≤ 12 V). Never connect anything to mains (230 V). Keep the Arduino, breadboard and laptop away from the water container, and dry your hands before touching the circuit. Wipe up spills immediately.
InteractiveIrrigation simulatorRun the system virtually: watch the soil dry out and the controller react.
PUMP OFF
wet ≈ 300
dry ≈ 900
Switch to hysteresis to add a “dead band” and stop the relay from chattering.
analogRead(A0)
520
Moisture
62%
Relay switches
0
Water used
0.00L

Compare the relay switch count with and without hysteresis — fewer switches means less wear on relay and pump.

04Hands-on

Exercise 1 — Data Acquisition & Visualization

Soil sensor wiring.
Soil sensor wiring.
Sensor pinConnects to
VCC3.3V or 5V
GNDGND
AOUTArduino A0
SoilMoisture.inoArduino · C++
const int sensorPin = A0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int moisture = analogRead(sensorPin);   // ~300 (wet) … ~1023 (dry)
  Serial.println(moisture);
  delay(300);
}
SoilDisplay.pde — text + barProcessing · Java
import processing.serial.*;

Serial myPort;
int moisture = 0;

void setup() {
  size(400, 200);
  myPort = new Serial(this, Serial.list()[0], 9600);
  myPort.bufferUntil('\n');
}

void draw() {
  background(255);
  fill(0);
  textSize(20);
  text("Soil Moisture: " + moisture, 50, 60);

  fill(0, 100, 255);                         // full bar = wet
  float w = map(moisture, 1023, 300, 0, 300); // reversed range: low value = wet
  rect(50, 100, constrain(w, 0, 300), 30);    // adjust 300/1023 after calibration
}

void serialEvent(Serial p) {
  String val = p.readStringUntil('\n');
  if (val != null) {
    val = trim(val);
    if (val.matches("\\d+")) moisture = int(val);
  }
}
05Hands-on

Exercise 2 — Control the Water Pump from Processing

Relay and pump wiring with an external battery pack.
Relay and pump wiring with an external battery pack.
ConnectionDescription
Relay INArduino D8
Relay VCCArduino 5V
Relay GNDArduino GND
Relay COM+ terminal of external power supply
Relay NOPump (+) terminal
Pump (−) terminalPower supply GND
PumpControl.inoArduino · C++
const int RELAY_PIN = 8;
const int PUMP_ON  = LOW;    // active-LOW relay module
const int PUMP_OFF = HIGH;   // swap these if your module is active-HIGH

void setup() {
  Serial.begin(9600);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, PUMP_OFF);   // make sure the pump starts OFF
}

void loop() {
  if (Serial.available() > 0) {
    char cmd = Serial.read();
    if (cmd == '1')      digitalWrite(RELAY_PIN, PUMP_ON);
    else if (cmd == '0') digitalWrite(RELAY_PIN, PUMP_OFF);
    // any other character (e.g. newline) is ignored
  }
}
UpdatedThe original used pin 9 while the wiring table uses D8. Now consistently D8, with named ON/OFF constants.
PumpKeys.pdeProcessing · Java
import processing.serial.*;

Serial myPort;

void setup() {
  size(360, 100);
  myPort = new Serial(this, Serial.list()[0], 9600);
}

void draw() {
  background(200);
  fill(0);
  text("Press '1' to turn ON pump, '0' to turn OFF", 20, 50);
}

void keyPressed() {
  if (key == '1' || key == '0') myPort.write(key);
}
06Project

Exercise 3 — Full Automatic Irrigation System

Level up
This exercise is suitable as a complete project. Goal: combine sensing and pump control so watering happens automatically when the soil is too dry, with a real-time Processing display.
Complete system: soil sensor on A0, relay on D8, pump on the external supply.
Complete system: soil sensor on A0, relay on D8, pump on the external supply.
AutoIrrigation.inoArduino · C++
#define RELAY_PIN  8
#define SENSOR_PIN A0
#define THRESHOLD  600       // above = too dry

const int PUMP_ON  = LOW;    // active-LOW relay
const int PUMP_OFF = HIGH;

void setup() {
  Serial.begin(9600);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, PUMP_OFF);
}

void loop() {
  int moisture = analogRead(SENSOR_PIN);
  Serial.println(moisture);

  if (moisture > THRESHOLD) digitalWrite(RELAY_PIN, PUMP_ON);   // dry → water
  else                      digitalWrite(RELAY_PIN, PUMP_OFF);  // wet → stop
  delay(1000);
}
UpdatedUses the same active-LOW constants as Exercise 2 — the original switched the relay the opposite way.
IrrigationStatus.pdeProcessing · Java
import processing.serial.*;

Serial myPort;
int moisture = 0;

void setup() {
  size(400, 200);
  myPort = new Serial(this, Serial.list()[0], 9600);
  myPort.bufferUntil('\n');
}

void draw() {
  background(255);
  fill(0);
  textSize(20);
  text("Soil Moisture: " + moisture, 50, 100);

  if (moisture > 600) {
    fill(255, 0, 0);
    text("Status: DRY \u2013 Watering", 50, 140);
  } else {
    fill(0, 150, 0);
    text("Status: WET \u2013 Idle", 50, 140);
  }
}

void serialEvent(Serial p) {
  String val = p.readStringUntil('\n');
  if (val != null && trim(val).matches("\\d+")) moisture = int(trim(val));
}
07From the original handbook

Student tasks

Basic
Display the moisture value and status text
Intermediate
Colour-coded moisture bar (blue = wet, red = dry)
Advanced
Add a manual pump override button in Processing
Challenge
Log moisture data with timestamps to a CSV file
08When it doesn’t work

Troubleshooting

ProblemLikely causeFix
Pump does not turn onRelay wiring incorrect or pin mismatchRelay IN must match RELAY_PIN (8). Listen for the relay “click”.
Pump is ON when it should be OFFRelay is active-HIGH, not active-LOWSwap the PUMP_ON / PUMP_OFF constants.
Sensor always reads maxSensor not in soil or damagedInsert up to the line; never submerge the electronics.
Pump runs continuouslyThreshold too low for your soilCalibrate: measure dry and wet values and choose a threshold between them.
Relay clicks on/off rapidlyValue hovers around the thresholdAdd hysteresis (exercise P5.4).
Processing shows no dataWrong COM port or baud rateprintArray(Serial.list()) and use 9600 on both sides.
Golden rule
Check the physical connections first, then the code. If nothing works, unplug, close both programs, reconnect and try again.
09New in this edition

Exercises

Basic · 2Intermediate · 1Advanced · 2Challenge · 1
P5.1BasicCalculate 10 min

Calibrate to percent

Your sensor reads 820 in dry soil and 340 in freshly watered soil. Convert a reading of 580 into a moisture percentage (0 % = dry, 100 % = wet). Write the Processing map() call.

(820 − 580) / (820 − 340) × 100 = 240 / 480 × 100 = 50 %. In code: float pct = constrain(map(moisture, 820, 340, 0, 100), 0, 100);
P5.2BasicExplain 5 min

Why a relay?

An Arduino pin can supply about 20 mA at 5 V. A small pump needs about 200 mA. Explain why we can’t connect the pump directly to a pin, and what the relay does instead.

The pump needs ~10× more current than the pin can safely give — it could damage the Arduino. The relay lets the weak Arduino signal switch a separate, stronger power supply, while the two circuits stay electrically separated.
P5.3IntermediateCode 20 min

Manual override button

Add an on-screen WATER NOW button to the Processing dashboard that sends 1 while held and 0 when released. Show the pump state with an icon or colour.

Use mousePressed() and mouseReleased(); check the mouse is inside the button rectangle.
solutionProcessing · Java
boolean pumping = false;

// in draw():
fill(pumping ? color(61, 155, 255) : color(180));
rect(50, 160, 140, 30, 6);
fill(255);
text("WATER NOW", 65, 182);

void mousePressed() {
  if (mouseX > 50 && mouseX < 190 && mouseY > 160 && mouseY < 190) {
    myPort.write('1');
    pumping = true;
  }
}

void mouseReleased() {
  if (pumping) {
    myPort.write('0');
    pumping = false;
  }
}
P5.4AdvancedCode 20 min

Add hysteresis

With a single threshold the relay can click on and off every second when the value hovers around 600. Change the Arduino code so the pump turns ON above 650 and only turns OFF below 450. Explain why this is better for the pump and the plant.

Between 450 and 650 the system keeps its previous state, so it doesn’t flicker. This reduces wear on the relay and pump, and waters the plant thoroughly instead of in tiny bursts. A home thermostat works the same way.
Hysteresis.ino (loop)Arduino · C++
const int DRY_ON  = 650;
const int WET_OFF = 450;
bool pumpOn = false;

void loop() {
  int moisture = analogRead(SENSOR_PIN);
  Serial.println(moisture);

  if (!pumpOn && moisture > DRY_ON)  pumpOn = true;
  if (pumpOn  && moisture < WET_OFF) pumpOn = false;

  digitalWrite(RELAY_PIN, pumpOn ? PUMP_ON : PUMP_OFF);
  delay(1000);
}
P5.5AdvancedDebug 10 min

The thirsty pump

A team’s pump runs all the time, even in wet soil, and stops only when the soil is dry. Their code is the original Exercise 3 with HIGH = water ON. What is wrong, and how do you prove it with a single test?

Their relay is active-LOW, so HIGH actually switches the pump OFF and LOW switches it ON — the logic is inverted. Test: upload a sketch that only does digitalWrite(8, HIGH) and listen/look: if the pump is off, the module is active-LOW. Fix by swapping the constants.
P5.6ChallengeDesign 60 min

Water-saving study

Run two identical plants for one week: one watered by hand daily, one by your automatic system. Measure the water used (fill the reservoir to a mark, measure refills) and log moisture. Present which method uses less water and keeps moisture more stable.

  1. 01Define fair-test conditions (same plant, pot, soil, location).
  2. 02Log moisture every 10 minutes to CSV.
  3. 03Record water volume used per day.
  4. 04Present a chart and a conclusion with numbers.
Open-ended. Strong reports discuss variables controlled, show a moisture-vs-time chart for both plants, compare total water (ml), and reflect on threshold choice, evaporation and sensor placement.
10Check yourself

Self-check quiz

Progress
0/5 answered · 0 correct
  1. Q01

    As soil gets wetter, the capacitive sensor’s value…

  2. Q02

    What is the main job of the relay?

  3. Q03

    An active-LOW relay module turns ON when its input is…

  4. Q04

    What problem does hysteresis solve?

  5. Q05

    Which is the safest power choice for the pump in a classroom?

11Beyond the classroom

Real world & extensions

Where this is used
smart gardens and home automationprecision agriculture and farminggreenhouse climate controlurban farming and vertical gardensIoT environmental monitoringsoil and plant research stationswater-saving systems in dry regions
Extension ideas
  • +OLED display showing moisture on the device (I²C)
  • +Send data over WiFi with ESP8266 / ESP32
  • +Web dashboard to monitor soil moisture remotely
  • +Cloud logging (ThingSpeak, Blynk)
  • +Multi-zone irrigation for several plants
  • +Real-time moisture graph in Processing
  • +Weather API: skip watering when rain is forecast
  • +Battery + solar panel for an off-grid system
Cross-curricular connections
SubjectConnection
PhysicsCapacitance, analog voltage, circuits, relay switching
Biology & EcologyPlant biology, soil composition, the water cycle
Computer ScienceControl loops, state, serial communication
Technology & EngineeringSensor integration, actuator control
MathematicsScaling, thresholds, interpreting graphs
Environmental ScienceWater conservation, sustainable agriculture, climate
12Think about it

Reflection & conclusion

?1

Your system is a “closed loop”. Find two other closed-loop systems in everyday life.

?2

What could go wrong if the sensor fails while the pump is ON? How could you design a safety timeout?

?3

How could automatic irrigation help farmers in regions affected by drought?

Conclusion

You built a practical automatic system that senses, decides and acts. Combining a soil moisture sensor, a relay and Processing, you gained hands-on experience in electronics, programming and environmental monitoring — the same principles behind smart greenhouses and precision agriculture that help conserve water worldwide.