🔘 Circuiti e progettazione · Guida 11

Debouncing di pulsanti e interruttori

Un pulsante reale non genera quasi mai una transizione elettrica perfetta. Quando i contatti si toccano o si separano possono rimbalzare per alcuni millisecondi, producendo più transizioni HIGH/LOW che un microcontrollore può interpretare come pressioni multiple. Vediamo perché accade e come eliminarlo via software o hardware.

Livello: base → intermedioHardware + softwareArduino / ESP32RC + Schmitt trigger

Che cos’è il contact bounce?

I contatti metallici di un pulsante possiedono massa ed elasticità. Quando vengono premuti non passano necessariamente da aperti a chiusi in un solo istante: possono toccarsi, separarsi e toccarsi nuovamente più volte prima di stabilizzarsi.

Una sola pressione meccanica può quindi produrre diverse transizioni elettriche.Per una persona avviene troppo rapidamente per essere percepito, ma un microcontrollore che esegue milioni di operazioni al secondo può rilevarle tutte.

Come appare il rimbalzo di un pulsante?

Idealmente vorremmo una singola transizione netta. Nella realtà il fronte può contenere numerosi cambi di stato ravvicinati.

Segnale ideale Pulsante reale zona di rimbalzo

Perché il bouncing crea problemi?

Se il programma incrementa un contatore ogni volta che rileva una transizione, una sola pressione può incrementarlo diverse volte. Lo stesso problema può interessare menu, relè, interrupt, contatori di impulsi e sistemi di comando.

Esempio praticoL’utente preme una volta il pulsante “+”. Il contatto rimbalza e il software rileva cinque fronti. Il valore passa da 10 a 15 invece che da 10 a 11.

Quanto dura il rimbalzo?

Non esiste un tempo universale: dipende dalla costruzione del pulsante, dall’usura e dalle condizioni meccaniche. Nei normali comandi manuali il fenomeno è spesso nell’ordine di pochi millisecondi, ma il progetto non dovrebbe basarsi su un numero scelto alla cieca.

Una finestra di debounce di 10–20 ms è un punto di partenza comune per molti pulsanti.Se il comando è critico o molto veloce conviene misurare il comportamento reale, per esempio con un oscilloscopio o un analizzatore logico.

Debouncing software

Il metodo software consiste nel considerare valido un nuovo stato soltanto quando rimane stabile per un certo intervallo di tempo.

Evitare delay() quando il programma deve fare altro.Bloccare il microcontrollore per 20 o 50 ms può sembrare semplice, ma diventa scomodo quando devono funzionare contemporaneamente display, comunicazioni, sensori o più pulsanti.

Debouncing non bloccante con millis()

Con Arduino possiamo memorizzare l’istante dell’ultima variazione letta e accettare il nuovo stato solo dopo che è rimasto invariato abbastanza a lungo.

const byte BUTTON_PIN = 2;
const unsigned long DEBOUNCE_MS = 20;

bool stableState = HIGH;
bool lastReading = HIGH;
unsigned long lastChange = 0;

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

void loop() {
  bool reading = digitalRead(BUTTON_PIN);

  if (reading != lastReading) {
    lastChange = millis();
    lastReading = reading;
  }

  if ((millis() - lastChange) >= DEBOUNCE_MS &&
      reading != stableState) {

    stableState = reading;

    if (stableState == LOW) {
      // Una nuova pressione valida
    }
  }
}
Il timer riparte a ogni rimbalzo.Lo stato viene accettato soltanto quando la lettura smette di cambiare per almeno DEBOUNCE_MS.

Debouncing con macchina a stati

Nei programmi più complessi è utile separare chiaramente gli stati: rilasciato, verifica pressione, premuto e verifica rilascio. Questo permette di riconoscere eventi come pressione, rilascio, pressione lunga e ripetizione automatica senza bloccare il programma.

È particolarmente utile con interfacce utente.Il debounce diventa parte della gestione degli eventi anziché una semplice pausa temporale.

