8x8 LED Matrix: scrolling text
Rion Kurihara
8x8 LED Matrix: scrolling text
Rion Kurihara
What I wanted to learn, and why it interested me:
I wanted to learn how to display scrolling text using LED matrices, similar to the displays seen in train stations and bus route indicators. These types of screens are everywhere in daily life, and I was curious about how complex it would be to build and program a comparable system from scratch.
Final outcome:
I successfully connected two 8×8 I2C LED matrices to function as one continuous display. The system shows four different scrolling text variations moving from right to left. Four buttons allow the user to switch between text versions, and a potentiometer provides real-time control over the scrolling speed.
Images of final creative/exploratory output
Complete build
Process images from development towards creative/exploratory output
Output at end of technical training: 1 LED matrix showing an animation of a heart filling up
Challenge 1: completely jumbled pixels due to row and column swap error
Soldered the A0 pads on 2nd matrix to prevent communication conflicts
Succesfully added a potentiometer that adjusts scrolling speed of the text
Process and reflection:
As part of my technical training, I began by displaying a static heart image. I used an LED matrix editor to generate a bitmap and upload it to the display. I then expanded this into a simple animation where the heart gradually filled in. Creating the bitmaps themselves was straightforward thanks to the online tool, but I quickly ran into an issue: the pixels displayed as a scrambled mess rather than simply being rotated or flipped. After debugging, I realized I needed to transpose the rows and columns in the bitmap data to match the matrix orientation.
Next, I moved on to scrolling text. I downloaded the Adafruit GFX library and prepared the hardware to support two matrices on the same I2C line. To avoid address conflicts, I soldered the A0 pads on the second matrix to change its address to 0x71. (This was my first time soldering!) Once configured, the library made it surprisingly easy to get “Hello World” scrolling across both matrices.
Since the scrolling worked so smoothly, I decided to add physical controls. First, I implemented a potentiometer; this was straightforward because I had used one in Project 1. The 4-key keypad, however, initially produced mismatched outputs (e.g., button 2 triggering text intended for button 1). Instead of rewiring, I fixed the issue by reordering the text array in my code.
Overall, this project reinforced how powerful libraries can be. I initially struggled to find ones compatible with my specific Adafruit components, but once Joseph recommended the right libraries, implementation became simple. I was surprised by how quickly the system came together. On another note, building this made me curious about what input looks like in real life, whether they rely on timed automation, centralized software, manual entry, etc. Either way, I now understand the core mechanics and can envision building text-showing LED systems in the future!
Technical details
Electric Schematic
The 5V power came from my Macbook.
/*
60-223 Intro to Physical Computing, spring 2026
Domain-specific Skill Building exercise: 8x8 LED Matrix: scrolling text
This sketch connects two 8x8 LED matrices together to form a single
continuous scrolling display. It allows the user to select
different text messages using a 4-button keypad and control the
scrolling speed in real-time using a potentiometer.
Pin mapping:
Arduino pin | role | details
------------------------------
A0 input 10k Potentiometer to control scroll speed
A4 data I2C SDA
A5 clock I2C SCL
3 input Keypad Button 1 (Message: "Re:collect...")
2 input Keypad Button 2 (Message: "Up the Arsenal!")
5 input Keypad Button 3 (Message: "Hola!...")
4 input Keypad Button 4 (Message: "Root Access...")
Released to the public domain by the author, February 2026
Rion Kurihara, rkurihar@andrew.cmu.edu
*/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
Adafruit_8x8matrix matrix1 = Adafruit_8x8matrix(); // left
Adafruit_8x8matrix matrix2 = Adafruit_8x8matrix(); // right
const int POT_PIN = A0;
const int BTN_PINS[] = {3, 2, 5, 4}; // Reordered to match wires!
const char* messages[] = {
"Hello World", // Button 1 Message
"Welcome to 60-223", // Button 2 Message
"Arduinos are cool!", // Button 3 Message
"North London Forever" // Button 4 Message
};
int currentMessageIndex = 0;
int x = 16;
void setup() {
Serial.begin(9600);
matrix1.begin(0x70);
matrix2.begin(0x71);
// Rotate to match setup
matrix1.setRotation(3); matrix1.setBrightness(10); matrix1.setTextWrap(false);
matrix2.setRotation(3); matrix2.setBrightness(10); matrix2.setTextWrap(false);
for (int i = 0; i < 4; i++) {
pinMode(BTN_PINS[i], INPUT_PULLUP);
}
}
void loop() {
// --- CHECK BUTTONS ---
// see if any are pressed= LOW
for (int i = 0; i < 4; i++) {
if (digitalRead(BTN_PINS[i]) == LOW) {
// switch to its message if button pressed
currentMessageIndex = i;
// Reset so the new message starts from the beginning immediately
x = 16;
// Small delay to prevent issues
delay(200);
}
}
// --- DRAW THE SCROLLING TEXT ---
matrix1.clear();
matrix2.clear();
matrix1.setCursor(x, 0);
matrix1.print(messages[currentMessageIndex]);
matrix2.setCursor(x - 8, 0);
matrix2.print(messages[currentMessageIndex]);
matrix1.writeDisplay();
matrix2.writeDisplay();
// --- RESET ---
x--;
// Length of current message
int msgLength = strlen(messages[currentMessageIndex]) * 6;
if (x < -msgLength) {
x = 16;
}
int potValue = analogRead(POT_PIN);
int speedDelay = map(potValue, 0, 1023, 10, 150);
delay(speedDelay);
}