7. diel - Čítanie užívateľských vstupov v Arduine
V minulej lekcii, Cykly a ich syntax a použitie , som sa zoznámili s cyklami v jazyku Wiring a ukázali si ich použitie.
V dnešnej lekcii Arduino tutoriálu sa budeme zaoberať témou čítania vstupov zadaných užívateľom. Čítanie vstupu od užívateľov je jednou z kľúčových funkcií v programovaní pre platformu Arduino. Umožňuje nám reagovať na akcie užívateľov. Tí môžu takto napríklad rozsvietiť LED diódy, nastavovať im intenzitu jasu a podobne regulovať rôzne komponenty.
V tomto článku si ukážeme rôzne spôsoby, ako čítať vstupy od používateľov. Uvedieme si aj konkrétne príklady, ako jednotlivé funkcie na čítanie implementovať do nášho kódu.
Funkcia Serial.available()
Predstavme si najskôr funkciu Serial.available()
. Pomocou tejto
funkcie získame informáciu o počte bajtov, ktoré sú k dispozícii na
čítanie v prijímacom buffere sériového portu. Môžeme ju teda použiť na
overenie, či sú k dispozícii údaje na prečítanie. Ďalšie funkcie tak
budeme volať až potom, čo používateľ pošle dáta na čítanie.
Funkcia Serial.available()
vracia celé číslo
zodpovedajúce počtu bajtov, ktoré máme k dispozícii. Pokiaľ je v bufferi
10 bajtov, vráti nám hodnotu 10
a podobne. Kým používateľ
nič nezadá, vracia funkcia hodnotu 0
.
Funkciu Serial.available()
použijeme v
kombinácii s cyklom while
alebo s podmienkou, aby sme overili, či
sú k dispozícii dáta na prečítanie. Až potom sa pustíme do samotného
čítania dát.
Použitie
Serial.available()
s while
cyklom
Príklad využitia funkcie Serial.available()
s
while
cyklom vyzerá takto:
byte hodnota_vstupu; void setup() { Serial.begin(9600); } void loop() { while (Serial.available() > 0) { hodnota_vstupu = Serial.read(); // Nyní s načtenou hodnotu můžeme dále pracovat, my si ji necháme vypsat. Serial.println(hodnota_vstupu); } }
Pomocou while
cyklu zisťujeme, či je hodnota funkcie
Serial.available()
vyššia ako 0
. Pokiaľ áno,
prikročíme k čítaniu dát a ich spracovaniu v tele cyklu.
Použitie
Serial.available()
s podmienkou
Použitie podmienky je podobné. Funkcia loop()
potom vyzerá
takto:
void loop() { if (Serial.available() > 0) { hodnota_vstupu = Serial.read(); // Nyní s načtenou hodnotu můžeme dále pracovat, my si ji necháme vypsat. Serial.println(hodnota_vstupu); } }
Na čítanie dát z užívateľského existuje niekoľko
funkcií. V ukážkach vyššie sme použili funkciu
Serial.read()
. K dispozícii máme ale aj ďalšie funkcie. Všetky
sa používajú na čítanie, avšak je medzi nimi rozdiel. Ten spočíva v tom,
aký typ dát chceme čítať a akým spôsobom sú tieto
dáta spracované. Poďme si ich postupne ukázať a popísať
si ich špecifiká.
Funkcia
Serial.readString()
Na prácu s textovými reťazcami využijeme funkciu
Serial.readString()
. Funkcia nám dobre poslúži, ak očakávame
na vstupe od užívateľa zadaný text.
Ukážkový kód s implementáciou tejto funkcie vyzerá nasledovne:
String text_vstup; // Vytvoříme si proměnnou typu String pro uložení textového řetězce. void setup() { Serial.begin(9600); // Nastavíme sériový monitor. } void loop() { if (Serial.available() > 0) // Zkontrolujeme, zda se v bufferu nacházejí data. { text_vstup = Serial.readString(); // Přečteme data a uložíme je do naší proměnné. Serial.print("Vase zprava: "); Serial.println(text_vstup); // Vypíšeme získaná data do sériového monitoru. } }
Pozor! Vývojové prostredie Tinkercad, ktoré v kurze používame, nepodporuje slovenskú diakritiku. Texty je teda potrebné písať bez háčikov a čiarok a ďalších špeciálnych znakov.
Funkcia Serial.read()
Prejdime k funkcii Serial.read()
. Táto funkcia číta
jeden bajt dát z buffera sériového portu a vracia ho
ako celé číslo. Postupne teda načíta dáta zo sériového portu a
vracia ASCII hodnotu pre každý zadaný znak. Funkciu
Serial.read()
môžeme použiť na čítanie ľubovoľného
typu dát.
Upravme náš ukážkový príklad a nechajme si vypísať hodnoty získané
pomocou funkcie Serial.read()
:
byte znak_vstup; // Vytvoříme si proměnnou typu byte pro uložení znaku. void setup() { Serial.begin(9600); } void loop() { if (Serial.available() > 0) // Zkontrolujeme, zda se v bufferu nacházejí data. { znak_vstup = Serial.read(); // Načteme zadaný znak a uložíme ho do naší proměnné. Serial.print("ASCII hodnota vlozeneho znaku: "); Serial.println(znak_vstup); // Vypíšeme číslo odpovídající hodnotě znaku v ASCII tabulce. } }
Ak napríklad zadáme písmeno a
, vypíše sa nám hodnota
97
. To je hodnota znaku a
ASCII kódovaní. Zadaním
písmena b
získame 98
atď. Skúsme si v príklade
zadať dlhší text, napr. ahoj
. Vidíme, že funkcia
Serial.read()
prejde postupne všetky znaky a vypíše pod seba ich
ASCII hodnoty.
Keby sme pomocou funkcie Serial.read()
načítali
číselnú hodnotu, získame opäť jej ASCII kód. Číslo 1
má
hodnotu 49
atď.
Funkcia Serial.parseInt()
Ukážme si teraz spracovanie celočíselných hodnôt načítaných zo
sériového portu. Na to nám najlepšie poslúži funkcia
Serial.parseInt()
. Funkcia číta bajty z bufferu, kým nenarazí
na koniec čísla alebo na iný nečíselný znak (napr. medzeru alebo koncový
znak reťazca).
Načítanie celých čísel potom vyzerá nasledovne:
int cislo_vstup; void setup() { Serial.begin(9600); } void loop() { if (Serial.available() > 0) { cislo_vstup = Serial.parseInt(); Serial.print("Vlozene cislo: "); Serial.println(cislo_vstup); } }
Ako dátový typ našej premennej sme použili int
. Skúsme si
ho v kóde prepísať na byte
. Vieme, že premenné typu
byte
môžu nadobúdať hodnoty 0
až
255
. Keď teraz zadáme -2
, prekročíme limit typu
byte
a na sériovom monitore sa nám vypíše 254
. Ak
funkciu Serial.parseInt()
skúsime poslať znak alebo celý
textový reťazec, vráti nám hodnotu 0
.
Parsovanie vstupu
Funkcia Serial.parseInt()
, ktorú sme si popísali vyššie, je
súčasťou knižnice Serial
pre Arduino. Túto funkciu je možné
volať priamo na objekte Serial
a automaticky prevádza
reťazec v bufferi na celé číslo. Prevodu dátových typov sa
hovorí parsovanie a tento termín figuruje už v názve
funkcie.
Pre parsovanie existuje ale aj metóda toInt()
. Tú využijeme,
kedykoľvek budeme potrebovať previesť textový reťazec na celé číslo.
Túto metódu voláme priamo na objekte typu
String
.
Rovnaký výsledok, ako v predchádzajúcom príklade, dosiahneme s
použitím metódy toInt()
nasledovne:
String vstup; int cislo; void setup() { Serial.begin(9600); } void loop() { if (Serial.available() > 0) { vstup = Serial.readString(); cislo = vstup.toInt(); Serial.print("Vlozene cislo: "); Serial.println(cislo); } }
Zadaný vstup sme teda najskôr načítali a uložili ako textový reťazec
funkciou readString()
. Potom sme do premennej typu int
uložili parsovaný vstup. Výsledok sme si opäť nechali vypísať na
sériový monitor.
Ošetrenie vstupov
Zastavme sa ešte pri téme, ktorá s čítaním vstupov úzko súvisí. V našom programe je veľmi dôležité myslieť aj na ošetrenie nesprávne zadaných hodnôt. Ide napríklad o prípad, keď vyžadujeme číslo a užívateľ nám zadá text. V našej aplikácii ho potom na to musíme upozorniť, aby sa program správal predvídateľne.
Na ošetrenie vstupov využijeme podmienky, prípadne konštrukciu
switch
.
Pre kontrolu, či používateľ zadal číslo, upravíme predchádzajúci kód napríklad takto:
String vstup; int cislo; void setup() { Serial.begin(9600); } void loop() { if (Serial.available() > 0) { vstup = Serial.readString(); cislo = vstup.toInt(); if (cislo != 0) { Serial.print("Vlozene cislo: "); Serial.println(cislo); } else { Serial.println("Nespravna hodnota, zadej znovu."); } } }
Pokiaľ sa nám podarí načítať číselnú hodnotu, necháme ju vypísať na sériový monitor. Ak používateľ zadá nečíselný znak, vyzveme ho na zadanie novému vstupu.
V nasledujúcom kvíze, Kvíz - Dátové typy, podmienky a cykly v Arduine, si vyskúšame nadobudnuté skúsenosti z predchádzajúcich lekcií.