Pages: [1]   Go Down
Author Topic: seconds timekeeping  (Read 659 times)
0 Members and 1 Guest are viewing this topic.
Ontario
Offline Offline
God Member
*****
Karma: 25
Posts: 881
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I sometimes wish there was seconds timekeeping in the Arduino core.  For a recent project, I implemented seconds timekeeping in wiring.c as follows.
See http://forum.arduino.cc/index.php?topic=172419.0 for some libraries to use this.

I reviewed a couple of "userland" tools for timekeeping based on millis(), but the code complexity is high and the overhead of constantly reading millis() and correlating to a userland seconds timekeeping is pretty high.  I want something where the normal timer interrupt does the work.  My solution adds a dozen instructions to the timer0 overflow and 6 bytes of static variables.

Code:
volatile unsigned long timer0_sec = 0;
static unsigned int timer0_sec_fract = 0;

#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ISR(TIM0_OVF_vect)
#else
ISR(TIMER0_OVF_vect)
#endif
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m;
unsigned int f = timer0_fract;

m = MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}

timer0_fract = (unsigned char) f;
timer0_millis += m;
timer0_overflow_count++;

/* Also keep track of seconds
*/
f = timer0_sec_fract + m;
if (f >= 1000) {
            timer0_sec += 1;
    f -= 1000;
}
timer0_sec_fract = f;
}

void time_set(unsigned long t)
{
   uint8_t oldSREG = SREG;
   cli();
   timer0_sec = t;
   timer0_sec_fract = 0;
   SREG = oldSREG;
}

unsigned long time_sec()
{
   unsigned long m;
   uint8_t oldSREG = SREG;

   // disable interrupts or we might get an
   // inconsistent value (e.g. in the middle of a write)
   cli();
   m = timer0_sec;
   SREG = oldSREG;

   return m;
}
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 208
Posts: 8842
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How is that different from:
Code:
static unsigned long timerStart = 0;

// Set the current time in seconds
void time_set(unsigned long t)
{
   timerStart = millis() - (t*1000UL);
}

// Return the current time in seconds
unsigned long time_sec()
{
   return (millis() - timerStart) / 1000UL;
}
Logged

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

Ontario
Offline Offline
God Member
*****
Karma: 25
Posts: 881
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It does not wrap after a few days like millis() does.
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 208
Posts: 8842
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It does not wrap after a few days like millis() does.

The millis() timer wraps after about 47 days.  The version I wrote should work properly across the wrap so unless you are measuring a single interval greater than 46 days it shouldn't be a problem.
Logged

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

Ontario
Offline Offline
God Member
*****
Karma: 25
Posts: 881
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The version I wrote should work properly across the wrap

I do not see that.  millis() is unable to tell the difference between now and 49 days 17 hours ago, or  49 days 17 hours from now.  A simple unchanging offset doesn't fix that.  To use millis() as the base timer for a longer term clock you have to guaranty that you sample millis() often enough (at least every two dozen days) to spot when it rolls over, and adjust the offset.  There are several implementations of that around, but they are more complex than what I wanted.

Quote
unless you are measuring a single interval greater than 46 days

That is the requirement.
Logged

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 537
Posts: 27068
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

So you are not going to look at the time for 49 days at a time?
What a patient program.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Pages: [1]   Go Up
Jump to: