Reading Servo PWM Signals on the Arduino & Wiring

We are interested in reading the number of microseconds that a digital pin is set to HIGH. Wiring natively lacks a micros() function to tell us this so we need to write an accurate one.This is the actual implementation of millis() in wiring.c for the Arduino.
unsigned long millis(){        // timer 0 increments every 64 cycles, and overflows when it reaches        // 256.  we would calculate the total number of clock cycles, then        // divide by the number of clock cycles per millisecond, but this        // overflows too often.        //return timer0_overflow_count * 64UL * 256UL / (F_CPU / 1000UL);        // instead find 1/128th the number of clock cycles and divide by        // 1/128th the number of clock cycles per millisecond        return timer0_overflow_count * 64UL * 2UL / (F_CPU / 128000UL);}
Timer0 is configured to use the /64 prescaler. This means it increments every 64 CPU cycles. Notice that they use the actual CPU frequency (F_CPU) to do the calculation.Note that the /64 prescaler will never give us a system that is more accurate than 512 steps. Most current radios support 1024 steps and some new 2.4Ghz and advanced FM systems have 2048 steps. Still 512 steps may be enough for our needs.The Paparazzi project, back when they were using an AVR chip, set Timer3 to have a prescaler of /8 so they could gain higher accuracy. This adds load to the chip though because it is more frequently handling an interrupt request for the counter overflow.

You need to be a member of diydrones to add comments!

Join diydrones

Email me when people reply –

Replies

  • Not sure if this thread is OBE (Overcome By Events), but I agree with Gareth, this function should be called on an interrupt and not run periodically. For more info on how to do that with Arduino, look here.

    http://www.arduino.cc/en/Reference/AttachInterrupt

    for a lot more info look here,

    http://www.uchobby.com/index.php/2007/11/24/arduino-interrupts/

    As for timer (hardware based) PWM output on the Arduino, it looks like there are 3 sets of pins, see the link above
  • 3D Robotics
    I'm just now getting to this function in my own code, and I'm confused by why you're not just using the PulseIn command. It does exactly what you want (read PWM), doesn't it?

    It works in Wiring, too.
  • So just what is going on here?:
    return timer0_overflow_count * 64UL * 2UL / (F_CPU / 128000UL);

    Here is what I do understand:

    The timer overflows once every 256 ticks. It ticks once ever 64 clock cycles. The CPU runs at 20 MHz and that value is stored in F_CPU. One overflow period takes 64 * 256 = 16384 clock cycles.

    for what its worth, at 20Mhz, one overflow period is ~0.8192 milliseconds. We say approximately because the CPU frequency isn't exactly 20MHz. Thats why its important to use the value in F_CPU.

    How many clock cycles does the overflow counter represent? Overflow count * clock ticks per overflow * prescaler value:
    timer0_overflow_count * 256UL * 64UL

    How many clock cycles make up a millisecond? CPU Frequency / milliseconds per second:
    (F_CPU / 1000)

    How do you get the number of milliseconds? clock ticks / clock ticks per millisecond
    (timer0_overflow_count * 256UL * 64UL) / (F_CPU / 1000)

    Thats yields the original implementation thats commented out in the source. It should yield accurate time. I think the current one is up to some tricks. Anyone want to try and explain?
This reply was deleted.

Activity

Neville Rodrigues liked Neville Rodrigues's profile
Jun 30
Santiago Perez liked Santiago Perez's profile
Jun 21
More…