Go Down

Topic: Millis() rover over handling (Read 3862 times)previous topic - next topic

SouthernAtHeart

Jul 05, 2013, 09:07 pm
In this code, will millis() roll over be a problem?  This routine is called to run a motor twice a day all year.  The mills() is only used to check for a stuck door.  If I've got the logic of it figured out, I think if the rollover does occur during this routine, it just won't have the error protection.  That's fine, I just don't want it to be forced into an error if the rollover happens during the routine.
Code: [Select]
`void OpenDoor(){  digitalWrite(HBRIDGEpower, HIGH);  //power up the H Bridge  delay(1000);  //give it a chance to stabilize  digitalWrite(motorOpenPin, HIGH);    //Turn on the motor pin that give the open direction  unsigned long startMillis = millis(); //create a counter  while(1){    if (millis() - startMillis > 30000) DoorError(); //longer than 30 sec means the string is tangled    if (digitalRead(TopSwitch) == 0) { //Switch is closed      digitalWrite(motorClosePin, LOW);  //Brake      digitalWrite(motorOpenPin, LOW);  //Brake      delay(500); //wait a bit      digitalWrite(HBRIDGEpower, LOW);  //power down the H Bridge      break;    }    delay(10);  }}`

Jack Christensen

#1
Jul 05, 2013, 09:20 pmLast Edit: Jul 05, 2013, 09:26 pm by Jack Christensen Reason: 1
As long as the interval being timed (30 sec here) is less than the ~50 day millis() rollover interval, and if the comparison is done with subtraction and unsigned variables as it is here (good job!) then the rollover will never be a problem. The code will operate the same even if rollover occurs during the 30 second interval.

SouthernAtHeart

#2
Jul 05, 2013, 10:10 pm

As long as the interval being timed (30 sec here) is less than the ~50 day millis() rollover interval, and if the comparison is done with subtraction and unsigned variables as it is here (good job!) then the rollover will never be a problem. The code will operate the same even if rollover occurs during the 30 second interval.

Thanks!

HugoPT

#3
Jul 06, 2013, 11:33 am
Quote
As long as the interval being timed (30 sec here) is less than the ~50 day millis() rollover interval, and if the comparison is done with subtraction and unsigned variables as it is here (good job!) then the rollover will never be a problem.

I don't agree with this.
There is a possible failure when the rollover occurs.
Code: [Select]
`unsigned long startMillis = millis(); //create a counter  while(1){    if (millis() - startMillis > 30000) DoorError(); //longer than 30 sec means the string is tangled    if (digitalRead(TopSwitch) == 0) { //Switch is closed      digitalWrite(motorClosePin, LOW);  //Brake      digitalWrite(motorOpenPin, LOW);  //Brake      delay(500); //wait a bit      digitalWrite(HBRIDGEpower, LOW);  //power down the H Bridge      break;    }    delay(10);`
Lets assume startMillis is now 4,294,967,293( near the end of an unsigned long) and then the mills() function return on the if the value of 4 because the rollover had just happened, this "if (millis() - startMillis > 30000) DoorError();" will be false even if the 30 seconds pass.So there is a leak in your code.
I know the probabilities of that happen are very very small but the failure is there.
Debian,Mint,Ubuntu
Arduino Mega 2560
Arduino Nano
Arduino Duemilanove
MAC OS Montain Lion
Raspberry PI Model B

robtillaart

#4
Jul 06, 2013, 11:40 am
Code: [Select]
`  while(1){    if (millis() - startMillis > 30000) DoorError(); //longer than 30 sec means the string is tangled    if (digitalRead(TopSwitch) == 0) { //Switch is closed      digitalWrite(motorClosePin, LOW);  //Brake      digitalWrite(motorOpenPin, LOW);  //Brake      delay(500); //wait a bit      digitalWrite(HBRIDGEpower, LOW);  //power down the H Bridge      break;    }    delay(10);`

