Rothschopf Werner

rowex ganz privat


Update of Arduino Led Control Library for MAX7219

Coming from the 80's I love the 7 segment displays. They are clearly readable, night and day. Combined with a dedicated driver chip - for example the Maxim MAX7219/MAX7221 - the usage with an Arduino gets pretty easy. Fortunatly there is a Library exisiting called "LED Control". On this page I want to present some extensions for easier writing mumbers and text using the "print" method.


Introduction Led Control

There are lot of cheap modules avalaible from China (obviously with counterfeight chips). That price might be the reason, why these displays have still fans nowadays. Each MAX7219/MAX7221 can drive up to 8 seven segment digits. And if 8 digits are not enough - you can daisy chain the chips.

The original Arduino library LED Control written by Eberhard Fahle is dating back to 2007 and - according to the files - seems to be last updated 2015. It provides a good starting point when you want to use the MAX7219 (or MAX7221). It's easy to show one character or one digit, but gets quite complex if you want to print  larger numbers or plain text on the display. And this is the point where my new modified library jumps in.

Modifications of Noiasca Led Control

In the Arduino world there is existing a so called "print" class. You will use it for Serial output (Serial.print), printing to LCDs, OLEDs or even for the output of a webserver. I added this "print" method to an updated library called "Noiasca Led Control". The new library should be fully compatible to the original library - and offers easier output with print (and some other helpers).

What's behind these modifications

One capability of C++ is, that a class can derive properties and characteristics from another class. This is called Inheritance. Exactly this method was used: the new library inherits the print method. To be precise: I needed to implemet the "write" method. This method writes one digit on the display. We inherite the print class (which uses the write method) and now we are able to "print" integers, floats, C-strings (char arrays), Strings to the display like you are used to from other libraries. Additionally I needed one additional byte variable to store the current position where to write the next character.

As you might know from other libraries they offer some helper methods. The method


is such an example, it will set the cursor to a defined position. More or less compareable to some parameters in the .setDigit method.

Understanding digit numbering and position of cursor

The original library uses "digit" - numbered from 7 to 0 (left to right) to set where to print. To keep in line with other displays I decided to use "positions" - starting with 0 (left) to right.

device   0                 1                 2                   7
addr     0 0 0 0 0 0 0 0   1 1 1 1 1 1 1 1   2 2 2 2 2 2 2 2     7 7 7 7 7 7 7 7
digit    7 6 5 4 3 2 1 0   7 6 5 4 3 2 1 0   7 6 5 4 3 2 1 0 ... 7 6 5 4 3 2 1 0
position 0 1 2 3 4 5 6 7   8 9 10  . . . .   16  . . . . . . ... 56            63

Example: if you have 2 MAX7219 and you want to write on the second chip - just remember that C++ starts counting at zero and define

lc.setCursor(1, 0);    // second chip (=address), first character (=position)
lc.print("2nd IC");    // print text to LED Display

The method can be used also with one parameter to set the absolute position:

lc.setCursor(8);       // second chip (row), first character
lc.print("2nd IC");    // print text to LED Display

Hint: Be carefull when you migrate existing code which used "setDigit". If you have used setDigit(int addr, int digit, byte value, boolean dp) like in

lc.setDigit(0, 1, 3, 0);
lc.setDigit(0, 0, 4, 0);

to print 34 on the two most right digits, you will need a

lc.setCursor(0, 6);

to get the same result with the print method.

Limitations of a 7 segment character set

Does it need an explanation, that it is not possible to print all characters with 7 segments? Even I tried to cover as many characters as possible, I was limited by the fact, to just have 7 straight lines for the Alphabet.

Characters like K W X are definatly not printable and are replaced with a blank. V is replaced by U. The small "r" needs quite good phantasie to be identified as r. The "a" is  "o." with dot. The "Q" uses a similar aproach, i used a "O." That reads quite complicated, but looks not so bad at all. Just give it a try. Sometimes there needs a mix of small and capital letters. If one has good ideas for improvements of the charTable - I appreciate your feedback.

Brackets - parentheses ( ), square brackets [ ], braces { }, and angle brackets - are always printed as square brackets.

There is a degree sign (which will also be used for %), the - and _ an the dot.

All together the character set could have 128 characters (=7bit). However only character 37-127 are printable, other values will cause a blank (technically you can also use 0-10 which will print the respective numbers 0-9 and the for 10).

Points and Dots

Points/dots are somehow anoying. As printing is character by character  we have to find a way how to "activate" the decimal point of previous printed digit. This is done by using an (existing) status array. The library stores each digit (up to 64) in RAM. Therefore we can "reprint" the previous digit with an activated dot.

This works quite well - up to the point if the previous character is a dot. This just breaks the print out. This means you can just print a dot after another character - but not dot dot.

So this is not allowed


instead print a blank before the next dot, like following:

. . .

This will be shown up correctly on the display - and if you carefully check your display it IS exactly what you want: 7 segments must not be enlighted (all off), but the decimal point does. So it makes absolutly sense to print blanks between the dots, doesn't it ;-).

End of Line

If we come to the 8th position we have to decide what should happen with the next character. Per default the library jumps to the "NEXT_DEVICE". If we have written the last postion on the last device, we wrap around to the first device. This behaviour can be changed with the method:

void setEndOfDevice(optionEndOfDevice newOption);

The available options are

NEXT_DEVICE:  the default behaviou as described: Jump to next adress - or if no more devices are available, jump to the first chip (adress=0)

THIS_DEVICE: only uses the same chip/adress, so wrap around within the sam e chip.

FIRST_DEVICE: always jumps to adress 0. <here are seldom usecases where you need this.

SHIFT_LEFT: whould be nice, but is not implemented yet.

Linefeed and Carriage Return

I decided to activly use the linefeed (LF, 0d10, 0x0A, \n) to force a linefeed. To be precise the linefeed will trigger an event causing the same behaviour like when the cursor reaches the end of the device. This means per default it will jump to the next device.

The carriage return (CR, 0d13, 0x0C, \r) will have NO EFFECT. It will even not print a blank.

By the way: as we inherited from print class we can also use println.

println prints text (or numbers) followed by CRLF. As the library ignores the carriage return but the linefeed gets recognized - println will cause a linefeed.

Installation and usage of the new Noiasca Led Control Library

Download the ZIP (at the end of this page) and unzip it to your libraries folder. It might be that you will need a restart of your Arduino IDE before you can use the library.

There is an additional example sketch called LCDemoNoiascaHelloWorld. It shows all available methods and some special things you should know about the library.

If you want to migrate an existing sketch you have to follow these steps:

a) Include the new libary with

 #include "NoiascaLedControl.h"

b) dont Include the original library any more

c) do a test compile of your sketch - it should still compile without any (new) errors, as the libary should be backward compatible.

d) adopt your print outs to the new print method, replace setting of cursor position and adopt your text to be shown as correctly as possible.


I was not able to contact Eberhard Fahle regarding licence topics. Therefore all copyright informations stayed in the .cpp/.h.



First upload: 2019-04-25 | Version: 2019-05-13