Zákmity tlačidiel

Page

Stránky / Arduino / Pod kapotou Arduina /

Skôr alebo neskôr sa každý dostane ku tomu, že chce niečo ovládať tlačidlami. Nájde si schému, na ktorej je tlačidlo a jeden pull-up rezistor a výsledok je pripojený na niektorý vstup Arduina. Poskladá si to a podľa digitálneho vstupu na pine bude zapínať a vypínať jednu LED diódu. Potiaľ bude všetko krásne fungovať. A potom sa pokúsite celý program prepracovať tak, aby jedno stlačenie LED diódu zaplo a druhé ju vyplo. A v tom okamihu sa začnú problémy. Bude to fungovať dosť dobre, ale občas sa to nezapne alebo nevypne podľa vašich predstáv. Objavili ste totiž fenomén, ktorý sa nazýva zákmit tlačidla.

Čo je zákmit tlačidla

Zákmity tlačidla spôsobuje nedokonalé mechanické spojenie medzi kontaktami tlačidla. Aj keď to človek nevidí, pri stlačení tlačidla sa kontakty nezopnú dokonale, ale na krátku chvíľu nastane jav, pri ktorom sú kontakty zopnuté a rozopnuté súčasne. Trvá to niekoľko milisekúnd, počas ktorých dôjde k niekoľkým takýmto javom. Výsledkom je, že elektrický obvod je niekoľkokrát zopnutý a rozopnutý, kým sa tlačidlo ustáli. Doba, počas ktorej sa to udeje trvá rôzne, ale vo všeobecnosti by malo platiť, že po pár milisekundách je tlačidlo už zopnuté. Vo video, kde som sa snažil tento jav zaznamenať sa mi všetky stlačenia ustálili do dvoch milisekúnd.
Ľudia sa snažili tieto problémy riešiť pomocou kondenzátorov a klopných obvodov, ale žijeme v digitálnej dobe a Arduino nám umožňuje ošetriť tento stav pomocou kódu. Ako vzorový kód všetci vychádzajú z kódu, ktorý bol publikovaný na stránke Arduina. Pri jeho štúdiu si treba dať pozor na to, že na tej stránke je zapojenie opačné. Nie je tam pull-up rezistor, ale pull-down.

Algoritmus ošetrenia zákmitov

Algoritmus ošetrenia zákmitu je nasledovný (pre prípad pull-up zapojenia):
  • Sledujeme v pravidelných intervaloch hodnotu na digitálnom vstupe, ktorý je pripojený ku tlačidlu.
  • Ak je hodnota HIGH, nič sa nedeje a znamená to, že tlačidlo nebolo stlačené.
  • Ak je hodnota LOW, znamená to začiatok stlačenia a poznačíme si čas, kedy to nastalo.
  • Počkáme definovaný počet milisekúnd (25-50 stačí) a skontrolujeme, či je hodnota stále LOW. Ak áno, vyhodnotíme stav ako stlačenie tlačidla a môžeme na to reagovať.
Samozrejme tvorivosti sa medze nekladú a dá sa s týmto základným princípom pracovať a získať takú informáciu, ktorá sa vám hodí. Napríklad sa dá sledovať dlhšie stlačenie tlačidla a automaticky generovať opakujúce sa stláčanie tlačidla.

Vzorový kód na ošetrenie zákmitov

Nasledovný vzorový kód bude vychádzať z knižnice, ktorú som poskladal z viacerých zdrojov. Výsledkom je knižnica, ktorá vie:
  • Ošetriť zákmity a volať callback funkciu s užívateľským kódom.
  • Pri dlhšom stlačení tlačidla generovať automaticky callback funkciu s užívateľským kódom.

Kód z knižnice, ktorý ošetruje zákmity

V príklade sú vybrané iba podstatné časti kódu. Definície premenných a samotnej triedy Button nájdete v kompletnom zdrojovom kóde knižnice.
  • Prvá časť ošetruje zákmity tlačidla.
  • Druhá časť zabezpečuje opakované volanie callback funkcie. Prvá prestávka trvá 5x definovaný interval a ostatné už trvajú iba definovaný interval. Implicitná hodnota intervalu je 250 ms, čo zabezpečuje svižnú reakciu na stlačené tlačidlo.
void Button::Read()
{
unsigned long ms = millis();  
int value = digitalRead(pin);
if (value != last_value)
  last_debounce_time = ms;

if ((ms - last_debounce_time) > debounce)
  {
  if (value != state)
    {
    state = value;
    pressed = state == LOW;
    last_callback=ms;
    callback_first=true;
    callback(this);
    }
  }
last_value = value;

// handle repeat
if(pressed)
  {
  // first repeat = 5* repeat time
  unsigned long rp = callback_first ? 5*repeat : repeat;
  if((ms - last_callback) > rp)
    {
    last_callback=ms;
    callback_first=false;
    callback(this);
    }
  }
}

Praktické použitie knižnice

Toto je ukážka z kódu, ktorý nastavuje celočíselnú hodnotu. Používa štyri tlačidlá, ktorými sa dá v kompletnom kóde pridávať alebo uberať hodnota. Vybral som z neho iba podstatné časti na pochopenie.
  • OnClickRight je callback funkcia.
  • Definícia Button b4(A3,&OnClickRight); vytvorí objekt b4 na analógovom pine A3 (aj analógové piny fungujú ako digitálne), ktorý je napojený na callback OnClickRight.
    • Alebo Button b4(A3,&OnClickRight,50,200); vytvorí objekt s debounce časom 50 ms a opakovaním stlačenia každých 200 ms.
    • [v. 1.1] Alebo Button b4(A3,&OnClickRight,25,100,true); vytvorí objekt s debounce časom 25 ms, opakovaním 100 ms a interným pull-up rezistorom.
    • [v. 1.1] Alebo Button b4(A3,&OnClickRight,25,0,true); vytvorí objekt bez oakovania s interným pull-up rezistorom.
  • Vo funkcii loop treba len pravidelne volať b4.Read(); a o zvyšok sa postará kód knižnice.
///
/// Cursor to the right
///
void OnClickRight(Button *b)
{
if(b->pressed) {
  // sem dáte vlastný kód
  }
}

Button b1(A0,&OnClickUp);
Button b2(A1,&OnClickDown);
Button b3(A2,&OnClickLeft);
Button b4(A3,&OnClickRight);

///
/// Setup
///
void setup()
{
}

///
/// Main loop
///
void loop()
{
b1.Read();
b2.Read();
b3.Read();
b4.Read();  
}

Na stiahnutie

  • v. 1.0 - Knižnicu si rozbaľte do pracovného adresára ...\Arduino\libraries\ Po jej rozbalení vznikne adresár button, ktorý bude obsahovať všetky potrebné súbory.
  • v. 1.1 - Bola doplnená možnosť používať interné pull-up rezistory.

Video

Vo videu som sa snažil zachytiť zákmity tlačidiel na osciloskope. Vo videu to nie je vidno, ale keď som to celé pripravoval, každé tlačidlo sa správalo inak. Jedno z nich ani náhodou nechcelo robiť zákmity tak, ako ich popisuje literatúra. To tlačidlo bolo skoro dokonalé, zákmit sa objavil možno pri jednom pokuse z desiatich. Našťastie druhé tlačidlo sa už správalo rozumnejšie a na ňom som zachytil celkom pekné priebehy. Trvali priemerne jednu milisekundu.


Download

05.07.2015


Menu