Millis() roll over

From the start to 47,9 days the value of millis() rollover will occur and millis() starts with zero again. Every mS the value of millis() is increased by one. It is an unsigned long (32bits). With the use of timers you have to code in the right way. Initially i have coded it in the wrong way and expirenced faulty behaviour after 47,9 days because of the millis() rollover. I noticed it using analogue poll actions for my fishtank; i got a "flat liner" for the analogue values in the trends; timers didn't fire anymore. Searching the internet, it is a known issue.

There is just one right way to overcome this problem; check durations not different times! With this in mind and the fact that millis() is an unsigned long (with certain behaviour), the solution is very simple. Below i will try to explain what happens and show the right way of coding. For the example i used a 4 bit timer. With a starting timer of "12" and e.g. a wait time of "7", the rollover occurs. Notice in section "faulty code"; when the current time has passed the rollover, the timer will not expire at the expected moment. Because of the behaviour of an unsigned integer, coding stays simple and easy. Don't try to make code for checking the rollover; just use the right code as explained below; keep it simple and always use "CurrentTime - StartTime > Interval". No more code necassery!

In equation 1 and 2 i have tried to document what is happening with unsigned variables when the current time is smaller than the start time. Again this is behaviour of unsigned variables... 

TimeLine2

 

Below the equations. When subtracting unsigned variables where the value to subtract is greater then the initial value; the processor will invert the value to subtract, add it to the initial value and add 1 for the total sum. Pffff... don't try to understand, it works. But keep in mind:  use "CurrentTime - StartTime > Interval" for working with timers.

Equation

 

In the AFSM the following functions are available for timing:

  • Timer(time,TimerID), after "time" the function will be true for one cylce.
  • DelayTimer(time, TimerID), after "time" the function will be true.
  • BlockWave(time, TimerID), the boolean function result will be inverter every "time" period.
  • RestartDelayTimer(TimerID), the timer will be reset and starts again
  • CancelTimer(TimerID), the timer is cancelled

In the Userconfiguration.h file, you have to declare TimerID. See also the standard application examples. Time is in milleseconds.