ATtiny85 - Tlačidlá

Zápisník experimentátora

Hierarchy: ATtiny85

Tlačidlá sú jednoduché súčiastky, pomocou ktorých môžete komunikovať s mikrokontrolérom. Obvykle sa využívajú mikrospínače, ktoré nájdete aj v bežnej spotrebnej elektronike. V dnešnom článku si vysvetlíme základné použitie tlačidiel a naprogramujeme si aj jednoduchý stavový automat, v ktorom budeme musieť ošetriť zákmity tlačidiel.

Ako funguje tlačidlo

Tlačidlo je jednoduchá súčiastka. Stlačením tlačidla sa medzi sebou vodivo prepoja dva vývody. V mikrokontroléri ATtiny85 vieme na pine zistiť, či sa na ňom nachádza logická nula alebo jednotka. Keby sme ale tlačidlo napriamo pripojili, jeden koniec na pin a druhý na GNG alebo VCC, nedokázali by sme spoľahlivo rozlíšiť, či je na tlačidle v rozpojenom stave nejaká definovaná úroveň napätie. Preto sa využíva pull-up rezistor, ktorý nám tlačidlo v rozpojenom stave pridrží na úrovni VCC. V praxi sa potom často namiesto externého rezistora využíva interný pull-up rezistor, ktorý je priamo v mikrokontroléri.

Pretože v mikrokontroléri ATtiny85 máme iba interné pull-up rezistory, obvykle budeme tlačidlo pripájať tak, ako je nakreslené v schéme. Stlačené tlačidlo bude na pine signalizovať logickú nulu a nestlačené tlačidlo logickú jednotku. Obvyklá hodnota pre rezistor je 10k. Ak použijeme interný rezistor, jeho hodnota je približne 50k. Táto hodnota nie je kritická a iba vo výnimočnom prípade (napríklad pri zvýsenom riziku výskytu rušivých signálov) by sa mohla použiť iná hodnota.

Indikácia stlačenia tlačidla pomocou LED

Najjednoduchším príkladom je rozsvietenie LED diódy pri stlačení tlačidla. Zapojenie je podľa priloženej schémy. Rezistor pri tlačidle má hodnotu 10k, rezistor pri LED dióde má hodnotu 1k. Aby sme mohli prečítať logickú hodnotu na pine, musíme pin definovať ako vstup pomocou funkcie pinMode. Funkciou digitaRead si prečítame logickú hodnotu na pine.

Pretože je stlačenie tlačidla detekované ako logická nula, musíme logickú hodnotu negovať, aby LED dióda svietila pri stlačenom tlačidle. To by sme mohli urobiť pomocou funkcie if a else, ale na takéto jednoduché úlohy je vhodné používať aj podmienený trojčlenný operátor (conditional ternary operator), ktorý vyhodnotí logickú hodnotu prvého výrazu a podľa výsledku dosadí druhý alebo tretí výraz. Zdrojový kód button_state ? LOW : HIGH znamená, použi LOW ak je button_state true a HIGH ak je button_state false.

const int led = 0;
const int button = 1;
int button_state = LOW;

void setup() {
  pinMode(led, OUTPUT);
  pinMode(button, INPUT);
}

void loop() {
  button_state = digitalRead(button);
  digitalWrite(led, button_state ? LOW : HIGH);
}

Interný pull-up rezistor

Spomenul som, že môžeme použiť aj interný rezistor a ušetriť si tak jeden externý rezistor. Program je skoro identický, len do funkcie pinMode použijeme ako druhý parameter INPUT_PULLUP. Zapojenie je podľa prvého obrázku.

const int led = 0;
const int button = 1;
int button_state = LOW;

void setup() {
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP);
}

void loop() {
  button_state = digitalRead(button);
  digitalWrite(led, button_state ? LOW : HIGH);
}

Zapnutie a vypnutie jedným tlačidlom

Druhým príkladom, ktorému sa budeme venovať je stavový automat, ktorý bude mať dva stavy. Prvý stav predstavuje vypnutú LED diódu. Druhý stav predstavuje zapnutú LED diódu.

Asi vás hneď napadne možné riešenie problému. Budete sledovať zmenu stavu na pine a podľa toho prepnete stav LED diódy. Má to ale drobný problém. Kontakty v tlačidle nefungujú dokonale a každé zopnutie kontaktov je sprevádzané drobnými zákmitmi. Počas niekoľkých milisekúnd sa kontakty viackrát zopnú a rozopnú, kým sa neustália v zopnutom stave. Výsledkom bude prepínanie stavu LED diódy, ktoré niekedy zareaguje správne a inokedy nie. Závisí to od toho, ako rýchlo dokáže váš program zaznamenať zmenu stavu. A mikrokontrolér ATtiny85 je aj na frekvencii 1 MHz schopný veľmi rýchlo sledovať zmeny a viackrát prepnúť stav LED diódy počas jedného stlačenia. Príklad takéhoto nespoľahlivého programu je v nasledovnom kóde.

const int led = 0;
const int button = 1;
int button_state = LOW;
int led_state = LOW;

void setup() {
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP);
}

void loop() {
  button_state = digitalRead(button);
  if(button_state == LOW)
    led_state = !led_state;
  digitalWrite(led, led_state);
}

Na odstránenie tohto problému sa využíva nasledovný kód. Po zistení zmeny stavu sa čaká niekoľko milisekúnd a ak zmena stavu je stále rovnaká, je to považované za stlačenie tlačidla.

const int led = 0;
const int button = 1;
int led_state = LOW;

// Button states and debounce
int buttonState = 0;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;

void setup() {
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP);
}

void loop() {
  int reading = digitalRead(button);
  if (reading != lastButtonState)
    lastDebounceTime = millis();

  if ((millis() - lastDebounceTime) > 50) {
    if (reading != buttonState) {
      buttonState = reading;
      if (buttonState == LOW) {
        led_state = !led_state;
      }
    }
  }

  lastButtonState = reading;

  digitalWrite(led, led_state);
}

Pokiaľ budete mať iba jedno tlačidlo, predchádzajúci kód bude fungovať dobre. Pokiaľ budete používať viac tlačidiel, je vhodné kód na spracovanie zákmitov presunúť do samostatnej triedy a využívať ho v podobe objektu. Takýto kód si nemusíte písať sami a je vhodné, ak siahnete po existujúcej knižnici. Napríklad knižnica Bounce2 vám poskytne dostatok funkcií na vyriešenie najrôznejších situácií. Predchádzajúci príklad bude pomocou tejto knižnice vyzerať takto.

#include <Bounce2.h>

const int led = 0;
const int button = 1;
int led_state = LOW;

Bounce debouncer;

void setup() {
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP);
  debouncer.attach(button);
  debouncer.interval(5);
}

void loop() {
  debouncer.update();
  if (debouncer.fell())
    led_state = !led_state;

  digitalWrite(led, led_state);
}

Tlačidlá a ATtiny85

V niekoľkých príkladoch sme si ukázali, ako sa ovládajú tlačidlá pomocou mikrokontroléra ATtiny85. Príklady sú napísané univerzálne, preto by mali bez problémov fungovať aj pre Arduino.

Zdrojový kód

Zdrojový kód sa nachádza na serveri GitHub.


26.02.2018


Menu