Generating Analog Voltage with Raspberry Pi

I recently had the need to generate analog voltages from the Raspberry PI, which has rich GPIO digital outputs but no analog outputs. I looked into the RPi.GPIO project which can create PWM (which I wanted to smooth using a low pass filter to create the analog voltage), but its output on the oscilloscope looked terrible! It stuttered all over the place, likely because the duty is continuously under software control. I ended up solving my problem with a MCP4921 12-bit DAC chip (about $1.50 on eBay). It’s controlled via SPI, and although I could have written a python program to bit-bang its protocol with RPi.GPIO I realized I could write directly to the Raspberry Pi SPI device using the echo command. Dividing 3.3V into 12-bits (4096) means that I can control voltage in steps of less than 1mV each, right from the bash console!

img_8696

Video: The Problem (RPi PWM jitters)

Video: My Solution (SPI DAC)

Hardware Connection

There’s very little magic in how the microchip is connected to the Pi. It’s a straight shot to its SPI bus! Here’s a quick drawing showing which pins to connect. Check your device against the Raspberry Pi GPIO pinout diagram for different devices.

img_8701-1

Controlling the DAC with a Bus Pirate

Before I used a Raspberry Pi to control the DAC chip, I tested it out with a Bus Pirate. I don’t have a lot of pictures of the project, but I have a screenshot of a serial console used to send commands to the chip. One advantage of the Bus Pirate is that I can type bytes in binary, which helps to see the individual bits. I don’t have this ability when I’m working in the bash console.

serial

I’m less familiar with the Bus Pirate, but this was a good opportunity to get to know it a little better. It look me a long time (requiring I pull out the logic analyzer) to realize that I had to manually enable/disable the chip-select line, using the “[” and “]” commands. When I set up the SPI mode (command m5) I told it to use active low, but I wasn’t sure how to reverse the active level of the chip-select commands, so I just did ]this[ instead of [this] and it worked great.

frompi

This is the signal probed when it was controlled by the Raspberry Pi, but it looked essentially identical when values were sent via the Bus Pirate. The only difference is there was an appreciable delay between the “]” commands and each of the bytes. It worked fine though.

Controlling the DAC with Console Commands

Once the hardware was configured, the software was trivial. I could control analog voltages by sending two properly-formatted bytes to the SPI hardware device. Importantly, you must use raspi-config to enable SPI.

# set analog voltage to minimum value (about 0V)
echo -ne "\x30\x00" > /dev/spidev0.0 # minimum

# set analog voltage to something a little higher
echo -ne "\x30\xAB" > /dev/spidev0.0 

# set analog voltage to maximum value (about 3.3V)
echo -ne "\x3F\xFF" > /dev/spidev0.0

Helpful Links:

 


     

Hacking a Cheap Ammeter / Voltmeter to Provide a Bluetooth PC Interface

I love analyzing data, so any time I see a cool device to measure something I usually want to save its output. I’ve lately come to enjoy the cheap panel-mount volt meters and current meters on eBay, and figured it would be cool to hack one to provide PC logging capability. After getting a few of these devices for ~$8 each on eBay and probing around, I realized they didn’t output measurement data on any of the pins (not that I really expected they would), so I coded a microcontroller to watch the lines of the multiplexed 7-segment display and figure out what the screen is displaying (an odd technique I’ve done once or twice before), then send its value to a computer using the microcontroller’s UART capabilities. Rather than interfacing a traditional serial port (using a MAX232 level converter, or even a TTL-level USB serial adapter) I decided to go full-scale-cool and make it wireless! I succeeded using a HC-06 Bluetooth serial adapter which you can find on eBay for ~$3. Although I have previously used custom software to hack the output of a TENMA multimeter to let me log voltage or current displayed on the multimeter, now I can measure current and voltage at the same time (wirelessly no less) and this is a far less expensive option than dedicating a multimeter to the task! The result is pretty cool, so I took pictures and am sharing the build log with the world.

The video summarizes the project, and the rest of this page details the build log. All of the code used to program the microcontroller (AVR-GCC), interface the device with the Bluetooth serial adapter, and plot the data (Python) is available as part of a GitHub project.

img_8436

This is what one of these modules looks like, and how it is intended to be used. One of the connectors has 3 wires (black = ground, red = power to run the display (anything up to 30V), and yellow = voltage sense wire). The other connector is thicker and is the current sense circuit. The black wire is essentially short-circuited to ground, so unfortunately this can only be used for low-side current sensing.

img_8134

The side of the display indicates which model it is. Note that if you wish to buy your own panel mount meters, look carefully at their current measuring range. Most of them measure dozens of amps with 0.1 A resolution. There are a few which only measure <1 A, but down to 0.1 mA resolution. This is what I prefer, since I rarely build equipment which draws more than 1 A.

img_8138

On the back you can see all of the important components. There’s a large current shunt resistor on the right, solder globs where the through-hole 4 character 7-segment displays fits in, and the microcontroller embedded in this device is a STM8S003 8-Bit MCU. This chip has UART, SPI, and I2C built-in, so it may be technically possible to have the chip output voltage and current digitally without the need for a man-in-the-middle chip like I’m building for this project. However, I don’t feel like reverse-engineering the hardware and software which takes measurements of voltage and current (which is an art in itself) and also figure out how to drive the display, so I’m happy continuing on developing my device as planned! I did probe all the pins just to be sure, and nothing looked like it was outputting data I could intercept. That would have been too easy!

img_8142

I snapped the device out of its plastic frame to be able to access the pins more easily.

img_8154

I then soldered-on headers to help with reverse-engineering the signals. Note that this was part of my investigation phase, and that these header pins were not needed for the end product. I have multiple panel mount ammeter / voltmeter modules on hand, so I left this one permanently “pinned” like this so I could access the pins if I needed to. A quick check with the continuity tester confirmed that every segment of every character (of both displays) is continuous (wired together).

img_8443

