Go Down

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

SouthernAtHeart

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 pm Last 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.
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

SouthernAtHeart


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

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

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

Debian,Mint,Ubuntu
Arduino Mega 2560
Arduino Nano
Arduino Duemilanove
MAC OS Montain Lion
Raspberry PI Model B

Nick Gammon

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!

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

SouthernAtHeart

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

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

When you just post snippets we have to guess what the rest does. :P
Please post technical questions on the forum, not by personal message. Thanks!

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

BenF


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

Coding Badly

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


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.


Coding Badly

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

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