Electronic – arduino – What’s the “accepted” way of driving LOTS of 2-digit, 16-segment, common-cathode displays

arduinodisplayled

I have a project that has 18 of these common-cathode displays, 36 digits in all, organized into three rows of 12 digits. My first version of the project used an Arduino and shift registers to drive them. I would shift out the 0th column of digits, latch them to provide power to the displays, then ground the 0th column. This would show the first character. Then, I'd shift out the next column of data, disable the ground on the 0th column, latch the 1th column, and provide ground to the 1th column to show it to the user.

It works, but it has a couple issues. It's very, very, very dim. I can make it brighter by holding each display on a while longer, but it doesn't go very far, and you can sense the low refresh rate when you look at it. Also, if I have a column that have very few segments active, they draw all the current I'm supplying and that column ends up being much brighter than the rest.

I have a ton (would you say I have "a plethora?") of MAX-7219 LED controllers, but there's a snag: the LED controller assumes a maximum of 8 segments per cathode. I considered using one LED controller to drive half of the segments on 8 digits, and another controller for the other half. This would (probably) work – I'd just deactivate the display on the upper half and activate the lower, then reverse the process a few milliseconds later.

I really want the drawing to be fire-and-forget. I have to generate the data I'm displaying, and this takes time. During this time, I can't really be burning CPU, flopping the displays. (Technically, I could do the flopping in a timer, but I'd have to stop the timer while I shifted out new data, and that timer might interfere with the LedController library, as well as the serial communications I'm using to get the data from a GPS module, anyway.)

So, is there a way that I can shift out 36 digits worth of data and completely forget about it for 100-1000ms, leaving the work of driving the display to someone else's hardware? I've even considered having one arduino to process data, then transfer it, somehow, to three – or even six – other arduinos for display.

Best Answer

Dimness and variable brightness might have two causes:

  • You're MUXing too many (36?).

  • Your LED current-limiting resistor(s) are in the COMMON leg, not in each of the LED legs.

Muxing more than about 8 requires the common-cathode pull-down switch to pull too much current, especially when all your digits are "8". A discrete N-channel MOSfet might be able to handle the current required of the common-cathode driver. You might consider daisy-chaining four shift registers and pushing it to nine MUX (4 x 9 array).

For the anodes, you might get away with HCMOS shift registers (HC164, HC595). Even so, it helps to start with efficient LED segments that give decent brightness @ 1mA DC. Shifts can be done quite fast, so that the time to shift five daisy-chained HC164 doesn't eat into the MUX period (which should loop faster than 30 per second, else it becomes optically annoying). You should still optimize the shifting code for speed. The basic shift-cell might look like this (do 9 more rows of this):

schematic

simulate this circuit – Schematic created using CircuitLab

Those nine MOSfets need a way to drive their gates. An HC595 might be used to drive the MOSfets, simply shifting a single "1" in a ring. You might need two HC595 to get the extra bit (to get a 9-bit shift register). It's tri-state output might be used to turn off all the LED's while you're shifting if interrupt routines take too long, or if background flicker is distracting: the 5k pull-down gate resistor will ensure that all MOSfets turn off.
That's a lot of wiring, and a lot of resistors. It'll likely cause some RFI: try to wire it all very compact.
All the shifting could be done as a background process - it doesn't need a timer and can easily be interrupted by your other peripherals so long as their handlers finish in a reasonable time. Consider using the watch-dog timer as the MUX timer (if you're short of timers), if it can be crudely set to about 3 ms.