These headers made it easy to attach my 16-channel logic analyzer. I’m using an off-brand Saleae compatible logic analyzer. Their software is open source and very simple and easy to use. Saleae sells their official logic analyzers (which are well made and company supported) on their website, but they are expensive (although probably worth it). I purchased an eBay knock-off logic analyzer ($40) which “looks” like a Saleae device to the computer and works with the same open source software. If I were really serious about building professional products, I would certainly invest in an official Saleae product. For now, this is a good option for me and my hobby-level needs. An 8-channel version if as low as $10 on eBay, and $149 from Saleae.

img_8447

Connections are straightforward. I began probing only a single display. This is a good time to mention that an understanding of display multiplexing is critical to understanding how I’m reading this display! If you don’t know what a multiplexed display is, read up on the subject then come back here. It’s an important concept. While you’re at it, do you know what charlieplexing is?

img_8460

After gazing at the screen of squiggly lines, I was able to piece together which signals represented characters (due to their regularity) and which represented segments (which changed faster, and were more sporadic).

img_8463

I’ll be honest and say that I cheated a bit, using a very high value current limiting resistor and applying current (backwards) into the pins when the device was unplugged. I manged to illuminate individual segments of specific characters in the LCD. This supported what I recorded from the logic analyzer, and in reality could have been used to entirely determine which pins went to which characters/segments.

img_8594-1

Here’s what I came up with! It’s not that complicated: 16 pins control all the signals. The microcontroller raises all lines “high” to only one character at a time, then selectively grounds the segments (A-H) to pass current through only the LEDs intended to be illuminated. Characters are numbers and segments are letters. Note that “A” of the top display (voltage) is connected to the “A” of the second display (current), so both rows of 4 characters make 8 characters as far as the logic is concerned. The transistor isn’t really a discrete transistor, it’s probably the microcontroller sinking current. I used this diagram to conceptualize the directionality of the signals. The sample site of letters is high when a letter is illuminated, and the sample site of a segment is low when that segment is illuminated (the sample site of the segment is the base of the imaginary transistor).

logic

Knowing this, I can intentionally probe a few segments of a single character. Here is the logic analyzer output probing the second character (top), and two representative segments of that character (bottom). You can see the segments go nuts (flipping up and down) as other segments are illuminated (not shown). If you look closely at the blue annotations, you can see that each character is illuminated for about 1 ms and repeats every 13 ms.

img_8471

Now it was time to make my device! I started with a new panel meter and an empty project box. By this point I had reverse-engineered the device and concluded it would take 16 inputs of a microcontroller to read. I chose an ATMega328 which was perfect for the job (plenty of IO) although I could have used a much less powerful microcontroller if I wanted to interface an IO expander. The MCP23017 16-bit IO expander may have been perfect for the job! Anyway, I drilled a few circular holes in the back with a step-bit and cut-away a large square hole in the front with a nibbler so everything would snap-in nicely.

img_8482

I soldered wires to intercept the signal as it left the device’s microcontroller and went into the LED display.

img_8517

I then soldered the wires directly to my microcontroller. I also have an extra header available for programming (seen at the bottom) which I was able to remove once the software was complete. The red clip is clamping the serial Tx pin of the microcontroller and capturing the output into a USB serial adapter. Initially I debugged this circuit using the microcontroller’s on-board RC oscillator (1MHz) transmitting at 600 baud. I later realized that the serial bluetooth module requires 9600 baud. Although I could hack this with the internal RC clock, it was very unstable and garbage characters kept coming through. Luckily I designed around the potential of using an external crystal (pins 9 and 10 were unused) so it was an easy fix to later drop in a 11.0592 MHz crystal to allow stable transmission at 9600 baud.

img_8548

Now you can see the power regulation (LM7805) providing power to the MCU and wireless bluetooth module. Here’s the HC-06 datasheet (which is similar to HC-05) and another web page demonstrating how to use the breakout board. Also, I added a switch on the back which switches the voltage sense wire between the power supply and a sense connector which is on the back of the project box (red plastic banana jack).

img_8554

The bluetooth adapter expects 3.3V signals, so I added a quick and easy zener diode shunt regulator. I could have accomplished this by running my MCU on 3.3V (I didn’t have 3.3V regulators on hand though, and even so the module wants >3.6V to power the wireless transmitter) or perhaps a voltage divider on the output. On second thought, why did I use a zener ($!) over a resistor? Maybe my brain is stuck thinking about USB protocol standards.

img_8557

Since the chip was unstable transmitting 9600 baud, I tightened it up using a 11.0592 MHz crystal. The advantage of making your entire circuit look sketchy is that bodge jobs like this blend in perfectly and are unrecognizable!

img_8563

A quick reprogram to set the AVR fuses to switch from internal clock to external full-swing crystal was easy thanks to the female header I was able to pop out. I only recently started soldering-on headers like this with ribbon cable, but it’s my new favorite thing! It makes programming so easy.

img_8559

I packed it all in then added hot glue around the primary components (not shown). Again, if this were a production product I would have designed the hardware very differently. Since it’s a one-off job, I’m happy with it exactly like it is! It works, and it withstands bumps and shakes, so it’s good enough for me.

img_8581

I tested on a big piece of electrical equipent I’m building on the other side of the room. This device has its own 13.8V regulated power supply (and its own shelf!), so the wireless capability is fantastic to have. I just dropped this device between the power supply and the device under test. Rather than record the power supply voltage (which would always be a boring 13.8V) I decided to record a voltage test point of interest: the point just downstream of an LM7809 voltage regulator. I expected this voltage to swing wildly as current draw was high, and was very interested to know the voltage of this test point with respect to current draw. Although I have previously used custom software to hack the output of a TENMA multimeter to let me log voltage or current of this exact circuit, now I can measure both at the same time! Additionally, this is a far less expensive option than dedicating a multimeter to the task.

img_8584

I’m using RealTerm to access the serial port and log its output to a text file.

img_8590

A quick python script lets me graph the voltage/current relationship with respect to time. The (short) code to do this is on the GitHub page, and is demonstrated in the YouTube video.

demo

Here’s some data which shows the relationship between voltage (red trace) probed just downstream of an LM7809 voltage regulator and the total current draw of the system (blue trace). This data was recorded in real time, wirelessly, from across the room! This is exactly the type of interesting reading I was hoping to see.

img_8599

