NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Lekce 6 - Arduino - Pokročilá práce s tlačítky

V minulé lekci, Arduino - Projekty s LED diodami a potenciometrem, jsem si ukázali další příklady práce s LED diodami, které již umíme ovládat i pomocí potenciometru.

Dnes se v Arduino HW tutoriálu budeme dále zabývat prací s tlačítkem. Tlačítko je asi nejjednodušší a zároveň nejproblematič­tější součástka, se kterou může Arduino pracovat. Kromě tlačítka totiž musíme zapojit na daný pin přes rezistor i nějakou výchozí hodnotu, aby nedocházelo k rušení ve chvíli, kdy není stisknuté a na pinu by nebyla přivedena ani 0 ani 1.

V předchozích příkladech jste si možná všimli, že tlačítko nereaguje vždy stoprocentně. Není totiž úplně snadné zařídit, aby jedním stisknutím tlačítka došlo k zapnutí a opětovným stisknutím toho samého tlačítka k vypnutí obvodu. Vše si dnes vysvětlíme. V dalších příkladech také budeme chtít, aby držení tlačítka zvyšovalo hodnotu rychleji, než opakované mačkání tlačítka.

Konstrukce tlačítka

Tlačítko, neboli mikrospínač, je elektromechanická součástka. Slouží k vytvoření krátkodobých ovládacích impulzů tak, že sepne nebo přeruší elektrický obvod:

Tlačítek existuje více druhů - Arduino - Hardware

Nejčastěji se tlačítka ve slaboproudé elektronice skládají z plastového hmatníku, kovového plíšku a kontaktů. Impulz pak vzniká stlačováním hmatníku, čímž se prohýbá plíšek, který vodivě spojuje kontakty. Po uvolnění tlačítka se plíšek narovná do původní polohy a funguje tedy i jako vratná pružina:

Princip tlačítka - Arduino - Hardware

Zapojení tlačítka

V programování se při práci s tlačítky používá jednoduché čtení stavů na digitálním nebo analogovém pinu. V prvním případě rozlišujeme pouhé dva stavy, jsou to:

  • logická jednička (1, HIGH, true) a
  • logická nula (0, LOW, false).

Jako logickou 1 bere digitální vstup hodnotu napětí vyšší než 3,0 V. Pro desky s napětím 3,3 V je to hodnota 2 V. Logickou 0 vrací napětí menší než 1,5 V. Pro desky s napětím 1 V je to 3,3 V. Oblast mezi 1,5 V - 3,0 V je tzv. "zakázaná oblast" a procesor na ni nijak nereaguje.

Nestačí ovšem přivést na pin hodnotu jen při stisknutí tlačítka, potřebujeme, aby tam neustále byla jasně definovaná hodnota 1 nebo 0, jinak by došlo k rušení. Výchozí stav se tedy řeší zapojením rezistoru a permanentním přivedením buď stavu 0, nebo 1 na pin, na který je tlačítko připojeno. Těmto dvěma režimům se říká INPUT (pull down) a INPUT_PULLUP (pull up) a každý má své výhody i nevýhody. První z nich vrací defaultně 0, zatímco druhý vrací 1.

Režim INPUT (pull down)

Tento způsob vyžaduje externě připojený "pull-down" rezistor mezi vybraný pin a GND, s hodnotou řádově v kΩ. Nepsaným pravidlem je použití hodnoty 10 kΩ. Takto je pin permanentně připojen k zemi přes velký odpor a je na něm tak logická 0, tj. hodnota LOW. Reagovat pak bude na logickou 1.

Tlačítko se poté připojí mezi napájecí 5V napětí a vybraný pin, na který pak stisknutím přivádí hodnotu HIGH. Osobně mohu tento způsob doporučit, jelikož částečně potlačuje vlivy elektromagnetických rušení, a zvyšuje tak stabilitu projektu.

Pozor! Pokud bychom v této verzi nastavení vstupu zvolili hodnotu rezistoru příliš nízkou, nebo zkratovali pin s GND, může dojít ke zničení procesoru Arduina!

Režim INPUT_PULLUP

Druhá varianta je jednodušší, tlačítko se připojí mezi pin a GND. Uvnitř procesoru Arduina se připojí k pinu interní "pull-up" rezistor, který na pin přivádí přes velký odpor logickou 1. Tento způsob vyhodnocuje logickou 0, čili LOW.

