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.
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);
}
}
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.
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(){}
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.
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.
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.
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
[...] 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)
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.