Now that it’s all together, I’m very happy with the result! This little device is happy serving as a simple voltage/current display (which is convenient in itself), but has the added benefit of continuously being available as a Bluetooth device. If I ever want to run an experiment to log/graph data, I just wirelessly connect to it and start recording the data. This build was a one-off device and is quite a hack (coding and construction wise). If I were interested in making a product out of this design, construction would greatly benefit from surface mount components and a PCB, and perhaps not necessitate super glue. For what it is, I’m happy how it came out, pleased to see it as a Bluetooth device I can connect to whenever I want, and I won’t tell anyone there’s super glue inside if you don’t.

Code used for this project is available at GitHub


     

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.

circuit

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.

testrig-1

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.

scope

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.

miniterm

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

data_touch

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.

data_ac

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


     

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

 

pc frequency counter schem

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

neo-60 gps 1pps

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

IMG_8207

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.

ss

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.

IMG_8277

IMG_8282

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

IMG_8330

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

IMG_8286

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.

IMG_8297

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!

IMG_8316

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.

IMG_8318

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…

IMG_8335

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.

IMG_8340

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.

IMG_8344

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

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



Afterthought: Using without GPS

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

Update: Integrating Counter Serial Output with GPS Serial Output

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

img_8401

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.

img_8402

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.

img_8403

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.

fullsizerender-2

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.

img_8404

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.

img_8405

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!

serial-combine

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.

combined-python

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.


     

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.

datasheet

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.

IMG_8104

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!

IMG_8111

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…

IMG_8113

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

IMG_8121

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

ics501-demo

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.

IMG_8179

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

IMG_8175

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…

IMG_8162

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

IMG_8161

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

SDS00018

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

SDS00005

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.

IMG_8166

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!


     

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.

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

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

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

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

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

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


     

Opto-Isolated Laser Controller Build

I just finished building a device to interface a modern fiber-coupled DPSS laser used for optogenetic experiments with 15 year old scientific hardware. I finished this project in one afternoon, and I’m very happy with how it came out! This project has a blend of analog and digital circuitry, microcontrollers, and lasers (all the fun stuff!) and turned out to be a pretty cool build, so I’m sharing the design and construction with the hope that it will be inspiring to someone else. I don’t intend anyone to replicate this project (it’s designed to fill a very small niche), but I’ve learned a lot over the years by reading other peoples’ project build web pages and I’m happy every time I get the opportunity to make one of my own. The hardware I needed to interface is made by Coulbourn Instruments and is essentially just a large multi-channel computer-controlled DAC/ADC and it does its job well (turning lights on and off, recording button presses, etc.), but this new task requires millisecond resolution and modulation patterns which [most likely] lie outside the specs of this system and software. My goal was to utilize a free hardware output line to signal to a device that I build to modulate the laser in a special way. This way there would be no modification to any existing equipment, and no software to install. Further, since this hardware isn’t mine, I don’t like the idea of permanently modifying it (or even risking breaking it by designing something which could damage it by connecting to it). The specific goal is to allow the existing software to cause the laser to fire 20 ms pulses at 15 Hz for a few dozen cycles of 5s on, 5s off. It’s also important to have some flexibility to reprogram this firing protocol in the future if a change is desired. What’s more is that experiments are already underway and I needed this device to be complete within a couple of days! As much as I’d love to go to the internet and order the perfect, cheap components from China and have a beautiful build completed after the 6-8 weeks of shipping time, I had to build this only using parts I already had at my home.

After a little poking around, I found an auxiliary output which could be controlled by software. This AUX port has a frustratingly rare connector 1mm dual keyhole touchproof connector which I couldn’t buy in bulk on eBay or amazon, and couldn’t figure out the part numbers of on Mouser or Digikey. Luckily the laboratory had an old (broken) device with that connector on it they said I could cannibalize. (The manual even says “you may find it convenient to fit them with CI-type connectors” which makes me wonder why it wasn’t designed this way in the first place) After plugging in the connector, I used a volt meter to measure the output. To my surprise, it wasn’t a TTL signal! I expected to see my volt meter read 5V, but it read 28V! After consulting the manual I found mention of this: “Graphic State Notation software is designed for use with our Habitest animal-behavior-analysis environments or any other animal-behavior-testing apparatus that operates on the industry-standard 28-Volt control voltage.” I was surprised that 28V signals is a standard for any industry. But wait, there’s more! Elsewhere in the manual I found the phrase “The power base is capable of delivering 8 Amps of -28 VDC” which made me question the voltage reading I took earlier. The voltmeter showed 28V, but that’s the difference between one keyhole connector output and the other. I became apparent that it really may be 0V and -28mV (an even more curious “industry standard”). I wondered if connecting the negative terminal to ground would destroy the unit (think about how easy this would be to do! If it were a TTL signal, the first thing you would do is connect the negative terminal to ground and start sampling the positive terminal). There was even talk of me interfacing with a different output port (which I hadn’t probed, so I didn’t know the voltage). Moving forward, I realized I had to tread very carefully. Doing something like connecting two grounds together could permanently damage this system! Not really knowing if I should design to expect a TTL signal, a +28V signal, or a -28V signal, I decided to design a circuit to accomodate all of the above, all the while respecting total electrical discontinuity from the circuit that I develop. I’m going to accomplish this using an opto-isolator on the input. I sketched the schematic on paper while I built the device, and only later came back and formally made it in KiCad. I considered laying out a PCB (I have most of these components in SMT form factors too) but I knew I wouldn’t manage a one day turnaround if I went that far so I let that idea go.

A major points about this circuit design: 

  • The input should be able to accomodate any signal (TTL, CMOS, 28V, etc)
  • The input is totally isolated electrically, so this should be very safe on the hardware
  • The microcontroller is a socketed ATTiny85 which I programmed with a Bus Pirate.
  • I decided to rely on a crystal rather than the internal RC clock to improve temporal precision of the output signal. A 11.0592 MHz crystal was chosen because I have a bucket of them (they’re perfect for serial communication at all common baud rates). Any crystal could be used, as long as it’s frequency is defined in software.
  • Capacitors were added more to ensure oscillation initiates than to bring down the oscillation frequency. (I’m told that omitting them may cause a case where the crystal doesn’t resonate as well, but I’ve never found this in my personal experience.) A good note on microcontroller clocks is in a Microchip PIC application note.
  • I included a “test” button (momentary switch) to simulate having an input signal.
  • Note that R1 must be able to handle the current applied to it. It was mistakenly designed as 1k, and later replaced with 10k. See the bodge note at the bottom of this post for details.

