Back to the bench: 7 segment display

Three 4-digit displays: red, yellow, and green.
Three 4-digit displays: red, yellow, and green. Ew, shiny pads!

Since the SOTA genie escaped the bottle, the blog has leaned towards operation rather than bench work, but rest assured that projects have been percolating in the background. Here’s an update on a few of them: a custom LED display, a soft latch circuit, and a high-current converted ATX power supply. Let’s start with the LED Display.

For an upcoming project (actually, one that was moth-balled last June, stuck in a butter-cookie tin, and just recently again saw the light of day, followed by several days of pouring over notes and head scratching to remember where I had left off), I needed an LED display that would show voltage, amps, and power. Sure, you could figure the power out from the amps and volts, but I wanted it to change in real time to give me feedback while I make adjustments.

Now, the typical thing to do would have been to use a multiline LCD display, which could display all that and more, but I wanted bigger and brighter. Moving from typical to sane, the sane thing to do would have been to order three LED arrays, each with an I2C backpack. This is for a microprocessor-based project, so all I’d need to drive it would be two pins. Easy-peasy, right? Well. Too darn easy. I’m using an ATmega328 and have lots of pins. The I2C backpacks cost about six bucks each. That’s $18 bucks for the whole display (beyond the cost of the LEDs themselves). Nope, I decided to multiplex the displays.

Hey, it's a prototype. The header strip just happens to fit an old IDE drive cable.
Hey, it’s a prototype. The header strip just happens to fit an old IDE drive cable.

One way to do this would be to light up all the upper segments at once, then all the middle segments, etc., and then repeat the pattern. I’d like the display to be bright, so I’m powering them at 15mA each, so that would be 12 segments x 15 mA =180 mA, which is too much to draw from the chip. Instead, I decided to light up one number at a time, at most seven segments for the number plus one for the decimal point (so, 8 segments x 15mA = 120mA, which is doable). I then loop through the other eleven digit positions so fast that the entire display appears to be lit up at once. Does this work? Yes. I’ve done it.

The displays I bought are common cathode, so one pin on the microcontroller is dedicated to each segment position (upper, middle, decimal point, etc.). Which of the twelve digits is lit depends on which cathode is grounded. While the ATmega328 has a lot of pins, I don’t want to use all of them on the display, so I used two TPIC6B595 shift registers to handle the chore of selecting which digit to display. These shift registers are about $2 each, so I’m still ahead of the game.


The way shift registers typically work is that they are loaded up with a value. That value is cranked in to the register bit-by-bit. That entire register is then latched into an output register. Some shift registers are equipped with an output-enable signal that makes the output register opaque. For these, the output can be shut off during this process and then restored when ready to display.

That seemed like a lot of work and I was concerned that it could eat processor cycles that could better be used in other ways. In my particular application, I don’t need the full power of the shift register, all I need is to first select the  first digit position, then the second, etc., up to the twelfth, and then back to position one. Using only the wires necessary for this degenerate case, here’s what I came up with:

  1. The clear shift register (active low) – is tied high to prevent it from zeroing out the register, which would be mighty counterproductive.
  2. Serial in – when initialized the shift register is filled with zeros. After that, the microprocessor writes a “1” to light up the first digit. After that is displayed, the microprocessor writes a zero and the register is shifted one position. The “1” in the register now aligns with the second digit to be displayed. This keeps up until the “1” shifts off the end (well, surpasses position 12 in this case, but the same system could easily be extended to run one more 4-digit display without needing more hardware since we’re only taking advantage of half the capacity of the second shift register). Serial out from the first shift register feeds serial in of the second.
  3. Output enable – Depending on timing, writes are fast enough that output enable could be left on all the time: write the digit, wait a bit, write the next, wait a bit. However, if the “wait a bit” is short, the display can get muddy, as some segments are “on”, carried over from the previous digit, when a new one is selected. My solution to this was to light the segments in a specific order, with the upper right and upper left segment (“b” and “c”) going last. These two segments are special since one of the two of them is always lit if a number is displayed. So, I logical “OR” these two together and let them drive the gate of an N-channel mosfet to negate the logic. When they are on, display enable is pulled low and the display is activated. This only happens after all other segments have been written and seems to produce a clean display regardless of timing issues. This gives me maximum flexibility in case I need to muck with the timing, stick actual computations inside a timing loop, and makes the display resilient to unpredictable flurries of interrupts related to other parts of the project.

This configuration uses three CPU pins to control the pair of shift registers: one to provide data on serial in (SER), and one for each clock, the shift register clock (SRCK) and the latch clock (RCK). The only time the shift register is loaded in the traditional matter is at initialization when it is pumped full of zeroes. Otherwise, one bit rotates through the shift register, selecting the corresponding digit to display. That process requires pulsing the shift register clock and then the latch clock (versus fully loading the two registers for each digit to display, which would require writing each of 16 bits on the serial line and pulsing the shift register to load and crank each bit and then pulsing the latch to lock it in; this approach would also require more sophisticated blanking of the display since all of this would take time and probably be visible).


Using this method, the display is flicker-free. Brightness does depend somewhat on timing – if the display does not persist for a certain number of microseconds, it is dimmer. I am still working out the minimum.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.