Millis() rover over handling

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!

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.

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.

  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

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(){}

Yes you are right.

 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.

There is no problem with rollover, however I can see DoorError being called every 10 mS.

why? I don't see it.

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.

When you just post snippets we have to guess what the rest does. :stuck_out_tongue:

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

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.

BenF:
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?

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.

   if (millis() - startMillis > 30000) DoorError(); //longer than 30 sec means the string is tangled

Hey! If there's a wager, I get 20% :wink:

[...] A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type. (ISO/IEC 9899:1999 (E) §6.2.5/9)

The second part of this page has a sketch to test it yourself.
And an example for a blinking led without rollover problem.
http://playground.arduino.cc/Code/TimingRollover

Ouch! You're as bad as my banker!

At first that also confuses me, subtracting an unsigned variable by another will always return a positive number.
Conclusion:
This is look like writing the range of an unsigned long around the globe and then travel by airplane around the globe.We will always see positive numbers during the travel even if we turn around and go back(subtracting the variable). The airplaine travel will always be between 0 and 4294967295 no matter if you go back or further. When it complete the the full range (4294967295 - rollover) it will see the number 0 and start again.
So there will never be negative number and the subtracting will always return a positive number or a 0.

Yes, and it works perfectly.
The only thing is that if you do this: if( ul_CurrentMillis - ul_PreviousMillis > ul_Interval)
The PreviousMillis value may be equal to the CurrentMillis, but never higher. That could cause a delay of 50 days.