This design could still benefit from:

  • Forward protection diodes on the input could protect accidental reverse polarity
  • Adding an ICSP header would prevent de-socketing of the MCU if reprogramming is desired
  • The BNC output is directly from a MCU pin. It should be at least transistor-buffered to deliver higher current.

Because there is a possibility that a different output (laser control) pattern may be desired in the future, I considered whether or not I should make the output pattern user-configurable. Adding buttons, a display, and designing a menu system in software would be a lot of work and no one’s really strongly asking for it, so I concluded that I’m going to build this device to the specific task at hand. If the end user eventually wants the ability to modulate the pattern on their own, the device they ask for would be a very different one than the one I was tasked to create. Since the current pattern is burned into a microchip, a compromise is that I could have new patterns burned into new microchips, and the end-user could change the chip (as long as it’s an infrequent occurrence).

Wait a minute, turning 20 ms pulses at 15 Hz sounds like an easy task for a 555 timer without the need for digital circuitry. Also, it would be easy for the end user to adjust both of these features by turning a knob! Is a microcontroller overkill? I struggled with this question for a while, but concluded that the advantage of the MCU (crystal-disciplined time precision of the output pulses) outweighed the convenience of  a purely analog circuit. A 555 timer in astable / multi-vibrator configuration would mostly get the job done, but you would either (1) only allow one output pattern and rely on precision passive components (which I don’t have on hand), or (2) allow the end-user to adjust duty/frequency with potentiometers (which would require the output to be quantitatively monitored on an oscilloscope). I considered a blend of analog and digital circuitry by using analog components (with knobs) to adjust the duty/frequency, and microcontroller to measure the pulse width and period and display this on a screen (essentially building the oscilloscope into the device). Again, this is more work, and without being asked by the end-user to have an adjustable product (they just indicated interest when I proposed it), I decided I’d continue with the simplest-case, high-resolution design. Also I’ll note that I’m relying on an external crystal (rather than the internal RC clock) to maximize precision from day to day use. Since this device will be used for scientific experimentation, I want to minimize the influence of temperature on the temporal precision of the output signal.

 

Luckily I had an enclosure ready to go. I always buy enclosures in bulk, and even though nice ones tend to be expensive, having them on hand encourages me to build devices as I think of them, rather than making flaky hardware which I have a history of doing which sometimes borders on ridiculousness. I usually stock unfinished Hammond diecast aluminum enclosures (which I write on with sharpie) for making quick RF projects, and generic fancier boxes with feet and side vents, but for this task I decided to (mostly) seal everything inside a typical (but a little more costly) aluminum enclosure (most likely an eBay special from China, but I can’t remember where I got it). I love using low current LEDs, and I started going with frosted instead of clear LEDs because they’re easier on the eyes. Also, I switched to mostly 3mm LEDs instead of 5MM because I think they look cooler. I have black bezels but they don’t snap in as well as I’d hope, so I find myself having to add a dot of super glue to retain the LED and the bezel in position.

I used nicer perfboard with platted-through holes to build this circuit. Normally I use cheap ubiquitous perfboard with little copper rings glued to one side.  It’s easy to solder to because the copper is so thin it heats quickly, but it’s not always a good long-term solution because the copper pads have a tendency to un-stick. I rarely use this nicer perfboard (it is more expensive, I order from China on ebay), but again I value having things like this stocked at my home ready to go at a moment’s notice!

I marked areas of optical isolation with a black marker. This makes it obvious where the potentially dangerous, potentially high-voltage (well, higher than TTL) input comes in. No wires or connections should invade this space on the board. The special connector which will connect this device to the scientific hardware is at the laboratory, and I’ll have to solder it at the time of delivery/installation. I left an extra hole in the back which I guesstimated would fit the wire. I didn’t have any rubber grommets stocked at my home… I need to get some!

Strong copper wires hold the front panel onto the circuit, but this wasn’t actually intentional. I first screwed down the circuit board, soldered everything together, and after I realized a change was needed on the underside of the board an unscrew was required. That’s when I realized that I could unscrew the front panel rather than desolder it, and it held its shape great! At first glance this doesn’t look like a robust construction technique, but is it really any different than soldering stiff coated wires?

IMG_7232

Once it was all together, the device seemed to perform well. The test button on the back made it easy to inspect the output. My RF background made me instinctively terminate the output into a 50 ohm resistor for the measurements, but the square waves looked like super wonky RC curves and I realized 50 ohms is far too low impedance. If it’s a TTL signal, let’s assume it’s virtually infinite impedance, and not worry about it. Note that this is a testament to the relatively low maximum output current of the microcontroller pin, and the potential need for a buffered output if anything more than high impedance TTL is to be driven. I think the datasheets suggests limiting its current to 20 mA per pin (requiring termination of no less than 250 Ohms) A 50 Ohm resistor pulled it out of spec. Oh well, I removed it and it survived fine, so let’s make some measurements

An important thing to note is that absolute time precision is preferred over accuracy. Specifically, I want this device to perform identically for years, and highly favor precision over accuracy. With that said, I trust the pulses to be 20ms wide, but not exactly 15 Hz. To do 15 Hz, I’d need 20ms on and 46.666667 ms off. I could probably get pretty close if I wanted to, but I rounded it to 20 ms on and 46 ms off. This gives time for the instruction cycles toggling the output pins to occur (although it’s on an order of magnitude faster time scale), which slightly biases the time in the right direction. I considered adding a _delay_us(666) after the _delay_ms(46) but I’m satisfied with it this knowing it’s within 1% accuracy of 15 Hz and that precision is locked to that of the crystal (around 10 ppm, or 0.001%).