Debouncing hardware

Il rimbalzo può essere filtrato anche prima che il segnale raggiunga il microcontrollore. Le soluzioni più comuni utilizzano reti RC, ingressi con isteresi o circuiti dedicati.

MetodoVantaggioLimite
SoftwareNessun componente aggiuntivo.Richiede codice e temporizzazione corretta.
RCSemplice ed economico.Produce fronti più lenti.
RC + SchmittFronte logico pulito e buona immunità.Richiede componenti aggiuntivi.
Debouncer dedicatoComportamento controllato.Costo e spazio maggiori.

Filtro RC per il debouncing

Una resistenza e un condensatore possono trasformare i rapidi rimbalzi in una variazione più lenta della tensione. Il parametro fondamentale è la costante di tempo.

τ = R · Cτ è espressa in secondi se R è in ohm e C in farad.
EsempioR = 10 kΩ e C = 1 µF:

τ = 10.000 × 0,000001 = 10 ms.
Un semplice RC non crea necessariamente un fronte digitale perfetto.Se l’ingresso attraversa lentamente la zona di soglia, un ingresso con isteresi può offrire un comportamento molto più robusto.

Trigger di Schmitt

Un ingresso Schmitt utilizza due soglie differenti: una per la transizione LOW→HIGH e una per HIGH→LOW. Questa isteresi impedisce a piccole oscillazioni attorno alla soglia di produrre molte commutazioni.

RC + Schmitt trigger è una soluzione hardware classica.Il condensatore filtra i rimbalzi veloci e l’isteresi ricostruisce un fronte digitale netto.

Debouncing e interrupt

Collegare direttamente un pulsante meccanico a un interrupt non elimina il bouncing. Al contrario, ogni rimbalzo può generare una nuova richiesta di interrupt.

Non inserire attese lunghe nella ISR.Una strategia migliore è registrare l’evento e gestire la validazione temporale nel ciclo principale oppure disabilitare/filtrare temporaneamente gli eventi secondo l’architettura del progetto.

Encoder rotativi meccanici

Anche gli encoder meccanici possono presentare rimbalzi, ma la gestione è più delicata perché due segnali in quadratura determinano direzione e movimento. Un semplice ritardo applicato indipendentemente ai due canali può perdere transizioni valide.

Per gli encoder conviene decodificare la sequenza degli stati A/B.Una macchina a stati può rifiutare molte transizioni impossibili causate dal rimbalzo mantenendo la corretta informazione sulla direzione.

Debouncing hardware o software?

SituazioneScelta pratica
Pulsante su Arduino/ESP32Debounce software non bloccante.
Molti pulsantiGestione software centralizzata.
Ingresso molto rumorosoFiltro hardware + software.
Segnale critico indipendente dal firmwareDebounce hardware.
Ingresso con fronte lentoValutare Schmitt trigger.
Encoder meccanicoDecodifica a stati + filtraggio appropriato.

Errori comuni

  • credere che un pulsante produca sempre un solo fronte;
  • usare delay() come unica soluzione in programmi complessi;
  • confondere bouncing con un ingresso flottante;
  • dimenticare pull-up o pull-down;
  • applicare lo stesso tempo di debounce a qualunque dispositivo senza verificarlo;
  • eseguire elaborazioni lunghe dentro una ISR;
  • usare un semplice RC senza considerare le soglie dell’ingresso;
  • filtrare un encoder come se fosse un normale pulsante.

📋 Cosa devi ricordare

BounceUna sola azione meccanica può generare più transizioni elettriche.
SoftwareAccetta lo stato soltanto dopo un periodo stabile.
millis()Permette un debounce non bloccante.
RCFiltra le variazioni rapide con τ = R·C.
SchmittL’isteresi rende più pulite le transizioni lente o rumorose.
InterruptIl bouncing deve essere gestito anche sugli ingressi interrupt.