The personal website of Scott W Harden
September 9th, 2016

Adding ADC to Microcontrollers without ADC

I recently had the need to carefully measure a voltage with a microcontroller which lacks an analog-to-digital converter (ADC), and I hacked together a quick and dirty method to do just this using a comparator, two transistors, and a few passives. The purpose of this project is to make a crystal oven controller at absolute minimal cost with minimal complexity. Absolute voltage accuracy is not of high concern (i.e., holding temperature to 50.00 C) but precision is the primary goal (i.e., hold it within 0.01 C of an arbitrary target I set somewhere around 50 C). Voltage measurement is usually a balance of a few factors: precision, accuracy, cost, simplicity, and speed. The method I demonstrate here maximizes precision and simplicity while minimizing cost. High speed operation is not of interest (1-2 measurements per second is fine), and as mentioned before accuracy is not a chief concern as long as precision is maximized. I would feel neglectful if I didn't give a shout out to a few alternatives to this method: Using the 10-bit ADC built into most AVR microcontrollers (my go-to for ATMega328 at ATTiny85, but the ATTiny2313 doesn't have any) often combined with an op-amp like this, using an IC like the MCP3208 8-channel 12-bit ADC (very expensive at $3.66 on mouser) are a good option, and fancy alternative dual slope methods as described in this really good youtube video and even mentioned nicely in the digital volt meter (DVM) / LCD driver ICL1706 datasheet. Those addressed, my quick and dirty idea uses only a couple cents of components and 3 pins of a microcontroller. There is much room for improvement (see my notes about a 555 timer, voltage reference, and operational amplifiers at the bottom) but this is a good minimal case starting point. This type of measurement is perfect for high precision temperature measuring using things like an LM335, LM35, or thermistor.

The concept behind this method is simple: use a current-limiting circuit to charge a capacitor at a constant rate so voltage rises linearly with time (rather than forming an exponential RC curve), and time how long that voltage takes to cross your test voltage. A circuit which compares two voltages and outputs high when one voltage surpasses the other is called a comparator, and many microcontrollers (including ATMEL AVRs) have analog comparators built in (which compare AIN0 and AIN1, the result of which accessable by accessing the ACSR&(1<<ACO)) bit value (at least for the ATMega328, according to the datasheet).

I can use the AVR's comparator to time how long it takes a capacitor to charge to the test voltage, and output to that to the serial port. Note that I designed this entire circuit to use the most common transistor/resistors I could think of. It can be fine-tuned to increase speed or increase precision, but this is a great starting point. To generate a constant current I need a PNP transistor (I had a 2N2907 on hand) with a voltage divider on the base and a current limiting resistor above the transistor for good measure (in retrospect, with a more carefully chosen set of values this may not be needed). This is all that's needed to charge the capacitor linearly and generate a positive ramp.

My test setup is a mess, but it demonstrates this idea works well, and is stable enough to run some experiments. In the frame you can see the ATMega328 microcontroller (big microchip), LM335 temperature sensor (the TO-92 closest to the MCU), a TTL FTDI serial/USB adapter (red board, top), and my USBTiny AVR programmer (blue board, right), and oscilloscope probes.

To prevent this linear charger from charging forever, I make the microcontroller read the comparator which compares my test voltage with that of the ramp. If the test voltage is reached, or if the ramp reaches a cutoff voltage first (meaning the test voltage is too high to be measured), the count (time between last reset and now) is sent to the computer via serial port, and the capacitor is discharged through a PNP resistor. In the schematic, this is the "reset" pin. Note that the "measure" pin is AVR AC0, and AC1 is the test voltage. When all this is assembled, you can see how the linear ramps are created every time the reset transistor shuts off. Note that every 10th ramp is higher than the rest (shown here as the one left from center). This is because every 10th reading the data is summed and sent to the serial port, causing a little extra time before it is reset again. While the time value has been recorded of the comparator match of the test voltage and the ramp voltage, the capacitor is allowed to continue charging until the next cycle.

Interestingly, this method is largely insensitive to power supply noise. I'm using an extremely noisy environment (breadboard, DIP power regulator) but the recordings are rock solid. I suspect this is because the ramps are timed based on constant current, not abbsolute voltage, and that the ramps are fast enough to not be sensitive to slow changes in voltage. In reality, I don't think I can adequately explain why the readings are so good when the supply is so shaky (the positive voltage rail is all over the place). It works, so I'm happy with it, and I'll keep pushing forward.

Lately I've been using RealTerm as a feature-rich alternative to HyperTerminal and a more convenient method than requiring custom python scripts be written every time I want to interact with the serial port in a way that involves debugging or logging or other advanced features. Here you can see the real time output of this device logging time to comparator match as it also logs to disk in a text file. This is great for simultaneously logging data (from RealTerm) and graphing it (from custom python scripts).

This is what happens when I touch the temperature sensor for about 30s. I'm recording the time to voltage crossing of an LM335, so the number decreases as temperature increases. Also each data point is the average (actually the sum) of 10 points. It would be trivial to create some voltage test points, create a calibration curve, and infer the voltages involved, but this is more than enough already to prove that this method is robust and clean and precise and I couldn't be more satisfied with the results! With a pair or capacitors and a few passives, this is totally implementable virtually anywhere. Considering my room is about 78F and my finger is about 98F, this 20F spread is about 1500 data points. That means each degree F is about 75 points, so I can resolve better 0.02 F (about 0.01 C) with this crude setup.

If I let it run for about an hour, I catch my air conditioning coming on and off. Warmer temperature is higher voltage which means less time to charge, so the downslopes are my AC cooling my home and the up slope is my home passively warming. The fluctuations are only about 100 units which I (backwards calculate) assume are about 1-2 F.

These numbers seem so arbitrary! How can we calibrate this? This opens up a Pandora's box of possible improvements. I'll close by saying that this project works great exactly how it is to meet my needs. However, some modifications could be made to change the behavior of this device:

  • Slowing things down: A larger capacitor value (or higher resistor value) would increase the time or charging, lengthen the time to comparator threshold crossing, and increase precision. The readings would be slower (and more susceptible to noise), but it's an option.
  • Self-calibration: Components (Rs and Cs) are sensitive to temperature and charge time can fluctuate with age, wear, temperature, etc. To self-calibrate with each sweep, add an additional comparator step which compares voltages between a precision voltage reference and your ramp would be a way to self-calibrate your ramp charge rate with each sweep. Optimally do this with two voltage references (3.3V and 1.8V are common) but comparing 0V to a single voltage reference would be a great step.
  • Don't have the microcontroller gate: A 555 is perfectably capable of generating pulses to reset the ramp every so often, and frees up a pin of the microcontroller.
  • Use an op-amp for constant current charging. It seems like a lateral move, but if your deign already has an op-amp chances are there may be some unused amps, so eliminate a transistor for this purpose! Check out the constant current source section from TIs handbook on operational amplifier applications.
  • Use an op-amp for the comparator(s). The microcontroller's comparator is handy, but if yours doesn't have one (or you don't feel like using one) configuring an unused op-amp stage as a comparator is a good option. The digital output could also trigger an interrupt on the digital input of a MCU pin as well!
  • Use timer and counters to measure time while using an external interrupt to gate the count. Your microcontroller's on-board counter is likely extremely powerful so utilize it! This example doesn't use it actually, but using it would let you count up to the CPU clock's frequency of ticks between ramp starts and the comparator match.
  • Eliminate the microcontroller. Yeah, you heard me. If you use an op-amp keep resetting the ramps, and op-amp comparators to generate digital outputs of threshold crossings, you can use a standard counter (configured to latch then clear when the reset event is engaged by the 555 which induces resetting of the ramp by draining the capacitor), just use a counter IC to capture the value. You can clock it as fast as you want! You could even have it output its value directly to LED or LCD displays. In fact, this is how some digital volt meters work without the need for a microcontroller.

All code used in this project is available on its GitHub page

Markdown source code last modified on January 18th, 2021
---
title: Adding ADC to Microcontrollers without ADC
date: 2016-09-09 03:00:31
tags: circuit, old
---

# Adding ADC to Microcontrollers without ADC

__I recently had the need to carefully measure a voltage with a microcontroller which lacks an analog-to-digital converter (ADC), and I hacked together a quick and dirty method to do just this using a comparator, two transistors, and a few passives.__ The purpose of this project is to make a [crystal oven](https://en.wikipedia.org/wiki/Crystal_oven) controller at absolute minimal cost with minimal complexity. Absolute voltage accuracy is not of high concern (i.e., holding temperature to 50.00 C) but precision is the primary goal (i.e., hold it within 0.01 C of an arbitrary target I set somewhere around 50 C). Voltage measurement is usually a balance of a few factors: precision, accuracy, cost, simplicity, and speed. The method I demonstrate here maximizes precision and simplicity while minimizing cost. High speed operation is not of interest (1-2 measurements per second is fine), and as mentioned before accuracy is not a chief concern as long as precision is maximized. I would feel neglectful if I didn't give a shout out to a few alternatives to this method: Using the [10-bit ADC built into most AVR microcontrollers](http://maxembedded.com/2011/06/the-adc-of-the-avr/) (my go-to for ATMega328 at ATTiny85, but the ATTiny2313 doesn't have any) [often combined with an op-amp like this](https://www.swharden.com/wp/2013-06-10-precision-temperature-measurement/), using an IC like the [MCP3208 8-channel 12-bit ADC](http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf) (very expensive at [$3.66 on mouser](http://www.mouser.com/Search/Refine.aspx?Keyword=mcp3208&Ns=Pricing%7c0&FS=True)) are a good option, and fancy alternative dual slope methods as described in this [really good youtube video](https://www.youtube.com/watch?v=pzXZnvEKMXs) and even mentioned nicely in the digital volt meter (DVM) / LCD driver [ICL1706 datasheet](http://www.intersil.com/content/dam/Intersil/documents/icl7/icl7106-07-07s.pdf). Those addressed, my quick and dirty idea uses only a couple cents of components and 3 pins of a microcontroller. There is much room for improvement (see my notes about a 555 timer, voltage reference, and operational amplifiers at the bottom) but this is a good minimal case starting point. This type of measurement is perfect for high precision temperature measuring using things like an [LM335](http://www.ti.com/lit/ds/symlink/lm135.pdf), [LM35](http://www.ti.com/lit/ds/symlink/lm135.pdf), or [thermistor](https://en.wikipedia.org/wiki/Thermistor).

<div class="text-center">

[![](circuit_thumb.jpg)](circuit.png)

</div>

**The concept behind this method is simple:** use a current-limiting circuit to charge a capacitor at a constant rate so voltage rises linearly with time (rather than forming an exponential RC curve), and time how long that voltage takes to cross your test voltage. A circuit which compares two voltages and outputs high when one voltage surpasses the other is called a [comparator](https://en.wikipedia.org/wiki/Comparator), and many microcontrollers (including ATMEL AVRs) have analog comparators built in (which compare AIN0 and AIN1, the result of which accessable by accessing the <code>ACSR&(<span class="pl-c1">1</span><<ACO)</code>) bit value (at least for the ATMega328, according to the [datasheet](http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf)). 

**I can use the AVR's comparator to time how long it takes a capacitor to charge to the test voltage, and output to that to the serial port.** _Note that I designed this entire circuit to use the most common transistor/resistors I could think of. It can be fine-tuned to increase speed or increase precision, but this is a great starting point_. To generate a constant current I need a PNP transistor (I had a 2N2907 on hand) with a voltage divider on the base and a current limiting resistor above the transistor for good measure (in retrospect, with a more carefully chosen set of values this may not be needed). This is all that's needed to charge the capacitor linearly and generate a positive ramp.

<div class="text-center img-border">

[![](testrig-1_thumb.jpg)](testrig-1.jpg)

</div>

__My test setup is a mess, but it demonstrates this idea works well, and is stable enough to run some experiments.__ In the frame you can see the ATMega328 microcontroller (big microchip), [LM335 temperature sensor](http://www.ti.com/lit/ds/symlink/lm135.pdf) (the TO-92 closest to the MCU), a TTL FTDI serial/USB adapter (red board, top), and my USBTiny AVR programmer (blue board, right), and oscilloscope probes.

<div class="text-center img-border">

[![](scope_thumb.jpg)](scope.png)

</div>

__To prevent this linear charger from charging forever, I make the microcontroller read the comparator which compares my test voltage with that of the ramp.__ If the test voltage is reached, or if the ramp reaches a cutoff voltage first (meaning the test voltage is too high to be measured), the count (time between last reset and now) is sent to the computer via serial port, and the capacitor is discharged through a PNP resistor. In the schematic, this is the "reset" pin. Note that the "measure" pin is AVR AC0, and AC1 is the test voltage. When all this is assembled, you can see how the linear ramps are created every time the reset transistor shuts off. Note that every 10th ramp is higher than the rest (shown here as the one left from center). This is because every 10th reading the data is summed and sent to the serial port, causing a little extra time before it is reset again. While the _time value_ has been recorded of the comparator match of the test voltage and the ramp voltage, the capacitor is allowed to continue charging until the next cycle.

__Interestingly, this method is largely insensitive to power supply noise.__ I'm using an extremely noisy environment (breadboard, DIP power regulator) but the recordings are rock solid. I suspect this is because the ramps are timed based on constant current, not abbsolute voltage, and that the ramps are fast enough to not be sensitive to slow changes in voltage. In reality, I don't think I can adequately explain why the readings are so good when the supply is so shaky (the positive voltage rail is all over the place). It works, so I'm happy with it, and I'll keep pushing forward.

<div class="text-center img-border">

[![](miniterm_thumb.jpg)](miniterm.png)

</div>

__Lately I've been using [RealTerm](http://realterm.sourceforge.net/) as a feature-rich alternative to HyperTerminal__ and a more convenient method than requiring custom python scripts be written every time I want to interact with the serial port in a way that involves debugging or logging or other advanced features. Here you can see the real time output of this device logging time to comparator match as it also logs to disk in a text file. This is great for simultaneously logging data (from RealTerm) and graphing it (from custom python scripts).

<div class="text-center">

[![](data_touch_thumb.jpg)](data_touch.png)

</div>

__This is what happens when I touch the temperature sensor for about 30s.__ I'm recording the time to voltage crossing of an LM335, so the number decreases as temperature increases. Also each data point is the average (actually the sum) of 10 points. It would be trivial to create some voltage test points, create a calibration curve, and infer the voltages involved, but this is more than enough already to prove that this method is robust and clean and precise and I couldn't be more satisfied with the results! With a pair or capacitors and a few passives, this is totally implementable virtually anywhere. Considering my room is about 78F and my finger is about 98F, this 20F spread is about 1500 data points. That means each degree F is about 75 points, so I can resolve better 0.02 F (about 0.01 C) with this crude setup.

<div class="text-center">

[![](data_ac_thumb.jpg)](data_ac.png)

</div>

__If I let it run for about an hour, I catch my air conditioning coming on and off.__ Warmer temperature is higher voltage which means less time to charge, so the downslopes are my AC cooling my home and the up slope is my home passively warming. The fluctuations are only about 100 units which I (backwards calculate) assume are about 1-2 F.

__These numbers seem so arbitrary! How can we calibrate this?__ This opens up a Pandora's box of possible improvements. I'll close by saying that this project works great exactly how it is to meet my needs. However, some modifications could be made to change the behavior of this device:

*   __Slowing things down: __A larger capacitor value (or higher resistor value) would increase the time or charging, lengthen the time to comparator threshold crossing, and increase precision. The readings would be slower (and more susceptible to noise), but it's an option.
*   __Self-calibration:__ Components (Rs and Cs) are sensitive to temperature and charge time can fluctuate with age, wear, temperature, etc. To self-calibrate with each sweep, add an additional comparator step which compares voltages between a [precision voltage reference](http://www.ti.com/lit/an/slyt183/slyt183.pdf) and your ramp would be a way to self-calibrate your ramp charge rate with each sweep. Optimally do this with two voltage references (3.3V and 1.8V are common) but comparing 0V to a single voltage reference would be a great step.
*   __Don't have the microcontroller gate:__ A 555 is perfectably capable of generating pulses to reset the ramp every so often, and frees up a pin of the microcontroller.
*   __Use an op-amp for constant current charging.__ It seems like a lateral move, but if your deign already has an op-amp chances are there may be some unused amps, so eliminate a transistor for this purpose! Check out the constant current source section from TIs [handbook on operational amplifier applications](http://www.ti.com/lit/an/sboa092a/sboa092a.pdf).
*   __Use an op-amp for the comparator(s).__ The microcontroller's comparator is handy, but if yours doesn't have one (or you don't feel like using one) configuring an unused op-amp stage as a comparator is a good option. The digital output could also trigger an interrupt on the digital input of a MCU pin as well!
*   __Use timer and counters to measure time__ while using an external interrupt to gate the count. Your microcontroller's on-board counter is likely extremely powerful so utilize it! This example doesn't use it actually, but using it would let you count up to the CPU clock's frequency of ticks between ramp starts and the comparator match.
*   __Eliminate the microcontroller.__ Yeah, you heard me. If you use an op-amp keep resetting the ramps, and op-amp comparators to generate digital outputs of threshold crossings, you can use a standard counter (configured to latch then clear when the reset event is engaged by the 555 which induces resetting of the ramp by draining the capacitor), just use a counter IC to capture the value. You can clock it as fast as you want! You could even have it output its value directly to LED or LCD displays. In fact, this is how some digital volt meters work without the need for a microcontroller.

>  All code used in this project is available on [its GitHub page](https://github.com/swharden/AVR-projects/tree/master/ATMega328%202016-09-07%20ramp%20DVM)
September 5th, 2016

VHF Frequency Counter with PC Interface

Projects I build often involve frequency synthesis, and one of the most useful tools to have around is a good frequency counter. I love the idea of being able to access / log / analyze frequency readings on my computer. 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.

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).

The 1PPS gate signal is generated from an inexpensive GPS module available on Amazon. I'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...None

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.

Source Code

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.

Markdown source code last modified on January 18th, 2021
---
title: VHF Frequency Counter with PC Interface
date: 2016-09-05 17:34:44
tags: amateur radio, circuit, python, old
---

# VHF Frequency Counter with PC Interface

**Projects I build often involve frequency synthesis, and one of the most useful tools to have around is a good frequency counter.** I love the idea of being able to access / log / analyze frequency readings on my computer. 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](http://www.mouser.com/Search/Refine.aspx?Keyword=sn74lv8154&Ns=Pricing%7c0&FS=True)) and an ATMega328 microcontroller ([$3.37 on Mouser](http://www.mouser.com/Semiconductors/Integrated-Circuits-ICs/Embedded-Processors-Controllers/Microcontrollers-MCU/8-bit-Microcontrollers-MCU/_/N-a86lo?P=1z0y33r&Keyword=atmega328p&Ns=Pricing%7c0&FS=True)). 

**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](https://www.swharden.com/wp/2016-08-20-breadboard-line-driver-module/)). If you don't have a GPS unit, consider getting one! I'm using a NEO-6M module ([$17.66 on Amazon](https://www.amazon.com/Andoer-AeroQuad-Multirotor-Quadcopter-Aircraft/dp/B00RCP9MLY)) 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](https://github.com/swharden/AVR-projects/tree/master/ATMega328%202016-09-04%20SN74LV8154)!** 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](https://www.u-blox.com/sites/default/files/products/documents/Timing_AppNote_%28GPS.G6-X-11007%29.pdf).

<div class="text-center">

[![](pc-frequency-counter-schem_thumb.jpg)](pc-frequency-counter-schem.png)

</div>

**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](http://www.ti.com/lit/ds/symlink/sn74lv8154.pdf)) 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](https://www.swharden.com/wp/2016-08-31-ics501-simple-frequency-multiplier/) 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).

<div class="text-center">

[![](neo-60-gps-1pps_thumb.jpg)](neo-60-gps-1pps.jpg)

</div>

**The 1PPS gate signal is generated from an inexpensive GPS module [available on Amazon](https://www.amazon.com/Andoer-AeroQuad-Multirotor-Quadcopter-Aircraft/dp/B00RCP9MLY).** I've hinted at the construction of this device before and [made a post](https://www.swharden.com/wp/2016-08-20-breadboard-line-driver-module/) 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](https://www.swharden.com/wp/2016-08-20-breadboard-line-driver-module/#jp-carousel-5918) (purple wire).

<div class="text-center img-border">

[![](IMG_8207_thumb.jpg)](IMG_8207.jpg)

</div>

**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](https://www.swharden.com/wp/2016-08-31-ics501-simple-frequency-multiplier/). 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.

<div class="text-center img-border">

[![](ss_thumb.jpg)](ss.png)

</div>

**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](https://en.wikipedia.org/wiki/Very_high_frequency) 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](http://www.ebay.com/sch/i.html?_nkw=extruded+split+body+aluminum+enclosure)), 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](https://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Dtools&field-keywords=Nickel+Plated+Nibbling+Tool), 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](http://www.qsl.net/pa2ohh/tlabels.htm). I tend to build one-off projects like this dead-bug / Manhattan style.

<div class="text-center img-border">

[![](IMG_8277_thumb.jpg)](IMG_8277.jpg)
[![](IMG_8282_thumb.jpg)](IMG_8282.jpg)

</div>

**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](https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=usbtiny+isp)) to do the programming (no longer the BusPirate, it's too slow) [like I describe here for 64-bit Windows 7](https://www.swharden.com/wp/2013-05-07-avr-programming-in-64-bit-windows-7/) (although I'm now using Windows 10 and it works the same).

<div class="text-center img-border">

[![](IMG_8330_thumb.jpg)](IMG_8330.jpg)

</div>

**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!)

<div class="text-center img-border">

[![](IMG_8286_thumb.jpg)](IMG_8286.jpg)

</div>

**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.

<div class="text-center img-border">

[![](IMG_8297_thumb.jpg)](IMG_8297.jpg)

</div>

**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!

<div class="text-center img-border">

[![](IMG_8316_thumb.jpg)](IMG_8316.jpg)

</div>

**This is an easy test frequency source.** I have a dozen [canned oscillators](https://en.wikipedia.org/wiki/Crystal_oscillator) of various frequencies. This is actually actually a voltage controlled oscillator ([VCO](https://en.wikipedia.org/wiki/Voltage-controlled_oscillator)) 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](https://en.wikipedia.org/wiki/Very_high_frequency).

<div class="text-center img-border">

[![](IMG_8318_thumb.jpg)](IMG_8318.jpg)

</div>

**You can see on the screen it's having no trouble reading the ~50 MHz frequency.** You'll notice I'm using [RealTerm](http://realterm.sourceforge.net/) (with a [good write-up on sparkfun](https://learn.sparkfun.com/tutorials/terminal-basics/real-term-windows)) 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...[None](https://www.swharden.com/wp/wp-content/uploads/2016/09/IMG_8316.jpg)

<div class="text-center img-border">

[![](IMG_8335_thumb.jpg)](IMG_8335.jpg)

</div>

**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](https://en.wikipedia.org/wiki/Ferrite_bead) 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.

<div class="text-center img-border">

[![](IMG_8335_thumb.jpg)](IMG_8335.jpg)

</div>

**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](https://www.swharden.com/wp/2016-08-20-breadboard-line-driver-module/#jp-carousel-5918) the GPS 1PPS enclosure.

<div class="text-center img-border">

[![](IMG_8344_thumb.jpg)](IMG_8344.jpg)

</div>

**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.

## Source Code

Microcontroller code (AVR-GCC), schematics, and a Python script to interface with the serial port are all available on [this project's GitHub page](https://github.com/swharden/AVR-projects/blob/master/ATMega328%202016-09-04%20SN74LV8154/main.c)

## 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](https://www.swharden.com/wp/2011-06-19-using-timers-and-counters-to-clock-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](http://www.nxp.com/documents/data_sheet/74HC_HCT4060_Q100.pdf) (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](https://www.u-blox.com/sites/default/files/NEO-M8_DataSheet_(UBX-13003366).pdf) at 9600 baud and continuously dumps [NEMA formatted](http://www.gpsinformation.org/dale/nmea.htm) 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.

<div class="text-center img-border">

[![](IMG_8401_thumb.jpg)](IMG_8401.jpg)

</div>

**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.

<div class="text-center img-border">

[![](IMG_8402_thumb.jpg)](IMG_8402.jpg)

</div>

**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.

<div class="text-center img-border">

[![](IMG_8403_thumb.jpg)](IMG_8403.jpg)

</div>

**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.

<div class="text-center img-border img-small">

[![](FullSizeRender-2_thumb.jpg)](FullSizeRender-2.jpg)

</div>

**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.

<div class="text-center img-border">

[![](IMG_8404_thumb.jpg)](IMG_8404.jpg)

</div>

**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.

<div class="text-center img-border">

[![](IMG_8405_thumb.jpg)](IMG_8405.jpg)

</div>

**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!

<div class="text-center img-border">

![](serial-combine.jpg)

</div>

**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](http://www.gpsinformation.org/dale/nmea.htm) GPS data.

<div class="text-center img-border">

[![](combined-python_thumb.jpg)](combined-python.png)

</div>

**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.
August 31st, 2016

ICS501 Simple Frequency Multiplier

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!

Markdown source code last modified on January 18th, 2021
---
title: ICS501 Simple Frequency Multiplier
date: 2016-08-31 03:57:50
tags: circuit, old
---

# ICS501 Simple Frequency Multiplier

**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](http://www.ebay.com/sch/i.html?&_nkw=ICS501), [$1.55 on mouser](http://www.mouser.com/Search/Refine.aspx?Keyword=ics501&Ns=Pricing%7c0&FS=True), and [$0.67 on Digikey](http://www.digikey.com/product-search/en/integrated-circuits-ics/clock-timing-clock-generators-plls-frequency-synthesizers/2556421?FV=fff40027%2Cfff80205&mnonly=0&newproducts=0&ColumnSort=1000011&page=1&stock=0&pbfree=0&rohs=0&k=ics501&quantity=&ptm=0&fid=0&pageSize=25), 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](http://www.ti.com/lit/ds/symlink/cd4046b.pdf) micro-power phased lock loop IC which has a [phase comparator](https://en.wikipedia.org/wiki/Phase_detector) 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](https://en.wikipedia.org/wiki/Voltage-controlled_oscillator) 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.

<div class="text-center img-medium">

[![](datasheet_thumb.jpg)](datasheet.jpg)

</div>

**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.

<div class="text-center img-border">

[![](IMG_8104_thumb.jpg)](IMG_8104.jpg)

</div>

**The IC I had on hand was [SOIC](https://en.wikipedia.org/wiki/Small_Outline_Integrated_Circuit).** I don't think they make this IC in [DIP](https://en.wikipedia.org/wiki/Dual_in-line_package). Luckily, I have breadboardable breakout boards on hand. These breakout boards are identical to those sold on [dipmicro](https://www.dipmicro.com/store/PCB-SSOP-DIP28) but I got mine from ebay and they're [all over ebay](http://www.ebay.com/sch/sis.html?_nkw=SMD+SMT+IC+PCB+Adapter)!

<div class="text-center img-border">

[![](IMG_8111_thumb.jpg)](IMG_8111.jpg)

</div>

**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...

<div class="text-center img-border">

[![](IMG_8113_thumb.jpg)](IMG_8113.jpg)

</div>

**Here's the test circuit.** I added a 100nF power [decoupling capacitor](https://en.wikipedia.org/wiki/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).

<div class="text-center img-border">

[![](IMG_8121_thumb.jpg)](IMG_8121.jpg)

</div>

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

<div class="text-center img-border">

[![](ics501-demo_thumb.jpg)](ics501-demo.png)

</div>

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.

<div class="text-center img-border img-small">

[![](IMG_8179_thumb.jpg)](IMG_8179.jpg)

</div>

**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).

<div class="text-center img-border">

[![](IMG_8175_thumb.jpg)](IMG_8175.jpg)

</div>

**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...

<div class="text-center img-border">

[![](IMG_8162_thumb.jpg)](IMG_8162.jpg)

</div>

**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).

<div class="text-center img-border">

[![](IMG_8161_thumb.jpg)](IMG_8161.jpg)

</div>

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

<div class="text-center img-border">

![](SDS00018.jpg)

</div>

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

<div class="text-center img-border">

![](SDS00005.jpg)

</div>

**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.

<div class="text-center img-border">

[![](IMG_8166_thumb.jpg)](IMG_8166.jpg)

</div>

**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!
August 24th, 2016

TENMA Multimeter Serial Hack

I just spent the afternoon reverse-engineering the 72 series TENMA multimeter serial interface, and can now access all of its readings from a standalone Python script. This lets me send all measurements made with the multimeter to my computer in real time (using an optically isolated connection), and eliminates the need for the TENMA PC interface software. In addition to allowing the development of custom software to use measurements from TENMA multimeters in real time, this project also lets allows TENMA multimeters to interface with Linux computers (such as the raspberry pi).

I have owned a TENMA 72-7750 multimeter for several years, and over all I've been happy with it! To be honest, 90% of my multimeter needs are just using a continuity tester or checking to see if there is voltage on a line. For checking electrical signals, I love my no-name (actually it's branded "KOMEC") $15 eBay special multimeter. The screen updates about 4 times a second, and I don't care if it's off by 10%, it's cheap and light and fast and easy for simple tasks. However, when I'm going to use a multimeter to actually measure something, I reach for a higher quality meter like my TENMA 72-7750. Although similar TENMA models may be more popular, I went with this particular one because it could measure frequency which is convenient when building RF circuits. While big fancy frequency counters are nice to have on your workbench, I liked the idea of having that functionality built into my multimeter. I believe my particular model is discontinued, but it looks like the 72-7745 is a similar product, and there are many TENMA multimeters on Amazon. Back in April of 2013 I mentioned on my website that I'd consider writing interface software in Python. Now that I'm [finally] out of school and have a little more free time, I decided to pick up the project again. I ran into a few tangles along the way, but I'm happy to report this project is now working beautifully! The pyTENMA project is open-sourced on my GitHub. I'm excited to see what kind of data I can get out of this thing!

This is my multimeter taking a measurement (resistance) and sending the data to my computer using the optically-isolated serial connector (which ships with the multimeter). In this picture, it's interacting with the official TENMA software. To try to figure out what was going on, I probed pins of the serial port while data was being exchanged. The yellow trace is the data signal.

There was a problem, and this problem took me hours to figure it out, but now that I realize what's going on it seems so obvious. The problem was that I could never get the multimeter to send my Python script data, despite the fact that the exact same configuration would send the commercial program data. I used serial port sniffing software to view the data too! I matched the baud rate (19200 / 19230), data bits (7), and parity (odd), and I just couldn't figure out why the heck this thing wouldn't work. I resorted to using an oscilloscope to probe the pins of the serial cable directly. I made a small man-in-the-middle test jig to give me headers I could easily probe or solder wires to. After poking around, I learned two things. (1) I really need a logic analyzer. They're so cheap now, I went ahead and ordered one. (2) The RTS line goes low and the DSR line goes high when data is being sent. I realized that the Python software was disregarding these pins. You wouldn't think you needed them if you're just going to be receiving data with software control... but I immediately realized that those pins may be important for powering the optoelectronics (likely a phototransistor and some passive components) underlying the data exchange. After all, it's not like the multimeter is able to source or sink appreciable current through an optical connection! I'll note that some sketchy schematics are floating around Hackaday (pun intended), but the web page they link to doesn't look very complete so I'm not sure how far that author got toward the same endeavor I'm chasing.

Here you can see some of the adjacent (non-data) pins change their voltage state during transmissions. Once I realized replicating these states was also necessary, everything quickly fell into place. After manually commanding the RTS pin to lie low (1 line of code), the data starting coming in! I finished writing a basic pyTENMA class (which does a lot of hardware detection, string parsing, etc. to generate simple no-nonsense value/unit pairs to return to the user as well as log values to disk automatically) and tried to make it as simple as possible. Without going into too much detail (see the note in the top of my source code for more information), the multimeter just sends a 9-character ASCII string every second. I refer to this string as ABBBBCDEF. Byte 1 is a multiplier and bytes 2-5 are the value displayed on the screen. The actual value of a read is BBBB*10^A. The units depend on the mode (resistance, capacitance, etc), which is indicated by byte 6. It's a little funny in that "4" means temperature and ";" means voltage, but once I figured out (through trial and error) which symbols match with which mode it was pretty easy to make it work for me. D is the sign (negative, zero, or positive), and I still haven't really figured what E and F are. I thought they might be things like backlight or perhaps indicators of the range setting. I didn't care to figure it out, because I already had access to the data I wanted!

To use the pyTENMA script, just drop it alongside a Python script you want to work on. Import it, tell it a COM port to use (if not, it'll try to guess one) and a log file (optional). This is all the code you need:

import pyTENMA # make sure pyTENMA.py is in the same folder
PT=pyTENMA.pyTenma("COM4","log.txt")
PT.readUntilBroken()

The output is very simple. Here it is compared to the commercial TENMA software. PyroElectro has a good demonstration of the PC interface software that ships with this unit. While the TENMA software is functional, it has some serious limitations that motivate me to improve upon it. (1) It's Windows only. (2) It doesn't automatically log data (you have to manually click save to write it to disk). (3) It seems to be limited to COM1-COM4. My USB serial adapter was on COM7 and inaccessible to this program. I had to go in the device manager and change the advanced settings to allow the commercial software to read my device. (4) The graphs are poor, non-interactive, and often broken. (5) Data output format is only an Excel spreadsheet (.xls), and I don't have control to save in other formats like CSV. If I'm going to use this on a raspberry pi, I don't want to fumble around with Microsoft Office! Yeah I know I can get modules (even for Python) to access data in excel spreadsheets, but it seems like an unnecessary complexity just to retrieve some voltage readings. Over all it seems a little unfortunate that a relatively great product is pulled down when its weakest link is its software. It's okay, we are on our way to can fixing this with pyTENMA!

Measuring Capacitor Leakage

I set up an experiment to demonstrate how logging data works. I charged a 22uF capacitor on a breadboard and let it sit there disconnected, slowly draining through leakage (and perhaps micro current draw from the multimeter). After a while I slowly charged it (using my body as a resistor, touching the +5V line and touching the capacitor lead with my fingers) and watched it discharge again. You can set pyTENMA software to save as little or often as you want. It defaults to every 10 reads, but I adjust it to every 100 reads for longer experiments. Also note that if you break it (with CTRL+C) it gently disconnects the serial device, logs remaining data to disk, then exits gracefully.

In this demonstration, voltage across the capacitor on the breadboard is being measured by the multimeter, and reported (and logged) in real time by pyTENMA seen on the screen. Here is what that data looks like after about a half hour of run time. The code to read the log file and make graphs from it (using numpy and matplotlib) is in the logPlot source code.

Measuring OCXO Warm-Up

Now that I know everything is up and running, I can use this device to make some measurements I'm actually interested in! In reality, this usage case is the reason I went through all the trouble to write custom data logging software for this multimeter is specifically for this case. I'm working on a large project involving a GPS-disciplined oven controlled crystal oscillator (OCXO) for a 1pps frequency reference, and spoiler alert it involves a raspberry pi to plot and upload live graphs of real-time frequency and accuracy statistics to my website. I don't want to discuss it yet (it's not complete), but I can't avoid mentioning it since I'm showing photos of it. I'll surely make a follow-up post when that project is complete and well documented. For now, the only relevant thing is that the device is an oven which takes a lot of current to heat from room temperature to a high temperature, and a smaller amount of current to maintain it at that temperature. I wanted to know how long it takes the current to stabilize over time (on a scale of hours), determine if its current draw oscillates, and also assess what the voltage at the oscillator reads during warm-up (high current draw) vs. stable conditions.

My test setup uses the TENMA multimeter in current measuring configuration. Note the configuration of the multimeter test leads as being in series with the power supply. This meter has two current measurement settings, one for <600 mA and one for up to 10 A. I know that the oscillator draws about 2 A during warm-up (this is because I'm intentionally limiting it to 2A), and stabilizes to somewhere near 200 mA after several minutes. To maximize my sample resolution, I started the recording using the 10 A setting, then after it dropped well below 600 mA I switched to the lower current setting. The data is colored red and blue, respectively:

current stabilizes within 10 minutes:

Current is maxed-out for a few minutes, oscillates then stabilizes. 10 A / 600 mA measuring settings are in red and blue (respectively):

once stable, current draw is stable for hours

I concluded that this thing stabilizes to within 10% of its final current draw well within 10 minutes. From there, it seems really stable, but slowly oscillates on a time scale of tens of minutes. I suspect this correlates with the AC unit of my house turning on and off. A similar recording of temperature of the oscillator (which the TENMA 72-7750 can also do with the thermocouple it was shipped with) may provide more insight as to whether or not the oscillator itself is actually changing temperature during these current oscillations. Now I'm curious what the voltage does during the warm-up period while the current is maxed out. I guess I need to reveal that my current limit is provided by two parallel LM7809 voltage regulators each in series with a 2 Ohm current limiting resistor before connecting to a common +9V rail which is running the oscillator. Since each regulator is current limited to about 1A, it's no surprise my maximum current is about 2A, but I'd be interested to learn what the voltage is doing during that period.

I measured voltage just downstream of the voltage regulators:

During current max-out, the voltage is <<9V

Voltage stabilizes after about 10 minutes

I am interested in seeing what of these measurements (with more such as temperature and OCXO frequency) look like when they are all measured simultaneously. The TENMA multimeter I'm using can't measure voltage and current at the same time (which would require a third lead, if you think about it), so this solution will require alternative equipment. Stay tuned, because I have a cool solution for that in the works! For now, I couldn't be happier with my TENMA multimeter's ability to log data to text files using pyTENMA and the ease in which numpy/matplotlib can read and graph them. A data logging multimeter is a great tool to have in any engineer's toolbox, and I'm glad I now have one that plays nicely with Python.

Resources

Markdown source code last modified on January 18th, 2021
---
title: TENMA Multimeter Serial Hack
date: 2016-08-24 03:08:28
tags: python, old
---

# TENMA Multimeter Serial Hack

__I just spent the afternoon reverse-engineering the 72 series TENMA multimeter serial interface,__ and can now access all of its readings from a standalone Python script. This lets me send all measurements made with the multimeter to my computer in real time (using an optically isolated connection), and eliminates the need for the TENMA PC interface software. In addition to allowing the development of custom software to use measurements from TENMA multimeters in real time, this project also lets allows TENMA multimeters to interface with Linux computers (such as the raspberry pi). 

**I have owned a [TENMA 72-7750](http://www.farnell.com/datasheets/1955368.pdf?_ga=1.217276502.1323514874.1471841353) multimeter for several years, and over all I've been happy with it!** To be honest, 90% of my multimeter needs are just using a continuity tester or checking to see if there is voltage on a line. For _checking_ electrical signals, I love my no-name (actually it's branded "KOMEC") $15 eBay special multimeter. The screen updates about 4 times a second, and I don't care if it's off by 10%, it's cheap and light and fast and easy for simple tasks. However, when I'm going to use a multimeter to actually _measure_ something, I reach for a higher quality meter like my TENMA 72-7750. Although [similar TENMA models may be more popular](http://www.newark.com/MarketingProductList?storeId=10194&catalogId=15003&langId=-1&orderCode=02J5540,02J5541,02J5542,02J5543,02J5546), I went with this particular one because it could measure frequency which is convenient when building RF circuits. While big fancy frequency counters are nice to have on your workbench, I liked the idea of having that functionality built into my multimeter. I believe my particular model is discontinued, but it looks like the 72-7745 is a similar product, and there are [many TENMA multimeters on Amazon](https://www.amazon.com/s/field-keywords=tenma+multimeter). Back in April of 2013 I mentioned on my website that I'd consider writing interface software in Python. Now that I'm [finally] out of school and have a little more free time, I decided to pick up the project again. I ran into a few tangles along the way, but I'm happy to report this project is now working beautifully! The [pyTENMA project](https://github.com/swharden/pyTENMA) is open-sourced on my GitHub. I'm excited to see what kind of data I can get out of this thing!

<div class="text-center img-border">

[![](IMG_7956_thumb.jpg)](IMG_7956.jpg)

</div>

**This is my multimeter taking a measurement (resistance) and sending the data to my computer using the optically-isolated serial connector (which ships with the multimeter).** In this picture, it's interacting with the official TENMA software. To try to figure out what was going on, I probed pins of the serial port while data was being exchanged. The yellow trace is the data signal. 

__There was a problem, and this problem took me hours to figure it out,__ but now that I realize what's going on it seems so obvious. The problem was that I could never get the multimeter to send my Python script data, despite the fact that the exact same configuration would send the commercial program data. I used serial port sniffing software to view the data too! I matched the baud rate (19200 / 19230), data bits (7), and parity (odd), and I just couldn't figure out why the heck this thing wouldn't work. I resorted to using an oscilloscope to probe the pins of the serial cable directly. I made a small man-in-the-middle test jig to give me headers I could easily probe or solder wires to. After poking around, I learned two things. (1) I really need a logic analyzer. They're so cheap now, I went ahead and ordered one. (2) The RTS line goes low and the DSR line goes high when data is being sent. I realized that the Python software was disregarding these pins. You wouldn't _think_ you needed them if you're just going to be receiving data with software control... but I immediately realized that those pins may be important for powering the optoelectronics (likely a phototransistor and some passive components) underlying the data exchange. After all, it's not like the multimeter is able to source or sink appreciable current through an optical connection! I'll note that some [sketchy schematics](http://hackaday.com/2014/12/05/fixing-a-multimeters-serial-interface/) are floating around Hackaday (pun intended), but the [web page they link to](http://www.wattnotions.com/tenma-72-7735-serial-interface/) doesn't look very complete so I'm not sure how far that author got toward the same endeavor I'm chasing.

<div class="text-center img-border">

[![](IMG_7961_thumb.jpg)](IMG_7961.jpg)

</div>

__Here you can see some of the adjacent (non-data) pins change their voltage state during transmissions. Once I realized replicating these states was also necessary, everything quickly fell into place.__ After manually commanding the RTS pin to lie low (1 line of code), the data starting coming in! I finished writing a basic pyTENMA class (which does a lot of hardware detection, string parsing, etc. to generate simple no-nonsense value/unit pairs to return to the user as well as log values to disk automatically) and tried to make it as simple as possible. Without going into too much detail ([see the note in the top of my source code for more information](https://github.com/swharden/pyTENMA/blob/master/pyTENMA.py)), the multimeter just sends a 9-character ASCII string every second. I refer to this string as ABBBBCDEF. Byte 1 is a multiplier and bytes 2-5 are the value displayed on the screen. The actual value of a read is BBBB*10^A. The units depend on the mode (resistance, capacitance, etc), which is indicated by byte 6. It's a little funny in that "4" means temperature and ";" means voltage, but once I figured out (through trial and error) which symbols match with which mode it was pretty easy to make it work for me. D is the sign (negative, zero, or positive), and I still haven't really figured what E and F are. I thought they might be things like backlight or perhaps indicators of the range setting. I didn't care to figure it out, because I already had access to the data I wanted!

__To use the pyTENMA script, just drop it alongside a Python script you want to work on.__ Import it, tell it a COM port to use (if not, it'll try to guess one) and a log file (optional). This is all the code you need:

```python
import pyTENMA # make sure pyTENMA.py is in the same folder
PT=pyTENMA.pyTenma("COM4","log.txt")
PT.readUntilBroken()
```

__The output is very simple.__ Here it is compared to the commercial TENMA software. [PyroElectro has a good demonstration](http://www.pyroelectro.com/tutorials/tenma_digital_multimeter/software.html) of the PC interface software that ships with this unit. While the TENMA software is functional, it has some serious limitations that motivate me to improve upon it. (1) It's Windows only. (2) It doesn't automatically log data (you have to manually click save to write it to disk). (3) It seems to be limited to COM1-COM4. My USB serial adapter was on COM7 and inaccessible to this program. I had to go in the device manager and change the advanced settings to allow the commercial software to read my device. (4) The graphs are poor, non-interactive, and often broken. (5) Data output format is only an Excel spreadsheet (.xls), and I don't have control to save in other formats like CSV. If I'm going to use this on a raspberry pi, I don't want to fumble around with Microsoft Office! Yeah I know I can get modules (even for Python) to access data in excel spreadsheets, but it seems like an unnecessary complexity just to retrieve some voltage readings. Over all it seems a little unfortunate that a relatively great product is pulled down when its weakest link is its software. It's okay, we are on our way to can fixing this with [pyTENMA](https://github.com/swharden/pyTENMA)!

<div class="text-center img-border img-small">

[![](screenshot_thumb.jpg)](screenshot.jpg)
![](commercialSoftware.jpg)

</div>

## Measuring Capacitor Leakage

__I set up an experiment to demonstrate how logging data works.__ I charged a 22uF capacitor on a breadboard and let it sit there disconnected, slowly draining through leakage (and perhaps micro current draw from the multimeter). After a while I slowly charged it (using my body as a resistor, touching the +5V line and touching the capacitor lead with my fingers) and watched it discharge again. You can set pyTENMA software to save as little or often as you want. It defaults to every 10 reads, but I adjust it to every 100 reads for longer experiments. Also note that if you break it (with CTRL+C) it gently disconnects the serial device, logs remaining data to disk, then exits gracefully.

<div class="text-center img-border">

[![](IMG_7981_thumb.jpg)](IMG_7981.jpg)

</div>

__In this demonstration,__ voltage across the capacitor on the breadboard is being measured by the multimeter, and reported (and logged) in real time by pyTENMA seen on the screen. Here is what that data looks like after about a half hour of run time. The code to read the log file and make graphs from it (using numpy and matplotlib) is in the [logPlot source code](https://github.com/swharden/pyTENMA/blob/master/extras/logPlot.py).

<div class="text-center img-medium">

[![](logDemo_thumb.jpg)](logDemo.png)

</div>

## Measuring OCXO Warm-Up

__Now that I know everything is up and running, I can use this device to make some measurements I'm actually interested in!__ In reality, this usage case is the _reason_ I went through all the trouble to write custom data logging software for this multimeter is specifically for this case. I'm working on a large project involving a GPS-disciplined oven controlled crystal oscillator (OCXO) for a 1pps frequency reference, and spoiler alert it involves a raspberry pi to plot and upload live graphs of real-time frequency and accuracy statistics to my website. I don't want to discuss it yet (it's not complete), but I can't avoid mentioning it since I'm showing photos of it. I'll surely make a follow-up post when that project is complete and well documented. For now, the only relevant thing is that the device is an oven which takes a lot of current to heat from room temperature to a high temperature, and a smaller amount of current to maintain it at that temperature. I wanted to know how long it takes the current to stabilize over time (on a scale of hours), determine if its current draw oscillates, and also assess what the voltage at the oscillator reads during warm-up (high current draw) vs. stable conditions.

<div class="text-center img-border">

[![](FullSizeRender-2_thumb.jpg)](FullSizeRender-2.jpg)

</div>

__My test setup uses the TENMA multimeter in current measuring configuration.__ Note the configuration of the multimeter test leads as being in series with the power supply.  This meter has two current measurement settings, one for <600 mA and one for up to 10 A. I know that the oscillator draws about 2 A during warm-up (this is because I'm intentionally limiting it to 2A), and stabilizes to somewhere near 200 mA after several minutes. To maximize my sample resolution, I started the recording using the 10 A setting, then after it dropped well below 600 mA I switched to the lower current setting. The data is colored red and blue, respectively:

current stabilizes within 10 minutes:

<div class="text-center">

[![](ocxo-1_thumb.jpg)](ocxo-1.png)

</div>

Current is maxed-out for a few minutes, oscillates then stabilizes. 10 A / 600 mA measuring settings are in red and blue (respectively):

<div class="text-center">

[![](ocxo-2_thumb.jpg)](ocxo-2.png)

</div>

once stable, current draw is stable for hours

<div class="text-center">

[![](ocxo-3_thumb.jpg)](ocxo-3.png)

</div>

__I concluded that this thing stabilizes to within 10% of its final current draw well within 10 minutes.__ From there, it seems really stable, but slowly oscillates on a time scale of tens of minutes. I suspect this correlates with the AC unit of my house turning on and off. A similar recording of temperature of the oscillator (which the TENMA 72-7750 can also do with the thermocouple it was shipped with) may provide more insight as to whether or not the oscillator itself is actually changing temperature during these current oscillations. Now I'm curious what the voltage does during the warm-up period while the current is maxed out. I guess I need to reveal that my current limit is provided by two parallel LM7809 voltage regulators each in series with a 2 Ohm current limiting resistor before connecting to a common +9V rail which is running the oscillator. Since each regulator is current limited to about 1A, it's no surprise my maximum current is about 2A, but I'd be interested to learn what the voltage is doing during that period.

<div class="text-center img-border">

[![](FullSizeRender-3_thumb.jpg)](FullSizeRender-3.jpg)

</div>

I measured voltage just downstream of the voltage regulators:
<div class="text-center">

[![](mV1_thumb.jpg)](mV1.png)

</div>

During current max-out, the voltage is <<9V
<div class="text-center">

[![](mV2_thumb.jpg)](mV2.png)

</div>

Voltage stabilizes after about 10 minutes
<div class="text-center">

[![](mV3_thumb.jpg)](mV3.png)

</div>

__I am interested in seeing what of these measurements (with more such as temperature and OCXO frequency) look like when they are all measured simultaneously.__ The TENMA multimeter I'm using can't measure voltage and current at the same time (which would require a third lead, if you think about it), so this solution will require alternative equipment. Stay tuned, because I have a cool solution for that in the works! For now, I couldn't be happier with my TENMA multimeter's ability to log data to text files using [pyTENMA](https://github.com/swharden/pyTENMA) and the ease in which numpy/matplotlib can read and graph them. A data logging multimeter is a great tool to have in any engineer's toolbox, and I'm glad I now have one that plays nicely with Python.

## Resources

* pyTENMA on GitHub: [github.com/swharden/pyTENMA](https://github.com/swharden/pyTENMA)
August 20th, 2016

Breadboard Line Driver Module

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 Mouser.com (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.

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. 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!

Markdown source code last modified on January 18th, 2021
---
title: Breadboard Line Driver Module
date: 2016-08-20 19:16:27
tags: circuit, old
---

# Breadboard Line Driver Module

__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](https://en.wikibooks.org/wiki/Practical_Electronics/Amplifiers#Type_of_load), 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](https://en.wikipedia.org/wiki/Buffer_amplifier#Impedance_transformation_using_the_MOSFET_voltage_follower) or a [Darlington transistor](https://en.wikipedia.org/wiki/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 Mouser.com](http://www.mouser.com/Semiconductors/Integrated-Circuits-ICs/Logic-ICs/Buffers-Line-Drivers/_/N-6j78c?P=1z0z63x&Keyword=74hc240&FS=True) (perhaps cheaper on ebay) and [according to their datasheet](http://www.nxp.com/documents/data_sheet/74HC_HCT240.pdf) 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](https://www.google.com/search?q=74hc240+transmitter) thousands of web pages discussing this! This [Portuguese site](http://py2ohh.w2c.com.br/trx/digital/rfdigital.htm) 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](http://www.aoc.nrao.edu/~pharden/hobby/_ClassDEF1.pdf) (no relation). Also his [part 2](http://www.aoc.nrao.edu/~pharden/hobby/_ClassDEF2.pdf).

<div class="text-center img-medium">

[![](schematic_thumb.jpg)](schematic.jpg)

</div>

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.

<div class="text-center img-border img-small">

[![](IMG_7890_thumb.jpg)](IMG_7890.jpg)
[![](IMG_7894_thumb.jpg)](IMG_7894.jpg)
[![](IMG_7897_thumb.jpg)](IMG_7897.jpg)

</div>

__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.

<div class="text-center img-border img-small">

[![](IMG_7898_thumb.jpg)](IMG_7898.jpg)
[![](IMG_7900_thumb.jpg)](IMG_7900.jpg)
[![](IMG_7909_thumb.jpg)](IMG_7909.jpg)

</div>

__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](https://en.wikipedia.org/wiki/Ferrite_bead) and decoupling capacitor on the VCC pin) and it's good to go. With only 4 pins (GND, +5V, IN, and OUT) this amplifier is easy to drop in a breadboard:

<div class="text-center img-border">

[![](IMG_7904_thumb.jpg)](IMG_7904.jpg)

</div>

__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](http://electronics.stackexchange.com/questions/30750/why-do-gps-receivers-have-a-1-pps-output)] 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. 

<div class="text-center img-border">

[![](IMG_7912_thumb.jpg)](IMG_7912.jpg)

</div>

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!

<div class="text-center img-border img-small">

[![](IMG_7943_thumb.jpg)](IMG_7943.jpg)
[![](IMG_7948_thumb.jpg)](IMG_7948.jpg)

</div>
Pages