Admittedly the _delay_ms() method of timekeeping is a little clumsy. I considered a few other methods of time keeping, but decided not to implement them (yet?). The schools of thought were largely on three categories, but all relied on the AVR timers. Here’s an awesome guide on the topic, and here’s another. Timers would be preferred if I wanted the program code of the microcontroller to be free to do other things like drive menus or multiplex a display. Think of hardware timers on a MCU like multi-threading on a computer – it helps you out by running in the background.

  • Thought 1: timers: Set the timer to overflow every 1 ms. On overflow, a counting variable would be incremented and a function would be called to determine what to do. At pre-programmed time points (with respect to the counting variable), the output pin would be toggled, or the counting variable would be reset.
  • Thought 2: output compare registers: Utilize the built-in OCR (output compare register) to turn the output signal on and off. Set the timer to overflow at 15 Hz, turning the output on. Set the OCR (to the fractional point between 0 and the maximum timer value) such that when it is passed, the output is turned off. This way 15 Hz, 20 ms pulses would be continuously running without any code being executed. Input sensing could simply enable and disable the timer.
  • Thought 3: input interrupts: Why stop at timers? Polling the input pin for a TTL signal puts the chip in an infinite loop. Relying on the AVR’s external (pin change) hardware interrupts could eliminate this as well. I always rely heavily on the datasheet when setting these interrupts.

Altogether these improvements could come in handy if a more accurate time source is desired, an advanced display is added, or menus are implemented which would benefit from letting the pulsing output operate in the background. For now, I’m happy with my dirt-simple code, and I’m still far within my one afternoon construction timeline goal!

After I was satisfied with construction, I started labeling the enclosure. I want to tip my hat to Onno Hoekstra on this one, as his webpage demonstrating how good clear labels make custom ham radio equipment look (and a personal email he sent me recently) made me start making clear labels for all of my custom equipment. FYI I’m using a DYMO LetraTag LT-100T Plus label maker and clear tape. It’s important to enable the black outline around the text, then cut carefully slightly outside the outline with regular scissors. The results look fantastic!

The morning I delivered my product, I added the final connector which I didn’t have at home. It’s an inelegant knot-retained configuration, but I think it’ll get the job done! Again this is a surprisingly rare fully shielded touchproof connector apparently used only in medical applications. At this point, I’m thinking this figure was chosen to (A) protect the user from accidentally shorting a 28V 8A power source (that’s over 200 watts!), (B) to prevent you from damaging the equipment by plugging in something that doesn’t belong (could you imagine what would happen if this -28V high current source had a BNC connector and you plugged this into something expecting a 5V TTL input?), and (C) prevent you from plugging in anything that wasn’t made by this company. The last option is more likely consumer protection rather than the company trying to maintain a status of sole distributor of accessories, but it does make you wonder. I would have preferred power pole sockets (that’s the ham in me), molded connectors like those on motherboards, or even barrel connectors! Surely there’s a more standard touchproof connector for moderate voltage/currents (although, to be honest, I’m struggling to think of one at the moment). CL-type connectors seem expensive and bulky.

I plugged the device in to the computer, attached the laser, and it worked immediately! I couldn’t say I was surprised that it worked, but it still felt good to watch the blue laser beam trigger like it was supposed to. Another cool one-off project is in the bag, and I got some great pictures for the website. I hope this little box lives many happy years in its laboratory home.

IMG_7316

The current software is so simple, it’s not worth discussing! This is the code I loaded onto the microcontroller.

#define	F_CPU (11059200UL)
#include <avr/io.h>
#include <util/delay.h>

int main (void){	
    DDRB=(1<<PB0); // TTL output
	PORTB=0; // internal pull-down
	while(1){
		while((PINB&(1<<PB2))==0){} // hang while LOW
		PORTB=(1<<PB0); // TTL ON
		_delay_ms(20);
		PORTB&=~(1<<PB0); // TTL OFF
		_delay_ms(46);
	}
}

Here’s the batch script I used to compile and load the code onto the microcontroller. I compiled the code with AVR-GCC and copied it onto the microcontroller with a Bus Pirate. Note also that I’m setting the fuses to respect an external oscillator.

@echo off
del *.elf
del *.hex
avr-gcc -mmcu=attiny85 -Wall -Os -o main.elf main.c
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
avrdude -c buspirate -p attiny85 -P com3 -e -U flash:w:main.hex
avrdude -c buspirate -p attiny85 -P com3 -U lfuse:w:0xff:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m
pause

If you have any ideas for how this could device could have been better designed or constructed, let me know!

IMG_7304

Bodge note: After a few days I got an email from someone concerned about the current handling capability of the front-end of the circuit. It was noted that a standard 1/4 watt resistor may not be suitable for R1, as a 28V potential would stress it beyond its specs. With 28V applied, R1 (a quarter-watt resistor) would experience P=IE=28mA*28V=784mW of current! It might last (especially if pulsed), but it also might fail with time. The advantage of the R1/D1/R2 system is that the output current will be identical across a wide range of input voltages. The disadvantage is that it’s hard to predict how beefy R1 needs to be. I could have placed five 4.7k resistors in parallel to replace R1 (this would let me handle over 1 watt of power), but I instead simply upped it from 1kOhm to 10kOhm. This further reduced the current that the opto-isolator sees (now only about 0.2 mA) but it seems to work still! So I’m satisfied with this bodge, but a little disappointed I didn’t catch it sooner. Note that the new input resistor (a 10k R1) should only have to dissipate about 80mW, well within its specs.

the bodge is the 10k resistor on the lower right
the bodge is the 10k resistor at the very bottom

