Developing in C for the ATmega328: Marking Time and Measuring Time

2 minute read

Where I discuss marking time and measuring time using the new Standard C framework.



The Arduino has two time routines, millis() and micros(). The former provides the ability to measure time in milliseconds for a long period of time (50 days) and the latter provides the ability to measure in microseconds (kinda) for a far shorter period of time, 70 minutes. The kinda arises from this comment from the arduino reference on micros()On 16 MHz Arduino boards (e.g. Duemilanove and Nano), this function has a resolution of four microseconds (i.e. the value returned is always a multiple of four). On 8 MHz Arduino boards (e.g. the LilyPad), this function has a resolution of eight microseconds.

The AVR_C approach is slightly different. It’s most fundamental time element is a tick, which is the clock period of the processor. On a 16MHz ATmega328P, this is 62.5 nanoseconds. To determine elapsed ticks, one needs to call ticks() twice, one before the event and one after, then the delta the number of ticks passes. There are two things to understand:

  1. Dividing a tick by 16 gets you 1 microsecond, which is the same as shifting to the right, 4 times. So micros() is effectively (ticks() » 4).
  2. There is a micros() routine which will return the number of micros() elapsed, however it is a derivative of ticks(), it simply returns ticks() shifted to the left four times (see point 1.) When this is done there can be rounding errors, to see examples of this, see the example micros. When run, it will show:
Testing System Ticks (1 tick = 62.5ns)
Delay of 1 ms
ticks() -> micros:      1001 1001 1001 1001 1001 1001 1001 1001 1001 1001  Complete
micros():               1003 62443 1003 1003 1003 62443 1003 1003 1003 1003  Complete
  1. The routine ticks() only counts to 65,535, so it rolls over at approximately 4 milliseconds. As of now, there isn’t a rollover mechanism to keep track, so you will need to do this manually.

Comments powered by Talkyard.