Is a more correct millis() rollover possible?

I’ve done the math and the Using millis() for timing sticky post is only somewhat correct in stating that it will work through a rollover. It depends on your definition of what will work.

Essentially the program will not crash. However if the currentMillis - ULONG_MAX (4294967295) < period when the code section is run then when the rollover happens for sure currentMillis - startMillis >= period. The problem is the elapsed time is actually less than the period.

So if your program is expecting exact timing then this will not work. Am I on the right track? Did I do the math right? Is there a way to check for this and make it exact. Of course this exactness depends on the other sections of code that run in between which could have variable amounts of execution time. But assuming all else equal. Thanks.

Please read this:

http://www.gammon.com.au/forum/?id=12127

Explain this exactly:

your program is expecting exact timing

Did I do the math right?

No

To make it easier to understand let's use a byte variable instead of unsigned long as the numbers are easier to get your head round.

Example: If your old time was at 250 and now you're at 5 , you calculate (5 - 250) and interpret the result as an unsigned byte, the result is 11, which is correct

Pretty unlikely that a “problem” with the millis() timing technique would have gone on “undiscovered” until 8 March, 2018.

This is the only warning you have to consider:

I found this to fix my problem.

It includes a technique for testing a solution without waiting 56 days.

alto777:
I found this to fix my problem.

programming - How can I handle the millis() rollover? - Arduino Stack Exchange

It includes a technique for testing a solution without waiting 56 days.

along with about a gajillion explanations on this forum, too.

alto777:
I found this to fix my problem.

programming - How can I handle the millis() rollover? - Arduino Stack Exchange

It includes a technique for testing a solution without waiting 56 days.

I have another technique. It is to use micros() rather than millis(). That way, rollover happens within an hour and a quarter.

alto777:
I found this to fix my problem.

programming - How can I handle the millis() rollover? - Arduino Stack Exchange

It includes a technique for testing a solution without waiting 56 days.

Thanks for the link to the explanation that is given regarding modular arithmetic. Initially I was doing the math by hand wrong. By exact timing I meant that my test condition would not be true until AT LEAST the period had elapsed. Okay so thats not exact timing. Sorry. I was concerned that at rollover the condition would become true. My test condition is in the program I wrote to simulate a timer rollover:

void setup() {
  unsigned long startMillis = 0xFFFFFFFA;
  unsigned long currentMillis = 0xFFFFFFFA;
  unsigned long period = 0x0000000C;

  Serial.begin(9600);
  Serial.println();

  Serial.print("currentMillis = ");
  Serial.println(currentMillis);
  Serial.print("startMillis = ");
  Serial.println(startMillis);
  Serial.print("millis before 0 rollover = ");
  Serial.println(0xFFFFFFFF - startMillis + 1);
  Serial.print("CurrentMillis - startMillis = ");
  Serial.println(currentMillis - startMillis);
  Serial.print("period = ");
  Serial.println(period);
  Serial.print("currentMillis - startMillis > period: ");
  Serial.println((currentMillis - startMillis > period)?"True":"False");

  // Rollover
  Serial.println();
  currentMillis = 0x00000000;
  Serial.print("currentMillis = ");
  Serial.println(currentMillis);
  Serial.print("startMillis = ");
  Serial.println(startMillis);
  Serial.print("CurrentMillis - startMillis = ");
  Serial.println(currentMillis - startMillis);
  Serial.print("period = ");
  Serial.println(period);
  Serial.print("currentMillis - startMillis > period: ");
  Serial.println((currentMillis - startMillis > period)?"True":"False");

  // Elapsed time = period
  Serial.println();
  currentMillis = 0x00000007;
  Serial.print("currentMillis = ");
  Serial.println(currentMillis);
  Serial.print("startMillis = ");
  Serial.println(startMillis);
  Serial.print("CurrentMillis - startMillis = ");
  Serial.println(currentMillis - startMillis);
  Serial.print("period = ");
  Serial.println(period);
  Serial.print("currentMillis - startMillis > period: ");
  Serial.println((currentMillis - startMillis > period)?"True":"False");
}

void loop() {
    // put your main code here, to run repeatedly:
}

And the output:

currentMillis = 4294967290
startMillis = 4294967290
millis before 0 rollover = 6
CurrentMillis - startMillis = 0
period = 12
currentMillis - startMillis > period: False

currentMillis = 0
startMillis = 4294967290
CurrentMillis - startMillis = 6
period = 12
currentMillis - startMillis > period: False


currentMillis = 7
startMillis = 4294967290
CurrentMillis - startMillis = 13
period = 12
currentMillis - startMillis > period: True