Pages: [1]   Go Down
Author Topic: How does the Time library adjust when millis() rolls over?  (Read 1136 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi!

I'm new to Arduino.  I wrote a sketch using the Time library (which works great, though my DS1307 seems to run very fast -- that's another topic...) and I became curious and dug into the library a bit to see how it works.  I think I mostly get what is going on, but I can't figure out how it handles the situation where millis() rolls back to zero.  Can somebody explain it to me?

Here's the meat & potatoes function that gets the time.  Doesn't the same value of sysTime just get returned over and over again since it's not being incremented anymore?  What am I screwing up?  I'm new to C/C++ so hit me with the cluestick please.

Code:
time_t now(){
  while( millis() - prevMillis >= 1000){      
    sysTime++;
    prevMillis += 1000;
#ifdef TIME_DRIFT_INFO
    sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift    
#endif  
  }
  if(nextSyncTime <= sysTime){
        if(getTimePtr != 0){
          time_t t = getTimePtr();
      if( t != 0)
        setTime(t);
      else
        Status = (Status == timeNotSet) ?  timeNotSet : timeNeedsSync;        
    }
  }  
  return sysTime;
}

Thanks!
« Last Edit: September 10, 2011, 09:35:01 pm by tagalog88 » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Code:
  while( millis() - prevMillis >= 1000){     

This works even when millis () rolls over back to zero.

Try it on a hex calculator (discarding the high-order bytes which don't fit into an unsigned long).
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't know about the rest of your code. It depends on how prevMillis is defined, etc.

But the concept is there - doing the subtraction handles the roll-over.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well that's damn sneaky.  I hadn't really had any exposure to integer overflow before.  Thanks!
Logged

Cape Town South Africa
Offline Offline
Edison Member
*
Karma: 19
Posts: 1189
A newbie with loads of posts, and still so much to learn !
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Nick,  will that also work for the Y2038 problem ?   ( which I only read about yesterday - it will only effect my projects if I get to be 90 :-) )
Logged

With my mobile phone I can call people and talk to them -  how smart can you get ?

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hmm, good point. I'm not sure whether to hope I have to worry about that, or hope I don't have to worry about it. smiley-wink

I doubt somewhat that every Unix programmer has used subtraction rather than addition, so the problem will probably arise sporadically. I think when the day gets closer libraries will be rewritten to use 64 bits rather than 32, so the problem will basically go away.
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 443
Posts: 23834
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 double-longs will have to be declared then??
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.

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think so.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12482
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


In arduino terms they are:  int64_t 

see - http://www.nongnu.org/avr-libc/user-manual/group__avr__stdint.html#gadb828ef50c2dbb783109824e94cf6c47 -

Warning, doing math with them is Sssssslllllllloooooowwwwww smiley-wink
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The type "long long" compiles.

Example:

Code:
volatile long long foo = 42;

void setup () {}

void loop ()
{
  foo++;
}

It generates a laughably large amount of code to do foo++ :

Code:
void loop ()
  a8: 1f 93        push r17
{
  foo++;
  aa: 80 91 00 01 lds r24, 0x0100
  ae: 20 91 01 01 lds r18, 0x0101
  b2: 30 91 02 01 lds r19, 0x0102
  b6: 40 91 03 01 lds r20, 0x0103
  ba: 60 91 04 01 lds r22, 0x0104
  be: e0 91 05 01 lds r30, 0x0105
  c2: a0 91 06 01 lds r26, 0x0106
  c6: 10 91 07 01 lds r17, 0x0107
  ca: b8 2f        mov r27, r24
  cc: bf 5f        subi r27, 0xFF ; 255
  ce: 91 e0        ldi r25, 0x01 ; 1
  d0: b8 17        cp r27, r24
  d2: 08 f0        brcs .+2      ; 0xd6 <loop+0x2e>
  d4: 90 e0        ldi r25, 0x00 ; 0
  d6: f9 2f        mov r31, r25
  d8: f2 0f        add r31, r18
  da: 81 e0        ldi r24, 0x01 ; 1
  dc: f2 17        cp r31, r18
  de: 08 f0        brcs .+2      ; 0xe2 <loop+0x3a>
  e0: 80 e0        ldi r24, 0x00 ; 0
  e2: 78 2f        mov r23, r24
  e4: 73 0f        add r23, r19
  e6: 81 e0        ldi r24, 0x01 ; 1
  e8: 73 17        cp r23, r19
  ea: 08 f0        brcs .+2      ; 0xee <loop+0x46>
  ec: 80 e0        ldi r24, 0x00 ; 0
  ee: 58 2f        mov r21, r24
  f0: 54 0f        add r21, r20
  f2: 81 e0        ldi r24, 0x01 ; 1
  f4: 54 17        cp r21, r20
  f6: 08 f0        brcs .+2      ; 0xfa <loop+0x52>
  f8: 80 e0        ldi r24, 0x00 ; 0
  fa: 38 2f        mov r19, r24
  fc: 36 0f        add r19, r22
  fe: 81 e0        ldi r24, 0x01 ; 1
 100: 36 17        cp r19, r22
 102: 08 f0        brcs .+2      ; 0x106 <loop+0x5e>
 104: 80 e0        ldi r24, 0x00 ; 0
 106: 28 2f        mov r18, r24
 108: 2e 0f        add r18, r30
 10a: 81 e0        ldi r24, 0x01 ; 1
 10c: 2e 17        cp r18, r30
 10e: 08 f0        brcs .+2      ; 0x112 <loop+0x6a>
 110: 80 e0        ldi r24, 0x00 ; 0
 112: 98 2f        mov r25, r24
 114: 9a 0f        add r25, r26
 116: 81 e0        ldi r24, 0x01 ; 1
 118: 9a 17        cp r25, r26
 11a: 08 f0        brcs .+2      ; 0x11e <loop+0x76>
 11c: 80 e0        ldi r24, 0x00 ; 0
 11e: 81 0f        add r24, r17
 120: b0 93 00 01 sts 0x0100, r27
 124: f0 93 01 01 sts 0x0101, r31
 128: 70 93 02 01 sts 0x0102, r23
 12c: 50 93 03 01 sts 0x0103, r21
 130: 30 93 04 01 sts 0x0104, r19
 134: 20 93 05 01 sts 0x0105, r18
 138: 90 93 06 01 sts 0x0106, r25
 13c: 80 93 07 01 sts 0x0107, r24
}
 140: 1f 91        pop r17
 142: 08 95        ret

So I don't see that as a viable way of tracking time on the Arduino. However of course, we can still use millis () and micros (). We can let the clock chips worry about how they store the time.
Logged

Pages: [1]   Go Up
Jump to: