# How to calculate time interval?

Hello,

I am using a DS1302 RTC module and Arduino UNO R3 with Arduino IDE 1.8.10 to set a timer to turn on and off a relay, and if there is a power cut, then when the power comes back again, as long as the operation time interval is valid, the relay should turn on.

I came up with a possible solution which involves calculating the time difference and if it is positive, then set a Boolean variable state to HIGH otherwise set to LOW to flag the operation time as valid or not. I’m not sure if that’s the best approach. But i am having trouble to calculate the time difference between the on and off times expressed in hours and minutes.

I did research and i found that a possible solution could be to use the Arduino Time library, which i never used before and it seems quite complicated: 59 - The new Arduino Time library | Prometec

For example, this would be quite easy to calculate by subtracting the hours and minutes:

``````// Set hour and minutes for ON and OFF
int pumpRelay_OnHour = 15;
int pumpRelay_OnMin = 26;
int pumpRelay_OffHour = 15;
int pumpRelay_OffMin = 36;
``````

But this example would be tricky to solve:

``````// Set hour and minutes for ON and OFF
int pumpRelay_OnHour = 15;
int pumpRelay_OnMin = 26;
int pumpRelay_OffHour = 15;
int pumpRelay_OffMin = 12;
``````

And this one even trickier (the relay operation time would cross over to the next day):

``````// Set hour and minutes for ON and OFF
int pumpRelay_OnHour = 23;
int pumpRelay_OnMin = 49;
int pumpRelay_OffHour = 1;
int pumpRelay_OffMin = 10;
``````

Any advice or suggestion would be very appreciated.

Here is my complete sketch:

``````#include <virtuabotixRTC.h> // DS1302 RTC module library

// Creation of the Real Time Clock Object
virtuabotixRTC myRTC(5, 6, 7);  // Wiring of the DS1302 RTC (CLK,DAT,RST)

const int pumpRelay = 8;  // set pump relay pin
unsigned long interval = 2000;  // print RTC time every 2s
unsigned long time_now = 0;

// Set hour and minutes for ON and OFF
int pumpRelay_OnHour = 15;
int pumpRelay_OnMin = 9;
int pumpRelay_OffHour = 15;
int pumpRelay_OffMin = 10;

bool pumpRelay_status = 0;

void setup() {
Serial.begin(9600); // open serial port and set the baud rate
Serial.println("Automated pump relay control with RTC");
Serial.println("**************************************");
pinMode(pumpRelay, OUTPUT); // set digital pin pumpRelay as an output

// Set the current date, and time in the following format:
// seconds, minutes, hours, day of the week, day of the month, month, year
myRTC.setDS1302Time(50, 8, 15, 5, 26, 1, 2020); // uncomment line, upload to reset RTC and then comment, upload.

myRTC.updateTime(); // update of variables for time or accessing the individual elements.

// Start printing elements as individuals
Serial.print("Preset RTC Time and Date: ");
Serial.print(myRTC.hours);
Serial.print(":");
Serial.print(myRTC.minutes);
Serial.print(":");
Serial.print(myRTC.seconds);
Serial.print(" ");
Serial.print(myRTC.dayofmonth);
Serial.print("/");
Serial.print(myRTC.month);
Serial.print("/");
Serial.println(myRTC.year);

Serial.println("********************************************************");
Serial.println("User Configuration:");
Serial.println("--------------------------------------------------------");
Serial.println("RTC-based Timers (Hours:Minutes)");
Serial.print("Pump ON: ");
Serial.print(pumpRelay_OnHour);
Serial.print(":");
Serial.println(pumpRelay_OnMin);
Serial.print("Pump OFF: ");
Serial.print(pumpRelay_OffHour);
Serial.print(":");
Serial.println(pumpRelay_OffMin);
Serial.println("********************************************************");
}

void loop() {
myRTC.updateTime(); // update of variables for time or accessing the individual elements.

// Start printing RTC time elements as individuals
if (millis() - time_now >= interval)  // non-blocking. prints RTC time every 2 seconds.
{
time_now = millis();
Serial.print("RTC Time: ");
Serial.print(myRTC.hours);
Serial.print(":");
Serial.print(myRTC.minutes);
Serial.print(":");
Serial.println(myRTC.seconds);
}
if ((myRTC.hours >= pumpRelay_OnHour && myRTC.hours <= pumpRelay_OffHour) && (myRTC.minutes >= pumpRelay_OnMin && myRTC.minutes < pumpRelay_OffMin))
{
if (pumpRelay_status == 0)
{
Serial.print("Pump activated at: ");
Serial.print(myRTC.hours);  // display the current hour from RTC module
Serial.print(":");
Serial.print(myRTC.minutes);  // display the current minutes from RTC module
Serial.print(":");
Serial.println(myRTC.seconds);  // display the seconds from RTC module
digitalWrite(pumpRelay, HIGH);  //turns on the pump relay
Serial.println("*** Pump relay turned ON ***");
pumpRelay_status = 1;
}
}
else
{
if (pumpRelay_status == 1)
{
Serial.print("Pump deactivated at: ");
Serial.print(myRTC.hours);  // display the current hour from RTC module
Serial.print(":");
Serial.print(myRTC.minutes);  // display the current minutes from RTC module
Serial.print(":");
Serial.println(myRTC.seconds);  // display the seconds from RTC module
digitalWrite(pumpRelay, LOW); // turn off the pump relay
Serial.println("*** Pump relay turned OFF ***");
pumpRelay_status = 0;
}
}
}
``````

You can get something called “ unix time “ from the DS321” and using that to calculate your time difference might be a simple route .

I'd first convert everything to a minutes time base so as not to have to deal with hours and minutes.

``````onMin = pumpRelay_OnHour*60 + pumpRelay_OnMin ;
offMin = pumpRelay_OffHour*60 + pumpRelay_OffMin ;
``````

We want the pump to turn on after the on time and remain on until after the off time which would be something like:

``````on = (time > onMin) != (time > offMin) ;
``````

This fails when the off time is earlier than the on time since we've rolled over to the next day. To deal with that we can change the equation above to invert the Boolean value "after the off time" if the off time is earlier than the on time, so:

``````on = (time > onMin) != ((time > offMin) != (onMin > offMin)) ;
``````

Note that "!=" in the above is operating on Boolean values so it is effectively a logical "xor" operator.

``````  bool relayOn = false;
if (onMinute <= offMinute)  // On before Off
relayOn = currentMinute >= onMinute && currentMinute < offMinute;
else // Crosses midnight, off the next day
relayOn = currentMinute < offMinute || currentMinute >= onMinute;
digitalWrite(RelayPin, relayOn);
``````