HOME - - - - - - - - Table of contents, my Arduino "How To" articles
Other material for programmers     

Matrix LED displays- MAX7219 driven

Early investigations/ Free code
Scrolling text

filename: aht3matrixLED7219.htm

How hard could it be?

How many times has that little thought got you in trouble? Me? Many times.

MAX7219 driven 8x8 LED matrix

January, 2019, a passing comment by a friend about wanting a "scrolling text" display for his shop sent me off down the rabbit hole. Again.

At least it wasn't expensive. I already had the Teensy that I used to drive it. (An Atmega328, 16MHz "will do"... but the pace of scrolling is a bit dull.) The basic MAX7219-driven unit is 8 rows of 8 LEDs. I bought (via Amazon) two panels of four 8x8s for £20 because I was impatient. I could have had similar products for £10. (Incl p&p, 1/19). The units "daisy-chained" without issues.

I eventually got something working okay for me. I will give you a link for downloading the Arduino/ Teensy code (free) later on in this page.


Hookup is easy. While I was using a 5v Arduino, it was super easy. With a 3v3 Arduino- not hard.

I pushed my luck, powered the LED matrix off of the USB power I was using to power the Arduino/ Teensy. I don't feel very guilty, but if you are thinking of daisy chaining more than eight 8x8 modules, you should probably take some measurements to see just how much current you are demanding.