Note regarding H11B1 minimum current and AC noise: After pondering it for a while, I considered that a 10K input resistor on 28V would only allow 2.8 mA to pass through. Considering only 3.3V will persist after the zener (a 11.7% current retaining ratio, if that’s valid math), I figured that a best 330uA were passing through the opto-isolator. That seems outside of the specs of the device, because their datasheet graphs always start at 1mA. I decided to run some tests at my home for kicks. I determined that a 10k resistor still works with 5V (500 uA into the device), but checking the output on the oscilloscope I realized that the device operates only partially, and slowly at that low voltage/current. The darlington transistor configuration is very high gain, which is the only reason this works at all, but such low currents are sensitive to parasitic capacitance and infiltrating RF currents. As such, I noticed the chip took a few ms to activate and deactivate. Since this application only uses 5s on and 5s off inputs, it’s fine… but I wouldn’t expect highspeed pulsing of the input to work well. Furthermore, in my breadboard I realized I was getting funny output currents. They were oscillating around 60Hz, which made me suspicious that the device was picking up AC somehow. I realized it was from pin 6 (the exposed darlington base). Normally the LED is so strong is blasts the device fully on or off, but hovering on the edge like this, that pin is picking up signals. Since it’s not connected to anything anyway, I cut the pin off as close to the microchip as I could, and noticed an instant improvement in 60Hz rejection. In conclusion, I wouldn’t try to reliably run an optoisolator on less than 1 mW, but it seems to work!


     

Controlling Bus Pirate with Python

After using the AVR-ISP mkII for years (actually the cheap eBay knock-offs) to program ATMEL AVR microcontrollers, today I gave the Bus Pirate a shot. Far more than just a microcontroller programmer, this little board is basically a serial interface to basic microcontroller peripherals. In a nutshell, you plug it in via USB and it looks like a serial port which has a command-line interface that lets you do things like turn pins on and off, perform voltage measurements, and it naively supports bidirectional use of common protocols like I2C, SPI, UART, and even HD44780 series LCDs. Note that although you could directly interface with the Bus Pirate using HyperTerminal, I recommend using TeraTerm. It can supply voltages (3.3V and 5V) to power small circuits, and if current draw is too high (indicating something is hooked-up wrong) it automatically turns the supply off. So clever! At <$30, it’s a cool tool to have around. In addition, it’s naively supported as an AVR programmer by AVRDUDE. Although I could write assembly to perform tasks, I almost always write in C for the convenience. For my reference (and that of anyone who may want to do something similar), I’m posting the simplest-case method I use to program AVR microcontrollers with the Bus Pirate on Windows (noting that Linux would be nearly identical). I also wrote a Python script to connect with the Bus Pirate and run simple commands (which turns the power supply on and report the voltage of the VCC line immediately after programming completes).  Yes, there are fancy packages that allow you to interact with Bus Pirate from Python, but the advantage of my method is that it runs from native Python libraries! To get this all up and running for yourself, just install WinAVR (which supplies AVRDUDE and AVR-GCC) and Python 3. I assume this code will work just as well on Python 2, but haven’t tried.

IMG_7092 (1)
the Bus Pirate programming an ATTiny85 microcontroller

 

To ensure my Bus Pirate is working properly, I start off by running the Bus Pirate’s built-in test routine. For full details read the guide. It just involves connecting two pairs of pins together as shown in the picture here, connecting to the Bus Pirate with the serial terminal, and running the command “~”. It will output all sorts of useful information. Once I know my hardware is up and running, I’m good to continue.

Bpv3v2go-pinout

Here’s the code which runs on the microcontroller to twiddle all the pins (saved as main.c). Note that my MCU is an ATTiny85. I’m using standard clock settings (internal RC clock, 8MHz), but if I wanted to modify fuses to do things like use an external clock source or crystal, I’d calculate them with engbedded’s handy dandy fuse calculator (which also shows AVRdude arguments needed to make the change!).

#define	F_CPU (8000000UL)
#include <avr/io.h>
#include <util/delay.h>

int main (void)
{
    DDRB = 255; 
    while(1) 
    {
        PORTB ^= 255;
        _delay_ms(500);
    }
}

To compile the code and program the MCU with it, I always have a bash script in the same folder that I can double-click on to delete old compiled files (so we don’t accidentally re-program our MCU with old code), compile main.c, and load it onto the MCU using the Bus Pirate. You may have to change COM3 to reflect the com port of your Bus Pirate. Note that it is required that you disconnect other terminals from the Bus Pirate before doing this, otherwise you’ll get an “access denied” error.

@echo off
del *.elf
del *.hex
avr-gcc -mmcu=attiny85 -Wall -Os -o main.elf main.c
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
avrdude -c buspirate -p attiny85 -P com3 -e -U flash:w:main.hex
python up.py

Although the programmer briefly supplies my MCU with power from the +5V pin, it’s cut after programming completes. Rather than manually re-opening my terminal program, re-connecting with the bus pirate, re-setting the mode (command “m”) to something random (DIO, command “9”), and re-enableing voltage output (command “W”) just to see my LED blink, I want all that to be automated. Thanks python for making this easy. The last line calls “up.py”. This fancy script even outputs the voltage of the VCC line after it’s turned on!

"""python3 control of buspirate (SWHarden.com)"""

import serial

BUSPIRATE_PORT = 'com3' #customize this! Find it in device manager.

def send(ser,cmd):
    """send the command and listen to the response."""
    ser.write(str(cmd+'\n').encode('ascii')) # send our command
    for line in ser.readlines(): # while there's a response
        print(line.decode('utf-8').strip()) # show it

ser=serial.Serial(BUSPIRATE_PORT, 115200, timeout=1) # is com free?
assert ser.isOpen() #throw an exception if we aren't connected
send(ser,'#') # reset bus pirate (slow, maybe not needed)
send(ser,'m') # change mode (goal is to get away from HiZ)
send(ser,'9') # mode 9 is DIO
send(ser,'W') # turn power supply to ON. Lowercase w for OFF.
send(ser,'v') # show current voltages
ser.close() # disconnect so we can access it from another app
print("disconnected!") # let the user know we're done.

When “burn.cmd” is run, the code is compiled and loaded, the power supply is turned on (and killed if too much current is drawn!), and the voltage on VCC is reported. The output is:

C:\Users\scott\Documents\important\AVR\2016-07-13 ATTiny85 LEDblink>burn.cmd

Detecting BusPirate...
**
**  Bus Pirate v3a
**  Firmware v5.10 (r559)  Bootloader v4.4
**  DEVID:0x0447 REVID:0x3046 (24FJ64GA002 B8)
**  http://dangerousprototypes.com
**
BusPirate: using BINARY mode
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.12s

