Precision Frequency Measurement Library For 8-bit Microcontrollers

[Paul] has been working on porting over Arduino libraries for use with the Teensy microcontroller platform. This tends to be pretty simple since they both use the same Atmel chip architecture. But once in a while he finds the Arduino libraries are not what they’re cracked up to be. When looking to port over a frequency measurement library he ended up writing his own that works better and is much more portable.

He had two big beefs with the Arduino Frequency Counter Library. The first is that it required the compensation factor the be calibrated using an accurate frequency counter. That’s a chick-and-egg problem since many people who build a frequency counter with an Arduino are doing so because they don’t already have a standalone tool. The second problem is that the Arduino library was hardcoded for ATmega168 or ATmega328 chips.

This new library fixes both issues with just one trade-off. Your hardware setup must be using a crystal oscillator. You can see above in the image above that the frequency measurement is quite accurate with this method. The package also uses a thin abstraction layer which will make it easy to port to any 8-bit microcontroller which is programmed in C.

7 thoughts on “Precision Frequency Measurement Library For 8-bit Microcontrollers

  1. @Scott – yes, sort of. The AVR timer appears to require your input to be high for at least one CPU clock and low for at least one, so if your waveform is exactly 50% duty you could directly measure up to about half the AVR’s clock speed. So a 20 MHz crystal ought to get you about 10 MHz. The timer abstraction file doesn’t have a #define for 20 MHz, so you’d need to add that.

    I wrote 5 MHz to be a bit conservative. That transistor input amp doesn’t preserve the duty cycle nicely, so in my testing it crapped out not far above 5 MHz.

    Of course, you can indirectly measure much higher frequencies if you use flip-flops or counters to divide the input down.

  2. The crystal oscillators on Arduinos are (in my experience) commonly off by a few hundred parts per million at room temperature, and with thermal coefficients of more than 10 ppm per degree C, so take any claims of accuracy with the requisite number of grains of salt.

  3. @Andrew – I wouldn’t be surprised by that on some boards.

    Atmel doesn’t publish a pin capacitance spec for XTAl1 and XTAL2, so the only way really design a good board is to guess about 5 pF and then try tuning by soldering different capacitors while checking with an accurate frequency counter.

    I did that on both Teensy boards using the OSCOUT fuse, and that BK Precision 1823A you see in the photo, soldering in 1 pF steps at a time, until I found between 10 to 11 pF, closer on the 10 side. A few times I’ve considered renting a far more accurate, NIST traceable counter, but since the 1823A matches pretty closely to that Protek B8010FD, I’ve been willing to call that “good enough”.

    Teensy also uses a higher quality crystal with ground connections to its case, and I put a dedicated (no other ground currents) ground plane under the crystals.

    Sadly, I suspect on many “duino” boards they just use 22 or 33 pF and never accurately measure or tune for their chip package and board layout. That’s sad, because just using the right capacitor makes the crystal as good as it can be. Unnecessary for most people, but then again, how hard is it to just use the best board layout capacitance value?

    The Uno even uses a ceramic resonator, which is truly sad. I tested on an Uno and it was off in the 4th digit. :-(

    But I tried to make the code as good as possible.

  4. @Paul: “The Uno even uses a ceramic resonator, which is truly sad. I tested on an Uno and it was off in the 4th digit. :-(”

    So true! On a $30.00 board can’t they spare another 50 cents for a crystal???

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.