Close

Základní struktury jazyka Wiring

Oficiální logo Arduino

V minulém díle jsme si ukázali první program, ve kterém Arduino blikalo LED diodou. Úvodní seznámení je tedy za námi a můžeme se pustit do dalšího programování. V dnešním článku se podíváme na základní náležitosti jazyka Wiring. Na začátek si vysvětlíme, jak Arduino komunikuje s počítačem. Poté si řekneme, jak používat proměnné a jak pracovat se vstupy a výstupy Arduina.

 

Sériová komunikace

Aby mohlo Arduino správně komunikovat s PC, musí mít několik základních součástí. Následující popis postihuje většinu desek Arduino. Najdou se však i speciální desky, které podporují jiný způsob programování (BT, Ethernet, Wifi…), ale těmi se dále zabývat nebudeme. Popišme si tedy proces programování, se kterým se setkáme u většiny desek.

Co je ke komunikaci potřeba:

Schéma sériové komunikace

Schéma komunikace

  1. Základním předpokladem je mít PC s USB portem.
  2. USB kabel
  3. S převodníkem se nám schéma trochu komplikuje. Můžeme se totiž setkat se třemi základními typy převodníku. Všechny tři převodníky fungují stejně. Liší se pouze způsobem připojení.
    1. Převodník, který je na pevno připájený k základní desce Arduina.
    2. Převodník, který mají některé čipy (ATmega32u4… ) přímo v sobě.
    3. Externí převodník, který musíme při programování Arduina připojit.
  4. Připojení převodníku a čipu. Při použití externího převodníku se většinou jedná o šest vodičů, které vystupují z desky. U zbylých dvou typů převodníku jsou to pouze kontakty na plošném spoji, nebo propojení uvnitř čipu.
  5. Mozek, který přijímá přeložené instrukce od převodníku.

Poznámka: Takto vypadá Arduino Pro s připojeným externím převodníkem.

Arduino s připojeným FTDI převodníkem

FTDI převodník

Sériová komunikace se ale dá využít k více věcem, než jen k programování. Pomocí ní totiž můžeme komunikovat s Arduinem, i když už na něm běží náš program. Poté můžeme například číst hodnoty ze senzorů a posílat je do PC, nebo ovládat Arduino jednoduchými textovými příkazy. Používání těchto funkcí si popíšeme v příštím článku, kdy už budeme mít dostatek informací k jejich pochopení.

 

Proměnné

Proměnná je místo ve kterém se dají uchovávat data. Každá proměnná má vlastní jméno, datový typ a hodnotu. Často se používají například tam, kde se v programu dokola opakují ty samé hodnoty. Praktické využití proměnných si ukážeme na následujícím příkladu napsaném v pseudokódu:

Představme si, že máme několik očíslovaných světel. Vždy si vybereme jedno, se kterým budeme blikat.

 zapniSvětlo(10); //zapni desáté světlo vypniSvětlo(10); //vypni desáté světlo zapniSvětlo(10); vypniSvětlo(10); zapniSvětlo(10); vypniSvětlo(10); ... 

Nyní si stejný program přepíšeme s užitím proměnných.

 číslo A = 10; //proměnná se jmenuje A, je datového typu číslo a má hodnotu 10 zapniSvětlo(A); vypniSvětlo(A); zapniSvětlo(A); vypniSvětlo(A); zapniSvětlo(A); vypniSvětlo(A); ... 

Kdybychom chtěli změnit světlo, se kterým blikáme, museli bychom v prvním případě změnit všechny čísla 10 na jiná. V případě druhém nám stačí přepsat pouze hodnotu proměnné a program ji už sám dosadí na potřebná místa.

 

Práce s proměnnými

Nyní už se podíváme na to, jak pracovat s proměnnými v jazyce Wiring. Jedním z číselných datových typů je typ integer (zkracuje se na int). Ukažme si tedy, jak vytvořit proměnnou, která v sobě uchová číselnou hodnotu. Abychom mohli v programu s proměnnou pracovat, musíme ji nejprve deklarovat (“vytvořit”). Poté jí můžeme přiřadit hodnotu.

//deklarace proměnné x int x; //přiřazení hodnoty x = 10; //tyto dvě operace se dají spojit do jedné int x = 10; 