Je vhodný pro ladění na nepájivém kontaktním poli (breadboard), kdy u náročnějších projektů odpadá nutnost externích rezistorů a tedy šetří místo na desce. Avšak v hotovém projektu neodstraňuje vlivy možných rušení.

Rozdíl mezi oběma způsoby je schematicky znázorněn na obrázku:

Arduino pull-up and pull-down rezistory a tlačítko - Arduino - Hardware

Příklad programu

Jdeme na praktickou ukázku programu. Využijeme vestavěnou LED diodu na pinu 13, proto postačí pouze nepájivé pole, pár tlačítek a propojky:

void setup()
{
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT);
  pinMode(13, OUTPUT);
}

void loop()
{
  if (!digitalRead(3)) digitalWrite(13, 1); // můžeme také použít výraz (digitalRead(3) == LOW)
  if (digitalRead(4)) digitalWrite(13, 0);
}

Ve smyčce setup() nastavíme piny 3 a 4 jako vstupy. Jeden je typu INPUT a druhý typu INPUT_PULLUP. A samozřejmě nastavíme i výstup na pinu 13. Stisknutím tlačítka na pinu 3 se LED rozsvítí, stisknutím tlačítka na pinu 4 zhasne. Vcelku jednoduché a spolehlivé.

Ovládání výstupu jedním tlačítkem

Mít jedno tlačítko na vypnutí a druhé na zapnutí může být někdy na obtíž, protože tlačítko na zapnutí a vypnutí často stačí jen jedno společné. Stisknutím zapneme, dalším stisknutím vypneme atd.

Spolehlivé ovládání jediným tlačítkem se může jevit jako snadný úkol, ale nastává tu řada problémů. Stisk tlačítka totiž nikdy není úplně bez závad.

Problém se zákmity

Během jediného stisku může být impulz nestálý, jelikož může mít tzv. "zákmity". To vede ke špatnému vyhodnocení signálu. Program si bude myslet, že impulzů bylo během doby jediného stisknutí několik, a podle toho také provede případné operace (inkrementace, dekrementace, změna stavu, vypnutí atd...) spojené s některou proměnnou.

Demonstrativní ukázkou je program níže. Zde je pro jednoduchost použito tlačítko pinu 3 z předchozí ukázky:

bool svitit = false;
void setup()
{
  pinMode(3, INPUT_PULLUP);
  pinMode(13, OUTPUT);
}

void loop()
{
  if (!digitalRead(3))
  {
    svitit = !svitit;
  }
  digitalWrite(13, svitit);
}

Program obsahuje proměnnou typu bool. Každé stisknutí tlačítka na pinu 3 změní její stav z true na false a naopak. Podobný kód obsluhy jsme měli i v předchozích příkladech. Schválně si však zkusme tlačítko několikrát stisknout. Možná teď vidíte, že se LED dioda rozsvěcí a zhasíná ne zcela pravidelně. Každý cyklus programu totiž čte stav tlačítka, a při kmitočtu 16 MHz je to opravdu hodně čtení za jedinou sekundu.

Řešení pomocí pauzy

Problém lze sice ošetřit pauzou prostřednictvím funkce delay() uvnitř těla podmínky, avšak nejedná se o šťastné řešení:

if (!digitalRead(3))
{
  svitit = !svitit;
  delay(200); // doplněná pauza
}

Co je na tomto řešení špatného? Zkusme tlačítko držet stisknuté delší dobu. Uvidíme, že nám LED dioda bliká. To může v některých případech způsobit problém. Pokud obsluha nechtěně přidrží tlačítko, může se pak výsledné zařízení chovat jinak, než je v daný moment žádoucí.

Řešení s cyklem

Možné řešení je pomocí cyklu while. Není zvlášť složité, a jeho výsledek jistě uspokojí nespočet projektů.

V programu je použita funkce millis(), která nezávisle na běhu programu počítá čas od spuštění Arduina v milisekundách. Jedná se o velice užitečnou funkci, která na rozdíl od funkce delay() nezasekne běh programu. Daní je ale o trošku složitější práce s ní:

unsigned long casomira;
int dobaStisku, limit = 25;
bool svitit;
void setup()
{
  pinMode(3, INPUT_PULLUP);
  pinMode(13, OUTPUT);
}

