Pages: [1]   Go Down
Author Topic: Looking for 5 minutes - the next nice round 5 minutes.  (Read 640 times)
0 Members and 1 Guest are viewing this topic.
UK
Offline Offline
Sr. Member
****
Karma: 1
Posts: 278
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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()
Code:
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.
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 211
Posts: 13042
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

unsigned long now = 408133571;

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

Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 212
Posts: 8970
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Assuming the RTC can also return minutes and seconds you could try:
Code:
   if ((now.minutes % 5) == 0 && now.seconds == 0)
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

UK
Offline Offline
Sr. Member
****
Karma: 1
Posts: 278
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 ?  :-)
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17303
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 ?  :-)

Code:
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.

Code:
volatile boolean time_is_up = false;
while(!time_is_up) {}
« Last Edit: December 06, 2012, 06:49:51 pm by retrolefty » Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Code:
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.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

UK
Offline Offline
Sr. Member
****
Karma: 1
Posts: 278
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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:

Code:
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.
« Last Edit: December 07, 2012, 07:38:08 am by point5 » Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
    while(alarmFlag != true) {}

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

UK
Offline Offline
Sr. Member
****
Karma: 1
Posts: 278
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is my ISR:

Code:
void Alarm()
{
    alarmFlag = true;
}
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
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.
Logged

UK
Offline Offline
Sr. Member
****
Karma: 1
Posts: 278
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

Code:
/*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?
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

It is as accurate as the rtc is.

Quote
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.
Logged

Pages: [1]   Go Up
Jump to: