Skip to Content

MAX7219 LED-Punktmatrix-Display Arduino Tutorial

MAX7219 LED-Punktmatrix-Display Arduino Tutorial

In diesem Tutorial lernst du, wie du ein MAX7219 LED-Punktmatrix-Display mit Arduino steuerst. Ich habe ein Schaltbild und viele Beispielcodes beigefügt! Der Code in diesem Tutorial kann für 8×8, 8×32 und sogar größere Displays verwendet werden.

Für dieses Tutorial verwende ich das MD_Parola in Kombination mit der MD_MAX72XX Arduino-Bibliothek. Diese Bibliotheken machen das Anzeigen von Lauftexten und anderen Animationen super einfach. Im ersten Teil dieses Artikels erkläre ich die Grundlagen des Textdrucks auf dem Display. Danach schauen wir uns Lauftexte und andere Textanimationen an. Zum Schluss zeige ich dir, wie du Text-Sprites verwenden kannst.

Wenn du mehr über dieses oder andere Displaytypen erfahren möchtest, schau dir die folgenden Artikel an:

Empfohlene Artikel

Materialien

Hardware-Komponenten

8×32 MAX7219 LED dot matrix display × 1 Amazon
8x8-MAX7219-LED-dot-matrix-display8×8 MAX7219 LED dot matrix display (Alternative) × 1 Amazon
generic-MAX7219-8x8-LED-dot-matrix-displayGeneric 8×8 MAX7219 LED dot matrix display (Alternative) × 1 Amazon
Arduino Uno Rev 3Arduino Uno Rev3 × 1 Amazon
Jumper wires  (männlich zu weiblich) × 4 Amazon
USB cable type A/B × 1 Amazon
Male headers ~ 20 Amazon
Jumpers ~ 20 Amazon

Software

Arduino IDEArduino IDE

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.

Über den MAX7219 LED-Treiber

Der MAX7219 LED-Treiber kann verwendet werden, um 7-Segment-Anzeigen mit bis zu 8 Stellen, Balkendiagrammanzeigen oder 64 einzelne LEDs zu steuern. Der Treiber kommuniziert mit dem Arduino über SPI, sodass du nur drei Kabel benötigst, um das Display zu steuern.

Da der MAX7219 maximal 64 LEDs steuern kann, ist die maximale Größe eines Punktmatrix-Displays, das er ansteuern kann, 8×8 Pixel. Du kannst jedoch mehrere Treiber und Matrizen kaskadieren und so problemlos viel größere Displays wie 8×32, 8×64 oder noch größere steuern. Trotzdem benötigst du nur drei Kabel, um alle ICs zu steuern, sodass nur wenige I/O-Pins des Arduino benötigt werden.

Unten findest du die Spezifikationen eines typischen MAX7219 8×32 LED-Punktmatrix-Displays.

Spezifikationen des MAX7219 LED-Punktmatrix-Displays

Betriebsspannung 5 V
Display-Treiber MAX7219 x 4
Helligkeitsstufen 16
Display-Abmessungen 32 x 128 x 15 mm
Pixel 8×32, ⌀ 3 mm
Kosten Check price

Weitere Informationen findest du im Datenblatt:

Fast alle Displays, die ich bisher verwendet habe, nutzten eine 1088AS Typ 8×8 LED-Matrix. Ein Datenblatt eines Herstellers findest du unten:

Wie man das Punktmatrix-Display mit dem Arduino verbindet

Der MAX7219 LED-Display-Treiber kommuniziert mit dem Arduino über SPI (Serial Peripheral Interface). Bei einer SPI-Schnittstelle gibt es immer ein Master-Gerät (den Arduino), das die Peripheriegeräte (auch als Slaves bezeichnet) steuert. Du kannst das Display entweder über die Hardware-SPI-Schnittstelle des AVR-Mikrocontrollers des Arduino oder über drei beliebige digitale Pins (Software-SPI) steuern.

Die Hardware-SPI-Pins (MOSI, MISO und SCK) befinden sich an einer festen Position auf jedem Arduino-Board. Diese Schnittstelle ist schneller als Software-SPI, aber du musst die folgenden festen Ausgangspins verwenden:

Hardware-SPI-Pin-Belegungen

Board MOSI MISO SCK Level
Arduino Uno 11 oder ICSP-4 12 oder ICSP-1 13 oder ICSP-3 5 V
Arduino Mega 51 oder ICSP-4 50 oder ICSP-1 52 oder 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
Hardware-SPI-Pin-Belegungen auf verschiedenen Arduino-Boards.

Beachte, dass die MOSI-, MISO- und SCK-Pins auch an einer festen physischen Position am 6-poligen ICSP-Header liegen:

ICSPHeader
Quelle: Arduino.cc

Um MAX7219-Displays zu steuern, musst du nur drei Verbindungen herstellen:

  • MOSI (Master Out Slave In) verbunden mit DIN – Die Master-Leitung, die Daten an die Peripheriegeräte sendet.
  • SCK (Serial Clock) verbunden mit CLK – Die Taktsignale, die die Datenübertragung synchronisieren und vom Master erzeugt werden.
  • SS (Slave Select) verbunden mit CS – Der Pin an jedem Gerät, den der Master verwendet, um bestimmte Geräte zu aktivieren oder zu deaktivieren.

Du kannst mehrere Displays kaskadieren, um ein großes Display zu erstellen, indem du DOUT des ersten Displays mit DIN des nächsten verbindest. VCC, GND, CLK und CS werden zwischen allen Displays gemeinsam genutzt.

