I have been experimenting using the Arduino to drive a seven-segment display (SSD). When ganging several together to form a multi-digit display, a common design is to wire a matrix and use multiplexing to reduce the number of control pins. The typical formula to determine the required number of pins is one for each segment LED plus one for each SSD. Thus, a four-digit display would require twelve pins - eight segment select lines (including the decimal point LED) and four SSD select lines.
Recently, I learned of a multiplexing technique called charlieplexing. The term applies to managing a matrix of LEDs with fewer control pins than the obvious approach. Charlieplexing is most advantageous in situations where each anode and cathode can be separately connected into the matrix. Unfortunately, SSDs are manufactured with either all the segment anodes or cathodes in common. Even with this interconnect constraint, it's still possible to control SSDs with fewer than the obvious number of pins using an arrangement that timeshares the use of the segment and SSD selects. Thus, from one to eight SSDs can be controlled with only nine pins. Obviously, the more SSDs in the display, the greater the charlieplexing advantage. In this test case using four SSDs, the savings are only three pins - but that's enough for a demonstration.
I couldn't find an online example that used the inexpensive SSD available from Radio Shack and the programs accompanying the examples I did find were too large and slow for what was being accomplished. The entire Arduino was being monopolized just driving the display! Acceptable as a demo but unusable for any purpose more complicated than an expensive digital clock. I thought it should be possible to have the display as an adjunct to a sketch with a different primary purpose. I constructed this as a proof of concept and thought it might help someone else if I published it.
Charlieplexing is actually exceptionally easy to accomplish with the Arduino. This demo sketch is less than 2K and leaves plenty of processor time for my main project.
Step 1: Theory of Operation
I’ll not state here the basic information about SSDs, the segment-naming convention or the concept of ordinary SSD multiplexing and why it works; all of which can be easily found in existing resources.
Assuming an understanding of this background, here is the schematic using the pinout of the Radio Shack common cathode SSD part 276-0075. Carefully observe how the twelve SSD LED connections (eight anodes each and the four common cathodes) are connected to the nine select (Sel) lines. For example, note that the common cathode of SSD0 (the “ones” position of the four-digit display) and the anodes of segment “a” of the other three SSDs share select line Sel0.
What states do the Sel lines have to be in to cause the digit “1” to be displayed on just SSD0? Only segments “b” and “c” are to be illuminated, so Sel2 and Sel3 must be high (H) with Sel1, Sel4, Sel5, Sel6, Sel7 and Sel8 low (L). The common cathode of SSD0 is connected to Sel0, so Sel0 must also be L. Under these conditions, a "1" will indeed be displayed on SSD0.
Charlieplexing is not without complications. At this point, note that the cathodes of SSD2 and SSD3 are H because they are also connected to Sel2 and Sel3 respectively. The segment "a" LED's anodes are connected to Sel0 which is currently L. Thus, the segment "a" LEDs are reversed-biased. Although that condition does not cause them to illuminate, it's important to understand that the LEDs are subjected to (and must be rated for) the maximum possible reverse voltage. The Arduino H is +5V and that is also the maximum reverse voltage rating given for the 276-0075.
But a problem remains. Rather than being unlit, SSD1 will also display "1"! This is a conundrum. Sel1 must be L to keep segment “a” from being illuminated but, because Sel1 is also connected to the common cathode of SSD1, it must be H or both SSD0 and SSD1 will be active.
Clearly a select pin cannot be both L and H simultaneously. However, if we disconnect Sel1 we get the desired result. A disconnected line is neither H nor L – it’s in a third "open-circuit" state which causes all the attached LEDs to be off. A disconnected Sel1 supplies no current to the segment "a" anodes and also provides no return path to ground for the common cathode of SSD1. Great! So how do we disconnect pins selectively?
Here’s where the Arduino makes this easy. Each Arduino pin can be programmed as either an output or an input. As an input, it can neither source nor sink current. We’re not using the pin for its input properties; merely for the fact that an input pin is not an output pin and is therefore “disconnected” from the LED matrix. This dependence upon tristate pins is a hallmark of charlieplexing. So the programming rules are straightforward: set the select pins H for the segments to be displayed, set the remaining segment select pins as inputs and set the SSD select pin L.