Automatic IoT Planter
A planter that monitors soil moisture, waters itself on a schedule, and sends reminders for all things plant-related — built as a classroom exploration of IoT systems using NodeMCU.

System diagram showing the NodeMCU microcontroller wired to a DS3231 RTC module, capacitive moisture sensor, relay, and submersible water pump.
The brief was to prototype a useful IoT device in a month. Plants are the obvious target — most people over- or under-water them, and a moisture sensor is cheap enough to build into almost anything. The goal: a planter that monitors its own soil and acts on what it finds, without needing intervention.
NodeMCU (ESP8266) handles control and Wi-Fi. A DS3231 RTC module tracks real time — the watering logic runs hourly, not on a simple delay loop, so the schedule survives power cycles. A capacitive moisture sensor on pin A0 reads the soil, and a relay switches a small submersible pump for watering bursts.
The control loop wakes every hour. If the moisture sensor reads above 600 (dry threshold), the pump runs for 10 seconds. The RTC prevents duplicate triggers within the same hour, and a separate input monitors the water reservoir level — flagging an alert when empty. Simple bang-bang control, reliable enough for a planter.
Sketch
The full NodeMCU sketch — RTC-driven hourly checks, moisture reading, pump control, and low-water alert.
// Automatic Watering System using NodeMCU, Moisture Sensor// Date and time functions using a DS3231 RTC connected via I2C and Wire lib#include <Wire.h>#include "RTClib.h"RTC_DS3231 rtc;const int waterStateButton = 12; // flush switch pinconst int ledPin = LED_BUILTIN;const int motorPin = 11;int waterState = 0;int currentHour, initialHour;int moistureSensorValue;void setup() {DateTime now = rtc.now();initialHour = now.hour();pinMode(motorPin, OUTPUT);pinMode(A0, INPUT);Serial.begin(9600);if (!rtc.begin()) {Serial.println("Couldn't find RTC");while (1);}if (rtc.lostPower()) {Serial.println("RTC lost power, setting time...");rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));}}void loop() {digitalWrite(motorPin, HIGH);DateTime now = rtc.now();Serial.println(now.hour());if (currentHour != now.hour() || currentHour == initialHour) {if (currentHour == initialHour) {initialHour--;}moistureSensorValue = analogRead(A0);Serial.println(moistureSensorValue);if (moistureSensorValue > 600) {digitalWrite(motorPin, LOW);delay(10000);digitalWrite(motorPin, HIGH);}if (waterState == HIGH) {Serial.println("No Water! Please fill");}currentHour = now.hour();}delay(1000);}
"A moisture sensor, a pump, and an RTC — three components solving a problem most people forget about until the plant is already dead."