avrdude: Device signature = 0x1e930b
avrdude: erasing chip
avrdude: reading input file "main.hex"
avrdude: input file main.hex auto detected as Intel Hex
avrdude: writing flash (84 bytes):

Writing | ################################################## | 100% 3.12s

avrdude: 84 bytes of flash written
avrdude: verifying flash memory against main.hex:
avrdude: load data flash data from input file main.hex:
avrdude: input file main.hex auto detected as Intel Hex
avrdude: input file main.hex contains 84 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 2.72s

avrdude: verifying ...
avrdude: 84 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

#
RESET

Bus Pirate v3a
Firmware v5.10 (r559)  Bootloader v4.4
DEVID:0x0447 REVID:0x3046 (24FJ64GA002 B8)
http://dangerousprototypes.com
HiZ>
m
1. HiZ
2. 1-WIRE
3. UART
4. I2C
5. SPI
6. 2WIRE
7. 3WIRE
8. LCD
9. DIO
x. exit(without change)

(1)>
9
Ready
DIO>
W
Power supplies ON
DIO>
v
Pinstates:
1.(BR)  2.(RD)  3.(OR)  4.(YW)  5.(GN)  6.(BL)  7.(PU)  8.(GR)  9.(WT)  0.(Blk)
GND     3.3V    5.0V    ADC     VPU     AUX     CLK     MOSI    CS      MISO
P       P       P       I       I       I       I       I       I       I
GND     3.17V   5.00V   0.00V   0.00V   L       L       L       H       L
DIO>
disconnected!


This is a minimal-case scenario, but can be obviously expanded to perform some complicated tasks! For example, all commands could be run from a single python program. Considering the Bus Pirate’s ability to communicate with so many different protocols (I2C, 2-write, etc.), being able to naively control it from Python without having to install special additional libraries will certainly prove to be convenient.

PS: I noted there is a surprising delay when initializing programming the AVR with the bus pirate. The process hangs for about 10 seconds after the bus pirate introduces itself with the welcome message, then seems to resume at full speed writing to the flash of the microchip. After a bit of Googling, I believe the delay is due to the Bus Pirate slowly bit-banging SPI to initialize the programming sequence. The AVR has rich SPI functionality, some of which involves its own programming. Satisfied with this answer for now, I’m not going to try to speed it up. It’s a little annoying, but not too bad that I won’t use this to program my AVRs.


     

Directly Driving 7-Segment Display with AVR IO Pins

I came across the need for a quick and dirty display to show a 4 digit number from a microcontroller. The right way to do this would be to use a microcontroller in combination with a collection of transistors and current limiting resistors, or even a dedicated 7-segment LED driver IC. The wrong way to do this is to wire LEDs directly to microcontroller IO pins to source and sink current way out of spec of the microcontroller… and that’s exactly what I did! With no current limiting resistors, the AVR is sourcing and sinking current potentially far out of spec for the chip. But, heck, it works! With 2 components (just a microcontroller and a 4 digit, 7-segment LED display) and a piece of ribbon cable, I made something that used to be a nightmare to construct (check out this post from 3 years ago when I accomplished the same thing with a rats nest of wires – it was so much work that I never built one again!) The hacked-together method I show today might not be up to spec for medical grade equipment, but it sure works for my test rig application, and it’s easy and cheap to accomplish… as long as you don’t mind breaking some electrical engineering rules. Consider how important it is to know how to hack projects like this together: Although I needed this device, if it were any harder, more expensive, or less convenient to build, I simply wouldn’t have built it! Sometimes hacking equipment together the wrong way is worth it.

IMG_2316
Segments are both current sourced and sunk directly from AVR IO pins. Digits are multiplexed with 1ms illumination duration. I don’t really have a part number for the component because it was a China eBay special. The display was $6.50 for 4 (free shipping). That’s ~$1.65 each. The microcontroller is ~$1.

SCHEMATIC? If you want it, read this.common cathode 7 segment display lcd It’s so simple I don’t feel like making it. Refer to an ATMega48 pin diagram. The LCD is common anode (not common cathode), and here’s the schematic on the right. I got it from eBay (link) for <$2.  The connections are as follows:

  • Segments (-) A…H are directly wired to PD0…PD7
    – I call the decimal point (dp) segment “H”
    – I don’t use current limiting resistors. I’m not making a consumer product. It works fine, especially multiplexed. Yeah I could use transistors and CLRs to drive the segments to have them bright and within current specifications, but I’m not building an airplane or designing a pacemaker, I’m making a test device at minimum cost! Direct LED wiring to my microcontroller is fine for my purposes.
    – I am multiplexing the characters of my display. I could have used a driver IC to simplify my code and eliminate the current / wiring issues described above. A MAX7219 or MAX7221 would have been easy choices for this (note common anode vs. common cathode drivers / displays). It adds an extra $5 to my project cost though, so I didn’t go with a driver. I drove the segments right out of my IO pins.
  • Characters (+) 1…4 are PC0…PC3
  • Obviously I apply +5V and GND to the appropriate AVR pins

Here it all is together in my microcontroller programming set up. I’ll place this device in a little enclosure and an an appropriate BNC connector and either plan on giving it USB power or run it from 3xAA batteries. For now, it works pretty darn well on the breadboard.

Here is my entire programming setup. On the top left is my eBay special USB AVR programmer. On the right is a little adapter board I made to accomodate a 6 pin ISP cable and provide a small breadboard for adding programming jumpers into a bigger breadboard. The breadboard at the bottom houses the microcontroller and the display. No other components! Well, okay, a 0.1uF decoupling capacitor to provide mild debouncing for the TTL input.
Here is my entire programming setup. On the top left is my eBay special USB AVR programmer. On the right is a little adapter board I made to accomodate a 6 pin ISP cable and provide a small breadboard for adding programming jumpers into a bigger breadboard. The breadboard at the bottom houses the microcontroller and the display. No other components! Well, okay, a 0.1uF decoupling capacitor to provide mild debouncing for the TTL input.