Other than the power connections (5v and Gnd), there are only three others to make, and they are all outputs from the Arduino. ("Arduino" henceforth is used to mean "Arduino, or Teensy, or other clone.)

If you use a Teensy, (or any other 3v3 Arduino) you will have to put level shifters on the three lines, to shift up from the Teensy's 3v3 to the 5v the MAX7219 expects. Something like the Sparkfun bidirectional 5v/ 3v3 level shifting module ($3) makes this easy.

In any code for driving MAX7219s, there will be some lines similar to...

//Connections to panel of LED matrices...
//If changed... change sInfo lines
const int DIN_PIN = 12;
const int CS_PIN = 10;
const int CLK_PIN = 11;

If the code you are using, has these lines, you connect the data in (DIN) input of the MAX7219 module to output D12 of the Arduino.

And the Chip Select input to Arduino's D10, and Clock input to D11.

Within reason, you can make changes, I think. (I don't believe that the interface relies on the Arduino's SPI or I2C or any other such features, which sometimes ARE "tied" to particular pins.)

But what the hardware connections are must "match up" with the way the software is set up.

Certainly with the library I am familiar with, and almost certainly any other library for daisy chained MAX7219 LED matrix controllers, you also have to specify how many modules you have. In the free code I am giving away with this, that is done with the following...

const byte bLastIndexM88=7;//Set to 3 if you have 4 LED...
   //modules of 8x8. (It is the INDEX of the right hand
   //module. Note, however, 4th argument of...
   //  LedControl lmc = LedControl(...
   //wants COUNT of M88s, hence the "+1" there.


Then I went off to the web, anticipating finding software easily.

Umm. Not. Especially if you want your text to scroll.

The documentation for the LumaLED line helped me some. If you are not buying 8x8 matrices already wired to one another, and to their controllers, first I would ask "why not"? It really isn't worth doing this for yourself. Secondly, I would point you to this blog by embedded-lab.com

I haven't the time to do you a full tutorial on using these nice devices... but besides the notes I have written here, there is much to learn from the code I am giving away.

If you decide to "play", here are some of the things you need to pay careful attention to...

Are the LEDs in the MAX7219 modules you are playing with wired in the same way as the ones the software you are trying to use?

Start small... try turning on the lower left LED of your display. Then the one next to it. Then the one above.

If you can get that working, try filling the whole display, from upper left to lower right, in the sequence you would read words on a page.

Which way "up" are things? (This follows on from the "doing the LEDs one by one" exercise I mentioned a moment ago, but you could be forgiven for not noticing the connection, or for jumping over that. Forgiven... but if you don't start small, you will be punished, I promise)

In my early work, I was getting recognizable text, but the letters were rotated 90 degrees from what I expected. I was getting a column of text, one letter per line, instead of a row of text, as in the illustration above.

It is another consequence of how the LEDs are wired to the MAX7219, I think. Overcoming it is easy (ish), but tedious. (You change the data that defines the different letters which can be displayed. To the controller, it is all just jumbles of LEDs on or off. The "characters" are in the eye of the beholder. Tell the controller to turn different LEDs on and off, and a character can be rotated or "flipped"... whatever you need.)

Another thing to look out for: How are the LEDs addressed by your library?

The one I settled on as the best compromise between features and likely support, robustness shows up (1/19) in the Arduino IDE (1.8.1, at 26 Jan 19) as "LedControl by Eberhard Fahle, Ver 1.0.6, A library for the MAX7219 and the MAX7221 Led display drivers..."

In that, you specify which 8x8 unit you want to use, and then which LED in that, as x/y values in the range 0-7.

I struggled some with the library at https://www.pjrc.com/teensy/td_libs_Matrix.html, which looked good! It uses "sprites", and the x coordinate of an LED is relative to the whole display. But I think that hardware assumes a wiring scheme that is uncommon, and that there's no easy way to "tweak" the code to overcome the wiring issue. Certainly re-defining the LEDs to be on or off for a given character isn't enough.

I mention the PJRC option to show that how a given LED is referenced can be done more than one way.


I'll return to the broader questions of software in a moment... first a mention for...

The magnificent character support from Xantorohara. Not least the several fonts already designed for you. "Play" with the site a bit... you can do what I expect you would assume you can do, even if the exact process wasn't immediately obvious to me. Eventually, though, I had something like...

const uint64_t IMAGES[] = {
const int IMAGES_LEN = sizeof(IMAGES)/8;

.. which, though you won't realize it just yet, probably, is what you need if you want to put characters from "0", "1", "2"... "9" on the LED matrix display.

0x003f0c0c0c0c0e0c (the first line) is the on's and off's for "1"...

Strip off the "0x"... it is only there to say that the rest of the line is hex. (I.e. a number written in hexadecimal.)

Take that two digits at a time. Convert each to four bits of binary... 0 is 0000, 1 is 0001, a is 1010, b is 1011... f is 1111. Those eight 1s and 0s tell you what LEDs should be on in a single column, to make the character you wanted.

So! Catching the character rabbit: Not hard. Xantorohara even lets you, easily, find the right numbers for ANY character.

Spacing between characters (and rows, if you have more than one row) is part of "the character", as you will see, if you look closely at the Xantorohara simulations of what different codes give rise to.

Back to the software

Eberhard Fahle's LedControl library (explained above) gives you a setColumn(m,c,d) command.

You set m to whatever module you want to do something to, c to the column of LEDs in that module, and in d you supply a byte (8 bits). The LEDs in that column will go on or off depending on the 1s and 0s in that byte.

So far, so simple... really. And all of that is there for you in the support material for the library, in the examples.

But scrolling with this library, I could not find.

My "answer", in a nutshell:

Put the "message" you want to scroll... including "spaces", i.e. blank 8x8 LED modules, into memory.

Refresh the ons and offs in every module, working from left to right, once per execution of the loop() subroutine.


For first module to last...
  For first column of LEDs in this module to last...
     Set or clear each of the 8 LEDs in the current column.

Separately... and this was the tricky bit...

Maintain a pointer that, AT THE BEGINNING of the program's execution, starts with the first byte of the "message" data, and is advanced one place (one byte) for each "Set or clear each of the 8 LEDs..".

But! When loop() has executed once, on the next pass, the pointer starts with the second byte of the message data. Next time, the third. Etc. AND you have to "deal with" "wrapping" the pointer... when it gets to the end of the message data, it goes back to the first byte. This will usually happen somewhere in the "middle" of a particular instance of executing "loop()", if you think about it, won't it?


There are a few frills in the code.

The pin defined by bMsgSelect is set up as an input. It's state decides which of two messages are displayed. (As supplied, the code offers "OPEN" and "CLOSED".)

Pin A0, an analog input by default, is read by the program. The voltage present there affects the speed that the message scrolls.. IF the pin defined by pEnableAnalogSpeedControl is NOT pulled low by a connection to ground. (pEnableAnalogSpeedControl can float if you WANT the voltage on A0 to determine the scroll speed.

The code!

It's messy. It has scraps of development work in it, remmed out. But it is free!

I know it works in a Teensy. I believe it works in simpler Arduinos, e.g. the Sparkfun "Redboard" Uno clone.

You have to install the library mentioned previously: LedControl by Eberhard Fahle, a library for the MAX7219 and the MAX7221 Led display drivers" I was using version 1.0.6, but install a more up to date one if one is on offer. I only used basic things, which should remain part of this library in later versions.

For that library:
Website http://wayoda.github.io/LedControl/
Github https://github.com/wayoda/LedControl

The following initiate a download of a .zip with my code in it: LedMatrix_TKB_19126_Teensy.zip.

I hope that helps?

Perfect? No. But maybe the back of the problem has been broken for you?

I hope so. PLEASE SPREAD THE WORD, if so? Mention this page... http://sheepdogguides.com/arduino/aht3matrixLED7219.htm in forum posts?

   Search this site or the web        powered by FreeFind
  Site search Web search
Site Map    What's New    Search

The search engine is not intelligent. It merely seeks the words you specify. It will not do anything sensible with "What does the 'could not compile' error mean?" It will just return references to pages with "what", "does", "could", "not".... etc.
In addition to the tutorials for which this page serves as Table of Contents, I have other sites with material you might find useful.....

Sequenced set of tutorials on Arduino programming and electronics interfacing.
Tutorials about the free database supplied with Open Office/ Libre Office.

Some pages for programmers.
Using the parallel port of a Windows computer.

If you visit 1&1's site from here, it helps me. They host my website, and I wouldn't put this link up for them if I wasn't happy with their service.

Ad from page's editor: Yes.. I do enjoy compiling these things for you... hope they are helpful. However.. this doesn't pay my bills!!! If you find this stuff useful, (and you run an MS-DOS or Windows PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!

Click here to visit editor's Sheepdog Software (tm) freeware, shareware pages.. Material on this page © TK Boyd 2/19

And if you liked that, or want different things, here are some more pages from the editor of these tutorials....

Click here to visit the homepage of my biggest site.

Click here to visit the homepage of Sheepdogsoftware.co.uk. Apologies if the "?FrmAht" I added to that link causes your browser problems. Please let me know, if so?

Click here to visit editor's pages about using computers in Sensing and Control, e.g. weather logging.

To email this page's editor, Tom Boyd.... Editor's email address. Suggestions welcomed!

Valid HTML 4.01 Transitional Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org

Why does this page cause a script to run? Because of the Google panels, and the code for the search button. Why do I mention the script? Be sure you know all you need to about spyware.

....... P a g e . . . E n d s .....