// https://curiousscientist.tech/blog/date-and-time-based-watering-system

#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));
 
  }
 
}
GND5VSDASCLSQWRTCDS1307+
NOCOMNCVCCGNDINLED1PWRRelay Module