Zákmity tlačítka (debouncing)

Vraťme se na chvíli k předchozímu příkladu počítání stisků tlačítka pomocí detekce hrany. Zahlásilo vám Arduino občas dva po sobě rychle jdoucí stisky, i když jste zmáčkli jen jednou? Je to dost dobře možné.

U obyčejných tlačítek zajišťuje spínání a rozepínání kontaktů membrána. A právě ta po zmáčknutí tlačítka kmitá kolem své osy. Arduino tak skutečně může napočítat více stisků tlačítka, neboť membrána tlačítka je za jeden stisk schopna obvod uzavřít a zase rozpojit vícekrát.

Zákmity tlačítka

Tento neduh se dá řešit více způsoby. Např. používáním kvalitnějšího tlačítka. My to ošetříme softwarově. Po detekci stisku tlačítka bude další stisk považován za platný, pokud rozestup mezi stisky je alespoň 150 milisekund. Membrána se za tento časový interval uklidní natolik, že samovolná změna stavu již nehrozí.

Podmínka, která detekuje platný stisk tlačítka, se tak rozšíří o kontrolu délky časového intervalu mezi změnami stavů pinu. Uživatel nebude mačkat rychleji než maximálně párkrát za vteřinu, takže ho toto řešení nijak neomezuje.

Zapojení je stejné jako u tlačítka bez externího rezistoru.

Kód

byte citac = 0; // počítá od nuly
const byte tlacitko = 12; // pin
const byte zakmit = 150; // milisekund
int predchoziStav = HIGH; // dosud nestisknuto
unsigned long naposledy = 0; // kdy naposledy stisknuto [ms]

void setup()
{ // pin 12 bude zapojen jako vstup ale s připojením na +5 V
pinMode(tlacitko, INPUT_PULLUP); //přes vnitřní 20k rezistor
Serial.begin(9600);
}

void loop()
{ // podmínka jako minule + navíc časová prodleva na zákmity
if ((digitalRead(tlacitko) == LOW) && // logický AND
(digitalRead(tlacitko) != predchoziStav) && // vše musí být splněno
((millis() – naposledy) > zakmit)){ // interval mezi stisky musí být delší 150 ms
naposledy = millis(); // uloží čas posl. stisku
citac++; // navýší hodnotu čítače o 1
Serial.print(„Tlacitko bylo stisknuto jiz „);
Serial.print(citac); // výpis do sér. linky
Serial.println(„x“); // odřádkování
} // uloží stav tlačítka pro další cyklus
predchoziStav = digitalRead(tlacitko);
}