[Solved]RTC time dependant actions, check if the clock is between 2 time values?


I am writing a code which will use a DS3231 to fetch the current time, which happens once every minute.

I have a device that should be turned on at a certain time each day and then stay on until the specified length of time has passed(activating the device is controlled by a single pin) and I want to do this in a way which allow me to change the time it turns on and how long it runs with functions such as:

void setTurnOnTime(uint8_t hours, uint8_t minutes);
void setRunTimeDuration(uint8_t hours, uint8_t minutes);

Since I always need a variable for the hours and another for minutes I’ve written a struct which are used:

struct aTime
    uint8_t hours;
    uint8_t minutes;

But I am not happy with my code since as it is right now I am simply collecting the time information from the DS3231 which is in a 24h format, and then I use an if statement in which I take the current hours value and subtracting the target hours value(for when to turn on for example) and if that expression is 0 then I do the same with the minutes and if that also is 0 then I act on it, but this means that if for some reason the microcontroller would miss the to do the check during the relevant minute then the hole ON-action would be missed.
The following code might not be very clear since it is taken out of context but to show you what I just described:

void checkTime()
    readTime();  // read the DS3231 data into the struct 't'.
    if (!(t.hours - turnOnTime.hours))
        if (!(t.minutes - turnOnTime.minutes))
            turnOn(); // this might be changed into a flag
    if (!(t.hours - turnOffTime.hours))
        if (!(t.minutes - turnOffTime.minutes))
            turnOff(); // this might be changed into a flag

I might be wrong but I don’t like the idea of only checking if the current time is matching up with ether the turn-on-time or the turn-off-time, what I would like is something that would check if the current time is somewhere in between the turn-on-time and the turn-off-time, or in between the turn-off-time and the turn-on-time. And every time it is in between any of those the code would call a function to turn the device in question on/off(if it was already turned on and the turn-on function was called it would just stay on).

That sounds to me as a much better and safer way to make this work but I cannot figure out how to write something like that since the time is kept in hours which is in the range of 0 - 24, and minutes which is in the range of 0 - 59.

Lets say that I have set the turn-on-time to 12:00 or:

struct aTime turnOnTime;
turnOnTime.hours = 12;
turnOnTime.minutes = 0;

and the turn-off-time is 02:00:

struct aTime turnOffTime;
turnOffTime.hours = 2;
turnOffTime.minutes = 0;

How would I then write a algorithm to check if the current time(let’s assume the current time is 22:35) is between the turn-on-time and turn-off-time or if it is between the turn-off-time and turn-on-time?

By the way, I find out the turn-off-time by doing this sort of thing(‘humidifier_dayLength’ is also a ‘aTime’ struct):

uint8_t hours = turnOnTime.hours;
uint8_t minutes = turnOnTime.minutes;
for (int i = 1; i <= humidifier_dayLength.hours; i++)
    hours = hours + 1;
    if (hours > 23)
        hours = 0;

for (int i = 1; i <= humidifier_dayLength.minutes; i++)
    minutes = minutes + 1;
    if (minutes > 59)
        minutes = 0;
        hours + 1;
turnOffTime.hours = hours;
turnOffTime.minutes = minutes;

So that’s it, I would very much welcome any ideas, critic or suggestion or whatever.
This would be very simple if a static situation existed but the thing is that in the end I will have a user-interface with a display and buttons/encoder through which these times would be adjustable so I need an algorithm to work out when to turn a pin ON/OFF based on whichever hours and minute the turn-on-time is and however long the on period should be(in the above case the ‘humidifier_dayLength’ struct)

I have been thinking about converting hours and minutes to minutes each day(24h = 1439 minutes) but that presents the same problem.


One way to simplify the task is to reduce the hours and minutes to minutes:

void loop()
 readTime();  // read the DS3231 data into the struct 't'.
  unsigned currentTime = (t.hours * 60) + t.minutes;
  unsigned startTime =  (turnOnTime.hours * 60) + turnOnTime.minutes;
  unsigned stopTime =   (turnOffTime.hours * 60) + turnOffTime.minutes;

  boolean on;

  // If the interval doesn't overflow into tomorrow
  if (stopTime > startTime )
    on = (currentTime >= startTime && currentTime < stopTime);
    on = (currentTime >= startTime || currentTime < stopTime);

  // We only need to write to the pin if it is set wrong
  if (digitalRead(pin) != on)
    digitalWrite(pin, on);
    // You can put code in here to notify of state changes

I might be wrong but I don't like the idea of only checking if the current time i.......... in the end I will have a user-interface with a display and buttons/encoder through which these times would be adjustable

You probably are, and that that is what the user of the user interface would do, particularly if it is somebody else. I don't think you have said anything that would preclude the use of the TimeAlarms library, and it rather looks like you are trying to re-invent the wheel and coming up with a square one.

If you really need to manipulate the time yourself, you might be better off using UnixTime, which is available in most, and probably all, time libraries, as it is what machines use and human-usable time is derived therefrom.

Yes... use the time library, it comes with all convenience of figuring out hours/minutes, and internally uses the unix time (seconds since epoch), which in itself is the easiest to work with in software.

Interesting, I've never thought of using boolean like that.

I have looked into that library and that will make this a lot easier as well as much better implemented, thanks for the suggestion.

it rather looks like you are trying to re-invent the wheel and coming up with a square one.

For some reason I really enjoyed that expression:-)

Using TimerAlarms I actually feel confident that I will be able to complete this project which I wouldn't have felt with my own code since after having set up the ON/OFF action that I already have described(device#1) I also need to turn on another device(device#2) so that it is turned on from 'x' minutes before to 'x' minutes after the turn-on-event or turn-off-event of device#1.
Which with this library doesn't appear to be too complicated.

Thank you all for your answers, really helpful.