Driving LED Matrices Conveniently

ꝺeshipuꝺeshipu wrote 11/04/2018 at 21:40 • 6 min read • Like

You can make a pretty neat low-resolution display out of LEDs arranged in rows and columns — you can even buy ready matrices that save you a lot of work with it. You "only" need one GPIO pin per every row and every column (you can save a lot of them by charlieplexing). The way you display things is that you enable one row (or column) at a time, and enable the columns (or rows) for that set of pixels, and then you disable it and switch to the next row (or column). If you do that quick enough, the LEDs won't even have time to stop shining, and you will have a pretty reasonable image displayed. But there are several problems with this.

First, you still need resistors on your LEDs. Second, because the number of LEDs that are on in a given row changes, so does the current taken by them, and since your resistor doesn't change, the row gets fainter the more pixels are shining on it. Third, you need your microcontroller to keep scanning the rows of the matrix and re-displaying the pixels all the time. Fourth, if you have too many rows, the total time each of them is on becomes rather short, and thus they become too faint. Fifth, if you want to have brightness control for the individual pixels, you need to scan the matrix even faster — the more different levels of brightness you need, the faster. Sixth, if your microcontroller does anything else at the same time, you might see some artifacts due to the timings not being exactly right. And finally, one pin per row and column is a lot of pins.

So can you do better? Of course!

First of all, you don't have to use GPIO pins to drive LEDs directly. There are mosfets, there are logic buffers, and finally, the best of them, there are constant-current drivers — those will let you get rid of the resistors and fix the varying row brightness problem! But what about the number of pins? You get a whole plethora of pin multiplexers, decade counters and shift registers you could use for that. What about the requirements on speed constant scanning? Well you could use a dedicated microcontroller that you just tell which pixels should be on or off once, and that will do the scanning for you.

All of those problems have their solutions, but all of them will add more and more components to your project's bill of materials, and also combining them all together and making sure they all fit together is a bit of a pain. Surely there must be integrated circuits that already contain all those required components inside a single package? You bet there are!

I know about roughly four families of chips dedicated to driving LED matrices (and also 7-segment displays and similar things). They vary in size, price, features and ease of use. They all have their own internal memory and some kind of a communication bus through which you can modify it, and they keep displaying their contest without you having to do anything more, however, the exact details tend to vary as well. I want to list the ones I know here, and if you know of any more, please feel free to leave a comment.

Maxim Integrated

One of the most widespread chips of this kind is the venerable MAX7219. You can still buy ready matrix modules with it. It can drive up to 8x8 pixels, switching them on or off (1 bit) and changing their global brightness. You control it over SPI and it also has a second SPI bus to which you can forward commands, so you can chain several of those chips on one bus this way. They also come in huge DIP and SO packages, which makes them perfect for breadboard use. It requires one extra component — the resistor for setting/measuring the current.

But they are not the only LED matrix drivers that Maxim makes. In fact, there is a whole big list of them. Unfortunately I didn't really have any opportunity to use any of those, so I won't be writing too much about them.


The second most popular chip for this that I know is the HT16K33. It's also popular in matrix modules, I think due to Adafruit using it in their matrix "backpacks". Depending on the package it can drive up to 8x8 or 16x8 pixels, switching them on or off (1 bit), and changing their global brightness (4 bit) and global blinking speed (4 bit). As a bonus, you can also make it scan a matrix of up to 13x3 buttons at the same time as it drives your display. You control it over I2C (TWI), and you can select the address, so you can have up to 8 (depending on the package) of them on the same bus. It comes in rather bulky SOP20, SOP24 and SOP28 packages easy to solder by hand. It the simplest use case it doesn't require additional components, other than the obligatory pull-up resistors on the I2C bus lines, but if you need to set a different address or scan the buttons, then you will need some extra diodes and resistors.

There are currently two more similar chips sold by Holtek, and three more advanced ones, as you can see on the list. Again, I never really had any experience with those, so I will not talk about them here.

Titan Micro Electronics

Let us look at some of the cheaper alternatives, such as the TM1640 that is being used in the official matrix shield for the D1 Mini boards and also is used in some bi-color matrix modules available out there. It can drive up to 16x8 pixels, switching them on or off (1 bit). You control it over some weird serial protocol that is a mixture of SPI and I2C that requires only two pins, but is not addressable, so you will need separate pins for every device. It comes in the same bulku SOP28 package as the previous chip, but it's not pin-compatible. It doesn't need additional components, apart from the pull-up resistors on the signal lines.

That company makes a lot of other LED driving chips, and there are also a lot of similarly named cheap clones available on the market, but unfortunately most of them use some custom non-standard serial protocol for control, and the datasheets come in Chinese, so they take some work to use.

Integrated Silicon Solution

The ISSI has a number of interesting chips in this category. I'm going to describe two of them, but you can also look at the more elaborate experiments I did with them.

The IS31FL3728 (pdf) can drive up to 8x8 (it has several modes, up to 11x5) pixels switching them on or off (1 bit) with global brightness (4 bit). It also has an analog input (audio) that can be used to modulate the global brightness or to display an "equalizer" bar graph of frequencies. You control it over I2C (TWI) with up to 4 different addresses. It comes in a tiny QFN-24 package, so it's nice for the projects where you don't have much space. At the minimum, it requires one resistor and one capacitor apart from the usual pull-up resistors on the bus lines.

