adding up millis

I am working on a speedometer and trying to keep track of "ride time". Below is my code for when the speedometer has stopped. Previously when it started, "time2" was set to the value of millis().

I am trying to make sure that the time is still added correctly if millis() rolls over. I know that "time" itself will not keep track of more than 49 days of milliseconds and that this code will not work if the speedometer doesn't stop for 49 days. "time" will likely be reset to 0 fairly frequently anyway. But the arduino will only ever sleep, not restart. So I do need to worry about millis() rolling over.

"time" is the millis() that I have tallied up. "time2" is the value of millis() when I started counting last. Both are unsigned longs.

  void (stoppedMoving){
    if(millis() >= time2){//if time has NOT rolled over
      time += (millis()-time2);//add the difference between time2 and millis().
    }
    else{////if time has rolled over
      time += (4294967295 - time2) + millis();//if millis() has rolled over, add the number of milliseconds before it rolled over plus the milliseconds since it rolled over.
      }//end if time has rolled over
      moving=false;
  }//end stoppedMoving

Will this work?

Thanks

You can't get any more bits in the variable time than are in the result of millis()...

You need to count rollovers perhaps:

unsigned long time_lo ;  // synthesize a 64 bit unsigned integer from two unsigned longs
unsigned long time_hi ;

...
  unsigned long new_time_lo = time_lo + (millis () - time2) ;
  if (new_time_lo < time_lo)
    time_hi ++ ; // detect carry-over
  time_lo = new_time_lo ;

(Or does long long work and give a 64 bit int??)

If your math is all done in the form of

elapsedTime = (timeNow - timeEarlier); // add elaspedTime to add rideTime summary
where timeNow is the stopped time, and timeEarlier is the time you started

and all time related variable are unsigned long,
then there will not be a rollover problem.

CrossRoads:
If your math is all done in the form of

elapsedTime = (timeNow - timeEarlier); // add elaspedTime to add rideTime summary
where timeNow is the stopped time, and timeEarlier is the time you started

and all time related variable are unsigned long,
then there will not be a rollover problem.

Ah yes, I get it, that makes perfect sense... I was just over complicating it. Thanks!

CrossRoads:
If your math is all done in the form of

elapsedTime = (timeNow - timeEarlier); // add elaspedTime to add rideTime summary
where timeNow is the stopped time, and timeEarlier is the time you started

and all time related variable are unsigned long,
then there will not be a rollover problem.

If timeNow and timeEarlier are values form millis(),
then that will only work if the millis() timer is guaranteed to never rollover
between TimerEarlier and timeNow.

To ensure no rollover during the elapsed time requires zeroing out the millis() timer value.
(which is easy)
And if the millis() timer value has to be zeroed to make it work, why not then just
zero at "timeEarlier" when the elapsed time starts, and then the elapsed time
is merely mills() when you get to timeNow.
This avoids the calculation altogether.
It then simply becomes a matter of when to zero out millis().

--- bill

I think the point is, though, that as long as they are all unsigned longs, if millis() were to rollover. Then when you subtract timeEarlier from timeNow, it will rollover backwards and still give you the difference. The only thing that would mess this up is if you tried to subtract more than 49 days, then your actual calculation would "rollover". But like I said, I'm not worried about that. I'm only worried about millis() rolling over.

bperrybap:

CrossRoads:
If your math is all done in the form of

elapsedTime = (timeNow - timeEarlier); // add elaspedTime to add rideTime summary
where timeNow is the stopped time, and timeEarlier is the time you started

and all time related variable are unsigned long,
then there will not be a rollover problem.

If timeNow and timeEarlier are values form millis(),
then that will only work if the millis() timer is guaranteed to never rollover
between TimerEarlier and timeNow.

To ensure no rollover during the elapsed time requires zeroing out the millis() timer value.
(which is easy)
And if the millis() timer value has to be zeroed to make it work, why not then just
zero at "timeEarlier" when the elapsed time starts, and then the elapsed time
is merely mills() when you get to timeNow.
This avoids the calculation altogether.
It then simply becomes a matter of when to zero out millis().

--- bill

Incorrect, subtracting two unsigned numbers will result in the difference between the two numbers, including wrap-around. Try it for yourself.

The only caveat is that you can only detect an elapsed time that is less than the maximum amount that can be stored in the n-bits you are working with.

Arrch, which part are you saying is incorrect?
To my mind,
time now - time earlier = elapsed time
0x00000020 - 0xFFFFFF20 = 0x00000100

You may get the wrong result if the calculation is made after the time has rolled over for 24+ days or something on the extremes:
But normally it will be correct.
I would expect "ride time" in this case might be on a per trip basis, or added & stored in EEPROM, but millis() would be reset when the engine was shutdown and later restarted.

CrossRoads:
Arrch, which part are you saying is incorrect?

This part:

If timeNow and timeEarlier are values form millis(),
then that will only work if the millis() timer is guaranteed to never rollover

byte timeEarlier = 250;
byte timeNow = 5;
byte timeDifference;
void setup(){
 Serial.begin(9600);
 timeDifference = timeNow - timeEarlier;
 Serial.println(timeDifference);
}

void loop(){
  
  
}

returns 11

That's the difference, despite the fact that the byte rolled over.

Arrch:
... subtracting two unsigned numbers will result in the difference between the two numbers, including wrap-around. Try it for yourself.

Yes, this is true. I stand embarrassedly corrected... :blush:

--- bill