Looking for 5 minutes - the next nice round 5 minutes.

Hi,

I am looking to use the DS3231 I2C RTC for a data logging project and I have been trying and failing to find a nice way to find out when the next nice round 5 Minute time value is reached....

The RTC can give total seconds since the begining of time itself (ie year 2000) with now.get()

2012/12/6 18:26:11 Fri
Seconds since 1/1/2000: 408133571

I am hoping to find the next round 5 minute time value and start logging from then:

So the time I am interested in, relative to the time above, would be 18:30:00.

Any idea how I would calculate a new 'rounded seconds count value' (ie the 408133571 number) so that I can evaluate it against the current time and then proceed when one equals the other?

long now = 408133571
long rounded = 40813xxxx ?

If now = rounded then..... do something.

Thanks for any help.

const unsigned long SecondsPerMinute = 60UL;
const unsigned long RoundToInMinutes = 5UL * SecondsPerMinute;

unsigned long now = 408133571;

unsigned long rounded = ((now + (RoundToInMinutes - 1)) / RoundToInMinutes) * RoundToInMinutes;

Assuming the RTC can also return minutes and seconds you could try:

   if ((now.minutes % 5) == 0 && now.seconds == 0)

You can poll the rtc - not terribly efficient.

Or you can use the rtc to trigger interrupt and use the mcu to keep track of elapsed time to 5 minutes.

The 2nd approach is more efficient as it doesn't tie up the mcu.

Thanks folks - I now have 3 working choices, wonderful. I'm just testing the 'if ((now.minutes % 5) == 0 && now.seconds == 0)' method overnight to see how we go.

I will also run a test on the interupt method - the DS3231 can generate an interupt every minute so I guess I could simply check the time at the point of interrupt with 'if ((now.minutes % 5) == 0 {LogData()};' which would give logged data every 5th interupt.

...now, one of those questions - Arduino has absolutely nothing to do whilst it waits for the next interupt so.... what is the best way to do absolutely nothing.... whilst waiting for a minute to go by ? :slight_smile:

point5:
Thanks folks - I now have 3 working choices, wonderful. I'm just testing the 'if ((now.minutes % 5) == 0 && now.seconds == 0)' method overnight to see how we go.

I will also run a test on the interupt method - the DS3231 can generate an interupt every minute so I guess I could simply check the time at the point of interrupt with 'if ((now.minutes % 5) == 0 {LogData()};' which would give logged data every 5th interupt.

...now, one of those questions - Arduino has absolutely nothing to do whilst it waits for the next interupt so.... what is the best way to do absolutely nothing.... whilst waiting for a minute to go by ? :slight_smile:

volatile int not_time = 1;
while(not_time) {}

Will just stay in a type loop until in your interrupt routine you set the not_time variable to 0.

Or if you like to look hip like all the other C programmers are.

volatile boolean time_is_up = false;
while(!time_is_up) {}

what is the best way to do absolutely nothing

You can just leave it looping around.

Or to put it to sleep, if your interrupt can wake up the mcu.

point5:
The RTC can give total seconds since the begining of time itself (ie year 2000) with now.get()

The number of whole five-minute increments since epoc would be

now.get() / 300

If the value changes then you know that a five minute interval has just passed. You could use the polling technique demonstrated in 'blink without delay' to detect the change, using the expression above in place of 'millis()'. With this approach, detection of the 'five minute crossing' can be done concurrently with serial port handling, elapsed interval detection, switch handling etc all in a consistent structure.

Thank you all - my code is now so much neater and works a treat :slight_smile:

I'm using an interrupt flag 'alarmFlag' to control the flow - the RTC interrupt is fired every minute on the minute with every interrupt ocurring at a 5minute value resulting in simple/logging.

This is what I ended up with:

void loop () 
{
    while(alarmFlag != true) {} 
    DateTime now = RTC.now();
    
    if ((now.minute() % 5)==0)
    {
    Sample the sensors and write to SD.
    }
    else
    {
    alarmFlag = false;
    RTC.clearINTStatus();
    }

}

Happy days.

    while(alarmFlag != true) {}

Unless alarmFlag is set in an interrupt, you will never get out of that loop.

This is my ISR:

void Alarm()
{
    alarmFlag = true;
}

Since you are already using an isr, you can simply your code this way:

ISR: (assuming this fires every second)
  static sec_counter=0;
  sec_counter+=1;
  if (sec_counter >= 60*5) { //if 5 minutes have passed
    sec_counter -= 60*5; //reset sec_counter
    alarmFlag=1; //set the flag
  }
}

user code
void loop(void) {
  ...
  if (alarmFlag) {
    alarmFlag = 0; //reset the flag
    do_something();
  }
  ...
}

So it runs do_something() once every 5 minutes.

Thanks dhenry - I guess thats kinda handy if you don't have an onboard RTC - do you know how accurate that method is by any chance?

I am now trying to get this all to work with sleep mode - making progress slowly.

Could I ask if:

/*Initialize INT0 for accepting interrupts */
     PORTD |= 0x04; 
     DDRD &=~ 0x04;

...is the same as attachInterrupt ? and if not what is it doing and is there an Arduino way of coding the same thing?

do you know how accurate that method is by any chance?

It is as accurate as the rtc is.

if not what is it doing and is there an Arduino way of coding the same thing?

It sets a pin (PD.2) and turns it as input -> with pull-up.