Arduino: Better Microsecond Resolution Than Micros()?


Answer :

Yes, depending your Arduino's basic clock rate. For example here are the counter-timer input frequencies and periods after pre-scaling, for an ATMega2560's counter-timer 2, and a basic clock rate of 16MHz. The timer has built in "prescaler" value options which determine frequency/period, shown in this table:

    TCCR2B bits 2-0    Prescaler    Freq [KHz], Period [usec] after prescale           0x0          (TC stopped)      --         --           0x1                1        16000.        0.0625           0x2                8         2000.        0.500           0x3               32          500.        2.000           0x4               64          250.        4.000           0x5              128          125.        8.000           0x6              256           62.5      16.000           0x7             1024           15.625    64.000 

For better timing resolution, you use a value called TCNT2. There is build in counter that goes from 0 to 255 because the timer is 8 bit. When the counter reaches the value assigned by TCNT2 it triggers an interrupt. This interrupt is called TIMER2_OVF_vect.

given this information, the resulting interrupt rate would be: 16MHz / (prescaler * (255 - TCNT2))

You could get the timer to run at the full 16MHz (62.5nSec) though that's way faster than you need; 2MHz with an initial count of (255-2) would give you 1MHz interrupt rate. Divide that by 2 in your ISR:

extern uint32_t MicroSecClock = 0;  ISR(TIMER2_OVF_vect) {// this is a built in function that gets called when the timer gets to the overflow counter number   static uint_8 count;            // interrupt counter    if( (++count & 0x01) == 0 )     // bump the interrupt counter     ++MicroSecClock;              // & count uSec every other time.    digitalWrite(53,toggle);// pin 53 is arbitrary   TCNT2 = 253;                    // this tells the timer when to trigger the interrupt. when the counter gets to 253 out of 255(because the timer is 8 bit) the timmer will trigger an interrupt   TIFR2 = 0x00;                   // clear timer overflow flag }; 

The data sheet for your MCU is the basic resource; this article will give you (and gave me!) a good head-start.


If dropping down to AVR Level is acceptable (as you mentioned in your question), you can set up a timer and even get the ticks of the AVR's clock.

You need to refer to your AVR's datasheet because it differs within the different ATMegas and ATTinys. But the procedure is always the same. What you need to do is:

  • decide which prescaler to use (for example set it to 1, i.e. no prescaling if you want the actual CPU clock speed), refer to the TCCR documentation
  • set up a timer overflow interrupt, an interrupt handler and activate interrupts globally
  • activate the timer in the Timer/Counter Control Register TCCR

That way can get the exact ticks from the timer register, however you need to count the overflows manually. This is as precise as possible by technology.

Here is some example code for the outdated AT90S2313, but it gives you good hints what to do basically:

/* uC: AT90S2313 */ #include <avr/io.h> #include <avr/interrupt.h>  int main(void) {   // set up timer 0   TCCR0 = (1<<CS01); // Prescaler 8    // enable overflow interrupt   TIMSK |= (1<<TOIE0);    // activate interrupts   sei();    while(1)   {      /* Do whatever you like */   } }   ISR (TIMER0_OVF_vect) {        /*       This gets called everytime there in an overflow in the timer register      */ } 

Mark, I decided to write a new set of functions, based on the Arduino Atmega328 Timer2, and using overflow interrupts, to get precision to 0.5us. My code is available for download and use here:

http://electricrcaircraftguy.blogspot.com/2014/02/Timer2Counter-more-precise-Arduino-micros-function.html

Here's a brief description: "I wrote a "libary" to get 0.5us precision on a "micros()" replacement function, so that I can get repeatable results reading a PWM or PPM signal, to within 1us. I searched all around the internet and could not find something comparable (or that was easy to use, and maintained the Arduino's ability to write PWM signals via the Servo Libary), so I think this is my first major contribution to the world of Arduino and Radio Control."


Comments

Popular posts from this blog

Are Regular VACUUM ANALYZE Still Recommended Under 9.1?

Can Feynman Diagrams Be Used To Represent Any Perturbation Theory?