Home · Academy · Robotics & Coding · Arduino · Project: Mini Auto-Watering Prototype

Project: Mini Auto-Watering Prototype

Build a prototype that safely waters when the soil is dry, using a moisture sensor and a small pump.

PROJECT COMPASS

What will you use this page for?

Core idea

We build an Arduino prototype that uses a soil moisture sensor to measure whether the soil is dry and, when it is, runs a small pump for a short time to water the plant.

Evidence to produce

Complete the page task with your own input, test conditions and reasoning.

Control trap

Connecting the pump directly to an Arduino pin An Arduino pin can only supply a very small current. The pump draws more and can permanently damage the pin. The pump is always powered separately; the Arduino only switches it on and off through a transistor. Forgetting the common GND If the battery pack and the Arduino…

Next connection

Robotic Systems module: We begin designing larger robot systems that combine sensing, decision-making and movement.

Module sources: Python Tutorial · Arduino Learn

LevelBeginner
Age10–16
Duration45–75 min
PrerequisiteProject: Line-Following Robot Logic
ContentProject guide · 1,625 words
Last updated

One-sentence summary

We build an Arduino prototype that uses a soil moisture sensor to measure whether the soil is dry and, when it is, runs a small pump for a short time to water the plant.

Why does it matter?

Watering a plant regularly sounds easy, but it is very easy to forget when you are away on holiday or having a busy week at school. Overwatering is just as harmful as underwatering. This is where computers do their best work: patiently measuring a situation and deciding based on a rule.

This project brings together parts we learned separately in earlier lessons into a single system: measuring with a sensor, making a decision with a condition, and controlling an output (the pump). The same idea is used in real greenhouses, smart farming and home gardens. We are building a small, safe copy of it.

This content is at a beginner level, and because it combines water and electronics it must always be done together with an adult.

How does the system work?

Three-stage thinking

Almost every automation system has three stages:

  1. Measure (input): The soil moisture sensor reads how wet the soil is.
  2. Decide (process): The Arduino compares the reading with a threshold.
  3. Act (output): If the soil is dry, the pump runs briefly and delivers water.

This loop repeats again and again. An example from everyday life: a thermostat that heats a room in winter works the same way. It measures the temperature, turns on the heater if it is below the target, and turns it off once the target is reached. In our system, "temperature" becomes "soil moisture" and "heater" becomes "pump".

The moisture value and the threshold

The sensor sends the Arduino a number between 0 and 1023. With the sensor we use, the value is high when the soil is dry and low when it is wet. We decide which number counts as "dry"; this is called the threshold.

The way to find the threshold is by testing: we dip the sensor first into dry soil, then into watered soil, and read the values on the serial monitor. We pick a number in between. This is like the everyday decision "how often should laundry be washed" — there is no exact number, you adjust it by observation.

Materials and wiring

Materials list

Wiring logic

Full sketch

First, the basic version that measures, prints to the serial monitor, and runs the pump briefly if the soil is dry:

const int moisturePin = A0;   // moisture sensor
const int pumpPin = 8;        // transistor base
const int ledPin = 9;         // watering indicator
const int dryThreshold = 600; // above this value = dry
const unsigned long waterTime = 3000; // 3 seconds

void setup() {
  Serial.begin(9600);
  pinMode(pumpPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pumpPin, LOW); // pump off at start
}

The main loop measures, decides, and waters when needed:

void loop() {
  int moisture = analogRead(moisturePin);
  Serial.print("Moisture value: ");
  Serial.println(moisture);

  if (moisture > dryThreshold) {  // is the soil dry?
    digitalWrite(ledPin, HIGH);
    digitalWrite(pumpPin, HIGH);  // pump on
    delay(waterTime);             // water briefly
    digitalWrite(pumpPin, LOW);   // pump off
    digitalWrite(ledPin, LOW);
  }
  delay(5000); // wait 5 seconds, then measure again
}

The logic is simple: read, compare, water briefly if needed, wait. Keeping the waterTime value small matters for safety; the pump never stays on for a long time.

Test and verify

