XR-2206 Function Generator
April 2016


Part 2 ~ The Frequency Counter

The 8-digit 7-segment LED display circuit is very simple and straightforward. An ATmega328 microcontroller uses an Arduino library (FreqCounter) to count the rising edges of the +5v square wave pulses from the waveform generator at digital pin D5.

The count per second (hence frequency in Hz) is displayed on a widely available 7-segment LED display module using another Arduino library - LedControl.

I tried several different Arduino frequency counter libraries and they all use more-or-less the same principle of setting up an ATmega328 internal 16-bit counter and measuring the pulses on pin 'T1' - which maps to Arduino pin D5. Luckily, it's all taken care of in the FreqCounter library.

The counter works reasonably well but, being implemented in software, there is a one-second delay between frequency measurements so isn't quite as responsive as a hardware implementation might be.

I'll show a simple PCB layout on Page 4.

One slight problem with the specified LED display module is that it's supplied with the pin header already soldered in place and, as it faces forward, it would make mounting the display flush with the front panel difficult. One solution would be to ignore the pin header and solder wires directly to the back of the PCB.

I took a chance and desoldered the pin header and fitted a new one facing to the rear. I say "took a chance" because plated-through holes can be difficult to desolder. It's easier if you cut off the header's black plastic spacer/separator so you can deal with each pin one at a time.

The Arduino Sketch

#include "LedControl.h"
// https://github.com/wayoda/LedControl/releases

#include <FreqCounter.h>
// https://codebender.cc/library/FreqCounter#FreqCounter
// Counter input must be D5.

//LedControl lc=LedControl(DIN,CLK,CS,1);
LedControl lc=LedControl(6, 8, 7, 1);

unsigned long frq;

void setup() {

void loop() {
  FreqCounter::f_comp=10;               // Cal Value - Calibrate with professional Freq Counter
  FreqCounter::start(1000);             // 1000 ms Gate Time for 1Hz resolution.

  while (FreqCounter::f_ready == 0);    // Wait for counter to be ready 

  lc.clearDisplay(0);                   // Clear LED display.
  printNumber(0, frq);                  // Break number into individual digits for LED display.

void printNumber(int addr, long num) {
  byte c;
  int j; 
  int d;
  num < 1000 ? d = 4 : d = countDigits(num); 
  for (j=0; j<d; j++) {
     c = num % 10;                      // Modulo division = remainder
     num /= 10;                         // Divide by 10 = next digit
     boolean dp = (j==3);               // Add decimal point at 3rd digit.
     lc.setDigit(addr, j, c, dp); 

int countDigits(long num) {
  int c = 0;
  while (num) {
    num /= 10;
  return c;


Back to Index | Page 1 | Page 2 | Page 3 | Page 4 | Page 5