Arduino pracuje s jazykem C přizpůsobeným pro danou platformu. Tento článek proto představuje základy programování v jazyce C a ukazuje jeho praktické využití na příkladu I/O portů.
Objednejte si sadu prvků a začněte se učit v praxi! Kliknutím sem přejdete do obchodu >>
Základní softwarový rámec Arduino
Každý počítačový program je souborem příkazů. Speciální obvod, čítač příkazů, vyvolává příkazy jeden po druhém. V jazyce C jsou všechny příkazy, které chceme vykonat, umístěny v hlavní funkci (o funkcích později), která vypadá takto:
int main() {
//Obsah programu
}
Poznámka: Musíte si to pamatovat!
Symboly „//“ označují komentáře. Jedná se o informace, které jsou obsaženy v jednom řádku a pomáhají uživateli porozumět programu. Při sestavování jsou vynechány. Pokud chcete vložit delší komentář, měli byste jej vložit /* do těchto symbolů */.
Komentáře jsou velmi důležité! Nezapomeňte kód komentovat, i když píšete programy pouze pro vlastní potřebu.
S Arduino se některé věci zjednodušují. V každém programu se některé příkazy provedou nejprve jednou a další pak ve smyčce.
void setup() {
//Instrukce, které se provedou jednou
}
void loop() {
//Instrukce, které se budou provádět v cyklu (ve smyčce)
}
Do druhé funkce umístíme vlastní kód aplikace, který se neustále provádí (ve smyčce). Následující praktické příklady vám to usnadní.
Funkce - co tyto položky znamenají?
V jazyce C existuje pojem funkce. Paralela s matematikou je zde na místě. Ukázalo se, že funkce v programovacích jazycích je blok (seznam) konkrétních příkazů vyčleněných z hlavního kódu, jejichž provedení vede k určitému výsledku.
To je pro nás praktické, protože jakmile je funkce jednou definována, můžeme ji vyvolat libovolně často, aniž bychom museli pracně opakovat stejné řádky kódu – potřebujeme pouze název funkce. Tex
Zaměřme se na nejdůležitější funkce v programech napsaných pomocí Arduino.
void setup() {
}
Procedura setup je navržena tak, aby blok instrukcí, který obsahuje, provedla jednou. Jak název napovídá, je určena především pro nastavení. V ní se inicializuje procesor, konfigurují periferie atd.
void loop() {
}
Funkce – smyčka (procedura) je nekonečná smyčka. Obsahuje instrukce, které se mají provádět ve smyčce (opakovaně). Nyní přejděme k praktickým příkladům.
Hotové sady pro kurzy Forbot
U našich prodejců si nyní můžete zakoupit sadu více než 70 elementů potřebných pro cvičení v kurzu!
Populární sada: Arduino Master – Robotics Master
Připojení ArduinoUNO
Jak bylo uvedeno v předchozí části, k Arduinu lze pomocí speciálních konektorů připojit externí komponenty, jako jsou diody a tlačítka. Než se k tomu však dostaneme, potřebujeme znát popis přiřazení pinů. Níže vidíte výkres s nejdůležitějšími signály přicházejícími z Arduina UNO:
Analogové vstupy (A0-A5) jsou zvýrazněny světle zelenou barvou. Jedná se o jedinečné piny, které umožňují měření napětí (v rozsahu 0-5 V). Jak vidíte, číslování těchto vstupů odpovídá univerzálním pinům (čísla 14 až 19). Analogový provoz je doplňkovou funkcí těchto pinů.
Nezapomeňte: Analogové piny A0-A5 mohou fungovat také jako běžné I/O piny.
Alternativní funkce pro jednotlivé signály jsou zvýrazněny modře. To znamená, že mohou být nejen standardním vstupem nebo výstupem, ale mohou plnit i složitější funkce. Těm se budeme věnovat později, ale nyní postačí základní vysvětlení:
- SDA, SCL – piny sběrnice I²C používané např. pro komunikaci s pokročilejšími senzory, piny jsou zdvojené (jsou umístěny v levém dolním a pravém horním rohu desky – jedná se o naprosto stejné signály),
- TX, RX – rozhraní UART, slouží především ke komunikaci s počítačem,
- PWM – Piny, na kterých lze generovat obdélníkový signál s proměnnou náplní. Velmi užitečná funkce, např. pro ovládání servomechanismů,
- LED – světelná dioda, která je trvale integrována do Arduino a je připojena na pin 13.
Připojení označená ICSP na výše uvedeném schématu slouží k přímému programování dvou mikrokontrolérů umístěných na desce Arduino UNO. Tyto spoje se používají ve velmi zvláštních případech a v této fázi je naprosto zbytečné se jimi zabývat.
Výstupy v praxi - LED
Obvod by měl být zapojen podle následujícího obrázku. LED diodu zapojíme do série s rezistorem (330R). Delší noha diody (anoda) je pak připojena k pinu 8, druhá noha přes rezistor k zemi, která je umístěna v napájecím připojení (označovaném jako GND). Na desce plošných spojů jsou 3 linky označené GND. Můžeme si vybrat kterýkoli z nich.
POZOR!
Nezapomeňte připojit většinu periferních zařízení (LED diody, bzučáky) k Arduino přes rezistory! Příslušné informace najdete v našich přehledových výkresech.
Chybějící rezistor může způsobit poškození připojených komponent a dokonce i Arduino!
Softwarová aktivace diody je velmi jednoduchá. Připojte Arduino k počítači pomocí kabelu USB. Spusťte Arduino IDE a zkopírujte níže uvedený kód. Následně jej nahrajte na desku. Popis tohoto kroku naleznete v první části kurzu.
Zkuste kódy zkopírovat! Kopírování je rychlejší, ale naučíte se méně!
void setup() {
pinMode(8, OUTPUT);
digitalWrite(8, HIGH);
}
void loop() {
}
Pomocí funkce pinMode (pin, mode) můžete určit, zda je pin vstup nebo výstup. Pin může být celkové číslo v rozmezí 0 až 13, režim je :
- INPUT,
- OUTPUT,
- INPUT_PULLUP.
Při této konfiguraci můžeme nastavit logický stav na výstupu (a tím zapnout diodu). K tomuto účelu slouží funkce digitalWrite(Pin, Status). Stav je logický stav, který může být HIGH nebo LOW.
V našem příkladu je LED dioda již připojena k zemi, takže Arduino ji musí uvést do vysokého stavu, tj. digitalWrite(8, HIGH);.
Každý příkaz ukončete středníkem!
Jakmile je pin nastaven na „high“, jeho hodnota se již nemění, dokud jej sami nenastavíme na jinou hodnotu. Proto program, jako je ten výše uvedený, udržuje diodu LED trvale rozsvícenou.
Zpoždění programu - LED bliká
Tentokrát se postaráme o to, aby LED dioda blikala. K tomu potřebujeme novou funkci, jejímž úkolem bude zavést zpoždění. Schéma zapojení je naprosto stejné jako v prvním případě. Kód však bude vypadat takto:
void setup() {
pinMode(8, OUTPUT); //Konfigurace pinu 8 jako výstupu
}
void loop() {
digitalWrite(8, HIGH); //Zapnutí diody
delay(1000); //Čekání 1 sekundu
digitalWrite(8, LOW); //Vypnutí diody
delay(1000); //Čekání jednu sekundu
}
Stav výstupu se neustále mění v nekonečné smyčce. Zpoždění bylo do programu přidáno pomocí funkce delay(time) (aby bylo blikání viditelné). Tato funkce obdrží jako argument počet milisekund, které má čekat.
Bez vložených zpoždění by obvod měnil stav svého výstupu tak rychle, že by změny nebylo možné rozpoznat pouhým okem. Takový experiment můžete provést nastavením zpoždění na 0 ms.
Domácí úkol 1.1
Zjistěte, při jaké nejmenší hodnotě zpoždění můžete vnímat blikání diody! Co se stane, když dioda bliká příliš rychle?
Domácí úkol 1.2
Vyberte volný pin a připojte k němu druhou LED diodu. Napište program, který rozsvítí obě LED diody. Pak napište program, který zajistí střídavé blikání obou LED diod.
Vstupy obvodů v praxi - podmíněná instrukce
To by mělo být provedeno podle níže uvedeného příkladu. Jedna strana spínače je připojena k zemi (mínus), druhá k přípojce č. 7.
Pozor!
Spínače obsažené v sadách mají 2 místo 4 konektorů, aby se lépe vešly na kontaktní desku. Nemusíte se obávat, že přepínač na grafice má 4 výstupy.
Nyní se dostáváme k realizaci úkolu. Očekáváme, že program bude neustále v jednom ze dvou stavů – LED zapnutá nebo vypnutá. Nejprve je nutné přečíst logický stav, který nastane na vstupu s přepínačem.
Zde se poprvé setkáte s konfigurací vstupu. Všimněte si již zmíněného režimu INPUT_PULLUP. Budeme ji používat pokaždé, když k Arduinu připojíme spínač.
První část názvu (input) samozřejmě znamená vstup, zatímco druhá část(pullup) označuje aktivaci vnitřního pull-up rezistoru pro vstup.
Odtud pochází podmíněná instrukce (běžně označovaný jako if nebo condition). Tento pokyn je velmi oblíbený. Umožňuje nám spustit určitou část kódu, když nastanou určité okolnosti. Například: Po stisknutí tlačítka.
Tuto instrukci lze velmi snadno rozšířit o část kódu, která se provede pouze v případě, že není splněna podmínka. K tomu se používá příkaz else.
[...]
void loop()
{
//Kód prováděný v každé smyčce
if ( PODMÍNKA ) {
/* Kód se provede pouze v případě, že v daném
obvodu smyčky je splněna PODMÍNKA */
}
//Kód prováděný v každé smyčce
}
[...]
void loop()
{
//Kód prováděný v každé smyčce
if ( PODMÍNKA ) {
/* Kód se provede pouze v případě, že v daném
obvodu smyčky je splněna PODMÍNKA *./
} else {
/* Kód se provede pouze v případě, že v daném
smyčce NENÍ splněna podmínka*./
}
//Kód prováděný v každé smyčce
}
Kombinací získaných znalostí můžeme vytvořit program, který splní náš úkol.lní náš úkol. Analyzujte ji a poté ji nahrajte do Arduina.
void setup() {
pinMode(8, OUTPUT); //Dioda jako výstup
pinMode(7, INPUT_PULLUP); //Tlačítko jako vstup
digitalWrite(8, LOW); //Vypnutí diody
}
void loop()
{
if (digitalRead(7) == LOW) { //Pokud je tlačítko stisknuto
digitalWrite(8, HIGH); //Zapněte diodu
} else { //Pokud není podmínka splněna (tlačítko není stisknuto).
digitalWrite(8, LOW); //Vypněte diodu
}
}
Takový program je však málo užitečný. Proč potřebujeme vypínač, který funguje, jen když ho přidržíme prstem? Nebylo by lepší, kdyby se LED dioda po stisknutí spínače rozsvítila na určitou dobu?
Příklad - Spínač světla s "časovačem"
Dokážete už takový program napsat sami? Doufám, že ano! Pokud máte nějaké problémy, můžete se podívat na můj kód:
Příklad - světelná signalizace
Naším dalším obvodem bude spínaný semafor. Naším hlavním cílem je napsat program, který po stisknutí tlačítka zobrazí další správnou sekvenci semaforů. Předpokládejme takový cyklus semaforu:
void setup() {
pinMode(8, OUTPUT); //Dioda jako výstup
pinMode(7, INPUT_PULLUP); //Tlačítko jako vstup
digitalWrite(8, LOW); //Vypnutí diody
}
void loop()
{
if (digitalRead(7) == LOW) { //Pokud je tlačítko stisknuto
digitalWrite(8, HIGH); //Zapni diodu
delay(10000); //Čekáme 10 sekund
digitalWrite(8, LOW); //Vypnutí diody
}
}
[…] -> Zelená -> Oranžová -> Červená -> Červená + oranžová[…].
Po stisknutí tlačítka by měl systém přepnout světla na další sekvenci. Toho dosáhneme v několika krocích. Nejprve připojíme 3 LED diody a přepínač, jak je uvedeno níže.
Připravme si základní strukturu programu, se kterým budeme pracovat. Jeho jediným úkolem je konfigurovat vstupy a výstupy.
Zapomeňme na vypínač a napišme program, který automaticky mění světla každou 1 sekundu. Mělo by to vypadat takto:
void setup() {
pinMode(10, OUTPUT); //Dioda červená
pinMode(9, OUTPUT); //Dioda žlutá
pinMode(8, OUTPUT); //Dioda zelená
pinMode(7, INPUT_PULLUP); //Tlačítko
digitalWrite(10, LOW); //Vypínání diod
digitalWrite(9, LOW);
digitalWrite(8, LOW);
}
void loop()
{
//Zde bude náš program
}
void setup() {
pinMode(10, OUTPUT); //Dioda červená
pinMode(9, OUTPUT); //Dioda žlutá
pinMode(8, OUTPUT); //Dioda zelená
pinMode(7, INPUT_PULLUP); //Tlačítko
digitalWrite(10, LOW); //Vypínání diod
digitalWrite(9, LOW);
digitalWrite(8, LOW);
}
void loop()
{
digitalWrite(10, LOW); //Červená
digitalWrite(9, LOW); //Oranžová
digitalWrite(8, HIGH); //Zelená
delay(1000); //Čekáme 1 sekundu
digitalWrite(10, LOW); //Červená
digitalWrite(9, HIGH); //Oranžová
digitalWrite(8, LOW); //Zelená
delay(1000); //Čekáme 1 sekundu
digitalWrite(10, HIGH); //Červená
digitalWrite(9, LOW); //Oranžová
digitalWrite(8, LOW); //Zelená
delay(1000); //Čekáme 1 sekundu
digitalWrite(10, HIGH); //Červená
digitalWrite(9, HIGH); //Oranžová
digitalWrite(8, LOW); //Zelená
delay(1000); //Čekáme 1 sekundu
}
Nahrajte program do Arduino a zkontrolujte, zda funguje. Než budeme pokračovat, musíme se ujistit, že je vše správně zapojeno.
Smyčka While
Zatím jsme v kódu Arduino loop() používali pouze nezbytnou „smyčku“. Nyní je čas seznámit se se smyčkami, které můžeme použít v rámci našich programů.
K dispozici bude řada různých smyček. Budeme se jim věnovat v dalších částech kurzu.
Nyní probereme cyklus while(), který běží, dokud není splněna podmínka. Způsob jejich fungování je uveden v následujícím kódu:
[...]
void loop()
{
//Kód, který se provede při každém spuštění hlavní smyčky loop.
while ( PODMÍNKA ) {
/* Kód vykonávaný v cyklu, dokud PODMÍNKA přestane být splněna */
}
//Kód, který se provede při každém spuštění HLAVNÍ smyčky loop
Vezměme obvod, který jsme právě sestavili se semaforem, a napišme program, který způsobí, že LED dioda začne blikat pouze po stisknutí tlačítka.
Pravděpodobně jste měli na mysli podmíněný příkaz if. Jak ale chcete blikání LED diody realizovat? Navzdory zdání je to obtížnější úkol než trvalé světlo, o kterém jsme psali dříve.Nejlepším způsobem, jak tento program implementovat, je použít smyčku while(), která vypadá takto:
void setup() {
pinMode(10, OUTPUT); //Dioda červená
pinMode(9, OUTPUT); //Dioda žlutá
pinMode(8, OUTPUT); //Dioda zelená
pinMode(7, INPUT_PULLUP); //Tlačítko
digitalWrite(10, LOW); //Vypínání diod
digitalWrite(9, LOW);
digitalWrite(8, LOW);
}
void loop() {
while (digitalRead(7) == LOW) { // Pokud je tlačítko stisknuto
digitalWrite(10, LOW); //Červená vypnuto
delay(1000);
digitalWrite(10, HIGH); //Červená zapnuto
delay(1000);
}
}
Tentokrát by se sekvence měly zobrazovat, dokud nestiskneme přepínač (pak by mělo dojít ke změně). Předpokládáme, že tlačítko stiskneme a uvolníme velmi rychle. Hotový program by měl vypadat jako níže uvedený:
void setup() {
pinMode(10, OUTPUT); //Dioda červená
pinMode(9, OUTPUT); //Dioda žlutá
pinMode(8, OUTPUT); //Dioda zelená
pinMode(7, INPUT_PULLUP); //Tlačítko
digitalWrite(10, LOW); //Vypínání diod
digitalWrite(9, LOW);
digitalWrite(8, LOW);
}
void loop()
{
digitalWrite(10, LOW); //Červená
digitalWrite(9, LOW); //Oranžová
digitalWrite(8, HIGH); //Zelená
while (digitalRead(7) == HIGH) {} //Počkejte na stisknutí tlačítka
digitalWrite(10, LOW); //Červená
digitalWrite(9, HIGH); //Oranžová
digitalWrite(8, LOW); //Zelená
while (digitalRead(7) == HIGH) {} //Počkejte na stisknutí tlačítka
digitalWrite(10, HIGH); //Červená
digitalWrite(9, LOW); //Oranžová
digitalWrite(8, LOW); //Zelená
while (digitalRead(7) == HIGH) {} //Počkejte na stisknutí tlačítka
digitalWrite(10, HIGH); //Červená
digitalWrite(9, HIGH); //Oranžová
digitalWrite(8, LOW); //Zelená
while (digitalRead(7) == HIGH) {} //Počkejte na stisknutí tlačítka
}
V tomto případě byla smyčka použita poněkud zvláštním způsobem. Jak vidíte, v závorkách není nic! Proč program stále funguje? Protože program používá k zastavení smyčky.
Jak to funguje?
1. začneme rozsvěcet LED diody podle určité posloupnosti,
2. vstoupíme do smyčky while(), která je hned pod ní,
3. smyčka je prázdná, takže program se stále točí dokola a….. nic nedělá,
4. teprve po stisknutí tlačítka (podmínka není splněna) program smyčku ukončí,
5. rozsvítí se další sekvence a situace se opakuje.
Podívejme se, jak program funguje v praxi!
Co se vlastně děje? Funguje vše, jak má? Ne! I když stiskneme tlačítko jen velmi krátce, program někdy funguje správně a někdy přeskočí o několik pozic. Proč se to děje?
Jak si jistě pamatujete z první části, zjednodušeně řečeno, procesor provádí přibližně 16 milionů operací za sekundu. V důsledku toho dokáže při stisknutí tlačítka projít všemi stavy naší signalizace (a ne jen jednou…). Různé efekty po uvolnění tlačítka jsou pouze výsledkem náhodné „akce“ v určitém pořadí.
Jak lze tento problém vyřešit? Jednoduše řečeno. Stačí program upravit tak, aby se světla neměnila častěji než například každou sekundu. K tomu můžeme použít již známou funkci delay().
void setup() {
pinMode(10, OUTPUT); //Dioda červená
pinMode(9, OUTPUT); //Dioda žluta
pinMode(8, OUTPUT); //Dioda zelená
pinMode(7, INPUT_PULLUP); //Tlačítko
digitalWrite(10, LOW); //Vypínání diod
digitalWrite(9, LOW);
digitalWrite(8, LOW);
}
void loop()
{
digitalWrite(10, LOW); //Červená
digitalWrite(9, LOW); //Oranžová
digitalWrite(8, HIGH); //Zelená
delay(1000); //Před vstupem do smyčky zastavíme program na 1 sekundu.
while (digitalRead(7) == HIGH) {} //Počkejte na stisknutí tlačítka
digitalWrite(10, LOW); //Červená
digitalWrite(9, HIGH); //Oranžová
digitalWrite(8, LOW); //Zelená
delay(1000); //Před vstupem do smyčky zastavíme program na 1 sekundu.
while (digitalRead(7) == HIGH) {} //Počkejte na stisknutí tlačítka
digitalWrite(10, HIGH); //Červená
digitalWrite(9, LOW); //Oranžová
digitalWrite(8, LOW); //Zelená
delay(1000); //Před vstupem do smyčky zastavíme program na 1 sekundu.
while (digitalRead(7) == HIGH) {} //Počkejte na stisknutí tlačítka
digitalWrite(10, HIGH); //Červená
digitalWrite(9, HIGH); //Oranžová
digitalWrite(8, LOW); //Zelená
delay(1000); //Před vstupem do smyčky zastavíme program na 1 sekundu.
while (digitalRead(7) == HIGH) {} //
Počkejte na stisknutí tlačítka
}
Nyní by mělo vše fungovat správně!
Nezapomeňte, že sada komponentů potřebných pro všechna cvičení je k dispozici u společnosti Botland. Zakoupením sad podpoříte budoucí vydání Forbota!
Shrnutí
Další část se zabývá komunikací s počítačem přes USB. To usnadní pozdější testování rozšířených programů.
Objednejte si sadu prvků a začněte se učit v praxi! Kliknutím sem přejdete do obchodu >>