The FT232 USB-to-serial converter is one of the most commonly-used methods of adding USB functionality to small projects, but recently I found that these chips are capable of sending more than just serial signals. With some creative programming, individual output pins can be big-banged to emulate a clock, data, and chip select line to control SPI devices. This post shares some of the techniques I use to bit-bang SPI with FTDI devices, and some of the perks (and quirks) of using FTDI chips to bit-bang data from a USB port. Code examples are available on GitHub, and links to additional resources are at the bottom of this post. After the final build I created a slightly more polished “ftdiDDS.exe” program to control an AD9850 frequency synthesizer from the command line by bit-banging a FT-232, and code (and binaries) are also available on GitHub.

Why Bit-Bang FTDI Pins?

The main reason I like using FTDI devices is because when you plug them in to a modern computer, they just start working! You don’t have to worry about drivers, driver versions, driver signing, third party drivers – most of the time it just does what it’s supposed to do with no complexity. If I’m going to build a prototype device for a client, a FT-232 USB to serial converter is the way to go because I can be confident that when they plug in, their device will start working right away. Yeah, there are third party drivers to get extra open-sourcey functionality from FTDI devices (libFTDI), but I don’t want to ask a client (with unknown tech-savviness) to install third-party unsigned drivers before plugging my device in (and heaven forbid the product doesn’t work in their hands and I have to ask them to verify the device is actually using the third-party drivers and not defaulting back to the official ones). In this project I seek to use only the generic, default, officially-supported FTDI driver and API access will be provided by libftd2xx. Don’t forget that USB ports supply 5V and GND, so in most cases you can power your project just from the USB port! All-in-all, the FT-232 is a great way to give a small device USB functionality. This post explores how to use it for more than just sending and receiving serial data…

Controlling FTDI Devices with C#

The goal of this post is not to describe every detail about how to control FTDI chips. Instead, the key points of the software are described here (and in the video) so you can get the gist of the main concepts. If you’re interested in additional detail, full code examples are provided on the GitHub folder for this project. All code examples were tested with Visual Studio Community 2017, are written in C#, and uses the FTD2XX_NET library installed with NuGet. Also, see the list of resources (including official FTDI datasheets and application notes) at the bottom of this post.

This block of code attaches to FTDI device 0 (the first FTDI device it sees) and sends the letter “a” using a traditional serial protocol. Since this code connects to the first FTDI device it finds, this could be a problem if you have more than 1 FTDI device attached. Alternatively you could have your program connect to a specific FTDI device (e.g., by its serial number). To see what FTDI devices are attached to your computer (and see or set their serial numbers), use the FT_Prog application provided by FTDI. Also, see the code I use to list FTDI devices from inside a C# program ftdiDDS program.

The full code of this example is here (GitHub)

public static FTDI ftdi = new FTDI();
public static FTDI.FT_STATUS ft_status = FTDI.FT_STATUS.FT_OK;
public static UInt32 bytesWritten = 0;

static void Main(string[] args)
	ft_status = ftdi.OpenByIndex(0);
	ft_status = ftdi.SetBaudRate(9600);
	string data = "a";
	ft_status = ftdi.Write(data, data.Length, ref bytesWritten);

LED Blink by Bit-Banging FTDI Pins

Here is a minimal complexity LED blink example. This code block alternates between writing 0 (all pins off) and 1 (TX pin high) over and over forever. Note that ftdi.SetBitMode is what frees the FTDI chip from sending serial data when ftdi.Write() gets called. The 255 is a byte mask which tells all 8 pins to be outputs (by setting all 8 bits in the byte to 1, hence 255). Setting bit mode to 1 means we are using asynchronous bit bang bode (sufficient if we don’t intend to read any pin states). For full details about these (and other) bit-bang settings, check out the Bit Bang Modes for the FT232R application note.

The full code of this example is here (GitHub)

ft_status = ftdi.OpenByIndex(0);
ft_status = ftdi.SetBitMode(255, 1);
ft_status = ftdi.SetBaudRate(9600);
int count = 0;

while (true)
	byte[] data = { (byte)(count++%2) };
	ft_status = ftdi.Write(data, data.Length, ref bytesWritten);

Bit-Bang SPI with a FT232

In reality all we want to send to SPI devices are a series of numbers which we can place in a byte array. These numbers are transmitted by pulling-low a clip select/enable line, setting a data line (high or low, one bit at a time) and sliding the clock line from low to high. At a high level we want a function to just take a byte array and bit-bang all the necessary SPI signals. At a low level, we need to set the state for every clock cycle, bit by bit, in every byte of the array. For simplify, I use a List<byte> object to collect all my pin states. Then I convert it to an array right before sending it with ftdi.Write().

The full code of this example is here (GitHub)

List<byte> bytesToSend = new List<byte>();
bytesToSend.Add(123); // just
bytesToSend.Add(111); // some
bytesToSend.Add(222); // test
bytesToSend.Add(012); // data


// given a byte, return a List<byte> of pin states
public static List<byte> StatesFromByte(byte b)
	List<byte> states = new List<byte>();
	for (int i=0; i<8; i++)
		byte dataState = (byte)((b >> (7-i)) & 1); // 1 if this bit is high
		states.Add((byte)(pin_data * dataState)); // set data pin with clock low
		states.Add((byte)(pin_data * dataState | pin_clock)); // pull clock high
	return states;

// given a byte array, return a List<byte> of pin states
public static List<byte> StatesFromByte(byte[] b)
	List<byte> states = new List<byte>();
	foreach (byte singleByte in b)
	return states;

// bit-bang a byte array of pin states to the opened FTDI device
public static void BitBangBytes(byte[] bytesToSend)
	List<byte> states = StatesFromByte(bytesToSend);
	// pulse enable to clear what was there before
	states.Insert(0, pin_enable);
	states.Insert(0, 0);

	// pulse enable to apply configuration
	ft_status = ftdi.Write(states.ToArray(), states.Count, ref bytesWritten);

Bit-Bang Control of an RF Synthesizer

The AD9850 is a SPI-controlled DDS (Direct Digital Synthesizer) capable of generating sine waves up to 65 MHz and is available on breakout boards for around $20 on eBay and Amazon. It can be programmed with SPI by sending 40 bits (5 bytes), with the first 4 bytes being a frequency code (LSB first) and the last byte controls phase.

To calculate the code required for a specific frequency, multiply your frequency by 4,294,967,296 (2^32 – 1) then divide that number by the clock frequency (125,000,000). Using this formula, the code for 10 MHz is the integer 343,597,383. In binary it’s 10100011110101110000101000111, and since it has to be shifted in LSB first (with a total of 40 bits) that means we would send 11100010100001110101111000101000 followed by the control byte which can be all zeros. In C# using the functions we made above, this looks like the following.

The full code of this example is here (GitHub)

int freqTarget = 12_345_678; // 12.345678 MHz
ulong freqCode = (ulong)freqTarget * (ulong)4_294_967_296;
ulong freqCrystal = 125_000_000;
freqCode = freqCode / freqCrystal;
bytesToSend.Add(ReverseBits((byte)((freqCode >> 00) & 0xFF))); // 1 LSB
bytesToSend.Add(ReverseBits((byte)((freqCode >> 08) & 0xFF))); // 2
bytesToSend.Add(ReverseBits((byte)((freqCode >> 16) & 0xFF))); // 3
bytesToSend.Add(ReverseBits((byte)((freqCode >> 24) & 0xFF))); // 4 MSB
bytesToSend.Add(0); // control byte

If somebody wants to get fancy and create a quadrature sine wave synthesizer, one could do so with two AD9850 boards if they shared the same 125 MHz clock. The two crystals could be programmed to the same frequency, but separated in phase by 90º. This could be used for quadrature encoding/decoding of single sideband (SSB) radio signals. This method may be used to build a direct conversion radio receiver ideal for receiving CW signals while eliminating the undesired sideband. This technique is described here, here, and here.

Polishing the Software

Rather than hard-coding a frequency into the code, I allowed it to accept this information from command line arguments. I did the same for FTDI devices, allowing the program to scan/list all devices connected to the system. Now you can command a particular frequency right from the command line. I didn’t add additional arguments to control frequency sweep or phase control functionality, but it would be very straightforward if I ever decided to. I called this program “ftdiDDS.exe” and it is tested/working with the FT-232R and FT-232H, and likely supports other FTDI chips as well.

Download ftdiDDS

Command Line Usage:

  • ftdiDDS -list lists all available FTDI devices
  • ftdiDDS -mhz 12.34 sets frequency to 12.34 MHz
  • ftdiDDS -device 2 -mhz 12.34 specifically control device 2
  • ftdiDDS -sweep sweep 0-50 MHz over 5 seconds
  • ftdiDDS -help shows all options including a wiring diagram

Building an Enclosure

Although my initial goal for this project was simply to figure out how to bit-bang FTDI pins (the AD9850 was a SPI device I just wanted to test the concept on), now that I have a command-line-controlled RF synthesizer I feel like it’s worth keeping! I threw it into an enclosure using my standard methods. I have to admit, the final build looks really nice. I’m still amused how simple it is.

Beware of the FT232R Bit Bang Bug

There is a serious problem with the FT-232R that affects its bit-bang functionality, and it isn’t mentioned in the datasheet. I didn’t know about this problem, and it set me back years! I tried bit-banging a FT-232R several years ago and concluded it just didn’t work because the signal looked so bad. This week I learned it’s just a bug (present in every FT-232R) that almost nobody talks about!

Consider trying to blink a LED with { 0, 1, 0, 1, 0 } sent using ftdi.Write() to the FT-232R. You would expect to see two pulses with a 50% duty. Bit-banging two pins like this { 0, 1, 2, 1, 2, 0 } one would expect the output to look like two square waves at 50% duty with opposite phase. This just… isn’t what we see on the FT-232R. The shifts are technically correct, but the timing is all over the place. The identical code, when run on a FT-232H, presents no timing problems – the output is a beautiful

The best way to demonstrate how “bad” the phase problem is when bit-banging the FT232R is seen when trying to send 50% duty square waves. In the photograph of my oscilloscope below, the yellow trace is supposed to be a “square wave with 50% duty” (ha!) and the lower trace is supposed to be a 50% duty square wave with half the frequency of the top (essentially what the output of the top trace would be if it were run through a flip-flop). The variability in pulse width is so crazy that initially I mistook this as 9600 baud serial data! Although the timing looks wacky, the actual shifts are technically correct, and the FT-232R can still be used to bit-bang SPI.

Unfortunately this unexpected behavior is not documented in the datasheet, but it is referenced in section 3.1.2 of the TN_120 FT232R Errate Technical Note where it says “The output may be clocked out at different speeds … and can result in the pulse widths varying unexpectedly on the output.” Their suggested solution (I’ll let you read it yourself) is a bit comical. It’s essentially says “to get a 50% duty square wave, send a 0 a bunch of times then a 1 the same number of times”. I actually tried this, and it is only square-like when you send each state about 1000 times. The data gets shifted out 1000 times slower, but if you’re in a pinch (demanding squarer waves and don’t mind the decreased speed) I guess it could work. Alternatively, just use an FT-232H.

Update (2018-10-05): YouTube user Frederic Torres said this issue goes away when externally clocking the FT232R chip. It’s not easy to do on the breakout boards, but if you’re spinning your own PCB it’s an option to try!

Alternatives to this Method

Bit-banging pin states on FTDI chips is a cool hack, but it isn’t necessarily the best solution for every problem. This section lists some alternative methods which may achieve similar goals, and touches on some of their pros and cons.

  • LibFTDI – an alternative, open-source, third party driver for FTDI devices. Using this driver instead of the default FTDI driver gives you options to more powerful commands to interact with FTDI chips. One interesting option is the simple ability to interact with the chip from Python with pyLibFTDI.
    While this is a good took for hackers and makers, if I want to build a device to send to a lay client I won’t want to expect them to fumble with installing custom drivers or ensure they are being used over the default ones FTDI supplies. I chose not to pursue utilizing this project because I value the “plug it in and it just works” functionality that comes from simply using FTDI’s API and drivers (which are automatically supplied by Windows)
  • Raspberry PI can bit-bang SPI – While perhaps not ideal for making small USB devices to send to clients, if your primary goal is just to control a SPI device from a computer then definitely consider using a Raspberry Pi! A few of the pins on its header are capable of SPI and can even be driven directly from the bash console. I’ve used this technique to generate analog voltages from a command line using a Raspberry PI to send SPI commands to a MCP4921 12-bit DAC.
  • Multi-Protocol Synchronous Serial Engine (MPSSE) – Some FTDI chips support MPSSE, which can send SPI (or I2C or other) protocols without you having to worry about bit-banging pins. I chose not to pursue this option because I wanted to use my FT232R (one of the most common and inexpensive FTDI chips), which doesn’t support MPSSE. ALthough I do have a FT232H which does support MPSSE (example project), I chose not to use that feature for this project, favoring a single code/program to control all FTDI devices.
  • Bus Pirate – If you don’t have a Bus Pirate already, get one! It’s one of the most convenient ways to get a new peripheral up and running. It’s a USB device you can interact with through a serial terminal (supplied using a FTDI usb-to-serial converter, go fig) and you can tell it to send/receive commands to SPI or I2C devices. It does a lot more, and is worth checking out.


  • Saleae logic analyzers – The official Saleae hardware (not what was shown in my video, which was a cheap eBay knock-off) can do a lot of great things. Their free software is really simple to use, and they haven’t gone out of their way to block the use of third-party logic analyzers with their free software. If you are in a place where you can afford to support this company financially, I suggest browsing their products and purchasing their official hardware.
  • DYMO Letra-Tag LT100-H label maker and clear tape – When labels are printed with black boxes around them (a tip I learned from Onno) they look fantastic when placed on project boxes! Don’t buy the knock-off clear labels, as they aren’t truly clear. The clear tape you need to purchase has the brand name “DYMO” written on the tape dispenser.
  • FT232H breakout board (adafruit) – This is where I got the FT232H board used in this video. You can find additional similar FT232H breakout boards on Amazon.
  • FT232R breakout board – Everyone sells these. I got some lately on Amazon, but I’ve gotten them before on eBay too.
  • TTL-232R cable – If you’re making a device which you want to appear a bit more professional, this cable has the FT232R built-in and it just has several pins (in a female header) you can snap onto your board.
  • Bit Bang Modes for the FT232R – FTDI datasheet detailing how to Bit-Bang the FT232R chip. In practice, the terms, language, and code examples in this datasheet seem similar enough to the FT232H that it probably is all you need to get started, since it’s the large-scale concepts which are most important.
  • Introduction to the FTDI BitBang mode – A Hack-A-Day article from 2009 mentions FTDI chips can be used to bit-bang pin states and they have their own LED blink examples. Their article does hint at using this method to bit-bang SPI, but it fails entirely to note the FT232R bug that surely has confused multiple people in the past…
  • FT232R BitBang SPI example – This code uses libftdi, not the default driver supplied by FTDI (libftd2xx).
  • FT232R BitBang mode is broken – an article from 2012 detailing how bad the timing is when bit-banging pin states on the FT232R.
  • Official acknowledgement of the FT232R timing problem is described in the TN_120 FT232R Errate Technical Note in section 3.1.2 where they state the problem as: “The output may be clocked out at different speeds to allow for different pulse widths. However this clocking stage is not synchronized with the incoming data and can result in the pulse widths varying unexpectedly on the output.
  • AD9850 Complete DDS Synthesizer Datasheet


Bit-banging pin states on FTDI devices is relatively simple, even using the standard drivers and API. The FTD2XX_NET library on NuGet provides a simple way to do this. The output of the FT232H is much more accurate in the time domain than the FT232R. Although there are crazy timing issues with the FT232R, it works fine when driving most SPI devices. Here we used this technique to write a console application to control an AD9850 DDS directly from an FT232R using command line arguments. When given a formal enclosure, this project looks (and works) great!

If you make something cool by bit-banging a FTDI device, let me know about it!

Additional Resources

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, frequency counters with a PC interface, and even hacked a classic frequency counter to add USB interface (twice, actually). My latest device uses only 2 microchips to provide a Raspberry Pi with RF frequency measurement capabilities. The RF signal clocks a 32-bit counter SN74LV8154 ($1.04 on Mouser) connected to a 16-bit IO expander MCP23017 ($1.26 on Mouser) accessable to the Raspberry Pi (via I²C) 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.


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, a spare pin on a microcontroller, a fancy 1PPS time reference, or like in my case a GPS module (Neo-6M) with 1PPS output to provide an extremely accurate gate.


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, but could be trivially written in any language.


Here’s a quick summary describing how the code 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 (GPIO B), and read the entire GPIO A bus (INTCAPB, 0x18). For address details, consult the datasheet. 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.


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 will allow me to perform some interesting experiments with a voltage controlled crystal oscillator.

Useful Links:


Additional Resources

Projects I build often involve frequency synthesis, and one of the most useful tools to have around is a good frequency counter. Being a budding programmer and data analysis guru, I love the idea of being able to access / log / analyze frequency readings on my computer too. Commercial frequency counters can be large, expensive, and their calibration is a chicken-and-egg problem (you need a calibrated frequency counter to calibrate a frequency reference you use to calibrate a frequency counter!). For about the cost of a latte I made a surprisingly good frequency frequency counter (which directly counts >100 MHz without dividing-down the input signal) by blending a SN74LV8154 dual 16-bit counter (which can double as a 32-bit counter, $1.04 on mouser) and an ATMega328 microcontroller ($3.37 on Mouser). Although these two chips are all you need to count something, the accuracy of your counts depend on your gate. If you can generate a signal of 1 pulse per second (1PPS), you can count anything, but your accuracy depends on the accuracy of your 1PPS signal. To eliminate the need for calibration (and to provide the 1PPS signal with the accuracy of an atomic clock) I’m utilizing the 1PPS signal originating from a GPS unit which I already had distributed throughout my shack (using a 74HC240 IC as a line driver). If you don’t have a GPS unit, consider getting one! I’m using a NEO-6M module ($17.66 on Amazon) to generate the 1PPS gate, and if you include its cost we’re up to $22.07. Also, all of the code for this project (schematics, C that runs on the microcontroller, and a Python to interact with the serial port) is shared on GitHub! You may be wondering, “why do GPS units have incredibly accurate 1PPS signals?” It’s a good question, but a subject for another day. For now, trust me when I say they’re fantastically accurate (but slightly less precise due to jitter) if you’re interested in learning more read up on GPS timing.


pc frequency counter schem

This is the general idea behind how this frequency counter works. It’s so simple! It’s entirely digital, and needs very few passive components. sn74lv8154 is configured in 32-bit mode (by chaining together its two 16-bit counters, see the datasheet for details) and acts as the front-end directly taking in the measured frequency. This chip is “rare” in the sense I find very few internet projects using it, and they’re not available on ebay. However they’re cheap and plentiful on mouser, so I highly encourage others to look into using it! The datasheet isn’t very clear about its maximum frequency, but in my own tests I was able to measure in excess of 100 MHz from a breadboarded circuit! This utilized two cascaded ICS501 PLL frequency multiplier ICs to multiply a signal I had available (the 11.0592 MHz crystal the MCU was running from) by ten, yielding 110 MHz, which it was able to measure (screenshot is down on the page).

neo-60 gps 1pps

The 1PPS gate signal is generated from an inexpensive GPS module available on AmazonI’ve hinted at the construction of this device before and made a post about how to send output signals like the 1PPS signal generated here throughout your shack via coax using a line driver, so I won’t re-hash all of those details here. I will say that this module has only VCC, GND, and TX/RX pins, so to get access to the 1PPS signal you have to desolder the SMT LED and solder a wire to its pad. It requires a bit of finesse. If you look closely, you can see it in this picture (purple wire).


I first built this device on a breadboard, and despite the rats nest of wires it worked great! Look closely and you can see the ICS501 frequency multiplier ICs I wrote about before. In this case it’s measuring the 10x multiplied crystal frequency clocking the MCU (11 MHz -> 110 MHz) and reporting these readings every 1 second to the computer via a serial interface.


Frequency measurements of the VHF signal are reported once per second. Measurements are transmitted through a USB serial adapter, and captured by a Python script. Note that I’m calling this signal VHF because it’s >30 MHz. I am unsure if this device will work up to 300 MHz (the border between VHF and UHF), but I look forward to testing that out! Each line contains two numbers: the actual count of the counter (which is configured to simply count continuously and overflow at 2^32=4,294,967,296), and the gated count (calculated by the microcontroller) which is the actual frequency in Hz.

This screenshot shows that my ~11.05 MHz crystal is actually running at 11,061,669.4 Hz. See how I capture the 0.4 Hz unit at the end? That level of precision is the advantage of using this VHF-capable counter in conjunction with a 10x frequency multiplier!

Once I confirmed everything was working, I built this device in a nice enclosure. I definitely splurge every few months and buy extruded split body aluminum enclosures in bulk (ebay), but they’re great to have on hand because they make projects look so nice. I added some rubber feet (cabinet bumpers from Walmart), drilled holes for all the connectors with a continuous step drill bit, made a square hole for the serial port using a nibbler, and the rest is pretty self-evident. Labels are made with a DYMO LetraTag (Target) and clear labels (Target, Amazon) using a style inspired by PA2OHH. I tend to build one-off projects like this dead-bug / Manhattan style.



I super-glued a female header to the aluminum frame to make in-circuit serial programming (ICSP) easy. I can’t believe I never thought to do this before! Programming (and reprogramming) was so convenient. I’m going to start doing this with every enclosed project I build from now on. FYI I’m using a USBTiny ISP ($10.99, Amazon) to do the programming (no longer the BusPirate, it’s too slow) like I describe here for 64-bit Windows 7 (although I’m now using Windows 10 and it works the same).


The front of the device has LEDs indicating power, serial transmission, and gating. Without a 1PPS gate, the device is set to send a count (of 0) every 5 seconds. In this case, the TX light will illuminate. If a gate is detected, the TX and GATE LEDs will illuminate simultaneously. In reality I just drilled 3 holes when I really needed two, so I had to make-up a function for the third LED (d’oh!)


The back of the device has serial output, frequency input, gate input, and power. Inside is a LM7805 voltage regulator, and careful attention was paid to decoupling and keeping ripple out of the power supply (mostly so our gate input wouldn’t be affected). I’m starting to get in the habit of labeling all serial output ports with the level (TTL vs CMOS, which makes a HUGE difference as MAX232 level converter may be needed, or a USB serial adapter which is capable of reading TTL voltages), as well as the baud rate (119200), byte size (8), parity (N), and stop bit (1). I just realized there’s a typo! The label should read 8N1. I don’t feel like fixing it, so I’ll use a marker to turn the 2 into an 8. I guess I’m only human after all.


I should have tried connecting all these things before I drilled the holes. I got so lucky that everything fit, with about 2mm to spare between those BNC jacks. Phew!


This is an easy test frequency source. I have a dozen canned oscillators of various frequencies. This is actually actually a voltage controlled oscillator (VCO) with adjustment pin (not connected), and it won’t be exactly 50 MHz without adjustment. It’s close enough to test with though! As this is >30 MHz, we can call the signal VHF.


You can see on the screen it’s having no trouble reading the ~50 MHz frequency. You’ll notice I’m using RealTerm (with a good write-up on sparkfun) which is my go-to terminal program instead of HyperTerminal (which really needs to go away forever). In reviewing this photo, I’m appreciating how much unpopulated room I have on the main board. I’m half tempted to build-in a frequency multiplier circuit, and place it under control of the microcontroller such that if an input frequency from 1-20MHz is received, it will engage the 10x multiplier. That’s a mod for another day though! Actually, since those chips are SMT, if I really wanted to do this I would make this whole thing a really small SMT PCB and greatly simplify construction. That sounds like a project for another day though…


Before closing it up I added some extra ripple protection on the primary counter chip. There’s a 560 uH series inductor with the power supply, followed by a 100 nF capacitor parallel with ground. I also added ferrite beads to the MCU power line and gate input line. I appreciate how the beads are unsecured and that this is a potential weakness in the construction of this device (they’re heavy, so consider what would happen if you shook this enclosure). However, anything that would yank-away cables in the event of shaking the device would probably also break half the other stuff in this thing, so I think it’s on par with the less-than-rugged construction used for all the other components in this device. It will live a peaceful life on my shelf. I am not concerned.


This is the final device counting frequency and continuously outputting the result to my computer. In the background you can see the 12V power supply (yellow) indicating it is drawing only 20 mA, and also the GPS unit is in a separate enclosure on the bottom right. Click here to peek inside the GPS 1PPS enclosure.


I’m already loving this new frequency counter! It’s small, light, and nicely enclosed (meaning it’s safe from me screwing with it too much!). I think this will prove to be a valuable piece of test equipment in my shack for years to come. I hope this build log encourages other people to consider building their own equipment. I learned a lot from this build, saved a lot of money not buying something commercial, had a great time making this device, and I have a beautiful piece of custom test equipment that does exactly what I want.

Microcontroller code (AVR-GCC), schematics, and a Python script to interface with the serial port are all available on this project’s GitHub page

Afterthought: Using without GPS

One of the great advantages of this project is that it uses GPS for an extremely accurate 1 PPS signal, but what options exist to adapt this project to not rely on GPS? The GPS unit is expensive (though still <$20) and GPS lock is not always feasible (underground, in a Faraday cage, etc). Barring fancy things like dividing-down rubidium frequency standards or oven controlled oscillators, consider having your microcontroller handle the gating using either interrupts and timers precisely configured to count seconds. Since this project uses a serial port with a 11.0592 MHz crystal, your 1PPS stability will depend on the stability of your oscillator (which is pretty good!). Perhaps more elegantly you could use a 32.768 kHz crystal oscillator to create a 1 PPS signal. This frequency can be divided by 2 over and over to yield 1 Hz perfectly. This is what most modern wristwatches do. Many AVRs have a separate oscillator which can accomodate a 32 kHz crystal and throw interrupts every 1 second without messing with the system clock. Alternatively, the 74GC4060 (a 14 stage ripple counter) can divide 32k into 1 Hz and even can be arranged as an oscillator (check the datasheet). It would be possible to have both options enabled (local clock and GPS) and only engage the local clock if the GPS signal is absent. If anyone likes the idea of this simple VHF frequency counter with PC interface but doesn’t want to bother with the GPS, there are plenty of options to have something almost as accurate. That really would cut the cost of the final device down too, keeping it under the $5 mark.

Update: Integrating Counter Serial Output with GPS Serial Output

The NEO-M8 GPS module is capable of outputting serial data at 9600 baud and continuously dumps NEMA formatted GPS data. While this isn’t really useful for location information (whose frequency counter requires knowing latitude and longitude?) it’s great for tracking things like signal strength, fix quality, and number of satellites. After using this system to automatically log frequency of my frequency reference, I realized that sometimes I’d get 1-2 hours of really odd data (off by kHz, not just a few Hz). Power cycling the GPS receiver fixes the problem, so my guess it that it’s a satellite issue. If I combine the GPS RX and counter in 1 box, I could detect this automatically and have the microcontroller power cycle the GPS receiver (or at the least illuminate a red error LED). I don’t feel like running 2 USB serial adapters continuously. I don’t feel like programming my AVR to listen to the output from the GPS device (although that’s probably the correct way to do things).  Instead I had a simpler idea that worked really well, allowing me to simultaneously log serial data from my GPS unit and microcontroller (frequency counter) using 1 USB serial adapter.


The first thing I did was open up the frequency counter and reconnect my microcontroller programmer. This is exactly what I promised myself I wouldn’t do, and why I have a nice enclosure in the first place! Scott, stop fidgeting with things! The last time I screwed this enclosure together I considered adding super glue to the screw threads to make sure I didn’t open it again. I’ll keep my modifications brief! For now, this is a test of a concept. When it’s done, I’ll revert the circuitry to how it was and close it up again. I’ll take what I learn and build it into future projects.


I peeked at the serial signals of both the frequency counter (yellow) and the GPS unit output (blue). To my delight, there was enough dead space that I thought I could stick both in the same signal. After a code modification, I was able to tighten it up a lot, so the frequency counter never conflicts with the GPS unit by sending data at the same time.


I had to slow the baud rate to 9600, but I programmed it to send fewer characters. This leaves an easy ~50ms padding between my frequency counter signal and the GPS signal. Time to mix the two! This takes a little thought, as I can’t just connect the two wires together. Serial protocol means the lines are usually high, and only pulled down when data is being sent. I had to implement an active circuit.


Using a few components, I built an AND gate to combine signals from the two serial lines. For some reason it took some thought before I realized an AND gate was what I needed here, but it makes sense. The output is high (meaning no serial signal) only when both inputs are high (no serial signals on the input). When either signal drops low, the output drops low. This is perfect. My first thought was that I’d need a NOR gate, but an inverted AND gate is a NOR gate.


Here’s my quick and dirty implementation. A reminder again is that this will be removed after this test. For now, it’s good enough.


After connecting the GPS serial output and frequency counter serial output to the AND gate (which outputs to the computer), I instantly got the result I wanted!


RealTerm shows that both inputs are being received. It’s a mess though. If you want to know what everything is, read up on NEMA formatted GPS data.


I whipped-up a python program to parse, display, and log key information. This display updates every 1 second. The bottom line is what is appended to the log file on ever read. It’s clunky, but again this is just for testing and debugging. I am eager to let this run for as long as I can (days?) so I can track how changes in satellite signal / number / fix quality influence measured frequency.

Additional Resources

Today I made a high frequency multiplier using a single component: the ICS501 PLL clock multiplier IC. This chip provides 2x, 5x, 8x (and more) clock multiplication using an internal phased-lock loop (PLL). At less than a dollar on eBay$1.55 on mouser, and $0.67 on Digikey, they don’t break the bank and I’m glad I have a few in my junk box! I have a 10MHz frequency standard which I want to use to measure some 1Hz (1pps) pulses with higher precision, so my general idea is to use a frequency multiplier circuit to increase the frequency (to 80 MHz) and use this to run a counter IC to measure the number of clock pulses between the PPS pulses. I spent a lot of time working with the CD4046 micro-power phased lock loop IC which has a phase comparator and a voltage controlled oscillator built in. It seemed this chip was the go-to for many years, but it requires external circuitry (ICs in my case) to divide by N and is intended to adjust a VCO output voltage based on the phase difference of two different inputs. Although I made some great progress using this chip, I found a few SMT ICS501 ICs in my junk box and decided to give them a try. I was impressed how easy it was to use! I just fed it 5V and my clock signal, and it output 8x my clock signal! Since I don’t have my 10MHz reference frequency running at the moment, I tested it with a 1MHz canned oscillator. It worked great, and was so easy! I’ll definitely be using this chip to multiply-up crystal oscillator frequencies to improve the precision of frequency counting.


The pin connections are straightforward: +5V and GND to pins 2 and 3, no connection for pins 7 and 8, clock goes in 1 and comes out on 5. Pins 4 and 6 are both set to +5V to yield a x8 multiplier, according to the chart. All of this is in the datasheet for the chip.


The IC I had on hand was SOIC. I don’t think they make this IC in DIP. Luckily, I have breadboardable breakout boards on hand. These breakout boards are identical to those sold on dipmicro but I got mine from ebay and they’re all over ebay!


I didn’t feel like changing my soldering iron tip so I gave it a go with a huge wedge, and it worked pretty well! I first melted a little bit of solder on all the rails, waited until it cooled, pressed the IC into the solder, then re-melted it with the iron. It was relatively easy and I had no shorts. I do have a hot air gun (which I also didn’t feel like setting up and waiting for to get warm) but this worked fine…


Here’s the test circuit. I added a 100nF power decoupling capacitor and a SMT LED (with a 1 kOhm current limiting resistor) so I could tell when it was powered. I am using a 1MHz can oscillator at the input of the ICS501, and capturing both outputs through a 0.1uF capacitors terminating in a 50 ohm loads (at the oscilloscope, seen better in the next photo).


It worked immediately with no trouble! The top trace is the original 1MHz clock signal, and the bottom is the 8MHz trace.


The frequency isn’t exactly 1MHz because the adjustment pin of the can oscillator has been left floating. Also, I recognize the power supply is noisy which is also getting noise in the signals. None of that matters, I’m just testing the concept here. The bottom line is that the ICS501 is an extremely easy way to multiply a clock frequency to beyond 100 MHz and it requires no external components! I will definitely be using this IC in some of my future designs. I’m glad I have it! I had to search my email to see when I ordered it because I had no memory of doing so. It looks like I got them in August 2013 (3 years ago!) and never used them. Regardless, I’m happy to have found them in my junk box, and will definitely be using them from now on.

Update: Cascading Two ICS501s for 10x Frequency Multiplication

My ultimate goal is to build a frequency counter using a 10 MHz frequency source, multiplied to a higher value for greater precision. Although I could achieve 8x frequency multiplication with a single ICS501, I didn’t like the idea of frequency steps not being decimal. I decided to try to cascade two ICS501 chips configured to multiply by 2 then by 5 to yield 10. Supposedly this could work on a range of frequencies up through 64x multiplication, but for me generating 100 MHz from a 10 MHz reference is exactly what I need.


Here’s my design. It’s simple. I configure S0 or S1 as floating, grounded, or high to set the multiplication factor (see the chart above).


Here’s my implementation. I didn’t have enough space on the breakout board to fit the whole chip (I was missing a single row!). Luckily the SMT perf board is spaced perfectly for SOIC. I was surprised how easy this thing was to solder on the SMT perf board. I’m going to have to buy some more and try prototyping with it. It would be cool to get good at it. That’s another story for another day though…


The breadboard design got way easier! This thing now just needs power (+5V and GND), an input signal (1 MHz in this demo), and the output signal is 10x the input (10 MHz).


This is what the output looks like. Signals terminate into a 10 ohm load at the level of the oscilloscope.


I had the USB drive in the thing so I went ahead and pushed the print button. Here’s the actual screen capture.


