Menu
CoddyTech

When millis() Rolls Over

Part of the Timing Without Delay section of Coddy's Arduino journey. Lesson 17 of 18.

An unsigned long stops at 4,294,967,295. After about 49.7 days, millis() reaches it and starts again at 0. This is called rolling over.

A smaller type shows the same thing. An unsigned int stops at 65535:

unsigned int a = 65530;
a = a + 10;   // 65540 does not fit: a is now 4

Subtraction wraps the same way, and that makes it safe: a clock that started at 65530 and now reads 4 has counted 10 steps, and 4 minus 65530, stored in an unsigned int, is exactly 10. In the same way, millis() - start is always the time since start, even across a rollover.

Adding is not safe. In now >= start + interval, the sum can pass the top and wrap to a small number, so the timer is done at once. And when now has wrapped but the sum has not, it is never done. Always subtract:

if (now - start >= interval) {
  // done
}
challenge icon

Challenge

Medium

Nobody can wait 49 days for a test, so this sketch feeds isDone() times close to the rollover and prints its answers. It says "done" too early and "waiting" forever. Fix the one line in isDone() so it compares the time since start with interval.

Press Run, read the four answers, fix the line, then Check.

Try it yourself

const unsigned long interval = 2000;

// Is the timer that started at start done at the time now?
bool isDone(unsigned long start, unsigned long now) {
  return now >= start + interval;   // fix this line
}

// Prints how long it has been and what isDone() says.
void test(unsigned long start, unsigned long now) {
  Serial.print(now - start);
  Serial.print(" ms: ");
  if (isDone(start, now)) {
    Serial.println("done");
  } else {
    Serial.println("waiting");
  }
}

void setup() {
  Serial.begin(9600);
  // millis() stops at 4294967295, then starts again at 0
  test(4294966000, 4294966500);   // just before the wrap
  test(4294966000, 4294967200);   // still before it
  test(4294966000, 900);          // the clock went past 0
  test(4294964000, 500);          // a timer that started earlier
}

void loop() {
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Timing Without Delay

Practice on your own: Arduino playground