Store millis() in an unsigned long and compare by subtraction. Written like that, the timer survives the roll-over.
What the message means
millis() counts up to a large number and then starts again from zero. A signed or smaller variable overflows sooner and breaks the comparison.
Fix it in this order
- Declare the variable as unsigned long.
- Use if (millis() – last >= interval) and then set last = millis().
- Do not write if (millis() > last + interval).
- Do not store millis() in an int, which wraps after about 32 seconds on an Uno.
- Use micros() for short times, and know that it rolls over much sooner.
Why it happens
millis() returns an unsigned long that wraps back to zero after about 49.7 days. Code that compares absolute times can fail at that point, and a variable that is too small, such as an int, wraps much sooner.
Store times in unsigned long variables and compare by subtracting, which stays correct across the wrap.
unsigned long last = 0;
if (millis() - last >= 1000UL) { // works across the wrap
last = millis();
}
Example sketch: change pins and values for your own wiring. It has not been bench-tested on your hardware.
If you see this, do this
| You see | Do this |
|---|---|
| Timer stops after some seconds | Variable is an int. |
| Timer fails after weeks | Use subtraction. |
Related
delay and millis, integer division.
Last reviewed: November 2026. These are the usual causes and the order that finds them fastest. Test on your own board; clones and cables differ.