Here it is converting 10 MHz into 100 MHz. The signals are a bit noisy, likely because both ICs are being powered together (behind the same inductor/capacitor). In a production device, each IC should have its own inductor/capacitor to isolate it from ripple on the power rail. Regardless, this works great in cascading arrangement to multiply HF frequencies to VHF frequencies. The 10MHz source is my oven controlled crystal oscillator (OCXO) which I haven’t written about yet.


All in all, the ICS501 was an easy cheap single-component solution to frequency multiplication, and cascading two in series easily allows me to multiply the frequency of an incoming signal. I look forward to posting details of my frequency counter build soon!

Additional Resources

Sometimes I rapidly want to amplify a signal, but building amplifiers, buffers, and line drivers can be a hassle, especially on a breadboard! It’s important to know how to carefully design build tuned and untuned amplifier circuits, but sometimes you just want to analyze or work with a signal without modifying it by sinking too much current, so being able to rapidly drop in a buffer stage would be a great help. Sometimes I want to buffer a signal so I can analyze it (with an oscilloscope or frequency counter) or use use it (perhaps to drive or gate something), but the signal source is across the room, so I need a beefy amplifier to drive it into coax as I run it across my ceiling while I’m experimenting. A MOSFET voltage follower or a Darlington transistor may do the job, but I have to worry about input conditioning, biasing, output voltage limiting, class A, B, C, D, etc., RF vs DC, copying this circuit multiple times for multiple signals, and before you know it I’m sinking more time into my task than I need to. Line driver chips are one of my go-tos for quickly amplifying digital signals because they’re so fast to drop in a breadboard and they provide a strong output with very high impedance inputs and need no external components. Individual buffer of the integrated chip can be paralleled to multiply their current handling capabilities too. One of the common variants is the 74HC240. I don’t know why it’s so popular (I still find its pinout odd), but because it is popular it is cheap. They’re $0.50 on (perhaps cheaper on ebay) and according to their datasheet they can be run up to 7V to deliver or sink 20mA/pin with a maximum dissipation of 500mW. With propagation, enable, and disable times of tens of nanoseconds, they’re not awful for lower-range radio frequencies (HF RF). This specific chip (somewhat comically at the exclusion of almost all others) has been latched onto by amateur radio operators who use it as an amplifier stage of low power (QRP) Morse code radio transmitters often pushing it to achieve ~1 watt of power output. A quick google reveals thousands of web pages discussing this! This Portuguese site is one of the most thorough. Even if not used as the final amplifier, they’re a convenient intermediate stage along an amplifier chain as they can directly drive FET final stages very well (probably best for class C operation). If you’re interested, definitely check out The Handiman’s Guide to MOSFET “Switched Mode” Amplifiers guide by Paul Harden (no relation). Also his part 2.

Typical configuration for RF or TTL amplification with a 74HC240 buffer / line driver

This is the circuit I commonly build. I have one variant on hand for RF (extremely fast oscillations which are continuously fed into the device and often decoupled through a series capacitor), and one for TTL signals (extremely fast). I find myself paralleling line driver outputs all the time. On a breadboard, this means tons of wires! It becomes repetitive and a pain. I’ve started pre-packaging highly parallel line drivers into little modules which I find really convenient. I have a half dozen of these soldered and ready to go, and I can use them by simply dropping them into a breadboard and applying ground, power (+5V), and input signal, and it amplifies it and returns an output signal. Note that in the “Case 2: RF input” example, the inverted output of the first stage is continuously fed back into the input. This will result in continuous oscillation and undesired output if no input is supplied. In case 2, RF must be continuously applied. The advantage is that the feedback network holds the input near the threshold voltage, so very little voltage swing through the decoupling capacitor is required to generate strong output.

Although I have made this entirely floating, I prefer using copper-clad board. Not only does it aid heat dissipation and provide better mechanical structure, but it also serves as a partial RF shield to minimize noise in the input and output signals. A Dremel with a diamond wheel does a good job at cutting out notches in the copper-clad board.

The best way to replicate this is to look at the picture. It’s surprisingly difficult to get it right just by looking at the datasheet, because when it’s upside down it’s mirror-imaged and very easy to make mistakes. I just connect all inputs and all outputs in parallel, for 7 of 8 gates. For one gate, I connect its output to the parallel inputs. I added some passives (including a ferrite bead and decoupling capacitor on the VCC pin) and it’s good to go.

Here's a closer look at the final amplifier
With only 4 pins (GND, +5V, IN, and OUT) this amplifier is easy to drop in a breadboard

Although I often use it in a breadboard, it’s easy to stick in a project. Since the back side is unpopulated, you can use a dot of super glue and stick it anywhere you want. In this example, I had a GPS receiver module which blinked a LED at exactly one pulse per second (1PPS) [check out why] and I wanted to do some measurements on its output. I couldn’t send this line signal out a coax line because it was so low current (in reality, I didn’t know what it could deliver). This is a perfect use for a buffer / line driver. I glued this board inside my temporary project enclosure (which admittedly looks nicer and more permanent than it’s actually intended to be) and set the output to deliver through 50 Ohm coax. It works beautifully!