RTC Timer Relay Problems when arduino resets

Good Day,

I’m Having a problem with my relay’s not starting on the correct state when the arduino resets or turned on after the lights on times has already passed.

The Lights Relay turns on at 6:00 and turns off at 23:59. If i turn on the arduino or it resets and the rtc time is after 6am, the relay does not turn on until the next 6am is reached. I would like the arduino when booting to check the DS3231 RTC time and start the relay it in the state it should be in for that time. below is the code that i have written

#include <DS3231.h>
#include <dht.h>

int LightsRelay = 8;
int PumpRelay = 7;

// Init the DS3231 using the hardware interface
DS3231  rtc(SDA, SCL);
Time t;
dht DHT;

#define DHT11_PIN 9

const int LightsOnHour = 6;
const int LightsOnMin = 0;
const int LightsOffHour = 23;
const int LightsOffMin = 59;
const int PumpOnMin0 = 0;                                                                             
const int PumpOffMin0 = 1;
const int PumpOnMin1 = 10;
const int PumpOffMin1 = 11;
const int PumpOnMin2 = 20;
const int PumpOffMin2 = 21;
const int PumpOnMin3 = 30;
const int PumpOffMin3 = 31;
const int PumpOnMin4 = 40;
const int PumpOffMin4 = 41;
const int PumpOnMin5 = 50;
const int PumpOffMin5 = 51;

void setup()
{
  Serial.begin(115200);
  rtc.begin();
  pinMode(LightsRelay, OUTPUT);
  digitalWrite(LightsRelay, HIGH);
  pinMode(PumpRelay, OUTPUT);
  digitalWrite(PumpRelay, HIGH);
}

void loop()
{
  t = rtc.getTime();
  Serial.print(t.hour);
  Serial.print(" hour(s), ");
  Serial.print(t.min);
  Serial.print(" minute(s), ");
  Serial.println(" ");
  Serial.print("Temperature: ");
  Serial.print(rtc.getTemp());
  Serial.println(" C");
  int chk = DHT.read11(DHT11_PIN);
  Serial.print("Temp = ");
  Serial.println(DHT.temperature);
  Serial.print("Humidity = ");
  Serial.println(DHT.humidity);
  delay (1000);


  if(t.hour == LightsOnHour && t.min == LightsOnMin){
    digitalWrite(LightsRelay,LOW);
    Serial.println("Lights ON");
  }
   
    else if(t.hour == LightsOffHour && t.min == LightsOffMin){
    digitalWrite(LightsRelay,HIGH);
    Serial.println("Lights OFF");
  }

  if(t.min == PumpOnMin0){
    digitalWrite(PumpRelay,LOW);
    Serial.println("Pump ON");
  }
    else if(t.min == PumpOffMin0){
    digitalWrite(PumpRelay,HIGH);
    Serial.println("Pump OFF");
  }

  if(t.min == PumpOnMin1){
    digitalWrite(PumpRelay,LOW);
    Serial.println("Pump ON");
  }
    else if(t.min == PumpOffMin1){
    digitalWrite(PumpRelay,HIGH);
    Serial.println("Pump OFF");
  }

  if(t.min == PumpOnMin2){
    digitalWrite(PumpRelay,LOW);
    Serial.println("Pump ON");
  }
    else if(t.min == PumpOffMin2){
    digitalWrite(PumpRelay,HIGH);
    Serial.println("Pump OFF");
  }

  if(t.min == PumpOnMin3){
    digitalWrite(PumpRelay,LOW);
    Serial.println("Pump ON");
  }
    else if(t.min == PumpOffMin3){
    digitalWrite(PumpRelay,HIGH);
    Serial.println("Pump OFF");
  }

  if(t.min == PumpOnMin4){
    digitalWrite(PumpRelay,LOW);
    Serial.println("Pump ON");
  }
    else if(t.min == PumpOffMin4){
    digitalWrite(PumpRelay,HIGH);
    Serial.println("Pump OFF");
  }

  if(t.min == PumpOnMin5){
    digitalWrite(PumpRelay,LOW);
    Serial.println("Pump ON");
  }
    else if(t.min == PumpOffMin5){
    digitalWrite(PumpRelay,HIGH);
    Serial.println("Pump OFF");
  }
}

Would i create a if statement in the setup to write the state? i did try the add the following if statement in my setup but would get eratic results when arduino restarted. not sure if the statment is correct?

void setup()
{
  Serial.begin(115200);
  rtc.begin();
  t = rtc.getTime();
  pinMode(LightsRelay, OUTPUT);
  if(t.hour >= LightsOnHour && t.min >= LightsOnMin && t.hour <= LightsOffHour && t.min <=LightsOffMin  ){
    digitalWrite(LightsRelay,HIGH);
  }
   else{
    digitalWrite(LightsRelay,LOW);
    } 
  pinMode(PumpRelay, OUTPUT);
  digitalWrite(PumpRelay, HIGH);
}

I’m Trying to learn as i go along here and been reading over examples, unfortunately my programming skills are not that great when it comes to C++. Any advice on where i am going wrong or if im going in the right direction? or where i can find any information to this sort or issue as i’ve been struggling to find much the past few hours. Any help will be greatly appreciated

You’re always going to get wrapped up with headaches when you start dealing with hours, minutes and seconds. I would suggest a small function like,

uint16_t get_time()
{
    uint16_t temp_time = 0;
    t = rtc.getTime(); 
    temp_time += t.hour * 60;
    temp_time += t.min
    return temp_time;
}

Now, every time you call get_time() the return value is the number of minutes since midnight. You can then set a window for testing,

uint16_t current_time = get_time();
if (current_time >= 360 && current_time <= 1439)
{
    // do whatever you want, like turn the light on
}
else
{
    // turn the light off
}