Du kannst jeden digitalen Pin des Arduino für den SS/CS-Pin wählen. Beachte, dass ich in diesem Tutorial Pin 3 verwendet habe (siehe Tabelle unten).

Das folgende Schaltbild zeigt, wie du das MAX7219 LED-Punktmatrix-Display mit dem Arduino verbindest. Beachte, dass du bei Verwendung der MD_Parola-Bibliothek das Display mit dem DIN-Anschluss rechts ausrichten musst, sonst wird der Text auf dem Kopf angezeigt. Weitere Informationen findest du im Abschnitt unten.

MAX7219-LED-dot-matrix-display-with-Arduino-Uno-wiring-diagram-schematic-pinout
Schaltbild des MAX7219 LED-Punktmatrix-Displays mit Arduino

Die Verbindungen sind auch in der folgenden Tabelle aufgeführt:

Anschlüsse des MAX7219 LED-Punktmatrix-Displays

MAX7219 Display Arduino
VCC 5 V
GND GND
DIN 11 (MOSI)
CS 3 (SS)
CLK 13 (SCK)

Wenn du stattdessen Software-SPI verwenden möchtest, kannst du DIN, CS und CLK an beliebige digitale Pins des Arduino anschließen. Du musst nur die Pinnummern im Setup des Arduino-Codes angeben (siehe Beispiele unten).

Stromversorgung

Die maximale Leistung, die der Arduino Uno bei USB-Stromversorgung sicher liefern kann, beträgt etwa 400 mA bei 5 V. Wenn du ein großes Display steuern möchtest, wird daher empfohlen, eine externe Stromversorgung zu verwenden.

Installation der MD_Parola- und MD_MAX72XX-Arduino-Bibliotheken

Zur Steuerung des MAX7219-Displays verwenden wir zwei großartige Arduino-Bibliotheken von Marco Colli von MajicDesigns. Die MD_Parola-Bibliothek kann viele verschiedene Textanimationen wie Lauftexte und Sprite-Text-Effekte erstellen. Diese Bibliothek hängt von der MD_MAX72XX-Bibliothek ab, die die Hardwarefunktionen der LED-Matrix implementiert.

Das sind einige Funktionen und Merkmale der Bibliothek:

  • Linksbündige, rechtsbündige oder zentrierte Textausrichtung
  • Textlauf mit Ein- und Ausblendeffekten
  • Steuerung von Anzeigeparametern und Animationsgeschwindigkeit
  • Mehrere virtuelle Displays (Zonen) in jeder LED-Modulkette
  • Unterstützung der Hardware-SPI-Schnittstelle
  • Benutzerdefinierte Schriftarten und/oder einzelne Zeichensubstitutionen
  • Unterstützung für doppelt hohe Displays
  • Unterstützung für die Kombination von Text und Grafik auf demselben Display

Marco arbeitet seit mehreren Jahren an dieser Bibliothek und hat einige ausgezeichnete Tutorials zu his blog geschrieben. Den Quellcode und die Dokumentation der Bibliotheken findest du hier:

Du kannst die Bibliotheken über den Library Manager der Arduino IDE installieren. Gehe zu Tools > Manage Libraries… oder drücke Strg + Shift + I unter Windows. Der Library Manager öffnet sich und aktualisiert die Liste der installierten Bibliotheken.

Installing an Arduino library step 1 open Library Manager
Bibliotheken verwalten

Suche nach ‚MD_MAX72XX‘ und suche die Bibliotheken von majicDesigns. Wähle die neueste Version aus und klicke auf Installieren. Achte darauf, sowohl die MD_MAX72XX- als auch die MD_Parola-Bibliothek zu installieren.

Installing an Arduino library step 2 MD_Parola and MD_MAX72XX
Bibliotheksmanager

Verschiedene Arten von LED-Punktmatrix-Displays

Viele verschiedene Typen und Größen von MAX7219 LED-Punktmatrix-Displays sind auf dem Markt erhältlich. Die MD_MAX72XX-Bibliothek unterstützt fast alle diese Displays, aber du musst die Bibliothek korrekt für den verwendeten Matrizen-Typ konfigurieren.

Unten findest du Informationen zum Anschluss und zur Konfiguration der gängigsten MAX7219 LED-Punktmatrix-Displays, die du auf Amazon, AliExpress und eBay kaufen kannst.

MAX7219 Dot LED Matrix Display (Find at Amazon)

Dies ist wahrscheinlich das am häufigsten anzutreffende MAX7219-Display. Es ist typischerweise als 8×8 oder 8×32 LED-Matrix erhältlich und du kannst sie mit LEDs in verschiedenen Farben kaufen.

Modulorientierung und Anschlüsse

Du kannst problemlos mehrere 8×8- oder 8×32-Module zusammenschließen, um ein größeres Display zu erstellen. Ich löte normalerweise gerade Stiftleisten auf die Rückseite der Module und verbinde sie mit Jumpern. So kannst du sie auseinandernehmen, ohne Verbindungen auslöten zu müssen.

Jumper (Find at Amazon)

Das Display ist so ausgerichtet, dass die DIN-Seite rechts ist. Beachte, dass der auf der Rückseite der Platine aufgedruckte Text in dieser Ausrichtung möglicherweise auf dem Kopf steht.

           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

MAX7219 8x8 Module (Find at Amazon)

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:

Text alignment

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.

Scrolling text

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!