MAX7219 LED Matrix Ticker with Text from Your Browser
Four 8×8 matrices make a bright scrolling ticker. Change the text from your phone via a simple web form — for a workshop, café or kids' room.
What you get
The FC-16 module is four 8×8 LED matrices driven by MAX7219 chips, chained together (32×8 dots in total). The MD_Parola library handles fonts, scrolling and dozens of animations, and the ESP32 adds a web form: open the page on your phone, type some text — and it scrolls across the display right away.
Parts
- ESP32 DevKit
- MAX7219 4-in-1 (FC-16) module, 32×8
- 5 female-female jumper wires
Wiring
| MAX7219 | ESP32 |
|---|---|
| VCC | 5V (VIN) |
| GND | GND |
| DIN | GPIO 23 (MOSI) |
| CS | GPIO 5 |
| CLK | GPIO 18 (SCK) |
At full brightness the matrices can draw up to 1 A — for long chains power them from a separate 5 V supply. The MAX7219 usually accepts the ESP32's 3.3 V logic just fine.
Libraries
- MD_Parola
- MD_MAX72XX (dependency)
Code
#include <WiFi.h>
#include <WebServer.h>
#include <SPI.h>
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 5
const char* WIFI_SSID = "YOUR_SSID";
const char* WIFI_PASS = "YOUR_PASSWORD";
MD_Parola display(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
WebServer server(80);
char message[128] = "Hello from ESP32!";
const char PAGE[] = R"rawliteral(
<!doctype html><html><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>LED Ticker</title>
<style>body{font-family:system-ui;max-width:420px;margin:40px auto;padding:0 16px}
input,button{font-size:1.1rem;padding:10px;width:100%;box-sizing:border-box;margin-top:8px}</style>
</head><body>
<h2>LED Ticker</h2>
<form action="/set">
<input name="msg" maxlength="120" placeholder="Text (Latin letters)" autofocus>
<input name="speed" type="range" min="20" max="150" value="60">
<button>Show</button>
</form></body></html>
)rawliteral";
void handleSet() {
String text = server.arg("msg");
// The default font is ASCII-only — drop everything else
String clean;
for (unsigned int i = 0; i < text.length(); i++) {
char c = text[i];
if (c >= 32 && c < 127) clean += c;
}
clean.trim();
if (clean.length()) {
clean.toCharArray(message, sizeof(message));
}
int speed = server.arg("speed").toInt();
if (speed >= 20 && speed <= 150) display.setSpeed(speed); // ms per step: lower is faster
display.displayReset();
server.sendHeader("Location", "/");
server.send(303);
}
void setup() {
Serial.begin(115200);
display.begin();
display.setIntensity(3); // brightness 0..15
display.displayText(message, PA_LEFT, 60, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
display.displayAnimate();
delay(10);
}
// Show the IP so you know where to go
snprintf(message, sizeof(message), "IP %s", WiFi.localIP().toString().c_str());
display.displayReset();
server.on("/", [] { server.send(200, "text/html", PAGE); });
server.on("/set", handleSet);
server.begin();
}
void loop() {
server.handleClient();
if (display.displayAnimate()) {
display.displayReset(); // scroll finished — start over
}
}
Testing
- On power-up the display scrolls
Hello from ESP32!, thenIP 192.168.x.xonce Wi-Fi connects. - Open that address on your phone, type some text, move the speed slider and tap Show.
If something's off
- Text is mirrored or scrambled across matrices — try another hardware type:
PAROLA_HW,GENERIC_HWorICSTATION_HW. - All dots lit or nothing at all — check DIN/CLK/CS and the shared ground.
- Non-Latin alphabets: the default font doesn't include them. MD_MAX72XX supports custom fonts — the library repo has instructions and a font builder tool.
Ideas
- A clock: show NTP time (see the "Accurate OLED Clock" project) with
PA_CENTERand no scrolling. - A YouTube subscriber counter or exchange rates via an HTTP API.
- Chain 8–12 modules for a big board — just change
MAX_DEVICES.