Matrice LED 8×8 con Arduino: lettere, simboli e scorrimento
Dopo il test dei collegamenti, impariamo a trasformare una griglia di 0 e 1 in lettere e disegni e a farli scorrere sulla matrice LED 8×8.
Dal test alla visualizzazione dei caratteri
Questo progetto è la continuazione diretta del test della matrice 8×8. Nel tutorial precedente verificavamo righe e colonne; qui utilizziamo la stessa struttura per visualizzare caratteri, disegni e sequenze scorrevoli.
← Rivedi il test della matrice 8×8
Come si crea una lettera
Nel progetto ogni disegno è descritto da una tabella di 65 valori: il primo elemento è un riempitivo e i successivi 64 rappresentano gli 8×8 LED della matrice. Un valore 1 indica un LED acceso, mentre 0 indica un LED spento.
Esempio di costruzione di un carattere tramite una matrice di 0 e 1. Nel sito la larghezza era automatica.
Materiale necessario
🧰 Kit Arduino consigliato
Molti progetti del sito utilizzano LED, resistenze, breadboard e cavetti. Un kit completo può essere comodo per iniziare.
👉 Guarda il kit Arduino consigliatoLink di affiliazione Amazon: in qualità di Affiliato Amazon ricevo un guadagno dagli acquisti idonei, senza alcun costo aggiuntivo per te.
📘 Vuoi imparare Arduino passo dopo passo?
Se vuoi approfondire e realizzare progetti più completi, puoi dare un’occhiata anche ai miei libri dedicati ad Arduino. All’interno troverai spiegazioni semplici, schemi chiari e molti progetti pratici pensati per chi parte da zero.
👉 Scopri i miei libri su ArduinoLink di affiliazione Amazon: in qualità di Affiliato Amazon ricevo un guadagno dagli acquisti idonei, senza alcun costo aggiuntivo per te.
Schema del circuito
Schema . Anche questa immagine nel sito era impostata su larghezza automatica.
Mappatura di righe e colonne
Il cablaggio è lo stesso del progetto 32. Lo sketch usa 16 linee, comprese A0–A3 come uscite digitali.
| Colonna | Pin | Riga | Pin |
|---|---|---|---|
| 1 | D9 | 1 | A3 |
| 2 | D12 | 2 | A2 |
| 3 | D7 | 3 | D3 |
| 4 | D13 | 4 | D8 |
| 5 | D2 | 5 | D4 |
| 6 | D6 | 6 | D10 |
| 7 | A1 | 7 | D11 |
| 8 | D5 | 8 | A0 |
Esempio: una lettera come matrice di bit
Invece del vecchio array da 65 interi possiamo rappresentare in modo più leggibile ogni carattere con otto byte: ogni byte descrive una riga e ciascun bit corrisponde a un LED.
// Ogni byte rappresenta una riga della matrice.
// 1 = LED acceso
// 0 = LED spento
const byte letteraM[8] = {
B10000001,
B11000011,
B10100101,
B10011001,
B10000001,
B10000001,
B10000001,
B00000000
};
Codice Arduino commentato
Lo sketch è piuttosto lungo perché implementa manualmente caratteri, scorrimento e refresh. Qui sotto trovi una versione didattica più compatta che mantiene gli stessi concetti: cablaggio diretto, multiplexing e bitmap.
// ==========================================================
// MATRICE LED 8x8 CON ARDUINO
// Lettere, simboli e scorrimento
// ==========================================================
// Colonne: stessa mappatura del progetto
const int colonne[8] = {
9, 12, 7, 13, 2, 6, A1, 5
};
// Righe: stessa mappatura del progetto
const int righe[8] = {
A3, A2, 3, 8, 4, 10, 11, A0
};
// ----------------------------------------------------------
// Alcuni caratteri 8x8.
// Ogni elemento descrive una riga.
// ----------------------------------------------------------
const byte carR[8] = {
B11100000,
B10010000,
B10010000,
B11100000,
B11000000,
B10101000,
B10010000,
B00000000
};
const byte carI[8] = {
B00100000,
B00000000,
B00100000,
B00100000,
B00100000,
B00100000,
B00010000,
B00000000
};
const byte carM[8] = {
B00000000,
B00000000,
B00000000,
B01101100,
B10010010,
B10010010,
B10010001,
B00000000
};
const byte carN[8] = {
B00000000,
B00000000,
B00000000,
B11100000,
B10010000,
B10010000,
B10010000,
B00000000
};
// Buffer visualizzato sul display.
// Ogni byte rappresenta una colonna dello schermo.
byte schermo[8] = {0,0,0,0,0,0,0,0};
// ----------------------------------------------------------
// Spegne completamente la matrice.
// ----------------------------------------------------------
void spegniMatrice() {
for (int i = 0; i < 8; i++) {
digitalWrite(righe[i], LOW);
digitalWrite(colonne[i], HIGH);
}
}
// ----------------------------------------------------------
// Visualizza per alcuni millisecondi il contenuto
// del buffer "schermo" tramite multiplexing.
// ----------------------------------------------------------
void refreshMatrice(unsigned long durataMs) {
unsigned long inizio = millis();
while (millis() - inizio < durataMs) {
for (int col = 0; col < 8; col++) {
// Evita accensioni fantasma mentre
// prepariamo la colonna successiva.
spegniMatrice();
// Per ogni riga controlla il bit
// corrispondente nel buffer.
for (int riga = 0; riga < 8; riga++) {
bool acceso = bitRead(schermo[col], 7 - riga);
digitalWrite(righe[riga], acceso ? HIGH : LOW);
}
// Nel cablaggio la colonna selezionata
// viene portata LOW.
digitalWrite(colonne[col], LOW);
// Tempo molto breve per la persistenza visiva
delayMicroseconds(800);
}
}
spegniMatrice();
}
// ----------------------------------------------------------
// Converte una bitmap descritta per righe
// in otto colonne da inserire nel buffer.
// ----------------------------------------------------------
void caricaCarattere(const byte carattere[8]) {
// Pulisce lo schermo
for (int c = 0; c < 8; c++) {
schermo[c] = 0;
}
// Legge riga e colonna del carattere
for (int r = 0; r < 8; r++) {
for (int c = 0; c < 8; c++) {
// Controlla il bit della bitmap
if (bitRead(carattere[r], 7 - c)) {
// Inserisce il pixel nella colonna
bitSet(schermo[c], 7 - r);
}
}
}
}
// ----------------------------------------------------------
// Mostra un carattere fermo.
// ----------------------------------------------------------
void mostraCarattere(const byte carattere[8], int durata) {
caricaCarattere(carattere);
refreshMatrice(durata);
}
// ----------------------------------------------------------
// Fa entrare un carattere da destra.
// La nuova colonna viene aggiunta e tutto il buffer
// viene spostato verso sinistra.
// ----------------------------------------------------------
void scorriCarattere(const byte carattere[8]) {
byte colonneCarattere[8] = {0,0,0,0,0,0,0,0};
// Converte la bitmap in colonne
for (int r = 0; r < 8; r++) {
for (int c = 0; c < 8; c++) {
if (bitRead(carattere[r], 7 - c)) {
bitSet(colonneCarattere[c], 7 - r);
}
}
}
// Inserisce una colonna alla volta da destra
for (int nuova = 0; nuova < 8; nuova++) {
// Sposta tutte le colonne verso sinistra
for (int c = 0; c < 7; c++) {
schermo[c] = schermo[c + 1];
}
// Inserisce a destra la nuova colonna
schermo[7] = colonneCarattere[nuova];
// Mantiene visibile questa posizione
// per creare l'effetto di movimento.
refreshMatrice(90);
}
// Aggiunge una colonna vuota come spazio
for (int c = 0; c < 7; c++) {
schermo[c] = schermo[c + 1];
}
schermo[7] = 0;
refreshMatrice(90);
}
void setup() {
// Configura righe e colonne come uscite
for (int i = 0; i < 8; i++) {
pinMode(righe[i], OUTPUT);
pinMode(colonne[i], OUTPUT);
}
spegniMatrice();
}
void loop() {
// Lo sketch scorre la parola "Rimini".
scorriCarattere(carR);
scorriCarattere(carI);
scorriCarattere(carM);
scorriCarattere(carI);
scorriCarattere(carN);
scorriCarattere(carI);
// Fa uscire completamente il testo
// aggiungendo otto colonne vuote.
for (int i = 0; i < 8; i++) {
for (int c = 0; c < 7; c++) {
schermo[c] = schermo[c + 1];
}
schermo[7] = 0;
refreshMatrice(90);
}
delay(500);
}
Come funziona lo scorrimento
L’idea centrale è semplice: invece di ridisegnare istantaneamente un nuovo carattere, spostiamo tutto ciò che è già sul display di una colonna verso sinistra e inseriamo una nuova colonna sul lato destro.
| Passaggio | Cosa accade |
|---|---|
| 1 | Si prepara il carattere come matrice 8×8 |
| 2 | Si estrae una colonna alla volta |
| 3 | Il contenuto corrente scorre verso sinistra |
| 4 | La nuova colonna entra da destra |
| 5 | Il multiplexing mantiene visibile il risultato |
La parola usata nello sketch
Nel programma vengono caricati in sequenza i caratteri R, i, m, i, n, i, formando la parola “Rimini”. Ogni carattere viene copiato in un’area di lavoro e poi passato alla routine di scorrimento.
Il refresh della matrice
Una matrice collegata direttamente ad Arduino deve essere continuamente aggiornata. La routine di refresh seleziona una colonna alla volta e accende le righe necessarie. Se questo processo è abbastanza rapido, l’occhio vede l’intera immagine stabile.
Perché il codice usa aree di lavoro
Nel sketch trovi array come comodo, carcomodo e colonna. Servono come buffer temporanei: prima viene copiato il carattere da mostrare, poi vengono estratte le colonne necessarie allo scorrimento e infine viene aggiornata la matrice visibile.
Creare i tuoi simboli
Puoi disegnare un simbolo su carta quadrettata 8×8 e trasformare ogni casella in 0 oppure 1. Per esempio un cuore potrebbe essere descritto così:
const byte cuore[8] = {
B00000000,
B01100110,
B11111111,
B11111111,
B01111110,
B00111100,
B00011000,
B00000000
};
Limiti della matrice collegata direttamente
Questo approccio occupa 16 pin e richiede che Arduino si occupi continuamente del refresh. È molto utile per imparare, ma per testi e animazioni più complesse è più pratico usare un driver come MAX7219.
Scarica lo sketch
⬇️ Scarica arduino_matrice_led_finito_sketch.inoDebug rapido
- verifica prima il circuito con il Progetto 32;
- controlla orientamento e piedinatura della matrice;
- se il carattere è specchiato, inverti l’ordine delle colonne;
- se è capovolto, inverti l’ordine delle righe;
- se il display sfarfalla, riduci il tempo di refresh per colonna;
- se compaiono LED fantasma, spegni righe e colonne prima di selezionare quella successiva;
- se una parte del carattere manca, verifica la bitmap e il relativo collegamento.
Varianti del progetto
- creare un alfabeto completo 8×8;
- visualizzare numeri e punteggiatura;
- creare faccine e icone;
- regolare la velocità di scorrimento con un potenziometro;
- ricevere il testo dalla porta seriale;
- passare a MAX7219 per concatenare più matrici;
- memorizzare i font in PROGMEM per risparmiare RAM.
Cosa devi ricordare
- Ogni carattere è una bitmap 8×8.
- Un valore 1 rappresenta un LED acceso e 0 un LED spento.
- Il display deve essere continuamente multiplexato.
- Lo scorrimento avviene spostando il buffer di una colonna alla volta.
- Il cablaggio è lo stesso del progetto di test precedente.
- Per progetti più complessi conviene usare un driver dedicato.
Domande frequenti
Perché il carattere appare specchiato?
La sequenza delle colonne della tua matrice potrebbe essere invertita rispetto alla mappatura usata nel codice. Puoi invertire l’ordine dell’array delle colonne oppure quello dei bit.
Come creo una nuova lettera?
Disegnala su una griglia 8×8 e converti ogni riga in una sequenza di 0 e 1. Poi inserisci la bitmap nel programma e richiamala nella sequenza desiderata.
Posso far scorrere una frase lunga?
Sì, ma con il collegamento diretto il codice e la gestione diventano rapidamente più complessi. Per scritte lunghe è più pratico usare uno o più moduli MAX7219.
Perché lo sketch usa 65 elementi e non 64?
Il primo elemento è un valore di riempimento non utilizzato; i successivi 64 corrispondono realmente agli 8×8 LED della matrice.

