In this post, we’ll explore how to build a high-frequency counter using an Arduino and an LM311 comparator. This setup enables accurate frequency measurement of various signal waveforms, such as sine, square, triangle, and sawtooth, with frequencies up to and beyond 6 MHz.
Unlike other methods, such as utilizing the input capture feature of an Arduino (discussed in detail in Programming ATmega328p Input Capture), this approach leverages the counter mode of Arduino’s Timer 1, ensuring compatibility with high-frequency signals. Whether you are designing electronic circuits or need a reliable tool for signal analysis, this DIY frequency counter is a versatile and cost-effective solution.
Why Use an LM311 Comparator?
The LM311 comparator plays a critical role in the circuit. It processes the input signal and converts it into a format suitable for the Arduino to measure:
- Voltage Level Shifting: The LM311 can handle low-amplitude signals in the millivolt range and outputs a clean digital signal (0V or 5V).
- Speed: It operates at high speeds, ensuring accurate frequency measurement. Alternatives like the LM393 or the uA741 operational amplifier configured as a comparator can also work but may not match the LM311's performance at higher frequencies
Circuit Design
Components Required
- Arduino Uno
- LM311 comparator
- 0.1µF coupling capacitor
- 6.8 kΩ and 10 kΩ resistors
- 16x2 LCD display (optional, for frequency visualization)
- Breadboard and connecting wires
Circuit Diagram
The circuit diagram is shown below.
The signal whose frequency is to be measured is fed into the non-inverting terminal (pin 2) of the LM311 via a 0.1 µF capacitor. The output (pin 7) of the LM311 is connected to Arduino’s Timer 1 input pin (pin 5, PD5) through a 6.8 kΩ resistor. A 10 kΩ pull-up resistor ensures stable logic levels at the comparator output.
Note: Ensure the 6.8 kΩ and 10 kΩ resistors are connected as shown in the schematic for proper operation.
Working Principle
- The input signal is processed by the LM311. For signal levels above 0V, the LM311 outputs ~5V; for signal levels below 0V, it outputs 0V.
- The Arduino Uno counts these pulses using Timer 1 configured in counter mode.
- The counted pulses are processed and displayed on an LCD, showing the frequency in Hz, kHz, or MHz.
Code Implementation
Below is the Arduino code for the high-frequency counter. It utilizes the FreqCounter library for pulse counting and the LiquidCrystal library for displaying results on a 16x2 LCD.
#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");
}
}
Libraries Used
- FreqCounter Library: Facilitates pulse counting during the specified gate time.
- LiquidCrystal Library: Manages the LCD for displaying frequency values.
Download the FreqCounter library from this GitHub repository.
Testing the Frequency Counter
For testing:
- Use a signal generator (or any device producing periodic signals) to provide input to the LM311.
- An Arduino Mega-based frequency generator (e.g., as described in Arduino 8MHz Signal Generator with ISR) can also serve as the signal source.
Connection Setup
- Connect the signal generator output to the LM311 input through the coupling capacitor.
- Adjust the signal generator’s frequency and observe the corresponding frequency on the LCD.
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.
Advantages of This Design
- Measures high-frequency signals up to 6 MHz or more.
- Compatible with various waveforms.
- Simple and cost-effective, leveraging readily available components.
Related Tutorials
- DIY LCR Meter Using PC
- Arduino 8MHz Variable Frequency Generator
- Programming ATmega328P Input Capture with Interrupt
- How to Use MATLAB Simulink as Oscilloscope
This frequency counter project is perfect for electronics enthusiasts and professionals alike. Experiment, calibrate, and use it as a valuable addition to your DIY electronics toolkit!