The IS31FL3733 (pdf) can drive up to 16x12 pixels with 256 (8 bit) individual brightness levels and 256 (8 bit) levels of global brightness. You control it over I2C (TWI) and you can set 4 different addresses. It comes in QFN48 or eTQFP48 package. Apart from the pull-up resistors on the bus lines it also requires a resistor for setting the current.

This company makes many more very interesting LED-driving chips, included ones for charlie-plexed displays. The two I described seem the most interesting to me.



Ken Yap wrote 11/28/2018 at 10:32 point

>If you do that quick enough, the LEDs won't even have time to stop shining

To be correct, it's the persistence of vision effect of the human eye ( The LED really does stop shining when not powered. A high frame rate camera will prove it.

  Are you sure? yes | no

ꝺeshipu wrote 11/28/2018 at 17:15 point

Actually it is both, but at those speeds of refresh the capacitance of the LEDs is enough to make them still shine until the next refresh. And yes, I actually did confirm that with a camera. If you need a crisp image, you can reduce that effect by using additional pull-down resistors to discharge them faster, some of the chips I mentioned (the ISSI ones) even have those built-in, optionally enabled in the chip's configuration.

  Are you sure? yes | no

Ken Yap wrote 11/28/2018 at 23:03 point

The capacitance of the LEDs is very small. It's really the stored charge at the gate of the FETs that's keeping the FET on, hence the pull-down resistors to dischage the gate.

  Are you sure? yes | no

Gregory P. Smith wrote 11/28/2018 at 07:22 point

The ISSI Charlieplexing chips are great, Adafruit sells a couple things based on the IS31FL3731 to drive 15x7 or 16x9 displays. Eight frame buffers with 256 shades per led over I2C is fun.

  Are you sure? yes | no

ꝺeshipu wrote 11/28/2018 at 17:16 point

I'm a big fan of them, even though the QFN packages are a huge pain to solder properly even with a hot air gun.

  Are you sure? yes | no

Morning.Star wrote 11/25/2018 at 07:13 point

Nice, these are good to know... It seems LEDs are extremely addictive. You only need to light one and before you know it you'll be lighting them up in hundreds.

Just say no kids :-D

I'm using a MCP23017 Port Expander Ars sent me, as it has I2C interface and a 16-bit wide interface organised as two 8bit IO ports. By CharliePlexing it can drive 128 LEDs, 64 directly.

Pros: Only 3 pins to control 16 IO lines, 3v, has Raspberry flavoured drivers.

Cons: Manual written in archaic Reptilian...

  Are you sure? yes | no

ꝺeshipu wrote 11/28/2018 at 17:20 point

Nice, I didn't know there are port expanders that can do high-z as well, but I guess I should have guessed.

  Are you sure? yes | no

Morning.Star wrote 12/03/2018 at 17:01 point

It appears to be a MCU without a brain (and thus no ADC) but it functions just the same with an I2C bridge. Its pretty quick too :-)

  Are you sure? yes | no

Mike Harrison wrote 11/07/2018 at 22:26 point

If you're going for a conventional anode row/ cathode column driver solution, the row drivers get messy, with lots of P-channel fets. There are a couple of nice  Chinese chips to tidy this up  - Chipone ICN2012 (Aliexpress) and Double Micro D7258 ( Lcsc .com ) They are pin compatible and AFAICS interchangeable. These are a 74HC138 3-to-8 line decoder with 8 built-in P-fets in a SO16. For column drivers, instead of the various 16-channel constant-current drivers you can sometimes get away with 74HC595's with or maybe witrhout current-limiting resistors. If you need to maintain constant-ish current over a small battery voltage range ( e.g. Lipo 4.2-3.4) you can measure the battery voltage and adjust the dead-time in the multiplex.

Another nice solution for white LEDs in particular, where you don;t need much current is 74HC595 as anode column driver and Npic6C595 ( like a HC595 with Nfets on the output) as a cathode row driver. Can use as few as 3 MCU pins  for as big a matrix as you like ( clock, data, latch/OE )

  Are you sure? yes | no

ꝺeshipu wrote 11/28/2018 at 17:19 point

Thank you for this! I have never actually tried the separate anode/cathode drivers approach myself, but I have seen it done in other projects (most notably, the first Hackaday Belgrade badge).

  Are you sure? yes | no

Jan wrote 11/05/2018 at 08:22 point

Nice overview. It's always a good idea to go to mouser or some other seller and just go to the corresponding category and have a little fun with the filters. Most ften I just filter by case, then by price and sift through the list :)

  Are you sure? yes | no

ꝺeshipu wrote 11/05/2018 at 12:02 point

Yeah, I tried that, unfortunately there is not a specific category for matrix drivers, and the descriptions are quite bad, so you have to actually read the datasheet to figure out what a given chip does (Why do they have ADC chips in there?), and there are hundreds to sieve through...

  Are you sure? yes | no