Project test matrix
TestConditionExpected behaviourObserved resultNext decision
NormalStandard input and complete connectionThe core task is completedFill in during testingKeep it or make a small improvement
BoundaryLowest or highest accepted valueThe system remains stableFill in during testingReview the threshold or rule
FailureMissing, incorrect or unexpected inputA safe and understandable responseFill in during testingAdd error handling
RepeatAt least three trials under the same conditionSimilar resultsFill in during testingInvestigate the source of inconsistency
  1. Before putting the pump in water, test only the sensor and the code. Open the serial monitor (Serial Monitor, 9600) and watch the values.
  2. Dip the sensor into dry soil: the value should be above the threshold. Dip it into a cup of water: the value should drop.
  3. Look at the values and adjust the dryThreshold number for your own soil.
  4. Place the pump in a cup of water, point the outlet hose into the pot, and fix the electronic parts high up and away from water.
  5. Watch a short watering, and confirm that the LED blinks and the pump stops after 3 seconds.

One bug and its fix

On my first attempt the pump ran but would not stop. The moisture value on the serial monitor stayed above the threshold. I looked for the problem step by step:

Goal: Water for 3 seconds when the soil is dry
Problem: The pump stays on all the time
Check: The sensor and pump were in the same cup of water
Reason: Water affected the electronics, corrupting the reading
Fix: Put the sensor in the pot, the pump in a separate water container

The lesson was this: if water and measurement mix, the system makes wrong decisions. The sensor should measure the soil, and the pump should draw water from a separate container.

Mini practice

Make the system a bit smarter. Right now the code cannot do anything while it runs delay(waterTime). Instead, build a non-blocking wait with millis() and require at least one minute between two waterings. That way the system will not water again before the soil has absorbed the water.

Starting idea:

unsigned long lastWatering = 0;
const unsigned long waitTime = 60000; // 60 seconds

void loop() {
  int moisture = analogRead(moisturePin);
  if (moisture > dryThreshold && millis() - lastWatering > waitTime) {
    digitalWrite(pumpPin, HIGH);
    delay(3000);                 // short watering
    digitalWrite(pumpPin, LOW);
    lastWatering = millis();     // record the time
  }
}

Extra task: count the number of waterings in a variable and print it to the serial monitor. Observe how many times a day the plant is watered.

Common mistakes

Connecting the pump directly to an Arduino pin

An Arduino pin can only supply a very small current. The pump draws more and can permanently damage the pin. The pump is always powered separately; the Arduino only switches it on and off through a transistor.

Forgetting the common GND

If the battery pack and the Arduino GND are not connected, the transistor switching will not work. The "zero point" of the two power sources must be shared.

Writing a threshold without testing

Every soil and every sensor is different. If you choose dryThreshold without looking at real readings, the system will either never water or water non-stop.

Setting a long watering time

Keeping waterTime large can overflow the pot. A short watering plus a waiting time is safer.

Safety note

Lesson summary

Check questions

  1. What are the three basic stages of an auto-watering system?
  2. With the sensor we use, is the moisture value high or low when the soil is dry?
  3. Why do we not connect the pump directly to an Arduino pin?
  4. How do we correctly set the dryThreshold value?
  5. What is the advantage of using millis() instead of delay()?

Answers

  1. Measure (input), decide (process), and act/output (run the pump).
  2. High; the value drops in wet soil. That is why the condition moisture > dryThreshold indicates dryness.
  3. The pump draws far more current than an Arduino pin can supply; it damages the pin. A separate power source and a transistor are needed.
  4. By reading the sensor in dry and wet soil on the serial monitor and picking a number between the two values — that is, by testing.
  5. millis() does not stop the program while waiting; the Arduino can keep measuring and doing other work during that time.

Source and verification note

For “Project: Mini Auto-Watering Prototype”, verification focuses on whether the relationship between How does the system work? and The moisture value and the threshold remains consistent across examples. Pin, voltage and current limits can differ between Arduino-compatible boards. Compiling code does not guarantee a safe circuit; loads such as motors and servos require a suitable driver and external power where appropriate.

Next lesson

Robotic Systems module: We begin designing larger robot systems that combine sensing, decision-making and movement.

Start QuizBack to Arduino
QUESTION POOL

Reinforce this lesson with 10 questions

This lesson has a pool of 20 questions. Each attempt selects 10 and reshuffles the choices.