don't know how DoorError() is implemented, should it shut down the HBRIDGE and motors?

@hugoPT
as the math is unsigned it will work, you can test it in a small sketch
Code: [Select]
`void setup(){  Serial.begin(9600);  unsigned long a = 4,294,967,293;  unsigned long b = 1000;  unsigned long c = b - 1;  Serial.println(c);}void loop(){}`
Rob Tillaart

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

HugoPT

#5
Jul 06, 2013, 12:21 pm
Yes you are right.
Debian,Mint,Ubuntu
Arduino Mega 2560
Arduino Nano
Arduino Duemilanove
MAC OS Montain Lion
Raspberry PI Model B

Nick Gammon

#6
Jul 06, 2013, 02:09 pm
Code: [Select]
` while(1){    if (millis() - startMillis > 30000) DoorError(); //longer than 30 sec means the string is tangled    if (digitalRead(TopSwitch) == 0) { //Switch is closed      digitalWrite(motorClosePin, LOW);  //Brake      digitalWrite(motorOpenPin, LOW);  //Brake      delay(500); //wait a bit      digitalWrite(HBRIDGEpower, LOW);  //power down the H Bridge      break;    }    delay(10);  }`

There is no problem with rollover, however I can see DoorError being called every 10 mS.
Please post technical questions on the forum, not by personal message. Thanks!

http://www.gammon.com.au/electronics

SouthernAtHeart

#7
Jul 06, 2013, 04:11 pm
Code: [Select]
`There is no problem with rollover, however I can see DoorError being called every 10 mS.`
why?  I don't see it.

SouthernAtHeart

#8
Jul 06, 2013, 04:28 pm
Oh, I see what you're saying.
If DoorError() is called, it shuts the whole system down ending with an endless while{} statement, waiting for the user to fix the problem.

Nick Gammon

#9
Jul 06, 2013, 10:34 pm
When you just post snippets we have to guess what the rest does.
Please post technical questions on the forum, not by personal message. Thanks!

http://www.gammon.com.au/electronics

BenF

#10
Jul 07, 2013, 07:18 am

As long as the interval being timed (30 sec here) is less than the ~50 day millis() rollover interval, ...

It will be good for 30 seconds, but not for ~50 days. The maximum interval we can time is half of that (2^32 / 2 - 1 = ~24.86 days).

32-bit max interval -> ~24.86days
16-bit max interval -> 32.767 seconds
8-bit max interval -> 127 milliseconds

#11
Jul 07, 2013, 08:13 am
It will be good for 30 seconds, but not for ~50 days. The maximum interval we can time is half of that (2^32 / 2 - 1 = ~24.86 days).

Are you certain?  Are you certain enough to wager?

BenF

#12
Jul 07, 2013, 09:13 am

It will be good for 30 seconds, but not for ~50 days. The maximum interval we can time is half of that (2^32 / 2 - 1 = ~24.86 days).

Are you certain?  Are you certain enough to wager?

Certain of what?

My post is addressing whether this quote is true or false:

"As long as the interval being timed (30 sec here) is less than the ~50 day millis() rollover interval, and if the comparison is done with subtraction and unsigned variables as it is here (good job!) then the rollover will never be a problem."

I say yes, but only if interval being timed is less than ~24 days.

#13
Jul 07, 2013, 09:16 am
I say yes, but only if interval being timed is less than ~24 days.

And I say you're wrong.  How would you like to proceed?

BenF

#14
Jul 07, 2013, 10:51 am
If you only care to express your opinion, I have nothing further to add.

If on the other hand, you want to contribute with insight or knowledge this is my take:

The difference between two unsigned quantities (as in the code discussed above and quoted below) is signed and so the interval is limited to the LONG_MIN ... LONG_MAX range.

Code: [Select]
`   if (millis() - startMillis > 30000) DoorError(); //longer than 30 sec means the string is tangled`

Go Up

Please enter a valid email to subscribe