LedMatrix - MAX7219/7221 Library for large dot matrix displays

I wanted to share a library I wrote last year for the MAX72XX display driver, specifically designed for displays arranged into larger square/rectangular shapes. The main focus was geared toward drawing and text, so there are functions for printing single characters, scrolling text, and basic drawing. It also includes 2 font libraries: 5x7 & 8x8. For setup, you just tell it how many rows and columns of 8x8 displays you have, and it does the rest.

There are two versions of the libraries: LedMatrix and LedMatrixSPI. They are identical except that one uses SPI, so is substantially faster, but requires using the dedicated SPI pins. The non-SPI version lets you choose the data, clock and load pins so if SPI is already tied up, or you want to drive multiple displays from the same MCU.

I know there are several libraries available for this already, but found they were either too slow, too simple (not enough functionality), or way too complicated (functionality overkill) for for the project I was doing. So I decided to make one simple enough that it's easy to use, but with enough functionality for more involved projects.

"Theoretically", it can support up to 32 rows and columns of 8x8 displays, but the ATmega328 will run out of variable memory well before that. Realistically you can have about 150 displays before the Arduino IDE starts giving memory warnings. I actually coded in a hard limit of 32 total displays to keep the variable memory size down, but can easily be changed in the header file as needed.

It does require the displays to be connected in a specific order though. The first display is in the upper-left corner (data in from Arduino), with each subsequent display in the row connected to its immediate right. The last display in a row is connected to the left-most display in the next row. It must also have an equal number of rows and columns. For example, you cannot have 4 displays in the first row, then 5 in the 2nd. Same goes for columns.

The library uses direct pin and register manipulation, so will probably only work for ATmega328 models. I wrote it this way so it could be easily ported for direct use with an AVR, though it can be modified for other MCUs with just a few minor changes.

Below is a list of the functions available. For detailed descriptions check out the Wiki page. Unfortunately I only have one example sketch at the moment (working on more), though for the most part it's pretty straightforward to use.

I also have a few videos on YouTube demonstrating its use.
Font Tables
Graphics w/ scrolling text


  • LedMatrix(rows, cols)
  • LedMatrix(rows, cols, dataPin, clkPin, csPin)
  • LedMatrixSPI(rows, cols)


  • shutdown(value)
  • setIntensity(intensity)


  • setFont(font f)
  • drawChar(c, x , y)
  • scrollChar(c, row)
  • scrollDelay(value)


  • setLed(x, y, value)
  • update()
  • clear()
  • clearScreen()
  • line(x1, y1, x2, y2)
  • triangle(x1, y1, x2, y2, x3, y3)
  • quad(x1, y1, x2, y2, x3, y3, x4, y4)
  • rect(x, y, width, height)
  • circle(x, y, radius)
  • ellipse(x, y, width, height)

I've used the library quite extensively, but I'm sure there are still several bugs I am not aware of. I'm also sure there are much better, more efficient ways to have written the functions, so welcome any help, advice or critiques.

Anyway, I hope someone can find it useful! Enjoy :slight_smile:

So, if I have ten 8x8 LED matrices, they should be arranged

1 2 3 4 5
6 7 8 9 10


So, if I have ten 8x8 LED matrices, they should be arranged

1 2 3 4 5

6 7 8 9 10


That is correct. Technically, the last row can have less and still function properly as long as they're still left-justified. For example, you could remove 9 and 10, leaving 6-8 in their current locations. Or something like this:

1 2 3 
4 5 6 
7 8 9 


I may give it a try whenever I get my 1 x 4 built.

Here’s one of the example sketches I wrote but haven’t uploaded yet. It’s a pixel test that turns each pixel on, and optionally off, to check if they’re working properly.

 * PixelTest.ino
 * Author:  Aaron Groom
 * Date:    01-27-2016
 * Descrption: 
 *    Tests each pixel by turning each on then off (optional).
 * Pins used:
 *    Data:    Digital pin 10
 *    Clock:   Digital pin 13
 *    CS/Load: Digital pin 11

// Include the LedMatrix library
#include <LedMatrixSPI.h>

const byte DISP_ROWS = 4;            // Number of 8x8 display rows
const byte DISP_COLS = 8;            // Number of 8x8 display columns
const byte LED_ROWS = DISP_ROWS * 8; // Number of LED rows
const byte LED_COLS = DISP_COLS * 8; // Number of LED columns

 * Create an LedMarix object.
 * The first parameter is the number of 8x8 display rows, 
 * the second is the number of 8x8 display columns. 
LedMatrixSPI lm = LedMatrixSPI(DISP_ROWS, DISP_COLS);

bool keepLedsOn = true;    // Whether LEDs stay on or turn on then off.
int delay_time = 20;       // Time in milliseconds a pixel is on.

void setup() {
   // No setup required

void loop() {

 * Turns each LED on starting in the upper left corner (0,0).
void singleLed() {
   for (int yPos = 0; yPos < LED_ROWS; yPos++) {        // Each row
      for (int xPos = 0; xPos < LED_COLS; xPos++) {     // Each column
         lm.setLed(xPos, yPos, 1);                       // Turn LED on
         lm.update();                                    // Update the display
         delay(delay_time);                              // Pause for a few milliseconds
         if(!keepLedsOn) {
            lm.setLed(xPos, yPos, 0);                    // Turn LED off
            lm.update();                                 // Update the display again