ESP32 MAX7219 LED Matrix Scrolling Display

Button-Controlled State Management & Dynamic Alphanumeric Sequences

📊 Operational Overview & Video Guide System Live Demo

This project showcases a 4-module MAX7219 8x8 LED matrix driven by an ESP32 microcontroller using the high-performance MD_Parola library[cite: 24, 25]. By default, the display smoothly scrolls a custom introductory message[cite: 25]. Pressing a dedicated push-button triggers state-machine switching, stepping the LED array through sequential numbers, uppercase alphabets, and lowercase loops[cite: 24, 25].

Display Default State
✨ Scrolls "ustad zulu khan" continuously[cite: 24, 25]
Hardware Structure
🧱 4x Cascade FC16_HW MAX7219 Modules[cite: 24, 25]
🛠️ Structural BOM Requirements Hardware List

Procure the following components to assemble this interactive digital signage prototype[cite: 25]:

Target Component Label Structural Allocation Quantity Functional Deployment Purpose
ESP32 Board1 UnitPrimary processing core running SPI hardware commands and button debouncing logic[cite: 24, 25].
MAX7219 8x8 LED Matrix (4-in-1)1 UnitThe visual output display cascaded horizontally for text layout animations[cite: 24, 25].
Push Button1 UnitTriggers display interrupt loops to toggle sequence profiles[cite: 24, 25].
Jumper Wires & Breadboard1 SetConnects SPI lines and route electrical pathways[cite: 25].
🔌 Device Interface Pin Maps I/O Infrastructure

Establish secure physical wiring connections matching these explicit GPIO pins assigned inside the SPI code structure[cite: 24, 25]:

Matrix SPI Control & Input Routing Configurations:
Device Terminal Pin OutESP32 Target GPIO Pin MappingFunctional Context
MAX7219 DINDigital Output Pin GPIO 41Master Out Slave In (MOSI) Data Line[cite: 24, 25]
MAX7219 CLKDigital Output Pin GPIO 40SPI Synchronous Serial Clock[cite: 24, 25]
MAX7219 CSDigital Output Pin GPIO 39Chip Select Line for SPI framing[cite: 24, 25]
Push Button (Pin 1)Digital Input Pin GPIO 21Configured with Internal Pull-up (GND active)[cite: 24, 25]
💻 Optimized Production Code Engine Firmware Source

Flash this optimized sketch directly onto your target ESP32 board inside the Arduino IDE environment[cite: 25]:

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

// Define hardware type and connected modules
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW  
#define MAX_DEVICES 4                      

// Pin definitions mapping to your ESP32 configuration
#define DATA_PIN  41
#define CS_PIN    39
#define CLK_PIN   40
#define BUTTON_PIN 21                      

// Initialize the Parola object instance
MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// Speed configurations (Lower numbers mean faster scrolling)
const uint16_t normalSpeed     = 129;  // Speed for default message
const uint16_t slowScrollSpeed  = 120; // Slower speed for alphanumeric sequence
const uint16_t pauseTime       = 0;

// State management variables
bool sequenceActive = false; 
int currentStep = 0;         
bool lastButtonState = HIGH; 

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);

  myDisplay.begin();
  myDisplay.setIntensity(15); // Adjust brightness level
  myDisplay.displayClear();

  // Set the initial default text
  myDisplay.displayText("ustad zulu khan", PA_LEFT, normalSpeed, pauseTime, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
}

void loop() {
  // Read current button state
  bool currentButtonState = digitalRead(BUTTON_PIN);

  // Detect state change from HIGH to LOW (Button Pressed down)
  if (currentButtonState == LOW && lastButtonState == HIGH) {
    sequenceActive = !sequenceActive; // Toggle loop state
    
    // Clear display buffer and reset the animation machine
    myDisplay.displayClear();
    myDisplay.displayReset();

    if (sequenceActive) {
      currentStep = 0; // Reset to the start of the alphanumeric loop
      startNewStep();
    } else {
      // Force immediate return to default text
      myDisplay.displayText("ustad zulu khan", PA_LEFT, normalSpeed, pauseTime, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
    }
    
    delay(50); // Small debounce delay to stabilize the button reading
  }
  
  // Save current button state for the next scan cycle
  lastButtonState = currentButtonState;

  // Handle display animations continuously
  if (myDisplay.displayAnimate()) {
    if (sequenceActive) {
      // Cycle through steps: 0 -> 1 -> 2 -> 0...
      currentStep = (currentStep + 1) % 3; 
      startNewStep();
    } else {
      // Keep resetting default text animation once it finishes scrolling
      myDisplay.displayReset();
    }
  }
}

// Helper function to update the text array
void startNewStep() {
  if (currentStep == 0) {
    myDisplay.displayText("0 1 2 3 4 5 6 7 8 9", PA_LEFT, slowScrollSpeed, pauseTime, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
  } else if (currentStep == 1) {
    myDisplay.displayText("A B C D E F G H I J K L M N O P Q R S T U V W X Y Z", PA_LEFT, slowScrollSpeed, pauseTime, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
  } else if (currentStep == 2) {
    myDisplay.displayText("a b c d e f g h i j k l m n o p q r s t u v w x y z", PA_LEFT, slowScrollSpeed, pauseTime, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
  }
  myDisplay.displayReset();
}
Required Software Dependencies: Ensure that you add MD_Parola, MD_MAX72xx, and default SPI libraries to your Arduino compiler layout environment to prevent compilation faults[cite: 25].