Here it is shown how to build a high frequency counter with Arduino and LM311 comparator to measure the frequency of a signal. The frequency counter shown here can measure frequency upto and above 6MHz which is quite high. There are several methods which can be used to build a frequency counter like using the input capture feature of Arduino(see Programming ATmega328p Input Capture) but they don't yield such high frequency measurement capability. This design uses counter to count the signal input waveform or pulses. It can measure of all kinds of waveforms like square wave, sine wave, sawtooth, triangle signals. The signal frequency measurement is important in electronics circuit design and such a DIY frequency counter could be helpful to many.
The circuit diagram of the frequency counter.
The Arduino frequency counter is based on measuring the number of pulses or count using the timer 1 T1 pin which is for Arduino Uno located at pin 5(PD5). It means that the Timer 1 is setup as counter which measures external events. The frequency of the signal to be measured is applied via 0.1uF capacitor at noninverting terminal pin 2 of the LM311 comparator. Here LM311 was used because it is a fast comparator. One can also use LM393 comparator or uA741 operational amplifier configured as comparator. When the signal input is higher than 0V then around 5V is output from the comparator and when the signal is lower than 0V then 0V is output from the comparator. The output appears at pin 7 which is then feed into the pin 5 of Arduino via the 6.8KOhm resistor. The output is also pulled up using a 10KOhm resistor. The LM311 actually is also performing voltage level shifting. The input signal amplitude can be low in milli volts range. The LM311 takes in that low voltage and outputs high level signal which can be detected by Arduino input pin. The frequency remains unchanged.
The following shows animation of how this Arduino frequency counter works.
In the above animation of the frequency counter, a signal generator applies signal of different amplitude and different frequency to the LM311 comparator whose output is connected to the Arduino pin 5. In the animation, there is missing 10KOhm and 6.8KOhm at the output pin 7 of the LM311 comparator. These resistors are necessary. See the connection in the circuit diagram shown above.
The program for the Ardiuno Frequency Counter is as follows.
#include <FreqCounter.h>
#include <LiquidCrystal.h>
#include <stdlib.h>
#define countdelay 1 // measurement delay
#define calibration 0 // adjusts frequency for variation in Arduino
#define gatetime 100 // gate time in milliseconds
#define onems 1000 // alias for 1000 milliseconds
LiquidCrystal lcd(12, 11, 9, 8, 7, 6); // setup the LCD interface pins
char units[][5] = {"Hz", "KHz", "MHz"}; //units of frequency to be used later
void setup(){
lcd.begin(16,2); // initialize the LCD
lcd.print("** Frequency **"); //initial message
lcd.setCursor(0,1);
lcd.print("** Counter **");
delay(100); //100ms startup delay
}
void loop() {
char Freq[16]; //to store frequency
unsigned long Fcalc=0;
float Fval;
FreqCounter::f_comp=calibration; // calibrate with known source
FreqCounter::start(gatetime); // count pulses for specified gating period
while (FreqCounter::f_ready == 0)
Fcalc = FreqCounter::f_freq;
delay(countdelay);
Fval = (float) Fcalc * (onems / gatetime); // scale the input
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Freq.:");
//check and display in frequency correct units
if(0 <= Fval && Fval < 1000){
dtostrf(Fval, 3, 2, Freq);
strcat(Freq, units[0]);
lcd.setCursor(0,1);
lcd.print(Fval);
lcd.print(units[0]);
}
else if(1000 <= Fval && Fval < 1000000){
Fval = Fval/1000;
dtostrf(Fval, 3, 2, Freq);
strcat(Freq, units[1]);
lcd.setCursor(0,1);
lcd.print(Freq);
}
else if(1000000 <= Fval){
Fval = Fval/1000000;
dtostrf(Fval, 3, 2, Freq);
strcat(Freq, units[2]);
lcd.setCursor(0,1);
lcd.print(Freq);
}
else{
lcd.setCursor(0,1);
lcd.print("Out of Range");
}
}
In the program code above, we have used the FreqCounter(FreqCounter.h header) library which you can download at the following url:
https://github.com/Arduino-IoT/libraries/tree/master/FreqCounter
We have used the #define to use alias name for some of variables required later in the program. A 16x2 LCD is used here to display the frequency and to use the LCD we have used the LiquidCrystal library. In the setup() we have initialiated and started the LCD library. Then we print out some initial message.
In the main loop() we start with calibration of the frequency counter library. Here calibration is done such that a known frequency is applied to the frequency counter. Using this known frequency calibration of timing is done internally by the frequency counter library. Then frequency counter is started with a certain gate time which is 100ms here. The gate time is the time over which sampling of the input signal is done. After this the frequency is calculated and then the frequency measured is scaled properly to get frequency in Hz. Using if else statement the measured frequency count is displayed in Hz, KHz or MHz.
Testing of Frequency counter
Here Arduino Mega frequency generator described in earlier tutorial Arduino 8MHz Signal Generator with ISR is used to generate signal and fed that signal into this Arduino Uno frequency counter.
The connection is as shown.
In the above diagram, the potentiometer on Arduino Mega is rotated to change the frequency of square wave which appears at Pin 13. This pin 13 of Arduino Mega is connected to the LM311 via the coupling capacitor.
The following video demonstrates how the above Arduino mega function generator with Arduino Uno frequency counter works.
Here we have used Arduino Uno Timer 1 in counter mode to measure the frequency of a signal with arbitrary amplitude. Another method suitable to measure frequency of a signal with Arduino is using the input capture method. This is explained with code in Programming ATmega328P Input Capture with Interrupt.
Also if you want DIY home electronics testing tools then see the following tutorials.
- High Frequency Counter with Arduino
- Arduino 8MHz Variable Frequency Generator
- How to use Matlab Simulink as Oscilloscope
- Arduino UNO sine wave generator
Hi. I came across your frequency counter for arduino project. Great job and thanks for sharing. If I can make a suggestion, I think leaving R2 out and adding a multiturn 100k pot between pin3 of the lm311 and ground, you should see a marked improvement in gain and linearity. The pot is useful in optimizing the voltages at pin 2 and 3 to sharpen the comparator threshold. Thanks again and good luck on your future projects.
i will try your suggestion. thank you.
To get an even sharper curve I added a 74LS04 and fed it with the signal cascading three of it's inverters. The final waveform was a decent square wave with only a few millivolts at the input of the opamp up to about 2-3Mhz at which point the LM311 is at the limit of its bandwidth. Thanks for your answer and keep it up !
nice share thank you
when I try to compile the sketch you have provided I keep getting
exit status 1
'FreqCounter' has not been declared
do you include the library, if not you can download and install from this link:https://github.com/Arduino-IoT/libraries/tree/master/FreqCounter
Hi when i try to compile the frequency counter sketch I keep getting "C:\Users\saira\AppData\Local\Temp\.arduinoIDE-unsaved2024410-20828-14afd95.g6mc\sketch_may10a\sketch_may10a.ino: In function 'void loop()':
C:\Users\saira\AppData\Local\Temp\.arduinoIDE-unsaved2024410-20828-14afd95.g6mc\sketch_may10a\sketch_may10a.ino:25:2: error: 'FreqCounter' has not been declared
FreqCounter::f_comp=10; // calibrate with known source
^~~~~~~~~~~
C:\Users\saira\AppData\Local\Temp\.arduinoIDE-unsaved2024410-20828-14afd95.g6mc\sketch_may10a\sketch_may10a.ino:26:2: error: 'FreqCounter' has not been declared
FreqCounter::start(100); // count pulses for specified gating period
^~~~~~~~~~~
C:\Users\saira\AppData\Local\Temp\.arduinoIDE-unsaved2024410-20828-14afd95.g6mc\sketch_may10a\sketch_may10a.ino:27:9: error: 'FreqCounter' has not been declared
while (FreqCounter::f_ready == 0)
^~~~~~~~~~~
C:\Users\saira\AppData\Local\Temp\.arduinoIDE-unsaved2024410-20828-14afd95.g6mc\sketch_may10a\sketch_may10a.ino:28:11: error: 'FreqCounter' has not been declared
Fcalc = FreqCounter::f_freq;
^~~~~~~~~~~
Using library FreqCount at version 1.3 in folder: C:\Users\saira\Documents\Arduino\libraries\FreqCount
Using library LiquidCrystal at version 1.0.7 in folder: C:\Users\saira\Documents\Arduino\libraries\LiquidCrystal
exit status 1
Compilation error: 'FreqCounter' has not been declared