Vytvořit proměnnou ale nemůžeme jen tak někde. Když budeme chtít používat danou proměnnou všude v programu, musíme ji vytvořit vně všech funkcí (tedy i mimo funkce setup a loop). Pokud nám stačí používat proměnnou uvnitř jedné funkce a nikde jinde ji nepotřebujeme, stačí, když ji deklarujeme uvnitř funkce.

int x = 10; //tuto proměnnou můžeme použít všude void setup() { int y = 11; //uvnitř této funkce můžeme použít proměnné x a y } void loop() { int z = 12; //zde můžeme použít proměnné x a z } 

Pokud bychom se pokusili do Arduina nahrát kód, ve kterém používáme proměnnou y ve funkci loop (nebo z ve funkci setup), překlad kódu skončí s chybovou hláškou a do Arduina se nic nenahraje.

 

Datové typy

Jak už jsem naznačil dříve, každá proměnná má svůj datový typ. Ten nám říká, jaká data můžeme v proměnné najít. Může se jednat o logické hodnoty (true/false), znaky, nebo čísla. Pojďme si nyní představit základní typy.

Číselné datové typy

  • byte – Proměnná datového typu byte má velikost 8 bitů a slouží k uchování celých čísel. Její rozsah je 28 hodnot – 0 až 255
  • integer – V programech se používá jen zkratka int. Slouží k ukládání celých čísel. Rozsah tohoto datového typu se liší podle použitého procesoru a zasahuje jak do kladných, tak i do záporných čísel. Nula leží přibližně v polovině rozsahu. U desek s procesory Atmega (tedy naprostá většina) uchovává 16-bit hodnotu – tedy od -32,768 do 32,767. U Arduino DUE s procesorem SAM je tato hodnota 32-bitová a může obsahovat čísla od -2,147,483,648 do 2,147,483,647.
  • long – Slouží k uchování celočíselných 32 bitových hodnot od -2,147,483,648 do 2,147,483,647.
  • float – Tento datový typ je určený pro uchování čísel s desetinnou čárkou. V jazyce Wiring se však používá desetinná tečka. Jeho velikost je 32 bitů. Můžeme v něm ukládat hodnoty od -3,4028235 * 1038 do 3,4028235 * 1038.

Logický datový typ

  • boolean – Proměnné tohoto datového typu v sobě uchovávají pouze dvě hodnoty. Buďto true (pravda), nebo false (nepravda).

Znakový datový typ

  • char – Tento datový typ slouží k uchování jednoho znaku textu. Znak je zde uchován jako jeho číselná hodnota v ASCII tabulce znaků. Písmena, slova i věty se píší v uvozovkách. K uchování řetězců textu slouží typ string, kterým se budeme zabývat za chvíli.

Poznámka: Existují i další číselné datové typy, ale ty se nepoužívají moc často. Jejich popis nalezneme v Arduino Reference [EN] v prostředním sloupci v části Data Types.

 

-byte byte a = 12; -integer int b = 400; -long long c = 12121212; -float float d = 1.256; -boolean boolean e = false; -char char f = 'A'; char f = 65; //v ASCII tabulce znaků má A hodnotu 65 

Pole

Pole (anglicky array) je speciální typ proměnné. Umožňuje shromáždit více hodnot do jedné proměnné. Můžete si jej představit, jako krabičku, která má jednotlivé přihrádky očíslované. Když víme, jakou krabičku používáme a do jaké přihrádky se chceme podívat, můžeme se dostat k požadované hodnotě. V programátorské terminologii se číslům přihrádek říká index.

 

Deklarace pole

Jejich deklarace je podobná, jako u proměnných – každé pole má datový typ hodnot, které v něm najdeme, jméno, hodnoty a navíc i velikost pole.

//pole můžeme deklarovat několika způsoby int jmeno[6]; //deklarace pole s šesti buňkami int jmeno[] = {2, 3, 4, 5}; //prvky v poli oddělujeme čárkami int jmeno[4] = {2, 3, 4, 5}; //v tomto případě velikost pole uvést můžeme, nemusíme //zvláštním typem pole je pole znaků (nazývané řetězec - string) //umožňuje totiž specifický způsob přiřazení hodnoty char jmeno[15]; //deklarace řetězce char jmeno[] = {'a', 'r', 'd', 'u', 'i', 'n', 'o'}; char jmeno[7] = {'a', 'r', 'd', 'u', 'i', 'n', 'o'}; char jmeno[] = "arduino"; char jmeno[7] = "arduino"; 

 

