In questo tutorial imparerai come controllare un MAX7219 display a matrice di LED con Arduino. Ho incluso uno schema di collegamento e molti esempi di codice! Il codice di questo tutorial può essere usato per display 8×8, 8×32 e anche più grandi.
Per questo tutorial userò il MD_Parola in combinazione con la libreria MD_MAX72XX per Arduino. Queste librerie rendono molto semplice visualizzare testo scorrevole e altre animazioni. Nella prima parte di questo articolo spiegherò le basi per stampare testo sul display. Successivamente vedremo il testo scorrevole e altre animazioni testuali. Infine, ti mostrerò come usare gli sprite di testo.
Se vuoi saperne di più su questo o altri tipi di display, dai un’occhiata agli articoli qui sotto:
Articoli consigliati
- Parola A to Z – Multi Zone Displays
- Coordinate Parola Zone Animations on MAX7219 Display
- Game of Life on a Dot Matrix Display with MAX7219
- TM1637 4 Digit 7 Segment Display Arduino Tutorial
- How to use a 16×2 character LCD with Arduino
- How to control a character I2C LCD with Arduino
Materiale necessario
Componenti hardware
| 8×32 MAX7219 LED dot matrix display | × 1 | Amazon | |
| 8×8 MAX7219 LED dot matrix display (alternativa) | × 1 | Amazon | |
| Generic 8×8 MAX7219 LED dot matrix display (alternativa) | × 1 | Amazon | |
| Arduino Uno Rev3 | × 1 | Amazon | |
| Jumper wires (maschio a femmina) | × 4 | Amazon | |
| USB cable type A/B | × 1 | Amazon | |
| Male headers | ~ 20 | Amazon | |
| Jumpers | ~ 20 | Amazon |
Software
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Informazioni sul driver LED MAX7219
Il driver LED MAX7219 può essere usato per controllare display a 7 segmenti fino a 8 cifre, display a barre o 64 LED singoli. Il driver comunica con Arduino tramite SPI, quindi servono solo tre fili per controllare il display.
Poiché il MAX7219 può controllare al massimo 64 LED, la dimensione massima del display a matrice di punti che può pilotare è 8×8 pixel. Tuttavia, puoi collegare in cascata più driver e matrici insieme e controllare facilmente display molto più grandi come 8×32, 8×64 o anche più grandi. In ogni caso, servono solo tre fili per controllare tutti gli IC, quindi usi pochissimi pin I/O di Arduino.
Di seguito trovi le specifiche di un tipico display a matrice di LED MAX7219 8×32.
Specifiche del display a matrice di LED MAX7219
| Tensione di funzionamento | 5 V |
| Driver del display | MAX7219 x 4 |
| Livelli di luminosità | 16 |
| Dimensioni del display | 32 x 128 x 15 mm |
| Pixel | 8×32, ⌀ 3 mm |
| Costo | Check price |
Per maggiori informazioni puoi consultare il datasheet:
Quasi tutti i display che ho usato in passato utilizzavano una matrice LED 8×8 tipo 1088AS. Puoi trovare un datasheet di uno dei produttori qui sotto:
Come collegare il display a matrice di punti ad Arduino
Il driver LED MAX7219 comunica con Arduino tramite SPI (Serial Peripheral Interface). Con un’interfaccia SPI c’è sempre un dispositivo master (Arduino) che controlla i dispositivi periferici (detti anche slave). Puoi controllare il display tramite l’interfaccia hardware SPI del microcontrollore AVR di Arduino o usando tre pin digitali qualsiasi (SPI software).
I pin hardware SPI (MOSI, MISO e SCK) si trovano in posizioni specifiche su ogni scheda Arduino. Questa interfaccia è più veloce rispetto alla SPI software, ma devi usare i seguenti pin di uscita fissi:
Posizioni dei pin hardware SPI
| Scheda | MOSI | MISO | SCK | Livello |
|---|---|---|---|---|
| Arduino Uno | 11 o ICSP-4 | 12 o ICSP-1 | 13 o ICSP-3 | 5 V |
| Arduino Mega | 51 o ICSP-4 | 50 o ICSP-1 | 52 o ICSP-3 | 5 V |
| Arduino Leonardo | ICSP-4 | ICSP-1 | ICSP-3 | 5 V |
| Arduino Due | SPI-4 | SPI1 | SPI-3 | 3.3 V |
| Arduino MKR1000 | 8 | 10 | 9 | 3.3 V |
Nota che i pin MOSI, MISO e SCK si trovano anche in una posizione fisica coerente sull’intestazione ICSP a 6 pin:

Per controllare i display MAX7219 servono solo tre collegamenti:
- MOSI (Master Out Slave In) collegato a DIN – La linea master che invia dati alle periferiche.
- SCK (Serial Clock) collegato a CLK – Gli impulsi di clock che sincronizzano la trasmissione dati generati dal master.
- SS (Slave Select) collegato a CS – Il pin su ogni dispositivo che il master usa per abilitare o disabilitare dispositivi specifici.
Puoi collegare in cascata più display per creare un display grande collegando DOUT del primo display a DIN del display successivo. VCC, GND, CLK e CS sono condivisi tra tutti i display.
Puoi scegliere qualsiasi pin digitale di Arduino per il pin SS/CS. Nota che in questo tutorial ho usato il pin 3 (vedi tabella sotto).
Lo schema di collegamento qui sotto mostra come collegare il display a matrice di LED MAX7219 ad Arduino. Nota che usando la libreria MD_Parola, devi orientare il display con il connettore DIN a destra, altrimenti il testo verrà stampato capovolto. Per maggiori informazioni vedi la sezione sotto.

I collegamenti sono anche indicati nella tabella sotto:
Collegamenti del display a matrice di LED MAX7219
| Display MAX7219 | Arduino |
|---|---|
| VCC | 5 V |
| GND | GND |
| DIN | 11 (MOSI) |
| CS | 3 (SS) |
| CLK | 13 (SCK) |
Se vuoi usare la SPI software, puoi collegare DIN, CS e CLK a qualsiasi pin digitale di Arduino. Devi solo specificare i numeri dei pin nel setup del codice Arduino (vedi esempi sotto).
Requisiti di alimentazione
La potenza massima che Arduino Uno può fornire in sicurezza quando alimentato via USB è circa 400 mA a 5 V. Se vuoi controllare un display grande, è consigliato usare un alimentatore esterno.
Installazione delle librerie Arduino MD_Parola e MD_MAX72XX
Per controllare il display MAX7219 useremo due fantastiche librerie Arduino create da Marco Colli di MajicDesigns. La libreria MD_Parola può essere usata per creare molte animazioni di testo diverse come lo scorrimento e gli effetti sprite. Questa libreria dipende da MD_MAX72XX che implementa le funzioni hardware della matrice LED.
Ecco alcune funzioni e caratteristiche della libreria:
- Giustificazione del testo a sinistra, destra o centro
- Testo scorrevole con effetti di entrata e uscita
- Controllo dei parametri del display e della velocità di animazione
- Più display virtuali (zone) in ogni stringa di moduli LED
- Supporto per interfaccia hardware SPI
- Font definiti dall’utente e/o sostituzioni di singoli caratteri
- Supporto per display a doppia altezza
- Supporto per mescolare testo e grafica sullo stesso display
Marco lavora su questa libreria da diversi anni e ha scritto ottimi tutorial su his blog. Il codice sorgente e la documentazione delle librerie si trovano qui:
- MD_Parola source code on GitHub
- MD_Parola documentation
- MD_MAX72XX source code on GitHub
- MD_MAX72XX documentation
Puoi installare le librerie tramite il Library Manager dell’IDE Arduino. Vai su Tools > Manage Libraries… oppure premi Ctrl + Shift + I su Windows. Si aprirà il Library Manager che aggiornerà la lista delle librerie installate.

Cerca ‘MD_MAX72XX’ e cerca le librerie di majicDesigns. Seleziona l’ultima versione e clicca su installa. Assicurati di installare sia la libreria MD_MAX72XX che la MD_Parola.

Diversi tipi di display a matrice di LED
Sul mercato sono disponibili molti tipi e dimensioni di display a matrice di LED MAX7219. La libreria MD_MAX72XX supporta quasi tutti questi display, ma devi configurare correttamente la libreria per il tipo di matrice usata.
Di seguito trovi informazioni su come collegare e configurare i display a matrice di LED MAX7219 più comuni che puoi acquistare su Amazon, AliExpress e eBay.

Questo è probabilmente il display MAX7219 più comune che puoi trovare. Di solito è disponibile come matrice LED 8×8 o 8×32 e puoi acquistarli con LED di diversi colori.
Orientamento del modulo e collegamenti
Puoi facilmente collegare insieme più moduli 8×8 o 8×32 per creare un display più grande. Di solito saldo header maschio dritti sul retro dei moduli e li collego con jumper. In questo modo puoi smontarli senza dover dissaldare alcun collegamento.

Il display è orientato con il lato DIN a destra. Nota che il testo serigrafato sul retro del PCB potrebbe essere capovolto in questa orientazione.
DP A B C D E F G
+------------------------+
| 7 6 5 4 3 2 1 0 | D0
CLK <---| 1 | D1 <--- CLK
CS <---| 2 | D2 <--- CS
DOUT <---| 3 | D3 <--- DIN
GND ----| O 4 | D4 ---- GND
VCC ----| O O 5 | D5 ---- VCC
| O O O 6 | D6
| O O O O 7 | D7
+------------------------+
Hardware configuration in Arduino code
When setting up the display in your Arduino code you need to set the HARDWARE_TYPE to FC16_HW and specify the number of devices you have connected. An 8×8 matrix counts as 1 device, so if you want to control an 8×32 module you need to set MAX_DEVICES to 4 (an 8×32 display contains 4 MAX7219 ICs).
// Hardware SPI: #define HARDWARE_TYPE MD_MAX72XX::FC16_HW #define MAX_DEVICES 4 #define CS_PIN 2 // Create a new instance of the MD_MAX72XX class: MD_Parola matrix = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); // For software SPI you also need to specify the DATA_PIN and the CLK_PIN connections: // #define DATA_PIN 3 // #define CLK_PIN 4 // Create a new instance of the MD_MAX72XX class: // MD_Parola matrix = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
Generic 8×8 module

This is an 8×8 module mounted on a green PCB with the MAX7219 IC below the LED matrix. They are characterized by the 5-pin connectors at the short ends of the rectangular PCB.
Module orientation and connections
The generic module needs to be oriented with the MAX7219 IC at the top. You can connect multiple modules together with some short female to female jumper wires. Simply connect all the pins of the DOUT side of the first module to the DIN side of the next module.
C C D G V
L S I N C
K N D C
| | | | |
V V V | |
D7 D6 D5 D4 D3 D2 D1 D0
+------------------------+
| 7 6 5 4 3 2 1 0 | DP
| 1 | A
| 2 | B
| 3 | C
| O 4 | D
| O O 5 | E
| O O O 6 | F
| O O O O 7 | G
+------------------------+
| | | | |
V V V | |
C C D G V
L S O N C
K U D C
T
Hardware configuration in Arduino code
For the generic display modules, you need to set the HARDWARE_TYPE to GENERIC_HW. The rest of the setup and MAX_DEVICES is the same as for the FC-16 modules.
// Hardware SPI: #define HARDWARE_TYPE MD_MAX72XX::GENERIC_HW #define MAX_DEVICES 1 #define CS_PIN 2 // Create a new instance of the MD_MAX72XX class: MD_Parola matrix = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); // For software SPI you also need to specify the DATA_PIN and the CLK_PIN connections: // #define DATA_PIN 3 // #define CLK_PIN 4 // Create a new instance of the MD_MAX72XX class: // MD_Parola matrix = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
Arduino example codes
Below you will find several example codes that cover the basic functions of the MD_Parola Arduino library. After each example I explain how the code works so you should be able to modify it to suit your needs. You can also find more examples when you go to File > Examples > MD_Parola in the Arduino IDE, but they don't include any explanation so they might be a bit hard to follow.
Basic Arduino example code to print text
With the example code below you can print text on the display without any animations.
You can upload the example code to your Arduino via the Arduino IDE. For this tutorial, I used this standard 8x32 LED dot matrix display (Find at Amazon) but you can use other types and/or sizes as well (see code explanation below).
/* Basic example code for MAX7219 LED dot matrix display
with Arduino. More info: https://www.makerguides.com */
#include "MD_Parola.h"
#include "MD_MAX72xx.h"
#include "SPI.h"
// Define hardware type, size, and output pins:
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 3
// Create a new instance of the MD_Parola class with hardware SPI connection:
MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Setup for software SPI:
// #define DATAPIN 2
// #define CLK_PIN 4
// MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
void setup() {
// Intialize the object:
myDisplay.begin();
// Set the intensity (brightness) of the display (0-15):
myDisplay.setIntensity(0);
// Clear the display:
myDisplay.displayClear();
}
void loop() {
myDisplay.setTextAlignment(PA_CENTER);
myDisplay.print("Center");
delay(2000);
myDisplay.setTextAlignment(PA_LEFT);
myDisplay.print("Left");
delay(2000);
myDisplay.setTextAlignment(PA_RIGHT);
myDisplay.print("Right");
delay(2000);
myDisplay.setTextAlignment(PA_CENTER);
myDisplay.setInvert(true);
myDisplay.print("Invert");
delay(2000);
myDisplay.setInvert(false);
myDisplay.print(1234);
delay(2000);
}
You should see the following output:

How the code works
The first step is to include all the required Arduino libraries. As I mentioned before, the MD_MAX72XX library implements the hardware functions of the LED matrix and the MD_Parola library the text effects. You will also need to include the SPI library, which comes pre-installed in the Arduino IDE. This library is used for the Serial Peripheral Interface communication between the display and the Arduino.
#include "MD_Parola.h" #include "MD_MAX72xx.h" #include "SPI.h"
Next, we need to specify which hardware we are using. Since I used a standard 8×32 display (also known as FC-16), I set the HARDWARE_TYPE to FC16_HW. The number of MAX7219 ICs in an 8×32 display is 4 so I set MAX_DEVICES to 4. Lastly, I defined to which pin the CS pin of the display is connected (output pin 3 in this case). See the section about display types for a more detailed explanation on how to set up other types of displays.
The statement #define is used to give a name to a constant value. The compiler will replace any references to this constant with the defined value when the program is compiled. So everywhere you mention CS_PIN, the compiler will replace it with the value 3 when the program is compiled.
// Define hardware type, size, and output pins: #define HARDWARE_TYPE MD_MAX72XX::FC16_HW #define MAX_DEVICES 4 #define CS_PIN 3
After this, a new instance of the MD_Parola class is created with the function MD_Parola(). This function needs three parameters, the first is the hardware type, the second the CS pin, and the third the number of max devices connected.
Note that I have called the MD_Parola object 'myDisplay' but you can use other names as well. You will need to change ‘myDisplay’ to the new name in the rest of the sketch.
When you want to use software SPI instead of hardware SPI, you also need to define the data and clock output pins and pass these as parameters when setting up the display object.
// Create a new instance of the MD_Parola class with hardware SPI connection: MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); // Setup for software SPI: // #define DATAPIN 2 // #define CLK_PIN 4 // MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
In the setup section of the code, we first initialize the object with the function begin(). The brightness of the display can be set with the function setIntensity(). You can enter a value between 0 (minimum brightness) and 15 (maximum brightness). The display is cleared with the function displayClear().
void setup() {
// Intialize the object:
myDisplay.begin();
// Set the intensity (brightness) of the display (0-15):
myDisplay.setIntensity(0);
// Clear the display:
myDisplay.displayClear();
}
In the loop section of the code, we first set the alignment of the text to be printed with the function setTextAlignment(). You can left, center, and right align the text with PA_LEFT, PA_CENTER, and PA_RIGHT respectively.
Next, the string ‘Center’ is printed with myDisplay.print("Center"). Note that you need to place quotation marks (” “) around the text since we are printing a text string. When you want to print numbers, no quotation marks are necessary. For example myDisplay.print(1234). You can invert the display, i.e. LEDs normally on turn off and vice versa, with myDisplay.setInvert(true).
void loop() {
myDisplay.setTextAlignment(PA_CENTER);
myDisplay.print("Center");
delay(2000);
myDisplay.setTextAlignment(PA_LEFT);
myDisplay.print("Left");
delay(2000);
myDisplay.setTextAlignment(PA_RIGHT);
myDisplay.print("Right");
delay(2000);
myDisplay.setTextAlignment(PA_CENTER);
myDisplay.setInvert(true);
myDisplay.print("Invert");
delay(2000);
myDisplay.setInvert(false);
myDisplay.print(1234);
delay(2000);
}
Scrolling text Arduino example code
When you want to print a message on a dot matrix display, you will often find that the display is too small to fit the entire message. The solution is in the MD_Parola library, which makes it super easy to create scrolling text effects. In the following examples, I will show you how to set this up, as well as how to use some of the other available text effects.

