Timer con Arduino e display a 4 cifre
Realizziamo un timer fino a 60 minuti con display a 7 segmenti multiplexato, pulsante di impostazione e buzzer di fine countdown.
Cosa imparerai
- come funziona un display a 4 cifre multiplexato;
- come condividere i segmenti tra più cifre;
- come selezionare una cifra alla volta molto rapidamente;
- come trasformare i secondi residui in minuti e secondi;
- come impostare un timer tramite pulsante;
- come gestire il countdown con
millis(); - come attivare un buzzer alla fine del tempo.
Come funziona il progetto
Il progetto utilizza un display a quattro cifre modello HS410561K-32. Il timer può essere impostato fino a circa un’ora tramite un pulsante; al termine del conto alla rovescia Arduino attiva un buzzer.
Esempi del timer con display a quattro cifre.
Materiale necessario
🧰 Kit Arduino consigliato
Molti progetti del sito utilizzano display, pulsanti, buzzer, resistenze e breadboard. 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
Il circuito è mostrato in due immagini per maggiore chiarezza, ma fisicamente va realizzato come un unico circuito.
Schema di collegamento del display a quattro cifre.
Schema collegamento buzzer e pulsante.
Pin utilizzati nello sketch
| Funzione | Pin Arduino |
|---|---|
| Buzzer | D0 |
| Segmenti display + punto | D1–D8 |
| Selezione delle 4 cifre | D9–D12 |
| Pulsante impostazione | D13 |
Che cos’è il multiplexing
Un display a quattro cifre non richiede sette pin separati per ogni cifra. I segmenti a–g vengono condivisi, mentre quattro pin aggiuntivi selezionano quale cifra deve essere accesa.
Arduino attiva una cifra, imposta i suoi segmenti, la spegne e passa immediatamente alla successiva. Ripetendo il ciclo abbastanza velocemente, l’occhio percepisce tutte e quattro le cifre come accese contemporaneamente.
Formato del tempo
| Cifra | Contenuto |
|---|---|
| 1ª da sinistra | Decine di minuti |
| 2ª | Unità di minuti |
| 3ª | Decine di secondi |
| 4ª | Unità di secondi |
Il punto decimale della seconda cifra viene utilizzato come separatore visivo tra minuti e secondi.
Codice Arduino commentato
// ==========================================================
// TIMER ARDUINO CON DISPLAY A 4 CIFRE
// Cablaggio basato sul progetto HS410561K-32
// ==========================================================
// Buzzer collegato al pin D0.
// NOTA: D0 è anche RX della seriale hardware.
const int buzzerPin = 0;
// Segmenti nell'ordine a, b, c, d, e, f, g.
// Mappatura dei segmenti utilizzata nel progetto.
const int segmenti[7] = {
3, // a
4, // b
6, // c
7, // d
8, // e
2, // f
1 // g
};
// Punto decimale
const int puntoPin = 5;
// Pin che selezionano le quattro cifre
const int cifrePin[4] = {9, 10, 11, 12};
// Pulsante di impostazione del tempo
const int pulsantePin = 13;
// Tabella dei segmenti per i numeri 0...9.
// Ordine: a,b,c,d,e,f,g
const bool numeri[10][7] = {
{1,1,1,1,1,1,0}, // 0
{0,1,1,0,0,0,0}, // 1
{1,1,0,1,1,0,1}, // 2
{1,1,1,1,0,0,1}, // 3
{0,1,1,0,0,1,1}, // 4
{1,0,1,1,0,1,1}, // 5
{1,0,1,1,1,1,1}, // 6
{1,1,1,0,0,0,0}, // 7
{1,1,1,1,1,1,1}, // 8
{1,1,1,1,0,1,1} // 9
};
// Minuti scelti dall'utente
int minutiImpostati = 0;
// Secondi rimanenti durante il countdown
long secondiResidui = 0;
// Momento di riferimento del countdown
unsigned long ultimoSecondo = 0;
// Indice della cifra multiplexata
int cifraCorrente = 0;
// Momento dell'ultimo cambio cifra
unsigned long ultimoRefresh = 0;
// Stato del timer
bool timerAttivo = false;
// ----------------------------------------------------------
// Spegne tutte le cifre.
// Le cifre vengono attivate portando il relativo pin HIGH.
// ----------------------------------------------------------
void spegniCifre() {
for (int i = 0; i < 4; i++) {
digitalWrite(cifrePin[i], LOW);
}
}
// ----------------------------------------------------------
// Imposta i segmenti per visualizzare una cifra.
// I segmenti sono attivi LOW in questo cablaggio.
// ----------------------------------------------------------
void impostaNumero(int numero) {
for (int i = 0; i < 7; i++) {
if (numeri[numero][i]) {
digitalWrite(segmenti[i], LOW);
} else {
digitalWrite(segmenti[i], HIGH);
}
}
}
// ----------------------------------------------------------
// Aggiorna rapidamente una sola cifra del display.
// Va richiamata molto spesso dal loop().
// ----------------------------------------------------------
void aggiornaDisplay(long secondiDaMostrare) {
// Limita il valore al formato massimo 59:59.
if (secondiDaMostrare < 0) secondiDaMostrare = 0;
if (secondiDaMostrare > 3599) secondiDaMostrare = 3599;
int minuti = secondiDaMostrare / 60;
int secondi = secondiDaMostrare % 60;
int valori[4] = {
minuti / 10,
minuti % 10,
secondi / 10,
secondi % 10
};
// Aggiorna una cifra circa ogni 2 ms.
if (millis() - ultimoRefresh >= 2) {
ultimoRefresh = millis();
// Prima spegne tutte le cifre
// per evitare immagini fantasma.
spegniCifre();
// Prepara i segmenti della cifra corrente
impostaNumero(valori[cifraCorrente]);
// Punto decimale come separatore minuti/secondi.
// È associato alla seconda cifra.
if (cifraCorrente == 1) {
digitalWrite(puntoPin, LOW);
} else {
digitalWrite(puntoPin, HIGH);
}
// Accende soltanto la cifra corrente
digitalWrite(cifrePin[cifraCorrente], HIGH);
// Passa alla cifra successiva
cifraCorrente++;
if (cifraCorrente > 3) {
cifraCorrente = 0;
}
}
}
// ----------------------------------------------------------
// Impostazione del tempo.
// Tenendo premuto il pulsante, aumenta di un minuto
// circa ogni secondo, fino a 60 e poi riparte da zero.
// ----------------------------------------------------------
void impostaTempo() {
unsigned long inizioPressione = millis();
int ultimoMinutoMostrato = -1;
while (digitalRead(pulsantePin) == HIGH) {
unsigned long trascorso = millis() - inizioPressione;
// 1 secondo di pressione = 1 minuto impostato
int nuovoValore = trascorso / 1000;
// Dopo 60 minuti riparte da 0
nuovoValore = nuovoValore % 61;
if (nuovoValore != ultimoMinutoMostrato) {
minutiImpostati = nuovoValore;
ultimoMinutoMostrato = nuovoValore;
}
// Durante l'impostazione mostra MM:00
aggiornaDisplay((long)minutiImpostati * 60);
}
// Se è stato scelto almeno un minuto,
// prepara e avvia il countdown.
if (minutiImpostati > 0) {
secondiResidui = (long)minutiImpostati * 60;
ultimoSecondo = millis();
timerAttivo = true;
}
}
// ----------------------------------------------------------
// Segnalazione acustica finale.
// Mantiene il buzzer attivo per circa 5 secondi.
// ----------------------------------------------------------
void allarmeFine() {
unsigned long inizio = millis();
digitalWrite(buzzerPin, HIGH);
while (millis() - inizio < 5000) {
// Continua a mostrare 00:00
// mentre il buzzer è attivo.
aggiornaDisplay(0);
}
digitalWrite(buzzerPin, LOW);
}
void setup() {
// Configura i segmenti
for (int i = 0; i < 7; i++) {
pinMode(segmenti[i], OUTPUT);
digitalWrite(segmenti[i], HIGH);
}
// Punto decimale
pinMode(puntoPin, OUTPUT);
digitalWrite(puntoPin, HIGH);
// Selezione delle quattro cifre
for (int i = 0; i < 4; i++) {
pinMode(cifrePin[i], OUTPUT);
digitalWrite(cifrePin[i], LOW);
}
// Pulsante con resistenza esterna da 10 kΩ
pinMode(pulsantePin, INPUT);
// Buzzer
pinMode(buzzerPin, OUTPUT);
digitalWrite(buzzerPin, LOW);
}
void loop() {
// Se il timer non è attivo,
// mostra il tempo impostato oppure 00:00.
if (!timerAttivo) {
aggiornaDisplay((long)minutiImpostati * 60);
// Pressione del pulsante = modalità impostazione
if (digitalRead(pulsantePin) == HIGH) {
impostaTempo();
}
return;
}
// Durante il countdown il display va aggiornato
// continuamente per mantenere il multiplexing.
aggiornaDisplay(secondiResidui);
// Ogni secondo riduce il tempo residuo.
if (millis() - ultimoSecondo >= 1000) {
ultimoSecondo += 1000;
if (secondiResidui > 0) {
secondiResidui--;
}
// Quando arriva a zero, termina il timer.
if (secondiResidui <= 0) {
timerAttivo = false;
allarmeFine();
// Torna pronto per una nuova impostazione.
minutiImpostati = 0;
secondiResidui = 0;
}
}
}
Come funziona il multiplexing nel codice
La funzione aggiornaDisplay() non accende tutte le cifre contemporaneamente. Ne attiva una alla volta, cambia cifra ogni pochi millisecondi e ripete il ciclo continuamente.
| Fase | Operazione |
|---|---|
| 1 | Spegne tutte le cifre |
| 2 | Imposta i segmenti del numero |
| 3 | Accende la cifra corrente |
| 4 | Passa alla cifra successiva |
Come viene calcolato il tempo
Il tempo residuo viene conservato in secondi. Da questo unico valore ricaviamo le quattro cifre:
int minuti = secondiResidui / 60;
int secondi = secondiResidui % 60;
int decineMinuti = minuti / 10;
int unitaMinuti = minuti % 10;
int decineSecondi = secondi / 10;
int unitaSecondi = secondi % 10;
L’operatore % restituisce il resto della divisione ed è molto utile per separare decine e unità.
Perché millis() è importante
Il progetto usa millis() per calcolare il tempo trascorso e il tempo residuo. È una scelta importante perché un display multiplexato deve continuare ad essere aggiornato molto rapidamente: un lungo delay() farebbe spegnere o sfarfallare le cifre.
millis() non serve soltanto per il countdown. Permette anche di tenere il programma reattivo mentre il display viene continuamente multiplexato.Limiti del collegamento diretto
- D0 viene usato dal buzzer, quindi occupa RX.
- D1 viene usato da un segmento, quindi occupa TX.
- quasi tutti i pin digitali di Arduino Uno risultano impegnati;
- la seriale hardware non è praticamente disponibile;
- il cablaggio è molto più complesso rispetto a un modulo display con driver.
Come lo realizzeremmo oggi
Per semplificare il circuito puoi usare un modulo a quattro cifre con driver integrato, per esempio basato su TM1637 o MAX7219. Servirebbero molti meno pin e il software sarebbe più semplice.
Il collegamento diretto resta comunque un ottimo esercizio per capire davvero come funziona il multiplexing.
Scarica lo sketch
⬇️ Scarica arduino_countdown_4_cifre.inoDebug rapido
- verifica che il display sia realmente il modello previsto o abbia una piedinatura compatibile;
- controlla la corrispondenza tra segmenti e pin D1–D8;
- controlla le quattro linee di selezione cifra su D9–D12;
- se alcune cifre sono invertite, verifica l’ordine dei quattro anodi;
- se il display sfarfalla, controlla che il multiplexing venga eseguito abbastanza rapidamente;
- se il pulsante non imposta il tempo, controlla D13 e la resistenza da 10 kΩ;
- se il buzzer non suona, verifica D0 e il tipo di buzzer utilizzato.
Varianti del progetto
- aggiungere un secondo pulsante per diminuire i minuti;
- aggiungere start/stop separato;
- implementare pausa e reset;
- usare
INPUT_PULLUPper semplificare il pulsante; - spostare buzzer e display lontano dai pin D0/D1;
- usare TM1637 o MAX7219;
- aggiungere memoria EEPROM per ricordare l’ultimo tempo.
Cosa devi ricordare
- Il timer arriva fino a circa 60 minuti.
- Il display mostra minuti e secondi su quattro cifre.
- D9–D12 selezionano le cifre una alla volta.
- D1–D8 comandano segmenti e punto decimale.
- Il pulsante è su D13 e il buzzer su D0.
- Il multiplexing deve essere aggiornato continuamente.
millis()permette di gestire il tempo senza bloccare il display.
Domande frequenti
Perché il display sembra avere tutte le cifre accese insieme?
È l’effetto del multiplexing: Arduino accende in realtà una cifra alla volta, ma lo fa abbastanza velocemente da ingannare la persistenza visiva dell’occhio.
Perché non posso usare facilmente il Monitor Seriale?
Perché il cablaggio usa D0 e D1, che su Arduino Uno sono RX e TX della seriale hardware.
Posso usare un display 4 cifre diverso?
Sì, ma devi verificarne piedinatura, tipo di comune e ordine delle cifre. Non è garantita la compatibilità diretta con HS410561K-32.
Posso usare un modulo TM1637?
Sì. Per un nuovo progetto è molto più semplice perché richiede pochissimi collegamenti e gestisce internamente il multiplexing.

