This photo show the PCB of the arduino frequency counter. Arduino Frequency Counter Shield
1 Hz - 2.5 GHz with 2x16 LCD display

This shield fits Arduino UNO and turns it to a very powerful frequency counter instrument.
The shield consist of all complex parts you need for a high performance frequency counter with an onboard high performance crystal.
The Arduino code is super simple, No Arduino interrupts, No Arduino timer register used for counting or gating.
Just one line of code and that is it...

  • The shield has two input channels (low frequency and high frequency).
  • Channel Fin Low: 1 Hz to 50 MHz with resolution of 1 Hz
  • Channel Fin High : 5 MHz to 2.5 GHz with resolution of 100 Hz
  • High sensitivity inputs typ -25dBm to -10dBm (12mV to 70mV) both channels
  • Channel Fin Low : Input Impedance > 1 M Ohm
  • Channel Fin High : Input Impedance 50 Ohm
  • Both inputs are protected for transients and ESD over voltage
  • Onboard accurate VCTXO (max error is 1 Hz at 50 MHz)
  • Option for External 10.00000 MHz reference signal (GPS time base)
  • No pre- or post-flank errors
  • Option to control 2x16 LCD display
  • Board size = match for Arduino UNO
  • Board size = 71 x 53.4 mm Drawing
  • This project comes only in a KIT version, see more details below

  • All contribution to this page are most welcome!

    Watch it here :

    A frequency counter is one of the most important measuring instruments when it comes to RF electronic.
    I love Arduino and I searched the NET for Arduino-counters and I found a lot of them!

    Great libraries and arduino code, BUT all of them works in the same way!
    They use several internal counters/timers of the processor to count and to handle gate timing.
    Most libraries use interrupts in some ways. The Arduino will be busy handling it all and there is not much left for other code.
    Another downside is that almost all counter projects on the web, uses the onboard arduino crystal as reference. This crystal is not accurate.

    What I want is an Arduino shield that handles Counting, Gate timing and have accurate Crystal.
    The counter timing must be exact down to every nano-second, else you will have bad measurement.
    The only thing Arduino should handle is presenting counter results from the shield.
    No interrupts, No timer register used for counting or gating, No complex arduino code.

    I want it simple...

    So, I created a shield myself which will handle all counting complexity. My Arduino will now be 99.999% free of time.
    Critical gate timing is controlled by the shield witch has a great VCTCXO, not using the Arduino crystal.
    The Arduino can now focus on presenting the counter value on a display or sending info over the serial line.
    The best thing is that the Arduino software is so simple that even I understand it.

    What is on this Shield?
    The picture below show the basic principle of the shield.
    To the left you will see that Arduino has 3 pins (D4, D2, D3) connected to the shield to control it. No more pins used.
    At the right you will see two frequency inputs (Low, High) and one Reference input to the shield.

    Gate time/Reference oscillator
    Look at the down-right corner and you will see the Gate timing unit.
    The hart on this shield is a VCTCXO (Voltage Controlled Temperature Controlled Crystal Oscillator)
    This oscillator is very exact and stable. It will control the gate timing of the counter, so the measurement will be exact in timing.

    If you have an accurate 10MHz reference as a GPS-reference or Rubidium oscillator you can connect that signal to this shield and use External 10MHz Reference input.
    The gating time can be selected between an internal VCTCXO oscillator or an external source by a small switch 2 on the PCB.(See pic at right)
    The golden rectangle on the picture is the internal VCTCXO. Below it you will find switch 2. You can choose between External or Internal oscillator reference.
    To the right of the switch is the calibration potensiometer for the VCTCXO. This potentiometer is used to calibrate the internal VCTCXO. (Factory Calibration)

    If you move the switch 2 to the left position (Ext), the Gatetime will be controlled from the External source and the accuracy will be dependent of that source.
    The reason of using an external 10.000 MHz reference frequency, is because it is common among reference oscillators, as rubidium oscillators or HP Z3801 GPS locked frequency source.
    When I calibrate the VXTCXO I use a GPS reference with the accuracy of 0.1 e-12 (1 Hz error at 10000 GHz).

    RF input
    To achieve the high performance I decided to split the rf inputs into two separate channels.
    Each channel has been designed to deliver maximum performance and high sensitivity.

    The Low input will measure frequencies from 1 Hz to 50 MHz with a resolution of 1 Hz.
    The High input will measure frequencies from 5 MHz to 2.5 GHz with a resolution of 100 Hz.
    A digital switch 1 choose which input will be connected to the 32 bits smart counter. The switch is controlled by your Arduino pin D4.

    It works like this:
    If you set D4 Low on your Arduino the Low input (0-50MHz) will be used for measurements.
    If you set D4 High on your Arduino the High input (5-2500MHz) will be used for measurements.

    Both inputs is impedance matched and have ESD protection and overpower protection. A clamping diode will handle any strong signals.
    The sesitivity is very high and you need only a few mV to get it working. A bit down I will show you a graph of the input sensitivity.

    Communication between the shield and Arduino
    Lets talk a bit how the Arduino can communicate with the shield.
    First I want to say that I have prepared software to handle all communication. You do not need to do anything yourself.
    Actually you can skip this section and still be able to use the shield. But for the curious once, I will explain in more details below.

    It is pretty simple and it works like this:
    The pin D2 of the Arduino is used to start a measurement. When D2 goes high-Low it will tell the shield to start a measurement.
    A measurement will take about 1000-1280ms for the shiled and when it is ready it will answer the Arduino by setting D3 high.
    So, when D3 goes high, the Arduino knows that the shield is done measuring and the data can be collected.
    Now it is time for Arduino to clock out the 32-bits data from the smart counter and D2 will be used as Clock and D3 for Data.

    The picture below will explain it in more details.

    A green LED will be ON indicating that the shield is ready for a new measurement. Arduino start a measurement by setting D2 high and low (pulse). Pulse length of D2 can be from 100uS to 50mS. (Default use is 100uS)
    When the pulse goes low, the green LED is OFF indicating that the shield is busy. A blue LED will turn ON to indicate that the Gate is open so the smart counter can count.
    After 1000-1280ms the Gate closes and the blue LED is OFF indicating measurement is done. The shield will now lift D3 high to tell the Arduino that measurement is done.
    The Arduino can now collect the 32-bit counter value from the smart counter.

    Arduino will now use Start/Clock line D2 to clock out the 32-bit counter value from the smart counter of the shield.
    When Clock goes high the highest data bit will be present on the Ready/Data line D3. Arduino put Clock low and read bit 31.
    When Clock goes high the next time, bit 30 will be present on Ready/Data line D3.
    By Clocking 32 times, the Arduino will collect the 32 bit counter value representing the frequency.

    If something goes wrong with the communication between the Arduino and the Shield, a red LED will be ON. it will be cleared only after next "Start" pulse arrive at D2.
    If you would wait more than 500 mS from that Ready goes high to you start to collect the data, the shield thinks something is wrong and the red LED will be ON.
    In my software examples below, you will see how I collect data far earlier...

    To make everything simple for you, I have made a software function for handling all this in a very simple way.
    The function is called GetCounterValue(input). The input can be either 0 or 1.

    GetCounterValue(0) is used when you want to measure the Low input.
    GetCounterValue(1) is used when you want to measure the High input.

    The function return a 32 bit value representing the measured frequency.
    I will show more examples in the software section below.

    Click here to view a larger format
    The picture at right show my own 10.000 MHz Atom ref oscillator, based on the well known Efratom Rubidium LPRO-101.
    It takes 2-3 minutes for it to lock, and the accuracy is then 0.5 e-9 (0.5 Hz error at 1 GHz).
    I have a RGB-LED at top right corner that starts to blink green when the unit is locked. (Red when unlocked.)
    After 20 minutes the efratom is stable in temperature and the LED gives a constant light. The accuracy is then 2 e-11 (2 Hz error at 100 GHz).
    To the left you can see my Transcendent counter with the two input connectors. I have three buttons with integrated blue LEDs, to control the menu.
    With this little unit, I have both a 10.000 MHz output reference signal and a frequency counter, which use the 10 MHz reference for accurate measurement.

    Bonus Feature
    The shield you have seen so far has no display. Arduino collect the counter information and you can present it as you wish.
    But some users might want to have a simple 2x16 Display attached to the shield...

    To make this shield even more complete, I have added an I2C LCD driver and a 2x16 LCD. (I will explain below in a schematic how it works)
    By adding a simple 2x16 Display, you can now use the shield and present counter information.
    The LCD is controlled by a I/O expander chip PCF8574. It is an I2C controlled I/O. This means that you can print any text to the LCD by using the I2C of Arduino.

    If you are new to this display and want to know how to drive it by using I2C, I advice you to follow this link:

    Display driver on the shield
    Below you will see the connection of the LCD display. I will explain how it works. As you can see, there is a circuit PCF8574 which is connected to the LCD display.
    Let's start at the right end of the schematic.
    Here is the i2c input SCL and SDA to the circuit. These two pins is connected to the Arduino UNO at pin A5 and A4. Click here to see Arduino board: UNOV3PDF.png
    No more pins are needed to control the display. It is very easy.

    All i2c units needs to have an address and in this case the i2c address is set with A0, A1 and A2. All are connected to +5V.
    In the software you need to define the address and set it to 0x27 hex. I will show examples below in software section.
    To the left side you will find a trimmer. This trimmer will set the contrast of the LCD display. You can find it on the PCB above the display.
    You will also find a transistor connected to port P7. In the software you have the ability to turn ON and OFF the background light of the display.
    At the bottom you find a lot of pins not being used.
    As you can see, this display driver is totally separated from the counter function.


    Click here to view a larger schematic Hardware and schematic
    Let's look at the schematic.
    At the bottom you find the Crystal oscillator. It is a Voltage Controlled oscillator and a trimmer will tune the oscillator during calibration.
    A Switch SW1 will select if you use the internal oscillator or an External oscillator.
    Fin Low is amplified with a FET and finally a transistor. Fin High is feed to a special pre-scaler.
    The microcontroller handles all timing and communication with Arduino. Several LEDs will indicate status.

    No pre- or post-flank errors!
    This frequency counter use intelligent gating system and special designed algorithm to detect eventual pre or post-flanks in the counter system.
    The result of this, gives a very accurate and stable frequency counter which you will only find in expensive commercial frequency counters.

    Arduino Software
    Let's talk about the Arduino Software to control this frequency Counter.
    First I want to say that I am NOT a software expert so please be humble with me.

    I will be happy to share YOUR work here both with code and pictures. Please contact me and I will add your work in the gallery at the bottom.

    Below, I will show you a basic example. I will explain all lines as well.

    I include the SPI standard library because I want to use the Serial port of the Arduino.
    After this I define which pin the shield uses on the Arduino board. Ready, Trigger and RFInput to pin 3,2,4

    Then you have to declare a variable "Incomming_Data" which will contain the frequency counter value.
    Now we come to the setup section of the Arduino. Here I set the Serial port to 9600 baud.
    Then I Set the direction of the 3 lines to the shield. I set Trigger and RFInput to output ports and Ready as input port.

    All done, lets look into the loop section. Here you find a function called GetCounterValue()
    When you add a "0" to the function, the shield will measure the LOW frequency input.
    The counting result will end up in the variable Incomming_Data
    Next line is comment // and here you find a "1" in the function call. This function will measure the HIGH frequency input.
    In this simple way, you can decide which input you want to measure

    My final line send out the result on the Serial port and I can se the result in any terminal window or in Arduino serial monitor.

    Where is the function GetCounterValue()?
    I will not go into details about this function here since it is pretty basic and you do not need to understand it, to get this shield working.
    When you download this Example below, you will see the function it in the code and I have lots of comments there.

    // Filename : CounterBasic.ino
    #include <SPI.h>
    // ==============================================================================================================
    //                                              Define Pins
    // ==============================================================================================================
    // Pins below are used by the Counter PCB and can not be changed
    #define Ready 3                                                       // Define Ready Pin
    #define Trigger 2                                                     // Define Trig Pin
    #define RFInput 4                                                     // Define RF input Pin
    // ==============================================================================================================
    //                                           Define Variables
    // ==============================================================================================================
    long Incomming_Data=0;                                                // Counter Value
    // ==============================================================================================================
    //                                              SETUP
    // ==============================================================================================================
    void setup(){
        Serial.begin(9600);                                               // Init serial
        pinMode(Trigger, OUTPUT);                                         // Set Pin as Output
        digitalWrite(Trigger,LOW);                                        // Set Pin Low     
        pinMode(RFInput, OUTPUT);                                         // Set Pin as Output 
        digitalWrite(RFInput,LOW);                                        // Set Pin Low
        pinMode(Ready, INPUT);                                            // Set pin as Input
    // ==============================================================================================================
    //                                              Loop
    // ==============================================================================================================
    void loop() {
        Incomming_Data=GetCounterValue(0);                                // Get Counter Value Low input
        //Incomming_Data=GetCounterValue(1);                              // Get Counter Value High input
        Serial.println(Incomming_Data,DEC);                               // Print out counter value

    LCD Software
    Let's talk about how to control the LCD to this shield.
    In the top section you will see how I have included a standard i2c library called Wire.h and a library called Adafruit_PCD8544.h
    The line below define the type of LCD and at which i2c address it is. This frequency shield use 0x27 as address.
    In the setup section I initiate the i2c and the LCD display.
    In the loop section you will see how I write some text to the LCD. It is all very simple to do.

    // LCD_Display.ino
    #include <SPI.h>
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    #include <Adafruit_PCD8544.h>
    #define PCF8574_I2C_Address 0x27                                      // Define the I2C address
    // ==============================================================================================================
    //                                        Define LCD display 2x16 Char
    // ==============================================================================================================
    LiquidCrystal_I2C lcd(0x27, 16, 2);                                   // LCD address to 0x27 
    // ==============================================================================================================
    //                                              SETUP
    // ==============================================================================================================
    void setup(){
        Wire.begin();                                                     // Init I2c
    // LCD Initiering 
        lcd.init();                                                       // initialize the lcd 
    // ==============================================================================================================
    //                                              Loop
    // ==============================================================================================================
    void loop() {
        lcd.clear();                                                      // Clear display   
        lcd.setCursor(0, 0);                                              // Position  
        lcd.print("Hello World");                                         // Print

    Download Arduino Software examples

    Sensitivity of input signal
    Below you will see a diagram of some sensitivity measurement I have made with a Marconi Signal Generator 2019A.
    The input sensitivity of the Transcendent Frequency counter can be found in the graph below.
    The blue line represent the Fin Low and the red line represent Fin High.
    The x-axle show frequency in log and the y-axle show input sensitivity in dBm.
    As you can see, both inputs are very sensitive. You only need to feed the shield with a few mV to get it working.

    One warning: if you feed power to your Arduino through USB, you may get a few dB worse sensitivity due to noise on the USB powerline.
    Best result is when arduino is feed with a clean DC voltage. I have noticed that many USB +5V has lot of high frequency noise.

    Sometimes your RF signal is to strong for the frequency counter and then you can add attenuators between the signal source and the frequency counter.
    An attenuator is an electronic device that reduces the amplitude or power of a signal without appreciably distorting its waveform.
    Attenuation are expressed in decibels of relative power.
    As a rule of thumb 3dB pad halves power, 6dB quarters, 10dB is tenth, 20dB is 100th, 30dB one in one thousand and so on.
    For voltage you double the dBs so for example 6dB is half in voltage.

    Attenuators are very simple to build, and they works really good.
    The picture at right show you how to build a 6dB attenuator.
    You can serial connect several attenuators if you need to.

    6dB means that the output power is only 1/4 of the input power.
    It also means that the output voltage is 1/2 of the input voltage.
    As you see I have used 100 ohm SMD resistor because they are cheap, purely resistive and also accurate.
    Here is a good and simple link for calculate attenuators: Pi Network Resistive Attenuation Calculator

    Order a KIT
    which will include all parts

    This shield can be ordered in 3 different Configurations.
    The reason is that some people wants the shield only, other wants to connect the display themselves using cables. Some people want the display assembled on the shield.

    Only shield, NO display!
    Shield it fully assembled, tested and calibrated!


    Click here to go to shop

    Shield and separate display!
    You connect the display yourself.
    Shield it fully assembled, tested and calibrated!


    Click here to go to shop

    Shield with mounted display!
    Shield it fully assembled, tested and calibrated!


    Click here to go to shop

    Final word
    I hope you have enjoyed reading about this frequency counter project.
    Hopefully you have found new inspiration for your own projects.
    The main reason I constructed this counter was my own need of a high quality counter based on Arduino. Beside all that, it looks pretty cool.

    Here I will present your work and shared Arduino softwares.

    Waiting for contribution...

    Back to main Page  |  Contact Me  |  Cheap components

    Copyright Last modified on 20 September 2023.