You can copy the code below by clicking on the button in the top right corner of the code field.
/* Example code for scrolling text effect on
MAX7219 LED dot matrix display with Arduino.
More info: https://www.makerguides.com */
#include "MD_Parola.h"
#include "MD_MAX72xx.h"
#include "SPI.h"
// Define hardware type, size, and output pins:
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 3
// Create a new instance of the MD_Parola class with hardware SPI connection:
MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Setup for software SPI:
// #define DATA_PIN 2
// #define CLK_PIN 4
// MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
void setup() {
// Intialize the object:
myDisplay.begin();
// Set the intensity (brightness) of the display (0-15):
myDisplay.setIntensity(0);
// Clear the display:
myDisplay.displayClear();
myDisplay.displayText("Scrolling text", PA_CENTER, 100, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
}
void loop() {
if (myDisplay.displayAnimate()) {
myDisplay.displayReset();
}
}
How the code works
The first part of the code up to the end of the setup section is exactly the same as in the previous example. At the end of the setup section, we specify how we want to display the text with the function displayText(pText, align, speed, pause, effectIn, effectOut). This function takes 5 arguments.
The first parameter is the text string, in this case "Scrolling text".
The second argument sets the alignment of the text during the optional pause. You can use the same alignment options as in the previous example, i.e. PA_CENTER, PA_LEFT, or PA_RIGHT.
The third and fourth arguments set the speed of the animation and pause time respectively. The speed of the display is the time in milliseconds between animation frames. The lower this time the faster the animation. If you want to pause the text in between the in and out animation, you can set the pause time in milliseconds. I set it to zero so the text scrolls continuously.
Next, the in and out effects are specified. In this case I used PA_SCROLL_LEFT for both. See the example below for other text effects.
myDisplay.displayText("Scrolling text", PA_CENTER, 100, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
In the loop section, you only need two functions to create a scrolling text display.
First, we use the function displayAnimate() in an if statement. This function animates the display using the currently specified text and animation parameters and returns true when the animation has finished. When the animation has finished, we reset the display with the function displayReset() so the text is displayed in a loop.
void loop() {
if (myDisplay.displayAnimate()) {
myDisplay.displayReset();
}
}
Other text effects
The library includes several other text effects that you can use:
- PA_PRINT,
- PA_SCAN_HORIZ,
- PA_SCROLL_LEFT,
- PA_WIPE,
- PA_SCROLL_UP_LEFT,
- PA_SCROLL_UP,
- PA_OPENING_CURSOR,
- PA_GROW_UP,
- PA_MESH,
- PA_SCROLL_UP_RIGHT,
- PA_BLINDS,
- PA_CLOSING,
- PA_RANDOM,
- PA_GROW_DOWN,
- PA_SCAN_VERT,
- PA_SCROLL_DOWN_LEFT,
- PA_WIPE_CURSOR,
- PA_DISSOLVE,
- PA_OPENING,
- PA_CLOSING_CURSOR,
- PA_SCROLL_DOWN_RIGHT,
- PA_SCROLL_RIGHT,
- PA_SLICE,
- PA_SCROLL_DOWN
The example code below steps through the different effect so you can see what they look like.
/*Example code for scrolling text and other text effects
on MAX7219 LED dot matrix display with Arduino.
More info: https://www.makerguides.com */
#include "MD_Parola.h"
#include "MD_MAX72xx.h"
#include "SPI.h"
int i = 0;
textEffect_t texteffect[] =
{
PA_PRINT,
PA_SCAN_HORIZ,
PA_SCROLL_LEFT,
PA_WIPE,
PA_SCROLL_UP_LEFT,
PA_SCROLL_UP,
PA_OPENING_CURSOR,
PA_GROW_UP,
PA_MESH,
PA_SCROLL_UP_RIGHT,
PA_BLINDS,
PA_CLOSING,
PA_RANDOM,
PA_GROW_DOWN,
PA_SCAN_VERT,
PA_SCROLL_DOWN_LEFT,
PA_WIPE_CURSOR,
PA_DISSOLVE,
PA_OPENING,
PA_CLOSING_CURSOR,
PA_SCROLL_DOWN_RIGHT,
PA_SCROLL_RIGHT,
PA_SLICE,
PA_SCROLL_DOWN
};
// Define hardware type, size, and output pins:
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 3
// Create a new instance of the MD_Parola class with hardware SPI connection:
MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Setup for software SPI:
// #define DATA_PIN 2
// #define CLK_PIN 4
// MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
void setup() {
myDisplay.begin();
myDisplay.setIntensity(0);
myDisplay.setTextAlignment(PA_CENTER);
myDisplay.setPause(1000);
myDisplay.setSpeed(100);
myDisplay.displayClear();
}
void loop() {
if (myDisplay.displayAnimate()) {
if (i < sizeof(texteffect)) {
i++;
}
else {
i = 0;
}
myDisplay.displayText("Hello", myDisplay.getTextAlignment(),
myDisplay.getSpeed(), myDisplay.getPause(),
texteffect[i], texteffect[i]);
myDisplay.displayReset();
}
}
Text sprites
A relatively new function of the MD_Parola library is animated text sprites. In computer graphics, a sprite is a two-dimensional bitmap that is integrated into a larger scene (in this case, the matrix display).
A sprite is made up of a number of frames that run sequentially to make the animation on the display. Once the animation reaches the last frame it restarts from the first frame.
Note that I used an 8×64 matrix display for this example by connecting two 8×32 displays together (MAX_DEVICES is set to 8).
/*Example code for sprite text effect on
MAX7219 LED dot matrix display with Arduino.
More info: https://www.makerguides.com */
#include "MD_Parola.h"
#include "MD_MAX72xx.h"
#include "SPI.h"
// Define hardware type, size, and output pins:
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 8
#define CS_PIN 3
// Create a new instance of the MD_Parola class with hardware SPI connection:
MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Setup for software SPI:
// #define DATA_PIN 2
// #define CLK_PIN 4
// MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Sprite definitions:
const uint8_t F_PMAN1 = 6;
const uint8_t W_PMAN1 = 8;
const uint8_t PROGMEM pacman1[F_PMAN1 * W_PMAN1] = // gobbling pacman animation
{
0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c,
0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c,
};
const uint8_t F_PMAN2 = 6;
const uint8_t W_PMAN2 = 18;
const uint8_t PROGMEM pacman2[F_PMAN2 * W_PMAN2] = // pacman pursued by a ghost
{
0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
};
const uint8_t F_WAVE = 14;
const uint8_t W_WAVE = 14;
const uint8_t PROGMEM wave[F_WAVE * W_WAVE] = // triangular wave / worm
{
0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10,
0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20,
0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40,
0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10,
0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08,
0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04,
0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02,
0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02,
0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04,
0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08,
};
const uint8_t F_ROLL1 = 4;
const uint8_t W_ROLL1 = 8;
const uint8_t PROGMEM roll1[F_ROLL1 * W_ROLL1] = // rolling square
{
0xff, 0x8f, 0x8f, 0x8f, 0x81, 0x81, 0x81, 0xff,
0xff, 0xf1, 0xf1, 0xf1, 0x81, 0x81, 0x81, 0xff,
0xff, 0x81, 0x81, 0x81, 0xf1, 0xf1, 0xf1, 0xff,
0xff, 0x81, 0x81, 0x81, 0x8f, 0x8f, 0x8f, 0xff,
};
const uint8_t F_ROLL2 = 4;
const uint8_t W_ROLL2 = 8;
const uint8_t PROGMEM roll2[F_ROLL2 * W_ROLL2] = // rolling octagon
{
0x3c, 0x4e, 0x8f, 0x8f, 0x81, 0x81, 0x42, 0x3c,
0x3c, 0x72, 0xf1, 0xf1, 0x81, 0x81, 0x42, 0x3c,
0x3c, 0x42, 0x81, 0x81, 0xf1, 0xf1, 0x72, 0x3c,
0x3c, 0x42, 0x81, 0x81, 0x8f, 0x8f, 0x4e, 0x3c,
};
const uint8_t F_LINES = 3;
const uint8_t W_LINES = 8;
const uint8_t PROGMEM lines[F_LINES * W_LINES] = // spaced lines
{
0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
};
const uint8_t F_ARROW1 = 3;
const uint8_t W_ARROW1 = 10;
const uint8_t PROGMEM arrow1[F_ARROW1 * W_ARROW1] = // arrow fading to center
{
0x18, 0x3c, 0x7e, 0xff, 0x7e, 0x00, 0x00, 0x3c, 0x00, 0x00,
0x18, 0x3c, 0x7e, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x18, 0x00,
0x18, 0x3c, 0x7e, 0xff, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x18,
};
const uint8_t F_ARROW2 = 3;
const uint8_t W_ARROW2 = 9;
const uint8_t PROGMEM arrow2[F_ARROW2 * W_ARROW2] = // arrow fading to outside
{
0x18, 0x3c, 0x7e, 0xe7, 0x00, 0x00, 0xc3, 0x00, 0x00,
0x18, 0x3c, 0x7e, 0xe7, 0xe7, 0x00, 0x00, 0x81, 0x00,
0x18, 0x3c, 0x7e, 0xe7, 0x00, 0xc3, 0x00, 0x00, 0x81,
};
const uint8_t F_SAILBOAT = 1;
const uint8_t W_SAILBOAT = 11;
const uint8_t PROGMEM sailboat[F_SAILBOAT * W_SAILBOAT] = // sail boat
{
0x10, 0x30, 0x58, 0x94, 0x92, 0x9f, 0x92, 0x94, 0x98, 0x50, 0x30,
};
const uint8_t F_STEAMBOAT = 2;
const uint8_t W_STEAMBOAT = 11;
const uint8_t PROGMEM steamboat[F_STEAMBOAT * W_STEAMBOAT] = // steam boat
{
0x10, 0x30, 0x50, 0x9c, 0x9e, 0x90, 0x91, 0x9c, 0x9d, 0x90, 0x71,
0x10, 0x30, 0x50, 0x9c, 0x9c, 0x91, 0x90, 0x9d, 0x9e, 0x91, 0x70,
};
const uint8_t F_HEART = 5;
const uint8_t W_HEART = 9;
const uint8_t PROGMEM heart[F_HEART * W_HEART] = // beating heart
{
0x0e, 0x11, 0x21, 0x42, 0x84, 0x42, 0x21, 0x11, 0x0e,
0x0e, 0x1f, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x1f, 0x0e,
0x0e, 0x1f, 0x3f, 0x7e, 0xfc, 0x7e, 0x3f, 0x1f, 0x0e,
0x0e, 0x1f, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x1f, 0x0e,
0x0e, 0x11, 0x21, 0x42, 0x84, 0x42, 0x21, 0x11, 0x0e,
};
const uint8_t F_INVADER = 2;
const uint8_t W_INVADER = 10;
const uint8_t PROGMEM invader[F_INVADER * W_INVADER] = // space invader
{
0x0e, 0x98, 0x7d, 0x36, 0x3c, 0x3c, 0x36, 0x7d, 0x98, 0x0e,
0x70, 0x18, 0x7d, 0xb6, 0x3c, 0x3c, 0xb6, 0x7d, 0x18, 0x70,
};
const uint8_t F_ROCKET = 2;
const uint8_t W_ROCKET = 11;
const uint8_t PROGMEM rocket[F_ROCKET * W_ROCKET] = // rocket
{
0x18, 0x24, 0x42, 0x81, 0x99, 0x18, 0x99, 0x18, 0xa5, 0x5a, 0x81,
0x18, 0x24, 0x42, 0x81, 0x18, 0x99, 0x18, 0x99, 0x24, 0x42, 0x99,
};
const uint8_t F_FBALL = 2;
const uint8_t W_FBALL = 11;
const uint8_t PROGMEM fireball[F_FBALL * W_FBALL] = // fireball
{
0x7e, 0xab, 0x54, 0x28, 0x52, 0x24, 0x40, 0x18, 0x04, 0x10, 0x08,
0x7e, 0xd5, 0x2a, 0x14, 0x24, 0x0a, 0x30, 0x04, 0x28, 0x08, 0x10,
};
const uint8_t F_CHEVRON = 1;
const uint8_t W_CHEVRON = 9;
const uint8_t PROGMEM chevron[F_CHEVRON * W_CHEVRON] = // chevron
{
0x18, 0x3c, 0x66, 0xc3, 0x99, 0x3c, 0x66, 0xc3, 0x81,
};
const uint8_t F_WALKER = 5;
const uint8_t W_WALKER = 7;
const uint8_t PROGMEM walker[F_WALKER * W_WALKER] = // walking man
{
0x00, 0x48, 0x77, 0x1f, 0x1c, 0x94, 0x68,
0x00, 0x90, 0xee, 0x3e, 0x38, 0x28, 0xd0,
0x00, 0x00, 0xae, 0xfe, 0x38, 0x28, 0x40,
0x00, 0x00, 0x2e, 0xbe, 0xf8, 0x00, 0x00,
0x00, 0x10, 0x6e, 0x3e, 0xb8, 0xe8, 0x00,
};
void setup() {
myDisplay.begin();
myDisplay.setIntensity(0);
myDisplay.displayClear();
myDisplay.setSpriteData(pacman2, W_PMAN2, F_PMAN2, pacman2, W_PMAN2, F_PMAN2);
myDisplay.displayText("Parola sprites", PA_CENTER, 50, 1000, PA_SPRITE, PA_SPRITE);
}
void loop() {
if (myDisplay.displayAnimate()) {
myDisplay.displayReset();
}
}
How the code works
After setting up the display like before, the text sprites are defined.
Two constants are used to define the sprite, one for the width (number of bytes) data for one sprite and the other for the number of frames contained in the animation. The total number of bytes required is the width * number of frames. Note that the sprite data is stored in PROGMEM to save RAM space.
Each row of the array is made up of hexadecimal numbers that set which LEDs need to light up in each column of the sprite.
The example includes many different sprite definitions, which you can also find in one of the examples that come with the library.
// Sprite definitions:
const uint8_t F_PMAN1 = 6;
const uint8_t W_PMAN1 = 8;
const uint8_t PROGMEM pacman1[F_PMAN1 * W_PMAN1] = // gobbling pacman animation
{
0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c,
0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c,
};
In the setup, the function setSpriteData(inData, inWidth, inFrames, outData, outWidth, outFrames) is used to set up user data needed so that the library can display the sprite when the PA_SPRITE animation type is selected in the displayText() function.
You can select any of the predefined sprites, in this case I used pacman2 (pacman pursued by a ghost).
myDisplay.setSpriteData(pacman2, W_PMAN2, F_PMAN2, pacman2, W_PMAN2, F_PMAN2);
myDisplay.displayText("Parola sprites", PA_CENTER, 50, 1000, PA_SPRITE, PA_SPRITE);
The loop section is the same as before.
Conclusion
In this article, I have shown you how you can use a MAX7219 LED dot matrix display with Arduino. We looked at the basics of printing text, scrolling text, other text effects, and text sprites. There still are some less frequently used functions in the MD_Parola library that I haven't covered in this tutorial but you can check those out in the MD_Parola documentation on GitHub.
We also haven't talked about the fact that the MD_Parola library can divide a display into multiple zones that run different animations. Read the post Coordinate Parola Zone Animations on MAX7219 Display and Parola A to Z – Multi Zone Displays for more information on that.
Finally, if you want to chain different animation, switch between different animations by pressing buttons, or regulate the speed of the animation via an analog input have a look at the Control Parola Animations on MAX7219 LED Display tutorial, where we cover these use cases.
If you have any questions, feel free to ask them in the comment section.
Happy tinkering!