Přístup k hodnotám v poli

Ve většině programovacích jazyků jsou indexy v poli číslovány od nuly. Prvek na prvním místě má tedy index 0. Čtení hodnoty prvku pole poté probíhá stejně, jako u proměnných, jen musíme připojit ještě jeho index.

int a[] = {1,2,3,5,7,11,13,17}; //deklarace pole a a[0]; //prvek s indexem 0 má hodnotu 1 a[5]; //prvek s indexem 5 má hodnotu 11 ... 

 

Digitální vstup a výstup

Jelikož je Arduino určeno k dalšímu rozšiřování, obsahuje vstupy a výstupy (nazývané piny), ke kterým se dá vodičem připojit další obvody, čipy, relé, paměti atd.. My už jsme se s takovýmto případem setkali v minulém článku, když jsme blikali LED diodou. K práci s těmito piny má Arduino k dispozici jednoduché funkce. Nejdříve ze všeho je však potřeba programu říci, jestli s pinem pracujeme jako se vstupem, nebo výstupem.

 

Vstup nebo výstup?

K nastavení pinu slouží funkce pinMode(). Ta pro svoji správnou činnost potřebuje dva vstupní parametry – pinMode(cislo_pinu, INPUT/OUTPUT); Pokud chceme daný pin používat jako vstup, bude druhý parametr INPUT, pokud jako výstup, bude to OUTPUT. Číslo pinu je většinou natištěno na desce Arduina. Ve verzi Arduino UNO tedy můžeme používat piny 0 až 13. Tímto ale nekončí, protože můžeme k digitálním operacím používat i piny označené jako ANALOG IN, jenom místo samotného čísla musíme před číslo napsat A. U Arduina UNO jsou to tedy A0 až A5.

byte cislo = 13; pinMode(cislo, OUTPUT); //nastavení pinu 13 na výstup pinMode(12, INPUT); //a pinu 12 na vstup 

 

Ovládání výstupu

K ovládání výstupu se používá funkce digitalWrite(). S touto funkcí jsme se setkali již v minulém článku, když jsme blikali LED diodou. Stejně jako pinMode() potřebuje i tato funkce dva parametry – číslo pinu a informaci o proudu. Pokud proud teče, je to HIGH, pokud ne, tak LOW.

digitalWrite(13, HIGH); digitalWrite(12, LOW); 

 

Čtení vstupu

Ke zjištění, zda proud do vstupu teče, nebo ne se používá funkce digitalRead(). Ta, narozdíl od předchozích dvou funkcí, potřebuje pouze jeden parametr, kterým je číslo pinu. Tato funkce navíc vrací hodnotu. Když proud teče, vrátí hodnotu HIGH, když ne, tak LOW.

int cteni; byte vstup = 13; cteni = digitalRead(vstup); //pokud proud teče, do proměnné cteni se uloží hodnota HIGH //pokud ne, tak LOW 

 

Příklad

Ukážeme si program, který bude zjišťovat, jestli je stisknuté tlačítko. Pokud bude, rozsvítí se LED dioda. K této ukázce budeme potřebovat:

  1. Desku Arduino
  2. PC
  3. Nepájivé kontaktní pole s vodiči
  4. Tlačítko
  5. 10K ohm rezistor pro tlačítko
  6. 220 ohm rezistor pro LED
  7. LED diodu

Vše zapojíme podle schématu. Poté nahrajeme do Arduina uvedený program.

Arduino LED a tlačítko

Arduino LED a tlačítko

 

int cteni; int led = 6; int tlacitko = 12; void setup() { pinMode(led, OUTPUT); pinMode(tlacitko, INPUT); } void loop() { cteni = digitalRead(tlacitko); digitalWrite(led, cteni); } 

 

Poznámka: Na závěr je nutno dodat, že pokud program nefunguje, nejčastější chybou je chybějící středník na konci řádku. Pokud tedy IDE napíše nějakou chybovou hlášku, zkontrolujte středníky. Ty se píší na konec řádku za: deklarací proměnné, za přiřazením hodnoty proměnné a za voláním funkce (pinMode…).

 

Zdroje obrázků

[Arduino Pro s převodníkem]

 

Zbyšek Voda

Zbyšek Voda

