High-Precision Timing Library for AVR

This lightweight library is specifically designed for millisecond-level time tracking. It supports the “unsigned long long” data type, allowing it to accurately track up to 584.9 million years! Additionally, it can adapt to clock frequencies of up to 20MHz, with most common frequencies having no timing errors.

Compared to Arduino’s built-in millis() timer, this library is especially useful when running at clock frequencies of 8MHz or below or when tracking time for more than 50 days.

Download from GitHub

Brief comparison against the Arduino millis()

Arduino millis()

  • Microsecond support
  • Doesn’t loose or gain time at any clock frequency
  • Loss of resolution at lower frequencies

This library

  • Faster execution
  • Less RAM used
  • Always updates millisecond count every millisecond
  • Support for ‘unsigned long long’ data type, 64 bit integer allows tracking time for up to 584.9 million years, Arduino millis() uses ‘unsigned long’ which goes up to 49.71 days
  • Uses CTC mode for the timer, which might make it a little bit more difficult to use the timer for multiple things

Accuracy at commonly used clock frequencies

ClockThis library (TIMER0)This library (TIMER1)This library (TIMER2)Arduino millis()
20MHzLoses 1.6ms each second
(0.16% error)
No errorLoses 1.6ms each second
(0.16% error)
No error
16MHzNo errorNo errorNo errorNo error
10MHzLoses 1.6ms each second
(0.16% error)
No errorLoses 1.6ms each second
(0.16% error)
No error
8MHzNo errorNo errorNo errorUpdates every 2ms
4MHzLoses 8ms each second
(0.8% error)
No errorNo errorUpdates every 4ms
2MHzNo errorNo errorNo errorUpdates every 8ms
1MHzNo errorNo errorNo errorUpdates every 16ms
500KHzLoses 8ms each second
(0.8% error)
No errorLoses 8ms each second
(0.8% error)
Updates every 8ms

When the table mentions ‘Updates every ##ms’ it means, for example, if it’s 16ms when getting the value of millis() then 10ms later getting the value again, they will both be the same value (unless the 16ms ended during the 10ms delay). Even when Arduino millis() gets ‘No error’ there is still a small jitter in the length of each millisecond since the interrupt doesn’t fire at exactly every 1ms.

Actual accuracy will ultimately depend on the accuracy of the uC clock source (external crystal, internal RC etc).

API

FunctionDescriptionParametersReturns
millis_init()Initializes library, must be called first!Nonevoid
millis_get()Get current millisecondsNonemillis_t
millis()Alias of millis_get(), only for non-Arduino since millis() is already usedNonemillis_t
millis_resume()Turn on timer and resume time keepingNonevoid
millis_pause()Pause time keeping and turn off timer to save powerNonevoid
millis_reset()Reset milliseconds count to 0Nonevoid
millis_add(millis_t ms)Add timems – Milliseconds to addvoid
millis_subtract(millis_t ms)Subtract timems – Milliseconds to subtractvoid