Go Down

### Topic: adding up millis (Read 3446 times)previous topic - next topic

#### stoopkid

##### Mar 01, 2013, 08:29 pmLast Edit: Mar 01, 2013, 08:33 pm by stoopkid Reason: 1
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.
Code: [Select]
`  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

#### MarkT

#1
##### Mar 01, 2013, 08:35 pm
You can't get any more bits in the variable time than are in the result of millis()...

You need to count rollovers perhaps:
Code: [Select]
`unsigned long time_lo ;  // synthesize a 64 bit unsigned integer from two unsigned longsunsigned 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??)
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

#2
##### Mar 01, 2013, 08:42 pm
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.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

#### stoopkid

#3
##### Mar 01, 2013, 08:49 pm

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!

#### bperrybap

#4
##### Mar 01, 2013, 09:34 pm

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

#### stoopkid

#5
##### Mar 01, 2013, 09:38 pm
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.

#### Arrch

#6
##### Mar 01, 2013, 09:46 pmLast Edit: Mar 01, 2013, 09:49 pm by Arrch Reason: 1

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.

#7
##### Mar 01, 2013, 10:04 pm
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.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

#### Arrch

#8
##### Mar 01, 2013, 10:19 pm

Arrch, which part are you saying is incorrect?

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

#### stoopkid

#9
##### Mar 01, 2013, 11:42 pm
Code: [Select]
`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.

#### bperrybap

#10
##### Mar 02, 2013, 12:29 am

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

--- bill

Go Up