12. díl - Arduino - Jazyk 2

Hardware PC Arduino Arduino - Jazyk 2

V minulém tutoriálu o Arduinu jsme začali popisovat programovací jazyk. Dnešním dílem jeho popis dokončíme.

Funkce

Máme dvě základní funkce - setup() a loop(). Jak již víme, setup se vykoná jen jednou, loop ve smyčce. Jako příklad si vezměme situaci, kdy chceme zablikat diodou. Pokud budete otrocky ve všech případech vypisovat

...
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, já vám v tom nebráním. Ale nebylo by jednodušší řešení? Samozřejmě, že je. Deklarujeme si vlastní funkci! Ta se deklaruje pomocí void, může brát i nějaké vstupní parametry a případně i vracet nějakou 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();
    ...
}

Není to jednoduší? A výhod je mnohem více. Pokud se rozhodnete, že LEDka nebude blikat po půl vteřině, ale po jedné vteřině, nemusíte v kódu hledat všechna místa, kde se bliká. Jen ve funkci přepíšete těch pár delay co tam jsou a rázem se změní úplně vše. A co kdybychom chtěli stejným způsobem klikat na více pinech? Nebudeme vypisovat funkce blinkiPin13, blikniPin12, blikniPin11, atd., ale dále funkci vstupní parametr:

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
        ...
}

Pokud se funkce dokončí, vrátí se kód na místo, kde se funkce zavolala, a pokračuje dál.

Pole

Omlouvám se zkušeným programátorům, vás teď budu chvíli nudit :) V minulém díle jsme dořešili proměnné. Co kdybychom potřebovali udělat databázi uživatelů? Co třeba zkusit něco takovéto:

String user1 = "pepa";
String user2 = "karel";
...

Určitě si domyslíte, že takhle by to nešlo. A co kdybychom měli třeba 500 uživatelů (u Arduina to moc nehrozí, ale jeden nikdy neví). K tomuto je lepší použít pole (ty jsme nakousli už v tomto díle ). Co to pole vůbec je? My si můžeme představit proměnnou jako kartičku se jménem uživatele. Pole si můžeme představit jako pořadač, ve kterém jsou kartičky narovnány do přihrádek. V tom jsou seřazeny podle čísel a můžeme je jednotlivě vyvolávat.

// databáze uživatelů
String uzivatele[5] = { "Pepa" , "David", "Franta", "Karel", "Michal" };
//v poli uzivatele je ulozeno 5 uzivatelu

není to jednodušší? Všimněte si, že před názvem musíme udat typ, který skladujeme. A jak vyvoláváme?

Serial.println(uzivatele[0]);

>>>Pepa

Serial.println(uzivatele[4]);

>>>Michal

Serial.println(uzivatele[1]);

>>>David

Protože programátoři začínají vždy od nuly, tak Pepa není pod indexem 1, ale pod indexem 0. Pod jedničkou je David, trojku má Franta... A co kdybychom chtěli kromě uživatelů ukládat i redaktory a administrátory? Je tu možnost pole uzivatele, pole redaktori, pole administratori, ale je i jednodušší možnost.

A v desátém díle jsme se setkali s pokročilejším polem - 2D polem. To si můžeme představit tak, že kartičky jsou v pořadačích a pořadače jsou umístěny do skříně. Opět zde použiji to pojmenování "pole polí", protože to je několik polí v poli. Vypadalo by to nějak 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 napsat, co v poli ukládáme. V našem případě tam je string, takže String. Poté musíme do hranatých závorek napsat počet polí a maximální hodnotu, kterou každé pole pojme. Pokud bychom 5 snížili na 4, tak redaktoři a admini projdou, ale protože uživatelů je 5, tak to vyhodí chybu. A už si asi domyslíte vyvolání:

Serial.println(clenove[2][0]);

>>>David

Serial.println(clenove[0][3]);

>>>Jirka

To by byly pole, tak co tu máme dále?

Knihovny

Knihovny už jsme tak jednou nakousli a to v tomto díle, ale já je tu znovu připomenu, abychom tu měli všechno. Knihovny slouží k tomu, abychom nemuseli spoustu věcí složitě programovat, protože již to někdo dořešil za nás. Podrobněji se na ně podíváme v příštím díle, kde si i nějakou vytvoříme.

Escapování

Ve čtvrtém díle se objevil jeden nevysvětlený řádek:

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.

