Alternate multiplexing method for 7-segment displays

I posted a video to my local OSH group's Youtube channel showing an alternate way to multiplex 7-segment displays that greatly reduces the parts count. There's also a related Github repo.

This was done for both the Arduino Nano using the Arduino IDE, and the TI MSP430G2553 using Energia. The video shows the TI processor, but the Github repo has Arduino sketches. I believe the sketches are interchangeable between the two systems except for pin assignments.

The idea is to multiplex by segment instead of by digit. That eliminates the need for resistors on all the segment driver lines and transistors on the common anode/cathode lines. All that's left is one resistor on each CA/CC line. Also shown is the use of a 74HC4017 to drive the segment lines, which reduces the required number of processor GPIO pins to the number of digits being used, plus one. So a four-digit display would require five GPIO pins plus the HC4017.

I'm not set up to respond to comments on Youtube, but can answer any questions here.

OK. Thanks. Multiplexing at a granularity of segment level is certainly another method of driving a 7 segment display, particularly for reducing the number of current limiting resistors to one per digit. Interesting was that you had chosen to illuminate the same segment on multiple digits simultaneously if it was appropriate. For example, with the display of 42, as in the video, segment G (the middle segment) was lit for both digits at the same time. I'd have thought (although it didn't show in the video) that because the middle bar of the 2 was illuminated twice as often as the top bar, there would be as noticeable difference in the light intensity. Maybe it is because the camera you used did some "smoothing". If you were to display 6668 I guess the top right bar of the 8 would appear noticeably weaker that the remaining bars since it is illuminated one eighth of the time of the others.

I have only heard of it being done, but another method still using only one current limiting resistor per digit, would be to multiplex at the digit granularity level, but to use pulse width modulation to even out the luminous intensity to prevent say a 1 appearing brighter than an 8.

As for the integrated circuits to minimise the pin usage of the MPU, one other to consider is the MAX7219. There, you need only one resistor per display group and it handles the multiplexing itself.

6v6gt:
OK. Thanks. Multiplexing at a granularity of segment level is certainly another method of driving a 7 segment display, particularly for reducing the number of current limiting resistors to one per digit. Interesting was that you had chosen to illuminate the same segment on multiple digits simultaneously if it was appropriate. For example, with the display of 42, as in the video, segment G (the middle segment) was lit for both digits at the same time. I'd have thought (although it didn't show in the video) that because the middle bar of the 2 was illuminated twice as often as the top bar, there would be as noticeable difference in the light intensity. Maybe it is because the camera you used did some "smoothing". If you were to display 6668 I guess the top right bar of the 8 would appear noticeably weaker that the remaining bars since it is illuminated one eighth of the time of the others.

I have only heard of it being done, but another method still using only one current limiting resistor per digit, would be to multiplex at the digit granularity level, but to use pulse width modulation to even out the luminous intensity to prevent say a 1 appearing brighter than an 8.

As for the integrated circuits to minimise the pin usage of the MPU, one other to consider is the MAX7219. There, you need only one resistor per display group and it handles the multiplexing itself.

The G segments are actually the same brightness, and the same brightness as the other segments. The current though each G segment is the same, as determined by the resistors, and that will be the case up to the point that the number of digits being driven (i.e.- the number of G segments) is greater than the port pin can source. But with these high-effiency displays, that point probably wouldn't occur until you get more than four digits. As I said in the video, I can produce "88" with this system using a total of 4ma, or 2ma per common cathode. An Arduino segment port can probably source 20ma before the voltage starts to drop.

Also, every segment is turned on for the same period of time. Remember that the segment lines cycle through one at a time, for exactly the same amount of time. So each segment lights up one interrupt out of seven. there is no difference in brightness because each segment gets the same current as determined by the resistors, for the same amount of time. The camera isn't smoothing anything. They really are equally bright. So your expectation about 6668 is not correct. Each segment is lit for the same amount of time, and they are all equally bright.

I agree that in theory you could eliminate the segment line resistors by using PWM to achieve consistent brightness, but I think you would still need the transistors, and resistors on their collector lines, unless the port pins can sink 8 segments of current at the same time. And the MAX 7219 is certainly another option, but it is a 24-pin part which I believe needs five processors pins to drive. For four digits, using the 74HC4017 with this system would use the same number of pins with a smaller, cheaper part. But it would have to be refreshed far more often than the 7219.

I've now looked in detail at your code and see how you have implemented it and it is clear now that there should not be, as you have correctly said, any difference in the luminous intensity irrespective of how many segments are lit. My mistake.
The MAX7219 / 7221 is Read only SPI or (or similar) and needs 3 MPU pins (clock, chip select, and data in, and can drive up to eight seven segment digits.

And I think with the MAX7219, you only have to update it when a displayed digit changes, rather than having to refresh it all the time.

One thing I forgot to post was that I modified the demo sketch to bring D12 HIGH as the first line of the millis IF statement, and bring it back LOW as the last line. Then I connected my scope to D12 to determine how long D12 stays high, which is how much time the servicing code takes up. With my Nano running at 16 MHz, it takes 25µs to get through one IF iteration, and that executes once every 2ms. That's 1.25% of the total time available to loop() taken up servicing the displays, which I think is reasonable. Of course this method probably won't work with any sketch that uses delay() anywhere.