Už nějaký čas se zajímám o věci kolem Internetu věcí a otevřeného hardware a software. Tak jsem se také v roce 2010 dostal k Arduinu, pro které dodnes programuji a taky píšu články o práci s ním. Baví mě vymýšlet, jak staré věci používat novým způsobem.
Zbyšek Voda

7 Comments on “Základní struktury jazyka Wiring

pedyngro
21.4.2017 at 15:14

Zdravím, pokusil jsem se funkci programu invertovat, tzn. tlačítkem zhasínat rozsvícenou diodu. Po nahrání následujícího programu se sice dioda tlačítkem zhasne, ale už se znovu nerozsvítí.
[code]
byte cteni;
byte led = 50;
byte tlacitko = 52;
void setup() {
pinMode(led,OUTPUT);
pinMode(tlacitko,INPUT);
Serial.begin(9600);
}

void loop() {
Serial.println(“loop”);
cteni = digitalRead(tlacitko);
while(cteni == 1){
digitalWrite(led,LOW);
Serial.println(“low”);
}
digitalWrite(led,HIGH);
}
[/code]
Přidal jsem proto do programu printy a zjistil jsem, že se program z nějakého důvodu zasekne ve while cyklu a zbytek loopu už neproběhne.
Nevíte, kde jsem mohl udělat chybu?

Zbyšek Voda
Zbyšek Voda
21.4.2017 at 17:32

Dobrý den,
cyklus while probíhá, dokud je podmínka pravdivá.
Vaše podmínka je “cykli, dokud cteni == 1”. A jelikož v průběhu cyklu hodnotu proměnné cteni nijak neměníte, dojde k zacyklení.
Nejjednodušším řešením může být to, že do while cyklu přidáte čtení tlačítka cteni = digitalRead(tlacitko);.

[code]
byte cteni;
byte led = 50;
byte tlacitko = 52;
void setup() {
pinMode(led,OUTPUT);
pinMode(tlacitko,INPUT);
Serial.begin(9600);
}

void loop() {
Serial.println(“loop”);
cteni = digitalRead(tlacitko);
while(cteni == 1){
digitalWrite(led,LOW);
Serial.println(“low”);
cteni = digitalRead(tlacitko);
}
digitalWrite(led,HIGH);
}
[/code]

Prakticky ale ten while takto nemá význam a stačilo by program napsat třeba následovně:
[code]
byte cteni;
byte led = 50;
byte tlacitko = 52;
void setup() {
pinMode(led,OUTPUT);
pinMode(tlacitko,INPUT);
Serial.begin(9600);
}

void loop() {
Serial.println(“loop”);
cteni = digitalRead(tlacitko);

digitalWrite(led, !cteni);
}
[/code]

Pozn.: Vykřičník znamená negaci, tedy z LOW udělá HIGH a naopak.

Dalibor
5.11.2015 at 17:23

1) Příkazem digitalWrite(tlacitko) lze aktivovat pull-up odpor a pak vstup (tlacitko) připojovat přes tlačítko na zem. Odpadne odpor 10k.
2) Z hlediska struktury procesoru je vhodnější připojit LED s předřadným odporem mezi napájení a port a ten spínat do LOW.

ghibulo
1.8.2015 at 16:45

Zdravím… neměla by být ta dioda připojená také přes odpor? … alespoň v offic.manuálu tam dávají 150Ohm odpor … možná aby diodka tak rychle neodešla? 😉

Oldřich Horáček
Oldřich Horáček
14.8.2015 at 16:27

Dobrý den Jirko,

díky za připomínku. Ano, odpor tam chybí.

Pro zajímavost přikládám hodnoty napětí, které naměříme na LED diodě podle její barvy:
Červená 1,6V
Žlutá 2V
Zelená 2V
Modrá 3,5V
Skutečné hodnoty se mohou mírně lišit podle konkrétní LED diody.
Hodnotu předřadného odporu pak spočítáme jako podíl napětí na předřadném odporu a proudu.
R=(5V-Uled)/I
Běžně uvažujeme proud I cca 10mA

Oldřich

Franta
1.5.2015 at 9:08

Našel jsem chybu v tomto článku:
//deklarace proměnné x
int x;
//přiřazení hodnoty
x = 10;

//tyto dvě operace se dají spojit do jedné
int y = 10;

Místo y na konci by se zde mělo nacházet X

Zbyšek Voda
Zbyšek Voda
1.5.2015 at 14:23

Napsat komentář