How to Turn on/off Every 4 Hours Using RTC + Arduino

Hi everybody,

#1. In my project, I used RTC DS1307 and Uno
So I need to turn on and off Servo motor every 4 hours.
with this code that I paste below, I able to turn on and off every 1 hours, While I use now.hour() I just set one time per every 24 hours…
I do not need to use any other libs like alarm or etc because this code is working just I do not know how should I set a logic flow.

  if (now.minute() == OnMin && now.second() == OnSec) {
      for (pos = 105; pos <= 150; pos += 1) {
          ServoE.write(pos); //Pos 1 : /
          delay(100);
        }
  }

  else if (now.minute() == OnMin && now.second() == OffSec) {
      for (pos = 150; pos >= 105; pos -= 1) {
          ServoE.write(pos); //Pos 3 : \
          delay(100);
        }
  }

#2. The other thing that I need is after finishing the job in (#1) the servomotor return to the (Pos 2 : --) position.

Pos 1 : /
Pos 2 : –
Pos 3 : \

:slight_smile:

Thanks

Pseudocode

if readhour() not equal to last hour
{
  last hour = readhour()
  if last hour mod 4 is equal to 0
  {
    do something
  }
}

You don't need to look at minutes and seconds at all.

What aarg said. I use a rtc too for timing functions. The rtc lets you just pull one element of time out. In this example- just the hour. Not min, sec etc.

What I do is have a separate timer function that’s only job is to set flags. DoMotorSpin = 0 (or 1). Then function for controlling the motor only needs to see if the flag is set or not.

To do this.. I use another var.. eventTrigger Time. I give this var the current hour WHEN the event happens (meaning in to doMotor function).

Then in the timer function- I check current hour against event trigger hour. If > valueDesired then set flag var to 1 so the other function knows to run.

If it needs to be precisely 240 minutes.. then you’ll like need a variation of this.

Thank you, I have now.hour() function for acquiring current time. But the current time for example "4 o'clock" will be true for 60min until "5 o'clock".

int lasthour = 0;

if (now.hour() != lasthour)
{
  lasthour = now.hour();
  if (lasthour % 4) = 0)
  {
    do something...
  }
}

You put your finger squarely on the problem of check hours changed versus how many minutes have passed. If it trips at 4:59, or 4:00 the hour is 4.

IMO- using millis() for very long tasks not great. Can do it, just not great. Rtc is better.

You could do same logic I called out above (a timer function setting a flag) but use value of minutes (not hours). Then, in the timer function- check to see if 60 minutes has passed- four times- then set flag.

FullOfBadIdeas: You put your finger squarely on the problem of check hours changed versus how many minutes have passed. If it trips at 4:59, or 4:00 the hour is 4.

IMO- using millis() for very long tasks not great. Can do it, just not great. Rtc is better.

You could do same logic I called out above (a timer function setting a flag) but use value of minutes (not hours). Then, in the timer function- check to see if 60 minutes has passed- four times- then set flag.

milis() function will idle the system... so this is not useful I think.

Could you please put your suggested algorithm or code here?

Sure. Just pop a few coins in my paypal...:).

You got the mod math going (%4).

When the motor spins.. set event flag in minutes. Say it’s 12. As in 12 past what ever hour. Then.. the timer check would have two stages.. maybe 3. First... wait at least 60 sec to start checking trigger minute to current minute. Then.. when current minute ==trigger minute.. increment a counter. That counter is your hour meter. When counter >= 4 times.. set flag to do task again.

FullOfBadIdeas: Sure. Just pop a few coins in my paypal...:).

You got the mod math going (%4).

When the motor spins.. set event flag in minutes. Say it’s 12. As in 12 past what ever hour. Then.. the timer check would have two stages.. maybe 3. First... wait at least 60 sec to start checking trigger minute to current minute. Then.. when current minute ==trigger minute.. increment a counter. That counter is your hour meter. When counter >= 4 times.. set flag to do task again.

Haha ;) Thank you my friend...

I understand somethings from your method. Will try and send the exact code here for other users.

const int OnMin = 59;
const int OnSec = 50;
const int OffMin = 59;
const int OffSec = 59;
.
.
.

  if ((now.hour() % 4) == 0 && now.minute() == OnMin && now.second() == OnSec) {
      for (pos = 105; pos <= 150; pos += 1) {
          ServoE.write(pos); //Pos 1 : /
          delay(100);
        }
  }

  else if ((now.hour() % 4) == 0 && now.minute() == OffMin && now.second() == OffSec) {
      for (pos = 150; pos >= 105; pos -= 1) {
          ServoE.write(pos); //Pos 3 : \
          delay(100);
        }
  }

What do you think about this code?

You have to make sure it gets executed at least once every second or you will miss the equality.

I’d approach it differently…

enum ServoState{
  SERVO_OFF,
  SERVO_ON,
  UNKNOWN,
};

void setup()
{
  
}

void loop()
{
  static ServoState lastState = UNKNOWN;

  ServoState currentState = getState();
  if (lastState != currentState)
  {
    if (currentState == SERVO_ON)
    {
      //servoOn();
    }
    else
    {
      //servoOff();
    }
    lastState = currentState;
  }
}


ServoState getState()
{
  if (hour() <= 3) 
    return SERVO_ON;
  else if (hour() <= 7)
    return SERVO_OFF;
  else if (hour() <= 11)
    return SERVO_ON;
  else if (hour() <= 15)
    return SERVO_OFF;
  else if (hour() <= 19)
    return SERVO_ON;
  else
    return SERVO_OFF;
}