Co se tu stalo? Proč se nevypsala ta lomítka? A proč je to jeden řetězec, když tam je několik uvozovek? Řešení je jednoduché. Nastala nám zde situace, kde potřebujeme do stringu přidat uvozovky, ale uvozovky nám string ukončí. Co s tím? Použijeme tzv. escapování, kde se pomocí zpětného lomítka "zruší" význam následujícího znaku. Takže pokud chceme do stringu vypsat uvozovky, musíme napsat \". Co ale když chceme napsat zpětné lomítko? No, prostě ho odescapujeme - *\*.

Komentáře

Pokud si do kódu potřebujete něco poznamenat, nebo část deaktivovat bez mazání, existují komentáře. Máme dva typy - jednořádkové a více řádkové

// 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

Pokud potřebujeme, aby se nám něco opakovalo, můžeme použít smyčku. Máme v podstatě dva typy - for a while. For je smyčka, která vykonává kód pro každou hodnotu řídící proměnné:

for (promena; podminka; akce)

Ve smyčce for nejdříve vytvoříme proměnnou. Poté za středníkem napíšeme podmínku, která musí platit, aby se smyčka vykonala. Za poslední středník pak přijde akce, která se po každém vykonání s proměnnou udělá. Pokud bychom třeba chtěli vypsat čísla od nuly do devíti, můžeme to udělat takto:

void setup()
{
        Serial.begin(9600);
        for (int i = 0; i < 10; i++) {
                Serial.println(i);
        }
}

void loop() {}

Otevření sériového portu známe. Pod ním je cyklus for. Nejdříve vytvoříme proměnnou int i s hodnotou nula. Podmínka je, že i bude menší než deset. Pokud bude rovno deseti, nebo větší (k čemuž tady nemůže dojít), tak se cyklus přestane vykonávat a kód přejde dál. Poslední je akce, která se s proměnnou vykoná, tudíž se k ní přičte jedna. Cyklus se tedy provede, když je v i nula, přičte se 1, i je jedna, znovu se provede a tak dále. A while?

While znamená dokud. Ten se hodí, pokud třeba chceme, aby při zmáčknutí tlačítka začala blikat LEDka a nepřestala dokud tlačítko neuvolníme.

while(digitalRead(10))
{
        // blikání
}

Tak dlouho, jak do pinu 10 bude proudit proud. Co ale kdybychom chtěli, aby se cyklus spustil při startu Arduina a neukončil se, dokud nestiskneme jedno tlačítko nebo druhé tlačítko? Šlo by to nějak zkombinovat do podmínky while, ale pokud by přibylo třetí tlačítko, pak čtvrté... Přece musí existovat lepší způsob, jak smyčku ukončit. Takže dejme tomu, že při spuštění Arduina se začne vykonávat cyklus, který bude něco dělat a ukončí se až při stisknutí jednoho, druhého, třetího nebo čtvrtého tlačítka bez nepřehledného zápisu v podmínce. Jak? Pomocí příkazu break, který 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 nějakých situací to může být lepší než hromada podmínek v jednom řádku, neměli bychom konstrukci ovšem používat příliš často? To je snad všechno, v příštím dílu se podíváme na knihovny a jednu si i vytvoříme (snad).


 

  Aktivity (1)

Článek pro vás napsal Adam Ježek
Avatar
Autor se převážně věnuje Arduinu a psaní tutoriálů z této oblasti, občas napíše příležitostně nějakou tu zprávičku. Většinu svého volného času momentálně věnuje Linuxu a/nebo Raspberry Pi. Také umí C#, HTML, CSS, PHP a Python.

Jak se ti líbí článek?
Celkem (4 hlasů) :
55555


 


Miniatura
Předchozí článek
Arduino - Jazyk
Miniatura
Všechny články v sekci
Arduino
Miniatura
Následující článek
Arduino a SD karta

 

 

Komentáře

Avatar
Jiří Šachl:

Nenašel jsem funkci aritmetický průměr pro výpočet průměrné číselní hodnoty v poli hodnot. Potřebuji pro průměrnou hodnotu měření. A co funkce vážený průměr. Ta by se nenašla ? Tzn z hromady čísel vyloučit ulítlé hodnoty nízké a vysoké a zprůměrovat "šedý průměr". To by nebylo ?

 
Odpovědět 10.4.2015 12:22
Avatar
Adam Ježek
Tým ITnetwork
Avatar
Odpovědět  +2 10.4.2015 13:49
Pokud chceš odpovědět, klikni na odpovědět. Pokud chceš vložit zdroják, klikni na vložit zdroják (</>)
Avatar
Jiří Šachl:

