ESP8266 NodeMCU Automated Soil Moisture Monitoring and Watering System
View and Edit Project In Cirkit Designer
Circuit Documentation
Summary
This circuit is designed to monitor and control the watering of soil using a NodeMCU V3 ESP8266 microcontroller. It includes two soil moisture sensors to measure the moisture level of the soil at different depths, an HC-SR04 ultrasonic sensor to monitor the water level in a reservoir, and a water pump to irrigate the soil when necessary. The system is powered by a 5V battery and is capable of activating an alarm if the water level is too low.
Component List
NodeMCU V3 ESP8266
- Description: A WiFi-enabled microcontroller based on the ESP8266 chip.
- Pins: A0, GND, VU, S3, S2, S1, SC, S0, SK, 3V3, EN, RST, Vin, D0, D1, D2, D3, D4, D5, D6, D7, D8, RX, TX
Soil Moisture Sensor (x2)
- Description: A sensor that measures the volumetric water content of the soil.
- Pins: VCC, GND, SIG
HC-SR04 Ultrasonic Sensor
- Description: A sensor that uses ultrasonic sound waves to measure distance.
- Pins: VCC, TRIG, ECHO, GND
5V Battery
- Description: A power source for the circuit.
- Pins: Positive, Negative
Water Pump
- Description: A pump used for moving water to irrigate the soil.
- Pins: VCC, GND
Wiring Details
NodeMCU V3 ESP8266
- A0: Connected to Soil Moisture Sensor SIG pins
- GND: Common ground with Soil Moisture Sensors, HC-SR04 Ultrasonic Sensor, Water Pump, and 5V Battery Negative
- Vin: Connected to 5V Battery Positive
- D1: Connected to Soil Moisture Sensor VCC
- D2: Connected to Soil Moisture Sensor VCC
- D5: Connected to HC-SR04 Ultrasonic Sensor TRIG
- D6: Connected to HC-SR04 Ultrasonic Sensor ECHO
- D7: Connected to Water Pump VCC
- 3V3: Connected to HC-SR04 Ultrasonic Sensor VCC
Soil Moisture Sensor
- VCC: Connected to NodeMCU V3 ESP8266 D1 or D2
- GND: Common ground with NodeMCU V3 ESP8266 and other components
- SIG: Connected to NodeMCU V3 ESP8266 A0
HC-SR04 Ultrasonic Sensor
- VCC: Connected to NodeMCU V3 ESP8266 3V3
- TRIG: Connected to NodeMCU V3 ESP8266 D5
- ECHO: Connected to NodeMCU V3 ESP8266 D6
- GND: Common ground with NodeMCU V3 ESP8266 and other components
5V Battery
- Positive: Connected to NodeMCU V3 ESP8266 Vin
- Negative: Common ground with NodeMCU V3 ESP8266 and other components
Water Pump
- VCC: Connected to NodeMCU V3 ESP8266 D7
- GND: Common ground with NodeMCU V3 ESP8266 and other components
Documented Code
// Soil Moisture Sensor Pins and Variables
#define topSoilVcc D1 // GPIO pin to power the top soil sensor
#define bottomSoilVcc D2 // GPIO pin to power the bottom soil sensor
#define soilMoisturePin A0 // Analog pin to read moisture level (shared by both sensors)
int topMoistureValue; // Store moisture sensor value for the top soil
int bottomMoistureValue; // Store moisture sensor value for the bottom soil
int moistureThreshold = 300; // Threshold value for soil moisture
// Ultrasonic Sensor Pins and Variables
#define trigPin D5 // Trig pin of Ultrasonic Sensor
#define echoPin D6 // Echo pin of Ultrasonic Sensor
long duration;
int distance;
int waterLevelThreshold = 20; // Set threshold for low water level in cm
// Water Pump Pin
#define pumpRelay D7 // Relay module controlling the pump
// Alarm Pin (Buzzer or LED for low water alert)
#define alarmPin D8 // Alarm pin for low water level
// Timing Variables
unsigned long previousMillis = 0; // Store the last time sensor was checked
const long interval = 10800000; // 3 hours interval in milliseconds (10800000)
// Total Water Used Calculation
int pumpIterations = 0; // Number of times the pump has been activated
void setup() {
Serial.begin(9600);
// Pin modes
pinMode(pumpRelay, OUTPUT);
digitalWrite(pumpRelay, LOW); // Ensure pump is initially off
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(alarmPin, OUTPUT);
digitalWrite(alarmPin, LOW); // Ensure alarm is initially off
// Set soil sensor VCC control pins as outputs
pinMode(topSoilVcc, OUTPUT);
pinMode(bottomSoilVcc, OUTPUT);
// Ensure both sensors are initially off
digitalWrite(topSoilVcc, LOW);
digitalWrite(bottomSoilVcc, LOW);
}
// Function to read top soil moisture level
int readTopSoilMoisture() {
digitalWrite(bottomSoilVcc, LOW); // Ensure bottom sensor is off
digitalWrite(topSoilVcc, HIGH); // Power the top soil sensor
delay(500); // Give time for sensor to stabilize
int value = analogRead(soilMoisturePin); // Read the value from analog pin
digitalWrite(topSoilVcc, LOW); // Turn off the top soil sensor
return value;
}
// Function to read bottom soil moisture level
int readBottomSoilMoisture() {
digitalWrite(topSoilVcc, LOW); // Ensure top sensor is off
digitalWrite(bottomSoilVcc, HIGH); // Power the bottom soil sensor
delay(500); // Give time for sensor to stabilize
int value = analogRead(soilMoisturePin); // Read the value from analog pin
digitalWrite(bottomSoilVcc, LOW); // Turn off the bottom soil sensor
return value;
}
// Function to read water level using the ultrasonic sensor
int readWaterLevel() {
// Send a trigger pulse
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Read echo time
duration = pulseIn(echoPin, HIGH);
// Calculate the distance in cm
int distance = duration * 0.034 / 2;
Serial.print("Water level distance: ");
Serial.print(distance);
Serial.println(" cm");
return distance;
}
// Function to activate the pump for watering
void activatePump() {
Serial.println("Turning on the water pump...");
digitalWrite(pumpRelay, HIGH); // Turn on the pump
delay(10000); // Pump water for 10 seconds
digitalWrite(pumpRelay, LOW); // Turn off the pump
pumpIterations++; // Count the pump cycle
Serial.println("Pump turned off.");
}
// Function to check water level and raise alarm if low
bool checkWaterLevelAndAlarm() {
int waterLevel = readWaterLevel();
if (waterLevel > waterLevelThreshold) {
Serial.println("Water level is too low! Raising alarm...");
digitalWrite(alarmPin, HIGH); // Turn on alarm (Buzzer or LED)
return false; // Break the loop and stop watering
} else {
Serial.println("Water level is sufficient.");
digitalWrite(alarmPin, LOW); // Turn off alarm
return true; // Continue with the process
}
}
// Main loop function
void loop() {
// Timing control: Check every 3 hours
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
pumpIterations = 0; // Reset pump iteration count for this cycle
// Read the soil moisture levels
topMoistureValue = readTopSoilMoisture();
bottomMoistureValue = readBottomSoilMoisture();
Serial.print("Top Soil Moisture Level: ");
Serial.println(topMoistureValue);
Serial.print("Bottom Soil Moisture Level: ");
Serial.println(bottomMoistureValue);
// Check if either top or bottom soil moisture is below the threshold
if (topMoistureValue < moistureThreshold || bottomMoistureValue < moistureThreshold) {
Serial.println("Moisture level is below threshold, checking water level...");
// Continue watering while either sensor is below the threshold
while (topMoistureValue < moistureThreshold || bottomMoistureValue < moistureThreshold) {
// Check water level before each iteration
if (!checkWaterLevelAndAlarm()) {
Serial.println("Watering process aborted due to low water level.");
break; // Break