Date and time based watering system using an Arduino and a RTC module
In this video I show you how to make an automated watering system based on a real time clock (RTC) module. You can expand this project to control anything based on date/time, and you can add more switches, relays, etc. For example, you can turn on and off your heater, lights, air purifier at a certain time of the day with this circuit.
Wiring diagram
Arduino source code
#include <Wire.h> #include <RTClib.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); RTC_DS1307 RTC; //-------------------------------- bool newData; //new data on serial bool watering = false; //status if watering is allowed or not bool wateredtoday = false; int wateringhour = 9; // water at 9:00 o'clock in the morning (24h time format!) float wateringlength = 6000; //10 sec default watering (pumping time) const int relaypin = 2; const int switchpin = 3; int switchstate = 0; char receivedCommand; //-------------------------------- void setup() { //------------------------------------------------------ lcd.init(); // initialize the lcd lcd.init(); lcd.backlight(); //------------------------------------------------------ pinMode(relaypin, OUTPUT); pinMode(switchpin, INPUT); Serial.begin(9600); Wire.begin(); RTC.begin(); //Refreshing time //remove "!", compile, upload to refresh the time in the RTC module //the time will be set to the time of the compilation if (! RTC.isrunning()) { Serial.println("RTC is NOT running!"); // following line sets the RTC to the date & time this sketch was compiled RTC.adjust(DateTime(__DATE__, __TIME__)); } Serial.println("Irrigation system."); //Fancy startup lcd.clear(); lcd.setCursor(0,0); //Defining positon to write from first row,first column . lcd.print("Watering System"); lcd.setCursor(0,1); lcd.print("Start in 5..."); //You can write 16 Characters per line . delay(1000); //wait 3 sec lcd.setCursor(0,1); lcd.print("Start in 4..."); //You can write 16 Characters per line . delay(1000); //wait 3 sec lcd.setCursor(0,1); lcd.print("Start in 3..."); //You can write 16 Characters per line . delay(1000); //wait 3 sec lcd.setCursor(0,1); lcd.print("Start in 2..."); //You can write 16 Characters per line . delay(1000); //wait 3 sec lcd.setCursor(0,1); lcd.print("Start in 1..."); //You can write 16 Characters per line . delay(1000); //wait 3 sec } void loop() { printtime(); checkSerial(); checktime(); switchcheck(); executecommand(); } //---------------------------------------------------------------------------------- void checkSerial() { //First we check if there is data on the serial port, i.e. we sent a command if (Serial.available() > 0) { receivedCommand = Serial.read(); newData = true; } //if there is a command, then we step inside and go through the possible commands if (newData == true) { if(receivedCommand == 'w') //w = watering { watering = true; //change the boolean, so the watering will be ENABLED } if(receivedCommand == 's') //s = stop { watering = false; //change the boolean, so the watering will be DISABLED } } else {} newData = false; } //---------------------------------------------------------------------------------- void executecommand() //execute the commands, i.e. checking which flag is en/dis-abled { if(watering == true) { //start pump digitalWrite(relaypin, HIGH); //------------------------------------------------------ //---print info on LCD lcd.clear(); lcd.setCursor(0,0); //Defining positon to write from first row,first column . lcd.print("Watering"); lcd.setCursor(0,1); lcd.print("Running"); //You can write 16 Characters per line . //---Run pump for some time (defined in the beginning of the code as a variable) delay(wateringlength); //---Shut down pump, set pin to LOW digitalWrite(relaypin, LOW); //---Clean screen lcd.clear(); //---Disable watering watering = false; //--Change the value of the bool, so we'll know that the watering had happened wateredtoday = true; } else { //do not do anything } //--------------------------- } //---------------------------------------------------------------------------------- void printtime() { //it is just a basic RTC and LCD exercise: reading the date and time and printing it with some formatting DateTime now = RTC.now(); //----------------- //--First line lcd.clear(); lcd.setCursor(0,0); //Defining positon to write from first row,first column . lcd.print(now.year()); lcd.setCursor(4,0); lcd.print("."); lcd.setCursor(5,0); lcd.print(now.month()); lcd.setCursor(7,0); lcd.print("."); lcd.setCursor(8,0); lcd.print(now.day()); lcd.setCursor(11,0); lcd.print("water"); //----------------- //--Second line lcd.setCursor(0,1); lcd.print(now.hour()); //You can write 16 Characters per line . lcd.setCursor(2,1); lcd.print(":"); lcd.setCursor(3,1); lcd.print(now.minute()); lcd.setCursor(5,1); lcd.print(":"); lcd.setCursor(6,1); lcd.print(now.second()); lcd.setCursor(10,1); //if the watering had happened, then we print it on the screen. if(wateredtoday == true) {lcd.print("true");} else {lcd.print("false");} //---------------------------------------- Serial.print(now.year(), DEC); Serial.print('/'); Serial.print(now.month(), DEC); Serial.print('/'); Serial.print(now.day(), DEC); Serial.print(' '); Serial.print(now.hour(), DEC); Serial.print(':'); Serial.print(now.minute(), DEC); Serial.print(':'); Serial.print(now.second(), DEC); Serial.println(); delay(1000); } //---------------------------------------------------------------------------------- void checktime() { //Here, we check the time, so we can see if the watering should be started DateTime now = RTC.now(); //after the watering time occured, we switch the variable back to false so when the //time occurs again (i.e. it is 9:00 in the morning) the watering will be started again if(now.hour() == (wateringhour +1)) { //Serial.println("Watered"); wateredtoday = false; } //If it is time to water, and we haven't watered, we enable watering if(now.hour() == wateringhour && wateredtoday == false) { //Serial.println("Not watered"); watering = true; wateredtoday = true; } } void switchcheck() { //We check the switch which is used to manually run the pump //this does not change ANYTHING with the regular, scheduled pumping. //Serial.println("SwitchCheck"); switchstate = digitalRead(switchpin); //read the pin if (switchstate == HIGH) { //Serial.println("switch is HIGH"); //Serial.println(digitalRead(switchpin)); digitalWrite(relaypin, HIGH); } else { digitalWrite(relaypin, LOW); //Serial.println("switch is LOW"); // Serial.println(digitalRead(switchpin)); } }