void loop()
{
  casomira = millis();
  digitalWrite(13, svitit);
  while (!digitalRead(3))
  {
    dobaStisku = millis() - casomira;
  }
  if (dobaStisku >= limit)
  {
    svitit = !svitit;
    dobaStisku = 0;
  }
}

Program obsahuje proměnnou typu unsigned long casomira, která slouží k měření času. Jakmile dojde ke stisknutí tlačítka, spustí se cyklus, který se provádí tak dlouho, dokud je tlačítko stisknuté. Uvnitř cyklu se měří doba stisku, kdy se od proměnné casomira odečítá hodnota millis(). Tento rozdíl se ukládá do proměnné dobaStisku.

Po uvolnění tlačítka měření ustává a následně se testuje, zda je doba stisku větší než požadovaný limit (v ukázce 25 ms). Pokud je tato podmínka splněna, změní se stav proměnné svitit, což vede k rozsvícení/zhasnutí LED diody. Nakonec vynulujeme proměnnou pro dobu stisku. Právě limit 25 ms v drtivé většině případů spolehlivě eliminuje případné zákmity tlačítka i rušivé vlivy.

Pokud by nedošlo k vynulování doby stisku, byl by program stejně nestabilní, jako v předchozích ukázkách!

Takto máme tedy jistotu, že každý stisk tlačítka bude zaznamenán jako jeden. Tento způsob nás samozřejmě neomezuje pouze na změnu stavů true/false, ale lze ho použit i jinde, například při výběru v menu možností, zvyšování/snižování požadované teploty, času, úrovně intenzity světla atd.

Dlouhý stisk tlačítka

Pojďme na poslední příklad. V něm budeme chtít změnit postupnými stisky například hodnotu od 0 do 255 pro PWM regulaci. V uvedených příkladech bychom museli desítky vteřin zběsile mačkat tlačítko, než se jas zvýší na maximum. Nešlo by to nějak pořešit? Samozřejmě, že šlo!

Po lehké úpravě můžeme elegantně tlačítkem měnit jas externí LED diody buď mačkáním, nebo dlouhým stiskem. Zapojímee obvod podle přiloženého schématu:

AnalogSche - Arduino - Hardware

Obslužný kód bude nyní následující, hned si jej vysvětlíme:

unsigned long casomira;
int dobaStisku, limit = 25;
byte pwm = 0;

void setup()
{
  pinMode(3, INPUT_PULLUP);
  pinMode(5, OUTPUT);
}

void loop()
{
  casomira = millis();
  analogWrite(5, pwm);
  while(!digitalRead(3))
  {
    dobaStisku = millis() - casomira;
    if (dobaStisku > 150)
    {
       break;
    }
  }

  if (dobaStisku >= limit && pwm < 255)
  {
    pwm += 5;
    dobaStisku = 0;
  }
}

Podmínka uvnitř cyklu říká programu, ať přeruší cyklus pokud dobaStisku překročí hodnotu 150 ms. Tato hodnota byla zvolena záměrně takto nízká. Tím je samozřejmě splněna i základní limitní podmínka 25 ms, tedy dojde k navýšení hodnoty PWM o 5 a vynulování doby stisku. V základní podmínce je ještě zarážka pro jas pwm < 255. Bez ní by po překročení hodnoty LED dioda nepříjemně blikla.

Určitě bychom při programování více než jednoho tlačítka použili pro tlačítko třídu, nebo si rovnou vytvořili vlastní Knihovnu pro přehlednější práci.

Do projektu si můžete vyzkoušet přidat i část pro snižování jasu nebo jinak lehce experimentovat.

V další lekci, Arduino - Membránová klávesnice a její programování, si ukážeme a popíšeme membránovou klávesnici a vytvoříme nové projekty, ve kterých se ji naučíme používat.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 295x (1.53 kB)
Aplikace je včetně zdrojových kódů

 

Předchozí článek
Arduino - Projekty s LED diodami a potenciometrem
Všechny články v sekci
Arduino - Hardware
Přeskočit článek
(nedoporučujeme)
Arduino - Membránová klávesnice a její programování
Článek pro vás napsal Vašek Doškář
Avatar
Uživatelské hodnocení:
41 hlasů
Autor pracuje jako pedagog v oblasti elektroniky, elektrotechniky a programování. Rád tvoří appky všeho druhu. Má přehled v jazycích C#, Java, Kotlin, Javascript, Python a Rust
Aktivity