Automatic Plant Watering System with PIR Sensor

Project Overview

This project creates a smart plant watering system that reminds you to water your plants when motion is detected nearby, or automatically waters based on soil moisture. It’s perfect for indoor plants that are easily forgotten.

Difficulty: Beginner/Intermediate
Estimated time: 2-3 hours
Estimated cost: $20-30

How It Works

A PIR sensor detects when someone approaches the plant. When motion is detected, a soil moisture sensor checks if watering is needed. If the soil is dry, a water pump is activated for a set duration. An LCD or LED indicates the plant’s status. Optionally, the system can water automatically on a schedule regardless of motion.

Materials Needed

  • Arduino Uno or ESP32 (1)
  • HC-SR501 PIR sensor (1)
  • Soil moisture sensor (capacitive type recommended)
  • Submersible water pump (5V, small)
  • MOSFET or relay module (to control pump)
  • Water reservoir (container for water)
  • Plastic tubing (for water delivery)
  • LCD 16×2 with I2C (optional)
  • Buzzer (for reminder alerts, optional)
  • LED (for status indication)
  • Resistors (220Ω, 10k)
  • Jumper wires
  • Power supply (5V 2A)

Circuit Diagram

Connection Table

Component Pin Arduino Pin
PIR Sensor VCC 5V
PIR Sensor GND GND
PIR Sensor OUT Digital Pin 2
Soil Moisture Sensor VCC 5V
Soil Moisture Sensor GND GND
Soil Moisture Sensor AO (analog) Analog Pin A0
Relay Module VCC 5V
Relay Module GND GND
Relay Module IN Digital Pin 3
LCD (I2C) VCC 5V
LCD (I2C) GND GND
LCD (I2C) SDA A4 (SDA)
LCD (I2C) SCL A5 (SCL)
Buzzer Positive Digital Pin 8
Buzzer Negative GND
Status LED Anode Digital Pin 13 (through 220Ω)
Status LED Cathode GND

Arduino Code

// Automatic Plant Watering with PIR
// Waters plants when motion detected and soil is dry

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

const int pirPin = 2;
const int pumpPin = 3;
const int moisturePin = A0;
const int buzzerPin = 8;
const int ledPin = 13;

// Thresholds
const int dryThreshold = 500;   // Soil dry below this value (adjust based on sensor)
const int wetThreshold = 800;    // Soil wet above this value

// Timing
unsigned long lastMotionTime = 0;
const unsigned long cooldownPeriod = 3600000; // 1 hour between waterings
bool wateredRecently = false;

