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
The real time clock module (DS3231) and the 16x2 LCD use the same i2C connection. The SDA is connected to A4 and the SCL is connected to A5. The pump is connected to the relay which is controlled by the D2 pin of the Arduino. If you want to use the interrupt function for some reason, it is better to use other digital pin for the relay. The switch is also connected to a digital pin (D3) to turn the pump ON/OFF.
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)); } }