4. Blikáme LEDkou 2
aneb trocha matematiky nikoho nezabije
Arduino je přeci počítač a ten by měl umět počítat. V dnešní lekci se tedy podíváme na čísla, proměnné a počítání s nimi. Abychom viděli co se uvnitř mikrokontroleru děje, použijeme opět led, ale tentokrát větší počet.
|
Zapojení
Nejprve si tedy připojíme k arduinu několik led (alespoň 4). Na schématu a v dalším
textu budeme předpokládat připojení 7 kusů led na piny 1 - 7.
Datové typy (konstanty a proměnné)
Abychom mohli v programu počítat, musíme trochu poznat tzv. datové typy.
Stejně jako matematici rozdělují čísla na různé typy - přirozená, celá, zlomky, ...,
tak i v počítači se používají různé typy čísel. Dnes si z nich vybereme jen několik:
bool ... logická hodnota (0/1)
byte ... nezáporné číslo v rozsahu 8b (0 - 255)
char ... celé číslo v rozsahu 8b (-128 - 127)
int ... celé číslo v rozsahu 16b (-32768 - 32767)
long ... celé číslo v rozsahu 32b (-2^31 - 2^32-1)
byte ... nezáporné číslo v rozsahu 8b (0 - 255)
char ... celé číslo v rozsahu 8b (-128 - 127)
int ... celé číslo v rozsahu 16b (-32768 - 32767)
long ... celé číslo v rozsahu 32b (-2^31 - 2^32-1)
V programu používáme konstanty, tj. přímé vyjádření číselné hodnoty, které
jsme je již v programu používali. Např. číslo pinu (2), délka časové prodlevy (500), ...
Jak už víme, konstantu můžeme zapsat přímo v daném místě programu nebo
si zadefinovat symbolické jméno (využitím příkazu preprocesoru), které číselnou hodnotu zastupuje.
#define LED 2
#define TLACITKO 5
#define TLACITKO 5
Mimo konstant v programu používáme proměnné. Proměnná je vyhrazené místo v paměti
mikrokontroleru, na které se odkazujeme jeho jménem (stejně jako existuje proměnná
v matematice).
Každou proměnnou musíme tzv. deklarovat (vytvořit) - říci překladači jakého je typu
(určuje velikost paměti pro proměnnou) a její jméno. Pojmenování proměnné může být téměř
jakékoliv, může obsahovat písmena, číslice a některé další znaky (např. _), nesmí
však číslicí začínat. Pozor, stejně jako u klíčových slov, kompilátor rozlišuje
malá a velká písmena (proto jména proměnných Pokus a POKUS nejsou stejná).
Příklad deklarace proměnných:
bool Start; // vytvoření logické proměnné se jménem "Start"
byte i; // vytvoření číselné proměnné (0 - 255) se jménem "i"
int x1; // vytvoření číselné proměnné (16b) se jménem "x1"
byte i; // vytvoření číselné proměnné (0 - 255) se jménem "i"
int x1; // vytvoření číselné proměnné (16b) se jménem "x1"
Výrazy
Konstanty a proměnné můžeme pomocí matematických operací a funkcí spojovat do
výrazů. Výsledkem vyhodnocením výrazu při běhu programu je číslo, proto můžeme
matematický výraz použít všude, kde se v programu očekává číselná hodnota.
Základní matematické operace:
+ ... sčítání
- ... odčítání
* ... násobení
/ ... dělení
! ... negace (logická operace 0 -> 1, 1 -> 0)
- ... odčítání
* ... násobení
/ ... dělení
! ... negace (logická operace 0 -> 1, 1 -> 0)
Přiřazení
Pro vložení požadované hodnoty do proměnné, použijeme přiřazovací příkaz.
Na levé straně příkazu je jméno proměnné, to následuje znak = a na pravé straně
je konstanta, proměnná nebo libovolný matematický výraz.
x = 10; // vložení hodnoty 10 do proměnné x
y = x; // vložení hodnoty proměnné x do proměnné y (opět 10)
z = 2 * x + 3; // vložení hodnoty výrazu do proměnné z (2*10+3, tj. 23)
y = x; // vložení hodnoty proměnné x do proměnné y (opět 10)
z = 2 * x + 3; // vložení hodnoty výrazu do proměnné z (2*10+3, tj. 23)
Příklad č. 1
Sestavte program pro postupné rozsvětcování a zhasínání led zleva doprava. Po doběhnutí
se celý cyklus opakuje ("běžící had"). Každá led svítí vždy 0,5s.
Řešení 1:
Tuto úlohu bychom samozřejmě zvládli i s tím co už jsme se naučili v minulých lekcích.
Program by mohl vypadat např. takto:
#define PRODLEVA 500
void setup()
{
pinMode(1, OUTPUT); // nastaveni pinu 1 jako vystup
pinMode(2, OUTPUT); // nastaveni pinu 2 jako vystup
pinMode(3, OUTPUT); // nastaveni pinu 3 jako vystup
pinMode(4, OUTPUT); // nastaveni pinu 4 jako vystup
pinMode(5, OUTPUT); // nastaveni pinu 5 jako vystup
pinMode(6, OUTPUT); // nastaveni pinu 6 jako vystup
pinMode(7, OUTPUT); // nastaveni pinu 7 jako vystup
}
void loop()
{
digitalWrite(1, HIGH); // rozsviceni led na pinu 1
delay(PRODLEVA); // casova prodleva
digitalWrite(1, LOW); // zhasnuti led na pinu 1
digitalWrite(2, HIGH); // rozsviceni led na pinu 2
delay(PRODLEVA); // casova prodleva
digitalWrite(2, LOW); // zhasnuti led na pinu 2
digitalWrite(3, HIGH); // rozsviceni led na pinu 3
delay(PRODLEVA); // casova prodleva
digitalWrite(3, LOW); // zhasnuti led na pinu 3
.
.
digitalWrite(7, HIGH); // rozsviceni led na pinu 7
delay(PRODLEVA); // casova prodleva
digitalWrite(7, LOW); // zhasnuti led na pinu 7
}
void setup()
{
pinMode(1, OUTPUT); // nastaveni pinu 1 jako vystup
pinMode(2, OUTPUT); // nastaveni pinu 2 jako vystup
pinMode(3, OUTPUT); // nastaveni pinu 3 jako vystup
pinMode(4, OUTPUT); // nastaveni pinu 4 jako vystup
pinMode(5, OUTPUT); // nastaveni pinu 5 jako vystup
pinMode(6, OUTPUT); // nastaveni pinu 6 jako vystup
pinMode(7, OUTPUT); // nastaveni pinu 7 jako vystup
}
void loop()
{
digitalWrite(1, HIGH); // rozsviceni led na pinu 1
delay(PRODLEVA); // casova prodleva
digitalWrite(1, LOW); // zhasnuti led na pinu 1
digitalWrite(2, HIGH); // rozsviceni led na pinu 2
delay(PRODLEVA); // casova prodleva
digitalWrite(2, LOW); // zhasnuti led na pinu 2
digitalWrite(3, HIGH); // rozsviceni led na pinu 3
delay(PRODLEVA); // casova prodleva
digitalWrite(3, LOW); // zhasnuti led na pinu 3
.
.
digitalWrite(7, HIGH); // rozsviceni led na pinu 7
delay(PRODLEVA); // casova prodleva
digitalWrite(7, LOW); // zhasnuti led na pinu 7
}
Řešení 2:
Tento program je funkční, ale je už poměrně dlouhý a hlavně pokud budeme chtít udělat
nějakou změnu, tak už i méně přehledný.
Můžeme si všimnou, že celý program je tvořen sedmi opakujícími se částmi, které se liší
pouze hodnotou pinu, na kterém je připojena led. Místo konstanty zde můžeme použít
proměnnou, a tak celý program podstaně zkrátit.
#define PRODLEVA 500
byte i; // deklarace promenne i (cislo 0 - 255)
void setup()
{
pinMode(1, OUTPUT); // nastaveni pinu 1 jako vystup
pinMode(2, OUTPUT); // nastaveni pinu 2 jako vystup
pinMode(3, OUTPUT); // nastaveni pinu 3 jako vystup
pinMode(4, OUTPUT); // nastaveni pinu 4 jako vystup
pinMode(5, OUTPUT); // nastaveni pinu 5 jako vystup
pinMode(6, OUTPUT); // nastaveni pinu 6 jako vystup
pinMode(7, OUTPUT); // nastaveni pinu 7 jako vystup
i = 1; // vlozeni hodnoty 1 do promenne x (prvni led)
}
void loop()
{
digitalWrite(i, HIGH); // rozsviceni led na pinu i
delay(PRODLEVA); // casova prodleva
digitalWrite(i, LOW); // zhasnuti led na pinu i
i = i + 1; // zvetseni hodnoty promenne i o 1 (posun na dalsi led)
if (i == 8) i = 1; // pokud i je 8, vloz hodnotu 1 (vrat se na prvni led)
}
byte i; // deklarace promenne i (cislo 0 - 255)
void setup()
{
pinMode(1, OUTPUT); // nastaveni pinu 1 jako vystup
pinMode(2, OUTPUT); // nastaveni pinu 2 jako vystup
pinMode(3, OUTPUT); // nastaveni pinu 3 jako vystup
pinMode(4, OUTPUT); // nastaveni pinu 4 jako vystup
pinMode(5, OUTPUT); // nastaveni pinu 5 jako vystup
pinMode(6, OUTPUT); // nastaveni pinu 6 jako vystup
pinMode(7, OUTPUT); // nastaveni pinu 7 jako vystup
i = 1; // vlozeni hodnoty 1 do promenne x (prvni led)
}
void loop()
{
digitalWrite(i, HIGH); // rozsviceni led na pinu i
delay(PRODLEVA); // casova prodleva
digitalWrite(i, LOW); // zhasnuti led na pinu i
i = i + 1; // zvetseni hodnoty promenne i o 1 (posun na dalsi led)
if (i == 8) i = 1; // pokud i je 8, vloz hodnotu 1 (vrat se na prvni led)
}
Tento program je podstatně kratší. Nyní upravte program tak, aby svítící had
běžel opačným směrem.
(Nápověda: stačí hodnotu proměnné i snižovat o jedničku a upravit test, kdy
je nutné přeskočit znovu na druhou stranu).
Příklad č. 2
Sestavte program pro postupné rozsvětcování a zhasínání led zleva doprava. Po doběhnutí
na konec se směr otočí a světélko běží zase zpět, celý cyklus opakuje.
Každá led svítí vždy 0,5s.
Řešení 1:
Stačí nepatrně upravit program z předchozí úlohy.
Po doběhnutí světla na led 7 musíme začít hodnotu proměnné i snižovat o 1 a
po doběhnutí na led 1 opět zvyšovat. Na to použijeme druhou proměnnou, ve které
si budeme pamatovat jestli se světlo pohybuje jedním nebo druhým směrem.
Program by mohl vypadat např. takto:
#define PRODLEVA 500
byte i; // deklarace promenne i (cislo 0 - 255)
bool smer; // deklarace logicke promenne pro urceni smeru pohybu
void setup()
{
pinMode(1, OUTPUT); // nastaveni pinu 1 jako vystup
pinMode(2, OUTPUT); // nastaveni pinu 2 jako vystup
pinMode(3, OUTPUT); // nastaveni pinu 3 jako vystup
pinMode(4, OUTPUT); // nastaveni pinu 4 jako vystup
pinMode(5, OUTPUT); // nastaveni pinu 5 jako vystup
pinMode(6, OUTPUT); // nastaveni pinu 6 jako vystup
pinMode(7, OUTPUT); // nastaveni pinu 7 jako vystup
i = 1; // vlozeni hodnoty 1 do promenne x (prvni led)
smer = 1; // 1 - pohyb dopredu, 0 - pohyb zpet
}
void loop()
{
digitalWrite(i, HIGH); // rozsviceni led na pinu i
delay(PRODLEVA); // casova prodleva
digitalWrite(i, LOW); // zhasnuti led na pinu i
if (i == 7) smer = 0; // pokud i je 7 ~ jsme na konci, nastav smer zpet
if (i == 1) smer = 1; // pokud i je 1 ~ jsme na zacatku, nastav smer vpred
if (smer == 1) // kdyz pohyb vpred
i = i + 1; // zvetseni hodnoty promenne i o 1
else // jinak (pohyb zpet)
i = i - 1; // zmenseni hodnoty promenne i o 1
}
byte i; // deklarace promenne i (cislo 0 - 255)
bool smer; // deklarace logicke promenne pro urceni smeru pohybu
void setup()
{
pinMode(1, OUTPUT); // nastaveni pinu 1 jako vystup
pinMode(2, OUTPUT); // nastaveni pinu 2 jako vystup
pinMode(3, OUTPUT); // nastaveni pinu 3 jako vystup
pinMode(4, OUTPUT); // nastaveni pinu 4 jako vystup
pinMode(5, OUTPUT); // nastaveni pinu 5 jako vystup
pinMode(6, OUTPUT); // nastaveni pinu 6 jako vystup
pinMode(7, OUTPUT); // nastaveni pinu 7 jako vystup
i = 1; // vlozeni hodnoty 1 do promenne x (prvni led)
smer = 1; // 1 - pohyb dopredu, 0 - pohyb zpet
}
void loop()
{
digitalWrite(i, HIGH); // rozsviceni led na pinu i
delay(PRODLEVA); // casova prodleva
digitalWrite(i, LOW); // zhasnuti led na pinu i
if (i == 7) smer = 0; // pokud i je 7 ~ jsme na konci, nastav smer zpet
if (i == 1) smer = 1; // pokud i je 1 ~ jsme na zacatku, nastav smer vpred
if (smer == 1) // kdyz pohyb vpred
i = i + 1; // zvetseni hodnoty promenne i o 1
else // jinak (pohyb zpet)
i = i - 1; // zmenseni hodnoty promenne i o 1
}
Řešení 2:
Jde to i trochu elegantněji. Pokud pro sledování směru nepoužijeme logickou
proměnnou, ale číselnou (se znaménkem), může ji použít přímo pro změnu
honoty proměnné i (tedy čísla led).
#define PRODLEVA 500
byte i; // deklarace promenne i (cislo 0 - 255)
char smer; // deklarace číselné promenne pro urceni smeru pohybu
void setup()
{
pinMode(1, OUTPUT); // nastaveni pinu 1 jako vystup
pinMode(2, OUTPUT); // nastaveni pinu 2 jako vystup
pinMode(3, OUTPUT); // nastaveni pinu 3 jako vystup
pinMode(4, OUTPUT); // nastaveni pinu 4 jako vystup
pinMode(5, OUTPUT); // nastaveni pinu 5 jako vystup
pinMode(6, OUTPUT); // nastaveni pinu 6 jako vystup
pinMode(7, OUTPUT); // nastaveni pinu 7 jako vystup
i = 1; // vlozeni hodnoty 1 do promenne x (prvni led)
smer = 1; // 1 - pohyb dopredu, -1 - pohyb zpet
}
void loop()
{
digitalWrite(i, HIGH); // rozsviceni led na pinu i
delay(PRODLEVA); // casova prodleva
digitalWrite(i, LOW); // zhasnuti led na pinu i
if (i == 7) smer = -1; // pokud i je 7 ~ jsme na konci, nastav smer zpet
if (i == 1) smer = 1; // pokud i je 1 ~ jsme na zacatku, nastav smer vpred
i = i + smer; // uprava hodnoty promenne i
// pokud je smer = 1, hodnota i se zvetsi o 1
// pokud je smer = -1, hodnota i se zmensi o 1
}
byte i; // deklarace promenne i (cislo 0 - 255)
char smer; // deklarace číselné promenne pro urceni smeru pohybu
void setup()
{
pinMode(1, OUTPUT); // nastaveni pinu 1 jako vystup
pinMode(2, OUTPUT); // nastaveni pinu 2 jako vystup
pinMode(3, OUTPUT); // nastaveni pinu 3 jako vystup
pinMode(4, OUTPUT); // nastaveni pinu 4 jako vystup
pinMode(5, OUTPUT); // nastaveni pinu 5 jako vystup
pinMode(6, OUTPUT); // nastaveni pinu 6 jako vystup
pinMode(7, OUTPUT); // nastaveni pinu 7 jako vystup
i = 1; // vlozeni hodnoty 1 do promenne x (prvni led)
smer = 1; // 1 - pohyb dopredu, -1 - pohyb zpet
}
void loop()
{
digitalWrite(i, HIGH); // rozsviceni led na pinu i
delay(PRODLEVA); // casova prodleva
digitalWrite(i, LOW); // zhasnuti led na pinu i
if (i == 7) smer = -1; // pokud i je 7 ~ jsme na konci, nastav smer zpet
if (i == 1) smer = 1; // pokud i je 1 ~ jsme na zacatku, nastav smer vpred
i = i + smer; // uprava hodnoty promenne i
// pokud je smer = 1, hodnota i se zvetsi o 1
// pokud je smer = -1, hodnota i se zmensi o 1
}
Úkoly na samostatnou práci
1. Sestavte program pro běh dvou světýlek proti sobě (jedno běží zleva a druhé zprava).
Tedy dva světelní hadi z úlohy 1 proti sobě. Po doběhnutí se celý cyklus opakuje.
Každá led svítí vždy 0,5s.
2. Sestavte program pro běh světelného hada z úlohy 1 upravený tak, že nesvítí jen jedna
led, ale vždy dvě sousední led (na konci svítí první a poslední led současně).