Originally your code waited for the exact moment of time to switch.

But what you really want is somewhat the opposite, you want your the relay pin to switch on/off between set times.

So the following will keep updating that relay each and every loop. If the relay is already on, sending a on command won’t do anything. Same as off.

if current time >= start time && current time <= stop time
then turn relay pin on
else
turn relay pin off.

Slumpert:
if current time >= start time && current time <= stop time

DKWatson:
if (current_time >= 360 && current_time <= 1439)

And the difference is?

DKWatson:
You’re always going to get wrapped up with headaches when you start dealing with hours, minutes and seconds. I would suggest a small function like,

uint16_t get_time()

{
    uint16_t temp_time = 0;
    t = rtc.getTime();
    temp_time += t.hour * 60;
    temp_time += t.min
    return temp_time;
}



Now, every time you call get_time() the return value is the number of minutes since midnight. You can then set a window for testing,



uint16_t current_time = get_time();
if (current_time >= 360 && current_time <= 1439)
{
    // do whatever you want, like turn the light on
}
else
{
    // turn the light off
}

Thank you ever so much that. that does make sense but i was not sure on how to implement it until i saw your logic.

I notice that the time to minute conversion seems to differ by an minute. for example if i choose to turn off at 1 the relay only switches off at 00:02. Would this be as the temp time is starting at 0 and not the 1 for the 1st minute?

Also if i wanted to keep the timer on past midnight from 10pm until 2am would i just change the Comparison Operators and the action around like below?

if (current_time <= 1320 && current_time >= 120)
{// Turn Light OFF}
else
{// Turn Light ON}

This is my working code now

#include <DS3231.h>
#include <dht.h>

int LightsRelay = 8;
int PumpRelay = 7;

// Init the DS3231 using the hardware interface
DS3231  rtc(SDA, SCL);
Time t;
dht DHT;

#define DHT11_PIN 9

const int PumpOnMin0 = 0;
const int PumpOffMin0 = 1;
const int PumpOnMin1 = 10;
const int PumpOffMin1 = 11;
const int PumpOnMin2 = 20;
const int PumpOffMin2 = 21;
const int PumpOnMin3 = 30;
const int PumpOffMin3 = 31;
const int PumpOnMin4 = 40;
const int PumpOffMin4 = 41;
const int PumpOnMin5 = 50;
const int PumpOffMin5 = 51;

void setup()
{
  Serial.begin(115200);
  rtc.begin();
  pinMode(LightsRelay, OUTPUT);
  digitalWrite(LightsRelay, HIGH);
  pinMode(PumpRelay, OUTPUT);
  digitalWrite(PumpRelay, HIGH);
}

uint16_t get_time()
{
    uint16_t temp_time = 0;
    t = rtc.getTime(); 
    temp_time += t.hour * 60;
    temp_time += t.min;
    return temp_time;
}

void loop()
{
  t = rtc.getTime();
  Serial.print(t.hour);
  Serial.print(" hour(s), ");
  Serial.print(t.min);
  Serial.print(" minute(s), ");
  Serial.println(" ");
  Serial.print("Temperature: ");
  Serial.print(rtc.getTemp());
  Serial.println(" C");
  int chk = DHT.read11(DHT11_PIN);
  Serial.print("Temp = ");
  Serial.println(DHT.temperature);
  Serial.print("Humidity = ");
  Serial.println(DHT.humidity);
  delay (1000);

uint16_t current_time = get_time();
  if (current_time >= 359 && current_time <= 1438){
    digitalWrite(LightsRelay,LOW);
    Serial.println("Lights ON");
  }
   else {
    digitalWrite(LightsRelay,HIGH);
    Serial.println("Lights OFF");
  }

    if(t.min == PumpOnMin0){
    digitalWrite(PumpRelay,LOW);
    Serial.println("Pump ON");
  }
   else if(t.min == PumpOffMin0){
    digitalWrite(PumpRelay,HIGH);
    Serial.println("Pump OFF");
  }

      if(t.min == PumpOnMin1){
    digitalWrite(PumpRelay,LOW);
    Serial.println("Pump ON");
  }
   else if(t.min == PumpOffMin1){
    digitalWrite(PumpRelay,HIGH);
    Serial.println("Pump OFF");
  }

      if(t.min == PumpOnMin2){
    digitalWrite(PumpRelay,LOW);
    Serial.println("Pump ON");
  }
   else if(t.min == PumpOffMin2){
    digitalWrite(PumpRelay,HIGH);
    Serial.println("Pump OFF");
  }

      if(t.min == PumpOnMin3){
    digitalWrite(PumpRelay,LOW);
    Serial.println("Pump ON");
  }
   else if(t.min == PumpOffMin3){
    digitalWrite(PumpRelay,HIGH);
    Serial.println("Pump OFF");
  }

      if(t.min == PumpOnMin4){
    digitalWrite(PumpRelay,LOW);
    Serial.println("Pump ON");
  }
   else if(t.min == PumpOffMin4){
    digitalWrite(PumpRelay,HIGH);
    Serial.println("Pump OFF");
  }

      if(t.min == PumpOnMin5){
    digitalWrite(PumpRelay,LOW);
    Serial.println("Pump ON");
  }
   else if(t.min == PumpOffMin5){
    digitalWrite(PumpRelay,HIGH);
    Serial.println("Pump OFF");
  }
}

R3plic8:
I notice that the time to minute conversion seems to differ by an minute. for example if i choose to turn off at 1 the relay only switches off at 00:02. Would this be as the temp time is starting at 0 and not the 1 for the 1st minute?

changing the if statement sorted the off time as changing the temp stat time then made the relay kick in a minute early

if (current_time >= 360  && current_time <= 1439 - 1)