Community project

MAX7219 Scrolling Display

Arduino
Photo of MAX7219 Scrolling Display
Generated with AI

Flavio Del Fiol Costa

Last updated August 11, 2026

This guide builds a scrolling text display using five chained MAX7219 8x8 LED matrix modules controlled by an Arduino Uno. The result is a 40×8 pixel display capable of smooth horizontal text animation, perfect for signs, notifications, or information panels.

The guide includes a complete wiring diagram showing how to connect the DIN, CLK, and CS pins from the Arduino to the matrix chain, a full parts list, and ready-to-use firmware with a built-in font renderer. Assembly takes about 30 minutes and requires only basic soldering; the included code handles all the timing and pixel-by-pixel rendering needed to make text scroll smoothly across the display.

Wiring diagram

Wiring diagram for MAX7219 Scrolling Display

Gather all the parts

QtyComponent
5

MAX7219 8x8 LED matrix chain

5 × matriz LED 8×8 com MAX7219

Cinco matrizes LED 8x8 genéricas com controlador MAX7219, montadas lado a lado e encadeadas por DOUT para DIN.

Assemble it in 4 steps

1. Monte a faixa de cinco matrizes

Coloque os cinco módulos MAX7219 lado a lado, formando uma faixa de 40 × 8 LEDs. Depois de encadear as placas, vire a faixa inteira 180° antes de fixá-la. Não gire uma placa isoladamente.

  • Todos os módulos devem manter a mesma orientação relativa.
  • O firmware compensa a montagem do conjunto girado.

2. Encadeie os dados entre os módulos

Ligue DOUT do módulo 1 ao DIN do módulo 2, DOUT do 2 ao DIN do 3, DOUT do 3 ao DIN do 4 e DOUT do 4 ao DIN do 5. Somente o DIN do módulo 1 recebe dados do Arduino.

  • Distribua CLK, CS/LOAD, 5 V e GND em paralelo para todos os módulos.
  • Não conecte todos os pinos DIN ao D11: isso repete a imagem, em vez de formar uma faixa única.

3. Ligue o painel ao Arduino Uno

Conecte D11 ao DIN do primeiro módulo, D13 ao CLK de todos os módulos, D10 ao CS/LOAD de todos, 5 V ao VCC e GND ao GND.

  • Mantenha os fios de alimentação curtos e una todos os GND.
  • O ESP-01 não é usado neste firmware; mantenha-o desconectado durante este teste.

4. Teste o texto rolante

Alimente o Uno pelo USB e use o botão Deploy. O painel exibirá continuamente a mensagem "OLA! SCROLLER PRONTO" rolando pela faixa.

  • O brilho inicial está no nível 3 e pode ser ajustado depois no código.
  • Se houver pixels instáveis, queda de brilho ou reinicializações, use uma fonte externa regulada de 5 V para as matrizes e conecte o GND dela ao GND do Uno.

Review all connections

1. Connections between "matrix_chain" and "Arduino"

Functionmatrix_chainArduino
powerVCC5V
groundGNDGND
spiCSGPIO 10
spiCLKGPIO 13
digitalDataGPIO 11

Deploy the firmware

#include <Arduino.h>
#include <MD_MAX72xx.h>
#include <SPI.h>

// Cinco matrizes MAX7219 genericas, em uma faixa de 40 x 8 pixels.

// Forward declarations
int glyphIndex(char c);
bool messagePixel(int logicalX, int y);
void drawFrame(int offset);

const uint8_t DIN_PIN = 11;
const uint8_t CLK_PIN = 13;
const uint8_t CS_PIN = 10;
const uint8_t MODULE_COUNT = 5;
const uint8_t PANEL_WIDTH = MODULE_COUNT * 8;
const uint16_t SCROLL_SPEED_MS = 30;

MD_MAX72XX matrix(MD_MAX72XX::GENERIC_HW, DIN_PIN, CLK_PIN, CS_PIN, MODULE_COUNT);
const char MESSAGE[] = "  OLA! SCROLLER PRONTO  ";

// Cada glifo possui 5 colunas; o bit 0 de cada coluna e a linha superior.
const uint8_t FONT[][5] = {
  {0x00,0x00,0x00,0x00,0x00},
  {0x00,0x00,0x5f,0x00,0x00},
  {0x7e,0x09,0x09,0x09,0x7e},
  {0x7f,0x49,0x49,0x49,0x36},
  {0x3e,0x41,0x41,0x41,0x22},
  {0x7f,0x41,0x41,0x22,0x1c},
  {0x7f,0x49,0x49,0x49,0x41},
  {0x7f,0x09,0x09,0x09,0x01},
  {0x3e,0x41,0x49,0x49,0x7a},
  {0x7f,0x08,0x08,0x08,0x7f},
  {0x00,0x41,0x7f,0x41,0x00},
  {0x20,0x40,0x41,0x3f,0x01},
  {0x7f,0x08,0x14,0x22,0x41},
  {0x7f,0x40,0x40,0x40,0x40},
  {0x7f,0x02,0x0c,0x02,0x7f},
  {0x7f,0x04,0x08,0x10,0x7f},
  {0x3e,0x41,0x41,0x41,0x3e},
  {0x7f,0x09,0x09,0x09,0x06},
  {0x3e,0x41,0x51,0x21,0x5e},
  {0x7f,0x09,0x19,0x29,0x46},
  {0x46,0x49,0x49,0x49,0x31},
  {0x01,0x01,0x7f,0x01,0x01},
  {0x3f,0x40,0x40,0x40,0x3f},
  {0x1f,0x20,0x40,0x20,0x1f},
  {0x7f,0x20,0x18,0x20,0x7f},
  {0x63,0x14,0x08,0x14,0x63},
  {0x07,0x08,0x70,0x08,0x07},
  {0x61,0x51,0x49,0x45,0x43}
};

int glyphIndex(char c) {
  if (c == ' ') return 0;
  if (c == '!') return 1;
  if (c >= 'A' && c <= 'Z') return c - 'A' + 2;
  return 0;
}

bool messagePixel(int logicalX, int y) {
  if (logicalX < 0) return false;
  int character = logicalX / 6;
  int column = logicalX % 6;
  if (character >= (int)strlen(MESSAGE) || column == 5) return false;
  return FONT[glyphIndex(MESSAGE[character])][column] & (1 << y);
}

void drawFrame(int offset) {
  // Uma escrita por coluna evita apagar o painel e reduz o flicker.
  for (int x = 0; x < PANEL_WIDTH; x++) {
    uint8_t columnData = 0;
    for (int y = 0; y < 8; y++) {
      if (messagePixel(x + offset, y)) {
        // Compensa a montagem fisica do conjunto girado 180 graus.
        columnData |= (1 << (7 - y));
      }
    }
    matrix.setColumn(x, columnData);
  }
}

void setup() {
  matrix.begin();
  matrix.control(MD_MAX72XX::INTENSITY, 3);
}

void loop() {
  static int offset = 0;
  static unsigned long lastFrame = 0;
  const int messageWidth = strlen(MESSAGE) * 6;
  unsigned long now = millis();

  if (now - lastFrame >= SCROLL_SPEED_MS) {
    lastFrame = now;
    drawFrame(offset);
    offset++;
    if (offset >= messageWidth) offset = -PANEL_WIDTH;
  }
}

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik