skip navigational linksPJRC
Shopping Cart Checkout Shipping Cost Download Website
Home MP3 Player 8051 Tools All Projects PJRC Store Site Map
You are here: Teensy Teensyduino Libraries FreqMeasure

PJRC Store
Teensy 3.1, $19.80
Teensy 2.0, $16.00
Teensy++ 2.0, $24.00
USB Cable, $4.00
Teensy
Main Page
Teensy 3.1
Getting Started
How-To Tips
Code Library
Projects
Teensyduino
Reference

FreqMeasure Library

FreqMeasure measures the elapsed time during each cycle of an input frequency. See FreqCount vs FreqMeasure below to choose the best library. FreqMeasure works well for RPM (rotations per minute) tachometer applications.

Download: FreqMeasure.zip (version 1.0)


FreqMeasure LCD_Output Example Running on Teensy++ 2.0

Hardware Requirements

FreqMeasure requires the input frequency as a digital level signal on a specific pin.

BoardFrequency
Input Pin
Pins Unusable
with analogWrite()
Teensy 1.01615, 17, 18
Teensy 2.0109
Teensy++ 1.01714, 15, 16
Teensy++ 2.01714, 15, 16

If the input signal may have noise or could be a high frequency, adding a low pass filter is a good idea.


An amplifier may be needed if the input signal is a sine wave or small AC signal which can not directly drive a TTL logic level input.

Basic Usage

FreqMeasure.begin();

Begin frequency measurement.

FreqMeasure.available();

Returns the number of measurements available to read, or 0 (false) if none are unread. If your program spends time on other tasks and a relatively fast waveform is being measured, several readings may be available.

FreqMeasure.read();

Read a measurement. An unsigned long containing the number of CPU clock cycles that elapsed during one cycle of the waveform. To convert to frequency, F_CPU should be divided by this number. Each measurement begins immediately after the prior one without any delay, so several measurements may be averaged together for better resolution.

FreqMeasure.end();

Stop frequency measurement. PWM (analogWrite) functionality may be used again.

Example Program

Open from the menu: File > Examples > FreqMeasure > Serial_Output
#include <FreqMeasure.h>

void setup() {
  Serial.begin(57600);
  FreqMeasure.begin();
}

double sum=0;
int count=0;

void loop() {
  if (FreqMeasure.available()) {
    // average several reading together
    sum = sum + FreqMeasure.read();
    count = count + 1;
    if (count > 30) {
      double frequency = F_CPU / (sum / count);
      Serial.println(frequency);
      sum = 0;
      count = 0;
    }
  }
}


Serial_Output Example, With 120 Hz Signal

Zero Handling

Because FreqMeasure works on a per-cycle time frame, it is impossible to directly measure zero frequency. When displaying frequency, such as the LCD_Output example, if the input frequency stops, the most recent measurement will remain on the display.

To detect zero, a timeout must be implemented. On simple approach would be to record the millis() time when FreqMeasure.available() returns true. When it returns false, check if too much time as elapsed and update the output to show zero.

CPU Requirements

At the end of each cycle, an interrupt routine runs. The actual capture of elapsed time is done by hardware, so some interrupt latency is acceptable.

At relatively low frequencies, under 1 kHz, only minimal CPU time is used. However, as the frequency increases, the interrupt demands more CPU time. A hardware low-pass filter is recommended if the input frequency could possibly be much higher than several kHz.

If interrupts are disabled for more than 1 cycle of the waveform, the measurement can span 2 or more cycles. Libraries which disable interrupts for long times (eg, NewSoftSerial) can be problematic.

FreqCount vs FreqMeasure

FreqCount: best for 1 kHz to 5 MHz
FreqMeasure: best for 0.1 Hz to 1 kHz

FreqCount measures the number of cycles that occur during a fixed "gate interval" time. This works well for relatively high frequencies, because many cycles are likely to be counted during gate interval. At lower frequencies, very few cycles are counted, giving limited resolution.

FreqMeasure measures the elapsed time during a single cycle. This works well for relatively low frequencies, because a substantial time elapses. At higher frequencies, the short time can only be measured at the processor's clock speed, which results in limited resolution.

Arduino Uno, Duemilanove, Mega, and Sanguino

FreqMeasure can be used on Arduino, Sanguino and probably other boards. See the file util/capture.h for details to port to other AVR-based boards.

BoardFrequency
Input Pin
Pins Unusable
with analogWrite()
Arduino Uno89, 10
Arduino Duemilanove89, 10
Arduino Mega496, 7, 8
Sanguino1412, 13

Arduino Mega's pin 49 may be used by the SPI library, or SPI-based libraries like Ethernet or SD. You may need to edit FreqMeasure's util/capture.h to use ICP5 (pin 48) instead of ICP4.

Other Frequency Measurement

Martin Nawrath's FreqCounter and FreqPeriod are similar to FreqCount and FreqMeasure. I originally ported FreqCounter to Teensy, but could not get it to work reliably. It did work, but had trouble at certain frequencies, and requires a "compensation" factor for accurate results. Ultimately I wrote a FreqCount from scratch, using a thin hardware abstraction layer for easy porting to different boards, and accurate results without a compensation factor. I also used a more Arduino-like API (begin, available, read) and designed for continuously repeating measurements. I did not try to use FreqPeriod.