The personal website of Scott W Harden
Source code for Raspberry Pi RF Frequency Counter
---
title: Raspberry Pi RF Frequency Counter
date: 2016-10-10 02:58:41
---

# Raspberry Pi RF Frequency Counter

__I build a lot of RF circuits, and often it's convenient to measure and log frequency with a computer.__ Previously I've built [standalone frequency counters](https://www.swharden.com/wp/2011-03-14-frequency-counter-finished/), [frequency counters with a PC interface](https://www.swharden.com/wp/2016-09-05-vhf-frequency-counter-with-pc-interface/), and even [hacked a classic frequency counter to add USB interface](https://www.swharden.com/wp/2011-07-11-aj4vd-arsenal-recently-expanded/) ([twice](https://www.swharden.com/wp/2013-06-22-adding-usb-to-a-cheap-frequency-counter-again/), actually). My latest device uses only 2 microchips to provide a [Raspberry Pi](https://www.raspberrypi.org/) with RF frequency measurement capabilities. The RF signal clocks a 32-bit counter [SN74LV8154](http://www.ti.com/lit/ds/symlink/sn74lv8154.pdf) ($1.04 [on Mouser](http://www.mouser.com/Search/Refine.aspx?Keyword=SN74LV8154)) connected to a 16-bit IO expander [MCP23017](http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf) ($1.26 [on Mouser](http://www.mouser.com/Search/Refine.aspx?Keyword=MCP23017)) accessable to the Raspberry Pi (via [I²C](https://en.wikipedia.org/wiki/I%C2%B2C)) to provide real-time frequency measurements from a python script for $2.30 in components! Well, plus the cost of the Raspberry Pi. All files for this project are on [my GitHub page](https://github.com/swharden/RasPi-Frequency-Counter).

<div class="center border">

![](IMG_8773.jpg)

</div>

__The entire circuit is only two microchips!__ I have a few passives to clean up the RF signal (the RF input is loaded with a 1k resistor to ground, decoupled through a series 100 nF capacitor, and balanced at VCC/2 through a voltage divider of two 47k resistors), but if the measured signal is already a strong square wave they could be omitted. The circuit requires a gate pulse which typically will be 1 pulse per second (1PPS) and can be generated by [dividing-down a 32.768kHz oscillator](http://electronics.stackexchange.com/questions/177844/why-do-we-use-32-768-khz-crystals-in-most-circuits), a spare pin on a microcontroller, a fancy 1PPS time reference, or like in my case a GPS module ([Neo-6M](https://www.google.com/search?q=Neo-6M&rct=j)) with 1PPS output to provide an extremely accurate gate.

<div class="center">

![](schem.jpg)

</div>

__The connections are intuitive!__ The I2C address is 0x20 when A0, A1, and A2 are grounded. GPB(1-4) control the register select of the counter, and GPA(0-7) reads each bit of the selected register. The whole thing is [controlled from Python](https://github.com/swharden/RasPi-Frequency-Counter/blob/master/count.py), but could be trivially written in any language.

<div class="center border">

![](IMG_8777.jpg)

</div>

__Here's a quick summary describing how [the code](https://github.com/swharden/RasPi-Frequency-Counter/blob/master/count.py) works:__ First I send bytes to address 0 and 1 to set all pins of GPIO A as inputs, and GPIO B as outputs. _Note that only 4 of 8 pins are used for the output, so technically 4 extra pins could be used for things like blinking LEDs or controlling other devices._ I then set the register select pins by sending a value to [0x13](https://en.wikipedia.org/wiki/Hexadecimal) (GPIO B), and read the entire GPIO A bus (INTCAPB, [0x18](https://en.wikipedia.org/wiki/Hexadecimal)). For address details, consult [the datasheet](http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf). I do this 4 times (1 for each byte of the 32-bit counter), do a little math to turn it into a frequency value, and compare the current value with the last value and take the difference to display as the measured frequency.

<div class="center border">

![](screenshot.png)

</div>

__An advantage of this continuously running mode__ is that no clock cycles are lost, so a gate which accidentally fires a bit early due to jitter and cuts-off a cycle will compensate for it on a subsequent read. This is shown above, as a very stable 10MHz frequency reference is measured with this method. A "slow" 1PPS clock tick causes a reading slightly higher, compensated-for by the next reading being slightly lower. In this way, clock sources which are extremely accurate but suffer from low precision (like GPS time sources) are able to maximize the long-term measurement of frequency. Combining this frequency measurement technique with the ability to [generate an analog voltage with a Raspberry Pi](https://www.swharden.com/wp/2016-09-28-generating-analog-voltages-with-the-raspberry-pi/) will allow me to perform some interesting experiments with a voltage controlled crystal oscillator.

## Useful Links:

*   [MathWorks / MatLab example controlling the MCP23017 with a RasPi](https://www.mathworks.com/help/supportpkg/raspberrypiio/examples/add-digital-i-o-pins-to-raspberry-pi-hardware-using-mcp23017.html?requestedDomain=www.mathworks.com)
*   [IBEX References for RasPi I2C](http://www.raspberry-projects.com/pi/programming-in-python/i2c-programming-in-python/using-the-i2c-interface-2) (lots of good console commands)
*   [The adafruit page is great](https://learn.adafruit.com/adafruits-raspberry-pi-lesson-4-gpio-setup/configuring-i2c) for configuring I2C is pretty good

Newer: 1 Rotary Encoder, 3 Pins, 6 Inputs
Older: Generating Analog Voltage with Raspberry Pi
All Blog Posts