Let’s talk about the code. Briefly, I use an infinite loop which continuously displays the value of the volatile long integer “numba”. In the display function, I set all of my segments to (+) then momentarily provide a current sink (-) on the appropriate digit anode for 1ms. I do this for each of the four characters, then repeat. How is the time (the value of “numba”) incremented? Using a hardware timer and its overflow interrupt! It’s all in the ATMega48 datasheet, but virtually every microcontroller has some type of timer you can use to an equivalent effect. See my earlier article “Using Timers and Counters to Clock Seconds” for details. I guess that’s pretty much it! I document my code well enough below that anyone should be able to figure it out. The microcontroller is an ATMega48 (clocked 8MHz with an internal RC clock, close enough for my purposes).

#define F_CPU 8000000UL // 8mhz
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

// for simplicity, define pins as segments
#define A (1<<PD0)
#define B (1<<PD1)
#define C (1<<PD2)
#define D (1<<PD3)
#define E (1<<PD4)
#define F (1<<PD5)
#define G (1<<PD6)
#define H (1<<PD7)

void setDigit(char dig){ // set the digit starting at 0
	PORTC=(1<<dig)|(1<<PC4); // always keep the PC4 pin high
}

void setChar(char c){
	// given a number, set the appropraite segments
	switch(c){
		case 0:	DDRD=A|B|C|D|E|F;	break;
		case 1:	DDRD=B|C;			break;
		case 2:	DDRD=A|B|G|E|D;		break;
		case 3: DDRD=A|B|G|C|D;		break;
		case 4: DDRD=F|G|B|C;		break;
		case 5: DDRD=A|F|G|C|D;		break;
		case 6: DDRD=A|F|G|E|C|D;	break;
		case 7: DDRD=A|B|C;			break;
		case 8: DDRD=A|B|C|D|E|F|G;	break;
		case 9: DDRD=A|F|G|B|C;		break;
		case 31: DDRD=H;			break;
		default: DDRD=0; 			break;
	}
}

void flashNumber(long num){
	char i;

	for (i=0;i<4;i++){
		setChar(num%10);
		if (i==2){DDRD|=H;} // H is the decimal point
		setDigit(3-i);
		num=num/10;
		_delay_ms(1); // time to leave the letter illuminated
	}
}

volatile long numba = 0;
volatile long addBy = 1;

ISR(PCINT1_vect){ // state change on PC4
	if ((PINC&(1<<PC4))==0) {addBy=0;} // pause
	else {numba=0;addBy=1;} // reset to 0 and resume
}

ISR(TIMER1_OVF_vect){
	TCNT1=65536-1250; // the next overflow in 1/100th of a second
	numba+=addBy;	  // add 1 to the secound counter
}

int main(void)
{
	DDRC=(1<<PC0)|(1<<PC1)|(1<<PC2)|(1<<PC3); // set all characters as outputs
	DDRD=255;PORTD=0; 	// set all segments as outputs, but keep them low

	TCCR1B|=(1<<CS11)|(1<<CS10); // prescaler 64
	TIMSK1|=(1<<TOIE1); //Enable Overflow Interrupt Enable
	TCNT1=65536-1250;   // the next overflow in 1/100th of a second

	// note that PC4 (PCINT12) is an input, held high, and interrupts when grounded
	PCICR |= (1<<PCIE1); // enable interrupts on PCING13..8 -> PCI1 vector
	PCMSK1 |= (1<<PCINT12); // enable PCINT12 state change to be an interrupt
	sei(); // enable global interrupts

	for(;;){flashNumber(numba);} // just show the current number repeatedly forever
}

I edit my code in Notepad++ by the way. To program the chip, I use a bash script…

avr-gcc -mmcu=atmega48 -Wall -Os -o main.elf main.c -w
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
avrdude -c usbtiny -p m48 -F -U flash:w:"main.hex":a -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m

Nothing here is groundbreaking. It’s simple, and convenient as heck. Hopefully someone will be inspired enough by this write-up that, even if they don’t recreate this project, they’ll jump at the opportunity to make something quick and dirty in the future. It’s another example that goes to show that you don’t have to draw schematics, run simulations, do calculations and etch boards to make quick projects. Just hack it together and use it.

Update a two days later… I found a similarly quick and dirty way to package this project in an enclosure. I had on hand some 85x50x21mm project boxes (eBay, 10 for $14.85, free shipping, about $1.50 each) so I used a nibbler to hack out a square to accomodate the display. After a little super glue, ribbon cable, and solder, we’re good to go!

Related reading for the technically inclined:

 


     

Calculate QRSS Transmission Time with Python

How long does a particular bit of Morse code take to transmit at a certain speed? This is a simple question, but when sitting down trying to design schemes for 10-minute-window QRSS, it doesn’t always have a quick and simple answer. Yeah, you could sit down and draw the pattern on paper and add-up the dots and dashes, but why do on paper what you can do in code? The following speaks for itself. I made the top line say my call sign in Morse code (AJ4VD), and the program does the rest. I now see that it takes 570 seconds to transmit AJ4VD at QRSS 10 speed (ten second dots), giving me 30 seconds of free time to kill.

program output
Output of the following script, displaying info about “AJ4VD” (my call sign).

Here’s the Python code I whipped-up to generate the results:

xmit=" .- .--- ....- ...- -..  " #callsign
dot,dash,space,seq="_-","_---","_",""
for c in xmit:
    if c==" ": seq+=space
    elif c==".": seq+=dot
    elif c=="-": seq+=dash
print "QRSS sequence:n",seq,"n"
for sec in [1,3,5,10,20,30,60]:
    tot=len(seq)*sec
    print "QRSS %02d: %d sec (%.01f min)"%(sec,tot,tot/60.0)

How ready am I to implement this in the microchip? Pretty darn close. I’ve got a surprisingly stable software-based time keeping solution running continuously executing a “tick()” function thanks to hardware interrupts. It was made easy thanks to Frank Zhao’s AVR Timer Calculator. I could get it more exact by using a /1 prescaler instead of a /64, but this well within the range of acceptability so I’m calling it quits!

Output frequency is 1.0000210 Hz. That'll drift 2.59 sec/day. I'm cool with that.
Output frequency is 1.0000210 Hz. That’ll drift 2.59 sec/day. I’m cool with that.