This rollover issue seems to cause quite a bit of confusion...
The right answer is that you need not worry about the millis()
rollover, as long as you do your calculation properly.
This is bad:
if (timeChanged + amountOfMs < currentTime) { ... }
This is good (rollover-safe):
if (currentTime - timeChanged > amountOfMs) { ... }
The reason it works is that arithmetics with unsigned integers (unsigned long in your case) reliably works modulo max+1 (ULONG_MAX+1
is 232). Thus, currentTime
, timeChanged
and their difference always have the correct value, modulo 232. As long as you test your button more often than once every 49 days (which is likely) the difference will be in the range of an unsigned long
, and your test will be correct.
Let put it another way: if millis()
rolls over between timeChanged
and currentTime
, then the difference currentTime - timeChanged
will be negative. But since the difference is actually computed with unsigned numbers, it will underflow and roll-over to the correct result. I do not like this explanation though, as it sounds like an error compensating another error. The truth is: if you think of unsigned numbers in terms of modular arithmetics, there is no error anywhere.