32×8 matrix/Making it say something/09. Scrolling a message
Making it say something · 09 of 10

Scrolling a message

Thirty-two columns holds about four characters. Anything longer has to move, and the number in the middle of displayText is not a speed — it is the delay between frames, one pixel each.

Why it has to move

Thirty-two columns is four characters in a fixed-width font and five or six in a proportional one. A sentence does not fit, and there is no smaller font worth having — eight pixels tall is already the whole display.

So the message moves through the window, one pixel at a time.

One pixel a frame, and the frame delay is yours
80 ms per frame
Frame delay80 ms
Pixels per frame
1
Frames to cross
66
"HELLO" takes
5.3 s
The sketch's message
16 s
A readable pace. The whole message has to travel its own width plus the 32 columns of the screen before it comes round again, so a longer message is not slower to read — it is just longer before the start comes back. If that wait matters, make the message shorter rather than the frames faster.

displayText(message, PA_LEFT, 80, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT) takes six arguments and only two of them usually get changed:

ArgumentHereWhat it is
messagethe stringKept by pointer, not copied
PA_LEFTalignmentWhere it rests when it is not moving
80frame delayMilliseconds between frames. One pixel per frame
0pauseHow long it waits at the end before leaving
PA_SCROLL_LEFTentryHow it arrives
PA_SCROLL_LEFTexitHow it leaves

The third one is the one people misread. It is not a speed in any unit of distance; it is a delay, and smaller means faster. Below about 40 ms the letters blur; above about 100 ms it is slow enough to be irritating on a desk. The repository's 80 ms is a good default.

What makes a message long

A message takes its own width plus the 32 columns of the screen to get all the way through. "Lonely Binary - 32x8 MAX7219" is 28 characters — at roughly six columns each in the proportional font, that is around 170 columns of travel plus 32 more, so about 200 frames, which at 80 ms is a little over fifteen seconds before the beginning comes round again.

That is the number to think about, not the frame delay. If the wait feels too long, shorten the message. Speeding up the frames only makes it harder to read.

loop() has to stay free

displayAnimate() is what advances the scroll, and it advances it by one frame per call. It does its own timing internally — it returns immediately if the frame delay has not elapsed — so the correct way to use it is to call it as often as possible and never block.

That means no delay() in loop(). If the sketch also has to read a sensor or check the network, do it with a millis() comparison the way a clock that fits does, so the loop keeps turning.

The green 32x8 matrix display seen from the front showing four digit ones in green LEDs behind a smoked cover, and from the back showing the black PCB printed lonely binary and CHAINABLE 32X8 MAX7219 LED MATRIX DISPLAY, with the OUT header at the left and the IN header at the right.
Front and back of one board. The four squares in the light are the four chips on the back, in the same order.

The code

02_ScrollingText.ino

A message that scrolls right to left forever. displayAnimate() advances it one pixel each time it is called and returns true when the message has left the screen, which is where displayReset() starts it again.

// Wiring for this sketch. Use the header marked IN, on the back of the board.
//
//   ESP32-S3 5V   -> VCC        Uno 5V  -> VCC
//   ESP32-S3 GND  -> GND        Uno GND -> GND
//   ESP32-S3 GPIO 10 -> CS      Uno D10 -> CS
//   ESP32-S3 GPIO 11 -> DIN     Uno D11 -> DIN
//   ESP32-S3 GPIO 12 -> CLK     Uno D12 -> CLK
//
// Arduino IDE: Tools > Manage Libraries, install "MD_Parola" by majicDesigns
// and let it install MD_MAX72XX with it. Then:
//   Tools > Board:  "Arduino Uno", or an ESP32-S3 board from the esp32 core
//   Tools > Port:   whichever port appears when you plug the board in

#include <MD_Parola.h>
#include <MD_MAX72XX.h>
#include <SPI.h>

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define DATA_PIN 11
#define CLK_PIN  12
#define CS_PIN   10

MD_Parola display = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

const char *message = "Lonely Binary - 32x8 MAX7219";

void setup() {
  display.begin();
  display.setIntensity(5);
  display.displayClear();
  // text, alignment, frame delay in ms, pause at the end, entry, exit
  display.displayText(message, PA_LEFT, 80, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
}

void loop() {
  if (display.displayAnimate()) {
    display.displayReset();
  }
}

Keep loop() free of delay(). The animation is advanced by displayAnimate(), so anything that blocks the loop stops the scroll dead — a delay(1000) in here makes the message move one pixel per second.

When it does not work

The message moves one pixel and stops

Something is blocking loop(). displayAnimate() has to be called over and over — it advances the animation by one frame per call and does its own timing. A delay() anywhere in loop() throttles the scroll to that rate.

It scrolls once and then the screen goes blank

displayReset() is missing, or the return value of displayAnimate() is not being checked. Without it the animation finishes and nothing restarts it.

The text scrolls the wrong way

Swap PA_SCROLL_LEFT for PA_SCROLL_RIGHT in both the entry and exit positions. They are separate arguments on purpose — a message can arrive one way and leave another — which means a half-changed call gives you something that scrolls in and then out backwards.

Changing the message while it runs does nothing

displayText keeps a pointer to your string rather than a copy, so writing new characters into the same buffer works and passing a new string means calling displayText again. The safest pattern is one char buffer, written with sprintf, and displayReset() after each change.

Where this goes next

Five characters on a thirty-two column screen, which works in one library and not in the other, for a reason that has nothing to do with the hardware.

A clock that fits

Edit this page — content/books/matrix-32x8/scrolling-a-message.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

Ask a question ↗

32x8 LED Matrix MAX7219, 3-Pack

Loading discussions…

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse Modules and blocks on the forum