void setup() {
  Serial.begin(9600);
  
  pinMode(pirPin, INPUT);
  pinMode(pumpPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  
  digitalWrite(pumpPin, LOW);
  digitalWrite(ledPin, LOW);
  
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Plant Watering");
  lcd.setCursor(0, 1);
  lcd.print("System Ready");
  
  Serial.println("Plant Watering System Ready");
  delay(2000);
  
  Serial.println("Waiting 60 seconds for PIR warm-up...");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("PIR warm-up...");
  lcd.setCursor(0, 1);
  lcd.print("60 seconds");
  delay(60000);
}

int readMoisture() {
  int value = analogRead(moisturePin);
  Serial.print("Soil moisture: ");
  Serial.println(value);
  return value;
}

bool needsWater() {
  int moisture = readMoisture();
  return moisture < dryThreshold;
}

void waterPlant() {
  Serial.println("Watering plant...");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Watering...");
  
  // Beep before watering
  digitalWrite(buzzerPin, HIGH);
  delay(200);
  digitalWrite(buzzerPin, LOW);
  
  // Turn on pump
  digitalWrite(pumpPin, HIGH);
  digitalWrite(ledPin, HIGH);
  
  // Water for 5 seconds (adjust based on your setup)
  delay(5000);
  
  // Turn off pump
  digitalWrite(pumpPin, LOW);
  digitalWrite(ledPin, LOW);
  
  // Beep after watering
  digitalWrite(buzzerPin, HIGH);
  delay(200);
  digitalWrite(buzzerPin, LOW);
  delay(200);
  digitalWrite(buzzerPin, HIGH);
  delay(200);
  digitalWrite(buzzerPin, LOW);
  
  wateredRecently = true;
  lastMotionTime = millis();
  
  Serial.println("Watering complete");
}

void checkAndWater() {
  if (needsWater()) {
    if (!wateredRecently || (millis() - lastMotionTime > cooldownPeriod)) {
      waterPlant();
    } else {
      Serial.println("Plant needs water but cooldown active");
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Needs water!");
      lcd.setCursor(0, 1);
      lcd.print("Cooldown active");
      // Brief beep as reminder
      digitalWrite(buzzerPin, HIGH);
      delay(100);
      digitalWrite(buzzerPin, LOW);
      delay(100);
    }
  } else {
    Serial.println("Soil moisture OK");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Soil Moisture OK");
    lcd.setCursor(0, 1);
    lcd.print("Plant is happy!");
  }
}

void displayStatus() {
  int moisture = readMoisture();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Moisture: ");
  lcd.print(moisture);
  lcd.setCursor(0, 1);
  if (moisture < dryThreshold) {
    lcd.print("DRY - Water soon!");
  } else if (moisture < wetThreshold) {
    lcd.print("OK");
  } else {
    lcd.print("WET");
  }
}

void loop() {
  bool motionDetected = digitalRead(pirPin) == HIGH;
  
  if (motionDetected) {
    Serial.println("Motion detected");
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    
    checkAndWater();
  } else {
    // Optional: display status periodically even without motion
    static unsigned long lastDisplay = 0;
    if (millis() - lastDisplay > 10000) { // Every 10 seconds
      displayStatus();
      lastDisplay = millis();
    }
  }
  
  delay(100);
}

Soil Moisture Sensor Calibration

  1. Insert sensor into dry soil and note the analog reading (usually 300-500).
  2. Water the plant thoroughly and note reading when soil is fully saturated (usually 800-1000).
  3. Set dryThreshold to about 100-200 points above the dry reading (e.g., if dry reading is 300, set threshold to 500).
  4. Set wetThreshold to the saturated reading minus 100-200.

Water Pump Assembly

  1. Place the submersible pump in the water reservoir.
  2. Connect tubing from pump outlet to plant soil.
  3. Secure tubing near plant base.
  4. Ensure reservoir has enough water for multiple watering cycles.
  5. Consider adding a water level sensor to detect when reservoir is empty.

Installation Steps

  1. Assemble electronics: Build circuit on breadboard and test.
  2. Calibrate soil sensor: Test in dry and wet soil to set thresholds.
  3. Test pump: Verify pump moves water properly.
  4. Place sensors: Insert soil moisture sensor into plant pot, mount PIR sensor to detect approach.
  5. Mount Arduino: Place Arduino and power supply in safe location away from water.
  6. Final test: Trigger PIR and verify watering occurs when soil is dry.

Project Extensions

  • Water level sensor: Add float switch or ultrasonic sensor to detect when reservoir is low and alert you.
  • Multiple plants: Add additional soil sensors and solenoid valves for multi-plant watering.
  • Wi-Fi monitoring: Use ESP32 to send soil moisture data to phone.
  • Rain sensor: Add rain sensor for outdoor plants to prevent watering in rain.
  • Temperature sensor: Adjust watering schedule based on temperature.
  • Fertilizer dosing: Add second pump for liquid fertilizer.

Troubleshooting

  • Pump not running: Check relay wiring. Ensure power supply can handle pump current (pumps can draw 200-500mA).
  • Inaccurate soil readings: Capacitive sensors are more reliable than resistive types (resistive sensors corrode over time).
  • PIR false triggers: Adjust sensitivity or position away from windows and heat sources.
  • Water not reaching plant: Check tubing for kinks. Ensure pump is fully submerged.

Conclusion

This smart plant watering system takes the guesswork out of plant care. It reminds you to water when you’re near the plant and only waters when needed, preventing both under-watering and over-watering.

Leave a Reply

Your email address will not be published. Required fields are marked *