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 …

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));
 
  }
 
}

Previous
Previous

Schmid factor and resolved shear stress in BCC crystal

Next
Next

STM32F103C with ST-Link and STM32duino, simplified!