12. diel - Arduino - Jazyk 2
V minulom tutoriále o Arduino sme začali popisovať programovací jazyk. Dnešným dielom jeho popis dokončíme.
Funkcie
Máme dve základné funkcie - setup () a loop (). Ako už vieme, setup sa vykoná len raz, loop v slučke. Ako príklad si vezmime situáciu, kedy chceme zablikať diódou. Ak budete otrocky vo všetkých prípadoch vypisovať
... digitalWrite(13, HIGH); // zabliká delay(500); digitalWrite(13, LOW); delay(500); digitalWrite(13, HIGH); delay(500); ... ... ... digitalWrite(13, HIGH); // zabliká delay(500); digitalWrite(13, LOW); delay(500); digitalWrite(13, HIGH); delay(500); ... ... ... digitalWrite... //zabliká
tak môžete, ja vám v tom nebránim. Ale nebolo by jednoduchšie riešenie? Samozrejme, že je. Deklarujeme si vlastné funkciu! Tá sa deklaruje pomocou void, môže brať aj nejaké vstupné parametre a prípadne i vracať nejakú hodnotu.
void blikniPin13() //nastavíme blikání { digitalWrite(13, HIGH); delay(500); digitalWrite(13, LOW); delay(500); digitalWrite(13, HIGH); delay(500); digitalWrite(13, LOW); } void loop() { ... blikniPin13(); //zabliká ... ... blikniPin13(); ... ... blikniPin13(); ... }
Nie je to jednoduchšie? A výhod je oveľa viac. Ak sa rozhodnete, že LEDka nebude blikať po pol sekunde, ale po jednej sekunde, nemusíte v kóde hľadať všetky miesta, kde sa bliká. Len vo funkcii prepíšete tých pár delay čo tam sú a razom sa zmení úplne všetko. A čo keby sme chceli rovnakým spôsobom klikať na viac pinoch? Nebudeme vypisovať funkcie blinkiPin13, blikniPin12, blikniPin11, atď., Ale ďalej funkciu vstupný parameter:
void blik(int pin) { digitalWrite(pin, HIGH); delay(500); digitalWrite(pin, LOW); ... } void loop() { ... ... blikni(13); //blikání na pinu 13 ... blikni(10); //blikání na pinu 10 ... }
Ak sa funkcia dokončí, vráti sa kód na miesto, kde sa funkcie zavolala, a pokračuje ďalej.
Poľa
Ospravedlňujem sa skúseným programátorom, vás teraz budem chvíľu nudiť V minulom diele sme vyriešili premenné. Čo keby sme potrebovali urobiť databázu užívateľov? Čo treba skúsiť niečo takéto:
String user1 = "pepa"; String user2 = "karel"; ...
Určite si domyslíte, že takto by to nešlo. A čo keby sme mali treba 500 užívateľov (u Arduino to moc nehrozí, ale jeden nikdy nevie). K tomuto je lepšie použiť pole (tie sme načali už v tomto diele). Čo to pole vôbec je? My si môžeme predstaviť premennú ako kartičku s menom používateľa. Pole si môžeme predstaviť ako zakladač, v ktorom sú kartičky narovnané do priehradiek. V tom sú zoradené podľa čísel a môžeme ich jednotlivo vyvolávať.
// databáze uživatelů String uzivatele[5] = { "Pepa" , "David", "Franta", "Karel", "Michal" }; //v poli uzivatele je ulozeno 5 uzivatelu
nie je to jednoduchšie? Všimnite si, že pred názvom musíme udať typ, ktorý skladujeme. A ako vyvolávame?
Serial.println(uzivatele[0]); >>>Pepa Serial.println(uzivatele[4]); >>>Michal Serial.println(uzivatele[1]); >>>David
Pretože programátori začínajú vždy od nuly, tak Pepa nie je pod indexom 1, ale pod indexom 0. Pod jednotkou je David, trojku má Franta ... A čo keby sme chceli okrem užívateľov ukladať aj redaktorov a administrátorov? Je tu možnosť poľa uzivatele, pole redaktor, pole administrátor, ale je aj jednoduchšia možnosť.
A v desiatom diele sme sa stretli s pokročilejším poľom - 2D poľom. To si môžeme predstaviť tak, že kartičky sú v zoraďovačoch a zakladače sú umiestnené do skrine. Opäť tu použijem to pomenovanie "pole polí", pretože to je niekoľko polí v poli. Vyzeralo by to nejako takto:
String clenove[3][5] = { {"Honza", "Jenda", "Mirek", "Jirka", "user"}, //uzivatele {"Nikola", "Adam", "Zdenda"}, //redaktoři {"David", "Michal"}, //admini }; //neberte ta jména osobně, je to jen příklad :)
Zas musíme napísať, čo v poli ukladáme. V našom prípade tam je string, takže String. Potom musíme do hranatých zátvoriek napísať počet polí a maximálnu hodnotu, ktorú každé pole pojme. Ak by sme 5 znížili na 4, tak redaktori a admini prejdú, ale pretože užívateľov, 5, tak to vyhodí chybu. A už si asi domyslíte vyvolanie:
Serial.println(clenove[2][0]); >>>David Serial.println(clenove[0][3]); >>>Jirka
To by boli polia, tak čo tu máme ďalej?
Knižnice
Knižnice už sme tak raz načali a to v tomto diele, ale ja ich tu znovu pripomeniem, aby sme tu mali všetko. Knižnice slúžia k tomu, aby sme nemuseli veľa vecí zložito programovať, pretože už to niekto vyriešili za nás. Podrobnejšie sa na ne pozrieme v budúcom diele, kde si aj nejakú vytvoríme.
Uvádzacích
Vo štvrtom diele sa objavil jeden nevysvetlený riadok:
Serial.println("Ajaj, asi sem ti nerozumel. Napis \"t\" pro teplotu a \"v\" pro vlhkost."); >>> Ajaj, asi jsem ti nerozumel. Napis "t" pro teplotu a "v" pro vlhkost.
Čo sa tu stalo? Prečo sa nevypísala tá lomky? A prečo je to jeden reťazec, keď tam je niekoľko úvodzoviek? Riešenie je jednoduché. Nastala nám tu situácie, kde potrebujeme do stringu pridať úvodzovky, ale úvodzovky nám string ukončí. Čo s tým? Použijeme tzv. Uvádzacích, kde sa pomocou spätného lomítka "zruší" význam nasledujúceho znaku. Takže ak chceme do stringu vypísať úvodzovky, musíme napísať \ ". Čo ale keď chceme napísať spätné lomítko? No, proste ho odescapujeme - * \ *.
Komentáre
Pokiaľ si do kódu potrebujete niečo poznamenať, alebo časť deaktivovať bez mazania, existujú komentáre. Máme dva typy - jednoriadkové a viac riadkové
// toto je jednořádkový komentář, ale tato část se již bere jako kód /* pokud chceme komentář na více řádků, stačí použít tento zápis */
Cykly
Ak potrebujeme, aby sa nám niečo opakovalo, môžeme použiť slučku. Máme v podstate dva typy - for a while. For je slučka, ktorá vykonáva kód pre každú hodnotu riadiace premenné:
for (promena; podminka; akce)
V slučke for najskôr vytvoríme premennú. Potom za bodkočiarkou napíšeme podmienku, ktorá musí platiť, aby sa slučka vykonala. Za posledný bodkočiarka potom príde akcie, ktorá sa po každom vykonaní s premennou urobí. Ak by sme napríklad chceli vypísať čísla od nuly do deviatich, môžeme to urobiť takto:
void setup() { Serial.begin(9600); for (int i = 0; i < 10; i++) { Serial.println(i); } } void loop() {}
Otvorenie sériového portu poznáme. Pod ním je cyklus for. Najskôr vytvoríme premennú int is hodnotou nula. Podmienka je, že aj bude menšia ako desať. Pokiaľ bude presne desiatich, alebo väčšie (k čomu tu nemôže dôjsť), tak sa cyklus prestane vykonávať a kód prejde ďalej. Posledný je akcia, ktorá sa s premennou vykoná, teda sa k nej pripočíta jedna. Cyklus sa teda vykoná, keď je vi nula, pripočíta sa 1, i je jedna, znovu sa vykoná a tak ďalej. A while?
While znamená kým. Ten sa hodí, ak treba chceme, aby pri stlačení tlačidla začala blikať LEDka a neprestala kým tlačidlo neuvoľníme.
while(digitalRead(10)) { // blikání }
Tak dlho, ako do pinu 10 bude prúdiť prúd. Čo ale keby sme chceli, aby sa cyklus spustil pri štarte Arduino a neukončil sa, kým nestiskneme jedno tlačidlo alebo druhé tlačidlo? Išlo by to nejako skombinovať do podmienky while, ale ak by pribudlo tretie tlačidlo, potom štvrté ... Predsa musí existovať lepší spôsob, ako slučku ukončiť. Takže dajme tomu, že pri spustení Arduino sa začne vykonávať cyklus, ktorý bude niečo robiť a ukončí sa až pri stlačení jedného, druhého, tretieho alebo štvrtého tlačidlá bez neprehľadného zápisu v podmienke. Ako? Pomocou príkazu break, ktorý cyklus ukončí.
... while(true) // nekonečná podmínka, ukončí se jen příkazem break, { // pokud k tomu nemáte pádný důvod, nepoužívejte jí ... if(digitalRead(10)) break; if(digitalRead(11)) break; ...
V nejakých situácií to môže byť lepšie ako hromada podmienok v jednom riadku, nemali by sme konštrukciu však používať príliš často? To je snáď všetko, v budúcom dieli sa pozrieme na knižnice a jednu si aj vytvoríme (snáď).