Vyřešil jsem to tak, že jsem na začátku definoval proměnné, udělal cyklus 10 měření kdy na začátku na proměnné nastavím 0- Při měření pak hodnotu přičtu k předchozí hodnotě tak, že se mi de fakto proměnná navyšuje o každou změřenou hodnotu. Pro zobrazení výsledků pak volám další funkci ve které celkovou hodnotu vydělím 10 ti. Ptal jsem se spíš, že když umí arduino goniometrické funkce, umí najít maximální a minimální hodnotu v poli zda se špatně dívám do knížek a nebo arduino neumí pole hodnot podělit. Prostě jsem nenašel funkci dělení čísel.

 
Odpovědět 11.4.2015 8:31
Avatar
boltjolt
Člen
Avatar
boltjolt:

Vyborne oba clanky, takovy navod usetri spousty casu.

 
Odpovědět 28.4.2015 7:12
Avatar
Pracka
Člen
Avatar
Pracka:

Ahoj :) vdaka za super clanky, ale ako to tak sledujem tie prikazy, tak mi to pride uplne ako C#, stiahol som si Visual Micro a tam bolo treba nastavit programovanie v C++, kedze ovladam zatial len C# tak predpokladam, ze ide o podobnu formu pisania, asi odvodenu uz od jazyka C, ci sa mylim?

PS: Neberte to ako skutocnost, skor sa iba informujem, ci som si to spravne premietol :)

Odpovědět 26.9.2015 2:17
Carpe Diem
Avatar
Adam Ježek
Tým ITnetwork
Avatar
Odpovídá na Pracka
Adam Ježek:

Ano, jazyk je odvozeny od C :)

Odpovědět 26.9.2015 6:38
Pokud chceš odpovědět, klikni na odpovědět. Pokud chceš vložit zdroják, klikni na vložit zdroják (</>)
Avatar
Ondřej Pohořelý:

Přemýšlel jsem a napadlo mě jestli by šlo udělat jakési menu kde by se vypsali uživatelé a každý by měl vlastní pin/kód a každý jiná práva (machr na hw) co ted je ten Chytrý dům že třeba Pepa by mohl zamykat dveře zhasinat světla a třeba Jirka by mohl vše kromě dveří šlo by udělat něco jako Permisse (práva) ??

Odpovědět 17. ledna 13:32
Nezastavuj se dlouho protože život nikdy nečeká !
Avatar
David Hart
Člen
Avatar
David Hart:

Ahoj, chci se zeptat, kolik místa v paměti RAM "sežere" deklarace proměnné:
String nejakyText;
Do proměnné nejakyText mohu posléze vložit hodnotu nejakyText="ok"; nebo i nejakyText = "Dobry den, jak se mate?";
Jde mi to to, jak šetřit RAM, když vím, že maximální délka obsahu proměnné typu string bude například 20 znaků. Nebo dochází k dynamické alokaci - dle momentální obsazenosti? Rád bych využíval string, protože často používám
xx=nejakyText­.substring(1,5); a podobně.
Díky David

 
Odpovědět 2. února 18:26
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na David Hart
ostrozan:

Nejsem si úplně jistý, jak je to v arduino IDE, ale ve všech ostatních pro osmibitové procesory jako je Atmel AVR v arduinu se deklarovaný string bere jako konstanta a je uložený ve flash - je to hlavně z důvodu, že mikrokontroler má malou RAM a rychle bys ji zahnojil právě stringama.
A pokud to IDE nedělá automaticky, tak to udělej ty - const string

Jinak deklarace proměnné ti nesežere nic - to až teprve definice :)

 
Odpovědět 3. února 0:07
Avatar
David Hart
Člen
Avatar
David Hart:

Ahoj, díky za odpověď, ale nerozuměli jsme si. Nepotřebuji uložit textovou konstatntu, ale pracovat s proměnnou typu String, o které vím, že nebude delší jak 10 znaků. Pokud se místo zabírá až při vlastním přiřazení NejakyText="Naz­dar"; a tudíž mi tato proměnná zabere pouze 6 bytů, není to problém. Pouze si musím ohlídat, aby při vlastním běhu programu nikdy nenastala situace, kdy do proměnných String dám opravdu dlouhé řetězce a RAM dojde.
Díky David

 
Odpovědět 3. února 8:10
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.