When working with Arduino, there are many times where you want to do something after a set time. The best way to do this is to determine how long it has been since a set time using the millis() function. However, this poses a problem. Millis returns the number of milliseconds that have elapsed since the program begin. It is stored as an unsigned long. On an AVR microcontroller, like on the UNO, an unsigned long (uint32_t) is an integer that is stored in 32 bits (4 bytes), giving it a value range of 0 – 4,294,967,295. Therefore, once 4,294,967,295 milliseconds have passed, millis will overflow and start again at 0. Since 4,294,967,295 is only about 50 days (49.71), we need to be sure to handle this rollover effect. Otherwise, after 50 days, our code will quit working until the board is reset.

Let’s begin with looking at the proper way to handle a millis() overflow and then we will look at why.

**This method will work even if millis() overflows.**

1 2 3 4 5 6 7 8 9 10 |
unsigned long lastTime = millis(); unsigned long interval = 1000; void loop(){ if (millis() - lastTime >= interval){ // do something every second lastTime = millis(); // reset last time fired } } |

In this example, we are using the recommended method of subtracting. In a non overflow state this will work like this. Let’s say the start time is 2000 ms. At 3000 ms this if statement will work like this.

1 |
if (3000 - 2000 >= 1000){ // true statement |

So this will cover us during normal operation. Now let’s look at how it will work during an overflow situation. Let’s say our lastTime is 4,294,967,000. Since the millis will overflow at 4,294,967,295 our 1 second fire time will need to fire at the new overflow time of 705 milliseconds, because it is after the rollover. This will give us a statement like this.

1 |
if (705 - 4294967000 >= 1000){ // true statement |

If we break it down, 705 – 4294967000 = -4,294,966,295. Obviously -4,294,966,295 is not greater than 1000 in normal math, but, we are using unsigned integers here and that makes math behave differently than it would in the normal world. unsigned integers do not go negative. It will actually roll over just like millis does, we are just rolling it over in reverse. To look at what the reverse rollover of -4,294,966,295 is, we just subtract the negative number from the max unsigned long value. so 4,294,967,295(max unsigned long value) – 4,294,966,295(our reverse rollover value) = 1000. Therefore, the statement is greater than or equal to 1000, and it will process as true.