Seznámení s Arduino

Co je to Arduino?

Arduino je open-source project. To znamená, že kdokoliv může editovat schémata všech oficiálních modelů a základní Arduino programy.
Schémata jsou navíc ke stažení na stránkách Arduina (www.arduino.cc). Stačí do vyhledávače napsat název modelu, jehož schéma požadujete. Jsou zde také ke stažení zdrojové kódy, které může kdokoliv upravovat.
Arduino pak stačí sestavit a pomocí programátoru do něj nahrát základní program.
Pokud byste si chtěli vytvořit vlastní Arduino, návod můžete najít třeba zde.
Já jsem si Arduino koupil, je u něj větší pravděpodobnost, že bude funkční, než kdybych se pokoušel nějaké sám postavit 🙂
Seznam eshopů, ve kterých je Arduino k dostání naleznete zde.
Arduino se dá programovat v C, C++ a Wiring, což je vlastně nadstavba pro C++, která ummožňuje jednoduché ovládání.
Výsledný kód z Wiring jazyka je sice o něco větší, než při použití C, ale vnitřní paměť Arduina je poměrně velká a postačí i na delší programy v jazyce Wiring. Při stažení Arduino IDE (vývojové prostředí) se automaticky stáhnou i tzv. examples (příklady). Jsou to ukázkové kódy pro výuku práce s Arduinem.
Navíc jsou na oficiální Arduino stránce v sekci Learning dostupná zapojení k těmto příkladům a jejich popis (anglicky).

Historie

Prvotní záměr autorů bylo vytvořit jednoduchý hardwarový prvek, vhodný i pro začátečníky, což se jim podařilo.
I přes to si Arduino rychle získalo oblibu i u pokročilých programátorů. Již od začátku je založeno na procesorech ATmega od firmy Atmel. V oficiálních verzích se můžete setkat s procesory
Atmega8,168,328,1280,2560.

Arduino modely

Modely by se daly rozdělit do dvou skupin: neoficiální a oficiální, které můžeme dále rozdělit na malé, střední a velké.
Téměř bez výjimky jsou jejich srdcem 8 bitové procesory. Napájení většiny oficiálních modelů zajišťuje buďto USB nebo 7-12V konektor.

Oficiální modely

Tyto modely můžete najít zde. Jejich design se téměř nemění, procesor uprostřed, kolem pinové (vodičové) zdířky. Uvedu však pár příkladů:

 

 

Malé

Arduino Mini a Nano
U těchto modelů je hlavní jejich velikost. Dají se schovat do dlaně. I přes to mají výkon srovatelný s většími modely.
Srdcem obou modelů je procesor Atmega168 nebo 328. Oba modely mají na spodní straně dvě řady pinů pro zapojení na nepájivé kontaktní pole.
Verze Nano má narozdíl od verze Mini USB port.

Arduino Fio
Tento model je vytvořen pro připojení bezdrátového modulu XBee. Piny modulu XBee se připojí k odpovídajícím zdířkám na Arduinu.
Po nahrátí programu pak může Arduino bezdrátově odesílat požadovaná data do druhého zařízení s XBee.

Lilypad Arduino
Opravdu netypická verze Arduina. Je určena pro vytváření obvodů na oblečení pomocí vodivých nití. Pomocí Lilypadu se dá vytvořit například jezdecké triko s blinkry.
I když by se zdálo, že výkon nebude úplně ideální, skrývá se v něm procesor Atmega 168, což je srovnatelné s ostatnímy typy.

Střední

Arduino serial
Je jeden z prvních modelů. Jeho srdce tvoří Atmega8, s maximální frekvencí 8 až 16MHz (podle verze procesoru).
Tento design se postupem času moc nezměnil a v různých obdobách se s ním můžeme setkat i u ostatních modelů.
Programuje se přes sériový port RS-32. Kdo si rád hraje s pájkou, toho potěší zpráva, že je tato verze k dostání jako i stavebnice.

Arduino NG, Diecimila, Uno…
Středně velké modely arduina se od sebe vzhledově moc neliší, jen sériový port nahradilo USB.Můžeme se zde setkat s procesory Atmega168 a 328.
Mezi první verze patří Arduino Extreme, NG, Diecimila. Poté Arduino Duemilanove a nakonec Arduino UNO.

Arduino BT
Jeden ze středních modelů. Jak už název napovídá, USB zde nahrazuje Bluetooth.

Velké

Arduino Mega
Zatím největší modely. V první verzi Arduino Mega najdeme procesor Atmega1280, v jeho nové verzi je procesor Atmega2560.
Arduino Mega ADK má dvě USB. Typ B je pro nahrávání programů, typ A pro připojení zařízení s Android 2.3.4 a vyšší.
Jedna z nejnovějších verzí Arduino Due je poháněna procesorem ATMEL SAM3U který je 32 bitový, což je srovnatelné se staršímy typy počítačů.

Neoficiální modely

Tzv. Arduino klony. Je jich nepřeberné množství. Klonem je i to Arduino, které si sami můžete sestavit.
Patří sem například Seeduino, Freeduino a mnohé další. Vzhledově se také velmi liší. Od malých druhů cca 1,5x5cm až po desky 10x10cm.

 

 

 

 

 

 

Arduino shieldy

Slovo shield sice znamená anglicky štít, v tomto kontextu by se ale lépe přeložilo jako „nadstavba“.
Bývají designem podobné Arduinu. Stejně jako Arduino mívají 2 řady pinů, které by měly být ve stejné vzdálenosti jako na Arduinu, což zajišťuje snadné připojení.

Ethernet shield
S pomocí tohoto shieldu můžete provozovat jednoduchý HTTP server. Na něj pak zasílat například informace ze senzorů, či textové zprávy.
Připojíte ho přes standartní síťový kabel RJ-45 k vaší síti, nastavíte IP adresu a nahrajete program do Arduina.

Motor shield

 
Tento shield je k dostání jen jako stavebnice. Umožňuje ovládat dva motory s napětím 12V, stačí jen připojit externí zdroj.
Motor shieldy existují v mnoha obdobách. Záleží jen na tom, co od něj požadujeme. Podle toho se samozřejmě orientuje i cena.

 

 

7 segment shield
I když je poměrně snadné vytvořit si vlastní obdobu, tento shield se hodí, když nechceme pořád dokola sestavovat a rozebírat naše zapojení. V tomto modelu je zahrnuta RGB (Red, Green, Blue) LED.

Zdroj obrázků: http://www.arduino.cc/en/Main/Boards

Arduino II.

V tomto díle se již přesuneme k software. Ukážeme si, jak nastavit uživatelské prostředí pro Arduino v Linuxu a Windows a jak ho v těchto systémech připojit a programovat. Ukážeme si i jednoduchý program, který nám umožní blikat LED diodou.
V minulém díle jste se mohli dozvědět, co to vůbec arduino je, jeho historii, jeho typy a možné nástavby. Budeme vycházet ze situace, že už jsme si Arduino koupili a to nám teď leží na stole. Podmínkou je mít PC. Arduino IDE (Integrated Development Environment = integrované uživatelské prostředí) je v dnešní době k dostání pro Windows, Linux i pro Apple OS. S Apple OS bohužel zkušenosti nemám, stručný návod pro Windows a Linux vám ukáži. Systémy po připojení automaticky nainstalují ovladače pro Arduino. My však budeme potřebovat Arduino IDE pro jeho programování.

 


Instalace IDE

Instalace pro Linux

V tomto případě budou mít situaci nejlehčí zřejmě uživatelé Ubuntu. Bohužel s ostatnímy Linuxy nemám zkušenosti, nevylučuji tedy, že jinde to nemůže jít ještě snáz. Uživatelům Ubuntu stačí spustit centrum software pro Ubuntu a do vyhledávače napsat Arduino. Objeví se Arduino IDE s ikonkou zobrazenou výše. Poté zmáčkněte tlačítko instalovat, a první část instalace je za Vámi. Máte li jiný Linux než Ubuntu, nezoufejte. Stačí si ze stránek Arduina v sekci Download stáhnout verzi Arduino IDE pro Linux a poté spustit. Tento postup nevyžaduje instalaci. Když se vše bez problémů vydařilo, můžete Vaše Arduino připojit. PC automaticky rozpozná přidané zařízení. Tímto je hotové připojení.

Instalace pro Windows

Postup je stejný jako pro Linux. Ze sekce Download stáhněte IDE pro Windows. Rozbalte archiv na vámi požadované místo a spusťtě kliknutím na ikonu Arduina. Připojte Arduino, a Windows automaticky nainstaluje potřebné ovladače.

Arduino IDE

Nyní se přesuneme k popisu uživatelského prostředí. Jeho design je ve všech operačních systémech stejný (až na pár drobností). Pozice a funkce všech tlačítek se nemění. V současné době je nejnovější verze IDE 0023.

Arduino – programování v čistém C(++)

O Arduinu bylo napsáno mnoho hello world článků, většina z nich ale ukazuje zdrojový kód napsaný v jazyku Wiring, který byl vyvinut pro snazší práci s Arduinem. Já tímto článkem půjdu proti proudu a onen hello world ukážu v čistém C.

Ve skutečnosti nejde o programovací jazyk, ale o knihovnu v C++, která díky různým technikám velmi usnadňuje práci s arduinem. Uživatelé tak programují v C++ a ani o tom neví. Protože jde ale o procesory, které mají proti klasickým PC velmi málo paměti a v praxi do nich uživatelé možná budou chtít implementovat rozsáhlou a složitou funkcionalitu, hodí se znát, jak obejít knihovnu, díky které výsledná „binárka” bobtná. Navíc Arduino není jedinou deskou s tímto procesorem, a tak se může stát, že knihovna Wiring na jinou desku, resp. jiný procesor nebude prostě připravená.

Jeden ze základních příkladů, takovou avrkovou hello world aplikací je blikání integrované ledky na pinu 13. Kód v „jazyce” Wiring vypadá takto:

void setup() {
  // nastavení digitálního pinu výstup výstup
  // pin 13 je na většině desek Arduina připojen na LED diodu
  pinMode(13, OUTPUT);
}

void loop() {
  digitalWrite(13, HIGH);   // zapne LED diodu
  delay(1000);              // počká jednu sekundu
  digitalWrite(13, LOW);    // vypne LDE diodu
  delay(1000);              // počká jednu sekundu
}

Pokud bychom tento kód chtěli napsat v čistém C, vypadal by takto:

#include <avr/io.h>             // definice registrů DDRB, PORTB a pinů PBn

#define F_CPU 16.0E6            // pro potřeby časování je třeba nastavit
                                // frekvenci procesoru
#include <util/delay.h>         // práce s časováním - funkce _delay_ms

// _delay_ms lze volat s maximální hodnotou 262.14 / F_CPU v MHZ, proto
// vytvoříme funkci, která bude čekat celou vteřinu

void _delay_s(const unsigned char sec){
    unsigned char i = 0;        // v C++ by mohla být definice ve for cyklu
    for (i = 0; i < sec*10; i++){
        _delay_ms(100);
    }
}

int main (void) {
    DDRB |= (1 << PB5);         // nastaví bit5 na portu B (pin 13) na výstup

    while (1) {
        PORTB |= (1 << PB5);    // nastaví bit5 na portu B na 1 (zapne LED)
        _delay_s(1);            // počká jednu vteřinu


        PORTB &= ~ (1 << PB5);  // nastaví bit5 na portu B na 0 (vypne LED)
        _delay_s(1);            // počká jednu vteřinu
    }

    return 1;
}

Jak je z kódu zřejmé, jde vlastně o totéž. Na rozdíl od Wiring varianty však C varianta pracuje přímo z registry procesoru, ty mohou být na různých čipech odlišné. Když bychom se však podívali do zdrojových kódů knihovny Wiring, našli bychom tam funkce, které dělají totéž, jen s omáčkou, která se stará o univerzálnost řešení.

Oba kódy přímo či nepřímo vyžadují knihovnu avr-libc, která je základní free knihovnou pro mikroprocesory AVR na kterých je Arduiono postaveno. Knihovna obsahuje to nejdůležitější co by mohl programátor AVR procesorů potřebovat. Najdeme v ní podporu pro práci s pamětí RAM i EEPROM, knihovnu stdio, stdlib, string i math a také knihovny pro časování, obsluhu přerušení nebo CRC výpočty.

Co ale v knihovně nenajdete jsou implementace kontejnery a iterátory, výjimky a žádné jiné třídy. C++ je v tomto směru jen otázkou syntaxe. Můžete tedy psát třídy, v nich používat identifikátor this a bez varovných hlášení kompilátoru použít například konstrukci (for int i = 0; i < 200; i++). Další a především podrobnější informace jsou k nalezení na stránkách projektu.

K článku je připojen i Makefile, který je jednoduší variantou uvedenou právě na stránkách avr-libc v sekci Demo projects. Ten obsahuje pravidla pro kompilaci i flashování aruduina. Nahrání nového firmware (flashování) do vašeho procesoru lze provádět různými technikami. Budu předpokládat že jste majiteli Arduina, a proto můžete použít program [avrdurde]. Dnešní Makefile i zdrojový kód je vytvořen pro Arduino Uno, bude ale fungovat i na jiných procesorech typu AVR. Proto pokud máte jiné arduino, je třeba zkontrolovat schéma zapojení, kde se nalézá ona LED dioda a případně upravit port ve zdrojovém kódu. A také je nutné před kompilací nastavit správný typ procesoru. Samotný proces kompilace a flashování lze provést jedním:

$ make blink.flash

V příštím článku se podíváme na PWM. Jako alternativu přidám i kód pro jiný AVR čip, který lze u nás pořídit se vším všudy do 100 korun. K jeho flashování už ale potřebujete programátor, který je různě drahý.

  1. Toto tlačítko zkompiluje            („přeloží“) váš kód do Arduinem čitelné podoby. Pokud je v kódu nějaká chyba, program vás na ní upozorní jejím zvýrazněním.
  2.  Zastaví běh kompilace nebo upload (nahrávání) do Arduina.
  3. Vytvoří nový soubor
  1. Po kliknutí se objeví nabídka s Vašimi projekty a příklady (které jsou součástí IDE).
  2. Uloží soubor
  3. Zkompiluje a nahraje program do  Arduina
  4. Spustí sériovou komunikaci (bude vysvětleno později)

 

V menu Tools v podseznamu Boards vyberte váš typ Arduina. Arduino ADK v seznamu mít nebudete. Zatím není v IDE zahrnto a lze ho tam vložit upravením zdrojového kódu IDE. Pokud máte o postup jak přidat Arduino ADK zájem, napište mi to prosím do komentářů. Ostatní typy (kromě těch nejnovějších) jsou však v IDE zahrnuty a neměl by s nimi být žádný problém.

Tento obrázek by se vám měl ukázat ve Windows. V Linuxu bude jediná změna a to místo COM10 bude napsáno přibližně: /dev/ttyACM0. Pro správnou funkci IDE musí být tento řádek zaškrtnut (kliknutím). Pro vysvětlení názvu COM se vrátím kousek do historie. Když se podíváme na zadní desku nějakého staršího počítače, měly bychom zde najít sériové porty. Sériové porty mají označení COM. Používaly se k připojování zařízení jako pokladní terminály, tiskárny etiket, nebo jednoduché zobrazovací jednotky. Jelikož byl tento port pro takovéto zařízení jako dělaný, našel své uplatnění i v programátorech pro mikroprocesory. I jeden z prvních typů Arduina (Arduino Serial) se programoval přes tento port. Když chceme dnes připojit něco se sériovým portem, musíme si většinou buďto pořídit přídavnou kartu k PC, nebo si koupit USB-COM převodník. Ten má v sobě malý čip, který vytváří virtuální sériový port. Ve verzích Arduina s USB je tento čip přímo na desce.

 

 

 

První program

Struktura

Už se pomalu dostáváme k prvnímu programu. Ještě předtím je však důležité seznámit se se základní syntaxí (strukturou) programu. Pro komentáře v jazyce wiring se používá značka //. Vše co je za touto značkou překladač ignoruje. Je to však pouze v oblasti jednoho řádku. Pokud chceme komentář na více řádků, použijeme /*text komentáře*/. Vše mezi /* a */ je bráno jako komentář bez ohledu na to, kolik řádků je mezi nimi.

V IDE si otevřete menu File a dále postupujte podle obrázku. Objeví se kód níže. Já ho pro jednoduchost přeložím a dovysvětlím.


void setup() {

 
  // zde je kód, který proběhne pouze jednou 
 
}
 
void loop() {
 
  /* tento kód bude probíhat stále dokola, až do odpojení napájení nebo nahrání jiného programu */
 
}
 

Blikáme LEDkou

Na stejném místě jako jsme našli program Bare Minimum najdeme program Blink. Po otevření se vám zobrazí kód s komentáři v angličtině. Na začátku je popis programu. Další komentáře jsou popisy toho, co který řádek dělá. Já příklad pro názornost přeložím. V tomto příkladu budeme blikat LED diodou (light emitting diode = svítivá dioda, záleží u ní na polaritě, delší nožička bývá plus, neboli anoda). Většina verzí Arduina má na již na desce na zdířce 13 připojenou malou LED diodu. My si však zapojíme LED delší nožičkou do zdířky 13 a kratší do zdířky GND (ground = země, uzemnění). Výsledek bude zřetelnější.

 
void setup() {                
 
                               // tento kód proběhne jen jednou
 
  pinMode(13, OUTPUT);   // nastaví zdířku(pin) 13 jako výstup(=output)  
 
}
 
void loop() {
 
                               //tento kód se bude neustále opakovat
 
  digitalWrite(13, HIGH);      // na pinu 13 nastavit logickou 1(=proud prochází, LED svítí)   
 
  delay(1000);                 // počká 1000 milisekund = 1 sekuda  
 
  digitalWrite(13, LOW);       // nastaví logickou 0   
 
  delay(1000);                 // počká sekundu   
 
 

Úkol

Jelikož nejlepší cesta, jak si něco zapamatovat a naučit vede přes zkoušení, zkuste si udělat jednoduchý úkol. Napište program, který bude blikat více diodami. Můžete začít dvěmi a postupně přidávat. Můžete programovat různé sekvence i kombinace, jak je libo. V příštím díle si ukážeme, jak by mohlo vypadat jedno z řešení.

 

 

 

 

 

Arduino III.

V dnešním díle si popíšeme funkce, které nám usnadní a zkrátí náš program. Jsou to například proměnné, pole, cykly nebo podmínky. Naučíme se s Arduinem komunikovat po sériové lince, s jejíž využitím si necháme do PC posílat data z potenciometru, nebo budeme testovat, zda je tlačítko stisknuté, či nikoliv.
V minulém díle jsme nainstalovali Arduino IDE v Linuxu i ve Windows a nastavili vše potřebné. Ukázali jsme si i jednoduchý program, kterým jsme blikali LED diodou.

Řešení úkolu

Různých obdob tohoto úkolu je vlastně nepočítaně. Záleží jen na nás, kolik LED si vybereme a v jakém pořadí je budeme rozsvěcovat. Pro ukázku řešení si zvolím 5 LED, které naprogramuji jako běžící pás. Všechny diody tedy postupně rozsvítím a ve stejném pořadí je vzápětí budu zhasínat.

 

void setup() {

// jako první musíme nastavit piny,

// na kterých jsou připojeny LED, jako výstupní

pinMode(12, OUTPUT);

pinMode(11, OUTPUT);

pinMode(10, OUTPUT);

pinMode(9, OUTPUT);

pinMode(8, OUTPUT);

}

void loop() {

//začneme programovat pás

digitalWrite(12, HIGH);

delay(500);

digitalWrite(11, HIGH);

delay(500);

digitalWrite(10, HIGH);

delay(500);

digitalWrite(9, HIGH);

delay(500);

digitalWrite(8, HIGH);

delay(500);

 

digitalWrite(12, LOW);

delay(500);

digitalWrite(11, LOW);

delay(500);

digitalWrite(10, LOW);

delay(500);

digitalWrite(9, LOW);

delay(500);

digitalWrite(8, LOW);

delay(500);

}

Jak vidíte, je tento kód poměrně dlouhý, za chvíli si tedy ukážeme, jak ho zkrátit.

Proměnné

Můžeme se setkat s různýmy druhy. Udáváme, jaký typ dat v proměnné bude. Jeden ze základních typů je integreer, který se značí int. Proměnná tohoto typu může nabývat hodnot od -(2^15) až po (2^15)-1 . Avšak pokud chceme zapsat delší číslo, musíme použít datový typ long, do kterého můžeme vepsat čísla od -2,147,483,648 do 2,147,483,647. Důležitým typem je také Array (pole). Do něj vkládáme data vždy s nějakým indexem (=“adresa“). Podle indexu pak můžeme lehce vyhledat uložené informace. Pokud se zajímáte o další typy můžete je nalézt zde

Int, long…

Většina proměnných se dá vytvořit velmi jednoduchou syntaxí. Vždy musíme programu říct, jaký datový typ od něj požadujeme, poté zadat název proměnné a její hodnotu (tu však není nutné zadat při vytvoření proměnné, ale můžeme ji přidat později). V názvu bychom se měli vyvarovat diakritiky. Ta by mohla způsobit chyby v zápisu do Arduina. Vytvoření proměnných vypadá následovně:

int jmeno = 250; //nyní jsme vytvořili proměnnou typu int s názvem jmeno a hodnotou 250

jmeno = jmeno + 200; // k proměnné jmeno jsme přičetli 200

 

//stejná situace nastane pro proměnnou long i většinu ostatních

long jmeno1 = 9 000 000 000; //jmeno1 má hodnotu 9000000000

jmeno1 = 0 //nyní jsme přepsali hodnotu jmeno1 na 0

Array

Další typ proměnné. Do češtiny se překládá jako pole nebo řada. Každý prvek má svůj index, pod kterým ho můžeme v poli najít. První prvek v poli má index 0 a každý další o 1 větší. Pokud je počet prvků v poli známý, měli bychom zapsat jejich počet za jméno pole. Podle hranatých závorek se pozná, že máme na mysli právě pole. Před jeho názvem musíme napsat, jakého typu budou prvky pole.

int pole[] = {2, 4, 8, 3, 6}; //vytvořili jsme pole s názvem pole, jsou  v něm hodnoty 2,4,8,3,6

//pokud chceme jiné proměnné přiřadit hodnotu jednoho z prvků, budeme postupovat následovně

int prvek = pole[2]; //do proměnné prvek jsme přiřadili 8, číslování indexů je totiž od nuly a 8 je na 3 místě

Cykly

Posledním krokem před zkrácením programu je naučit se něco o cyklech. Cyklus je operace která se x krát opakuje. Nejpoužívanější je cyklus for. Cyklu musíme říct, s jakou proměnnou má pracovat, počet opakování zajistíme podmínkou, a také mu řekneme, co má dělat při každém opakování.

 

for (int x=0; x< 8; x++) {

//na začátku nastavíme proměnnou int na 0, skript se provede 8 krát, x nabude hodnoty 0 až 7

digitalWrite(12, HIGH);  //logická 1 na výstupu 12

delay(250);

digitalWrite(12, LOW);   //logická 0 na výstupu 12

//tento kód osmkrát blikne LED připojenou pa pin 12

}

Nyní se můžeme přesunout ke zkrácení našeho prvního kódu v tomto díle.

Zkrácení

Z praktických důvodů pro Vás bude lepší, když si kód zkusíte upravit sami. Výsledný kód by ale mohl vypadat takto:

 

 

int cekej= 250;

int LED[5] = {12,11,10,9,8};

int y = 0;

int x = 0;

int z = 0; //této části se říká inicializace proměnných

//nastavíme si zde všechny proměnné, které v programu použijeme

//není to nutné, ale může se stát, že bez inicializace nebude program pracovat

 

void setup() {

for (x=0; x< 5; x++) {

pinMode(LED[x], OUTPUT);

}

}

 

void loop() {

for (y=0; y< 5; y++) {

digitalWrite(LED[y], LOW);

delay(cekej);

}

 

for (y=0; y< 5; y++) {

digitalWrite(LED[y], HIGH);

delay(cekej);

}

}

Tento kód sice není o moc kratší než původní, ale představte si, že budete mít tento pás s 20 LED diodami. To už bude kód podstatně kratší.

 

 

 

 

Sériová komunikace

Velmi užitečná funkce. Můžeme ji použít, když chceme zaslat nějaká data z Arduina do PC. Všechny modely mají alespoň jednu sériovou linku. Modely Mega mají tyto linky 3. Jak už bylo krátce zmíněno v minulém díle, Arduino je připojeno přes virtuální sériový port. Ve většině modelů je přímo na desce Serial to USB převodník, který tento port vytváří. Pouze k verzi Mini, Stamp a Lilypad je potřeba externí převodník.

Digital reading

Pro tento typ využijeme funkci digitalRead(). Tato funkce testuje binární hodnotu na zvoleném vstupu. V tomto případě je to vstup 2. Zbytek je vysvětlen v kódu. Schéma zapojení je na obrázku níže. Velikost rezistoru by se měla pohybovat mezi 2000 a 10000 Ohmy. Po nahrátí programu v menu Tools klikněte na Serial Monitor. Objeví se vám okno, které můžete vidět na obrázku níže. Tento kód můžete najít v menu Examples. Zde je pouze přidaná prodleva 500 ms.

 

void setup() {

 

Serial.begin(9600); //tímto příkazem spustíte sériovou komunikaci, 9600 je rychlost toku dat

pinMode(2, INPUT); //nastavení vstupního pinu

}

 

void loop() {

int sensorValue = digitalRead(2); //digitalRead pracuje s binární informací 0/1

//když je tlačítko stisknuto, rovná se 1

Serial.println(sensorValue); //vypíše hodnotu na senzoru na sériovou linku

delay(500); //počká 0,5 vteřiny

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Analog reading

Pro tento příklad zapojte potenciomer podle druhého schématu. Velikost odporu potenciometru si můžeme zvolit prakticky jakoukoliv od 0 do cca 10k ohm. Potenciometr je totiž zapojen jako dělič napětí. Nezáleží tedy, jaká je skutečná hodnota odporu, ale na poměru dvou částí v potenciometru, jejichž velikost otáčením měníme. Pro naše účely je nejlepší potenciometr s lineárním průběhem. Zkoušení je však možné provádět i s ostatními typy. V softwaru je použita nová funkce analogRead(). Je to obdoba funkce digitalRead(), jen s rozdílem, že rozlišuje 1024 hodnot (0-1023). Navíc musíme střední pin potenciometru připojit na analogový vstup (např A0). Po spustění Serial Monitor se otevře podobné okno jako u předchozího příkladu. Budou zde však čísla od 0 po 1023 (podle otočení potenciometru).

 

void setup() {

Serial.begin(9600); //spustí sériovou komunikaci

//u analogového čtení odpadá nutnost nastavení vstupu

}

 

void loop() {

int sensorValue = analogRead(A0); //čte analogovou hodnotu na vstupu A0

Serial.println(sensorValue); //vypíše tuto hodnotu

delay(100); //počká 100 ms

}

PWM

Zkratka pro Pulse Width Modulation. Do češtiny se překládá jako pulsně šířková modulace. Je to pokus o digitální nahrazení analogové hodnoty. Nedochází zde ale ke změně velikosti napětí. Arduino může generovat PWM v rozsahu 0 až 255. 0 znamená, že neproudí žádný proud. 255 je nepřerušovaných 5 voltů. Hodnota 1 znamená jeden „schod“ o velikosti 5 voltů o délce jednoho „taktu“. Zbylých 252 „taktů“ je na výstupu 0 voltů. Pokud tedy nastavíme hodnotu na 100, znamená to, že bude 100 „taktů“ +5V a 155 „taktů“ 0V. Poměr +5V ku 0V se nám projeví například jako různý jas LED, nebo jako různá rychlost otáčení motoru. Jak generovat PWM můžete vidět v následujícím kódu. Zapojte LED v sérii s 330 ohm resistorem mezi piny GND a 12. Vyzkoušejte různé velikosti proměnné jas. POZOR!! Arduino boardy mají pro PWM přímo určené výstupy. Na jiných výstupech nebude tato funkce fungovat.

 

int jas=20; //jaký jas má mít LED dioda

int LED=12; //na kterém pinu je LED připojena

void setup()  {

pinMode(LED, OUTPUT);

analogWrite(LED, jas); //funkce analogWrite() umožňuje generovat PWM signál

}

void loop()  {

}

 

 

Úkoly

Pro procvičení mám pro Vás dva úkoly.

  1. Napište program, který bude postupně rozsvěcovat a zhasínat LED diodu (nápověda: cyklus for). Nechte Arduino po sériové lince posílat informace o jasu LED.
  2. Pomocí potenciometru regulujte jas LED (analogRead() – analogWrite()).

,

Arduino IV.

V tomto díle si ukážeme řešení úkolu z minulého dílu, poté se vrátíme k pásu LED diod, na němž si ukážeme funkci 4-bitového dekodéru BCD kódu na 1 z 16 a funkci Map. Také si ukážeme logickou funkci If.

V minulém díle jsme si řekli něco o proměnných a cyklech. Ukázali sme si, jak funguje sériová komunikace a naučili jsme se číst analogová a digitální data. Nakonec jsme vyzkoušeli, jak funguje PWM.

Řešení úkolů

Úkol 1.

 

int cekej = 10; //kolik milisekund bude program čekat mezi jednotlivými kroky

 

void setup() {

pinMode(12, OUTPUT);  //pin 12 nastaven jako výstupní

Serial.begin(9600); //začátek sériové komunikace

}

void loop() {

//tento cyklus rozsvěcuje LED

for(int jas=0; jas < 255; jas++){

analogWrite(12, jas);

Serial.println(jas);

delay(cekej);

}

//tento ji zhasíná

for(int jas=255; jas > 0; jas–){

analogWrite(12, jas);

Serial.println(jas);

delay(cekej);

}

//oba dva cykly posílají data o jasu led diody přes sériovou linku

}

 

 

Úkol 2.

void setup() {

pinMode(12, OUTPUT);  //pin 12 nastaven jako výstupní

Serial.begin(9600); //začátek sériové komunikace

}

void loop() {

int jas = analogRead(A0) / 4; //čte hodnotu na potenciometru

/*důvod,proč je hodnota vydělena 4 je jednoduchý

funkce analogRead pracuje s 1024 hodnotami (0 – 1023),

kdežto analogWrite pouze s 256 hodnotami (0 – 255)

1024 je čtyřnásobek čísla 256, proto pro úpravu na správnou hodnotu dělíme čtyřmi*/

analogWrite(12, jas);

}

Pás z 10 LED

Vytvoříme si hada, jako v minulém díle, ale z 10 LED. Na něm si ukážeme užitečné funkce. Takto může vypadat kód, který postupně rozsvětsuje a zhasíná diody. Je to upravený kód z minulého dílu.

 

int cekej= 250;

int LED[10] = {12,11,10,9,8,7,6,5,4,3};

 

 

void setup() {

for (int x=0; x< 10; x++) {

pinMode(LED[x], OUTPUT);

}

}

void loop() {

for (int y=0; y< 10; y++) {

digitalWrite(LED[y], LOW);

delay(cekej);

}

 

for (int z=0; z< 10; z++) {

digitalWrite(LED[z], HIGH);

delay(cekej);

}

}

Funkce Map

Tato funkce se používá, když chceme převést data nabývající rozsahu například 0-1023 na data 0-255 tak, aby procentuální podíl zůstal zachován. Následujícím příkladem můžeme nahradit dělení čtyřmi v úkolu 2. Pokud váháte, zda použít raději dělení, nebo funkci map, je to jen na vás. Při použití map je výsledek „elegantnějsí a čistčí“. Na funkčnosti projektu se ale nic nemění. Při použití dělení by problém nastal, kdyby vstupní a výstupní rozsah byli nesoudělná čísla. Syntaxe je následovná:

 

int jas1 = analogRead(A0);

int jas2 = map(jas1, 0, 1023, 0, 255);

//z rozsahu 0-1023 jsme přemapovali proměnnou jas1 na 0-255

analogWrite(12, jas);

Podmínka IF

Do češtiny překládáme jako KDYŽ. Je to běžná funkce ve většině „vyšších“ programovacích jazyků. Než se pustíme do podmínek, ukážeme si porovnávací operátory, které se v podmínkách vyskytují.

== – rovná se

!= – nerovná se

<  – menší než

>  – větší než

<= – menší nebo rovno

>= – větší nebo rovno

 

&& – logické a (AND) – výsledek je logická 1, když jsou oba výroky pravdivé

|| – logické nebo (OR) – výsledek je logická 1, když je alespoň jeden výrok pravdivý

!  – logická negace (NOT) – když je výrok pravdivý, po znegování je nepravdivý a naopak

 

Zápis podmínky vypadá takto.

 

if(podmínka 1){

//co se stane, když je splněna podmínka

}

else if(podmínka 2) {

//co se stane když je splněna 2 podmínka

//tato část je nepovinná, může zde být libovolně mnohokrát

}

else {

//co se stane, když není splněna ani jedna podmínka

//tato část je také nepovinná

}

příklad:

if(abc < 0){

//když je proměnná abc menší než nula proběhne kód zde

}

else if(abc == 0){

//když je proměnná abc rovna kód zde

}

else if((abc > 10) && (abc < 20)){

//když je proměnná abc mezi 10 a 20 proběhne kód zde

}

else{

//když je proměnná abc větší než nula proběhne kód zde

}

 

4-bitový dekodér BCD kódu 1 z 16

Co to vlastně je? 4 bitový znamená, že dekodér pracuje se 4 bitovou vstupní informací. Jednoduše řečeno, má čtyři vstupní piny. Kombinací jedniček a nul na těchto vstupech se dá docílit nastavení logické 1 na jednom z 16 výstupů. BCD kód znamená binary coded decimal, neboli binárně zakódovaná číslice v desítkové soustavě. Převodní tabulky z BCD na desítkovou soustavu můžete najít ve spoustě zdrojů na internetu. Zapojení je pak jednoduché. Na internetu si najděte datasheet (popis) vašeho dekodéru a připojte napájení podle popisu v něm. Propojte vstupy dekodéru s Arduinem a na každý každý z výstupů dekodéru připojte LED diodu. Vše následující popíšu v kódu.

int piny[4]={12,11,10,9}; //na těcto pinech je dekodér připojen

//nastavíme, jaká kombinace je potřebná k rozsvícení každé LED

int led[16][4]={{0,0,0,0},    //pod indexem 0 je uložena

{1,0,0,0},    //kombinace 0,0,0,0 – bude svítit 1. LED

{0,1,0,0},

{1,1,0,0},

{0,0,1,0},

{1,0,1,0},

{0,1,1,0},

{1,1,1,0},

{0,0,0,1},

{1,0,0,1},

{0,1,0,1},

{1,1,0,1},

{0,0,1,1},

{1,0,1,1},

{0,1,1,1},

{1,1,1,1}};

int cislo = 10; //jakou led chceme zobrazit

 

void setup() {

for(int x=0; x<4 ; x++){

pinMode(piny[x],OUTPUT);

}

}

 

void loop() {

for(int x=0; x<4 ; x++){

digitalWrite(piny[x],led[cislo][x]);

}

}

 

Úkoly

Pro procvičení mám pro Vás dva úkoly.

  1. Pomocí potenciometru vyberte 1 z 16 LED (nápověda – 1. možnost: funkce Map 2. možnost: IF + For)
  2. Přidejte k prvnímu úkolu jeden potenciometr, kterým regulujte jas LED.

Arduino V.

V tomto díle se podíváme na funkce Arduina používané pro práci s časem. Poté si ukážeme, jak používat Arduino jako syntetizér. Nakonec si pomocí této funkce vytvoříme jednoduchý klavír.

V minulém díle jsme se naučili, jak se zapisují funkce If a Map. Také jsme si ukázali, jak připojit k Arduinu 4 bitový dekodér.

 

Řešení úkolů

Úkol 1.

K řešení tohoto úkolu použijeme kód z minulého dílu u 4 bitového dekodéru. Pro účely úkolu ho trochu upravíme.

  int piny[4]={12,11,10,9}; 
  int led[16][4]={{0,0,0,0},{1,0,0,0},{0,1,0,0},
                  {1,1,0,0},{0,0,1,0},{1,0,1,0},
                  {0,1,1,0},{1,1,1,0},{0,0,0,1},
                  {1,0,0,1},{0,1,0,1},{1,1,0,1},
                  {0,0,1,1},{1,0,1,1},{0,1,1,1},{1,1,1,1}};  
void setup() {
  for(int x=0; x<4 ; x++){
     pinMode(piny[x],OUTPUT); 
  }
}
 
void loop() {
 int pot = analogRead(A0);
        pot = map(pot, 0, 1023, 0, 15); //tímto jsme přemapovali
                                       data z potenciometru na 16 hodnot
                                      //nyní stačí napsat příkaz pro
                                      rozsvícení led diody
 for(int x = 0; x<4; x++){
        digitalWrite(piny[x],led[pot][x]);
 }
}

Pás z 10 LED

V tomto úkolu jsem se dopustil prohřešku. Nepromyslel jsem si pořádně zadaný úkol. Pokud bychom totiž použili na všechny výstupy funkci analogWrite(), podle mě by některé dekodéry nemusely stíhat, nebo by mohl vzniknout problém se synchronizací. Také můžeme použít transistory jako spínače u každé diody a funkci dekodéru zachovat. Například pin 13 bude společná zem, na který použijeme funkci analogWrite(). Poté budeme dekodérem ovládat, kterým transistorem bude procházet proud. My ale použijeme na součástky asi nejjednodušší zapojení, se kterým jsme v tomto seriálu už pracovali. Jeho způsob můžete vidět na obrázku. Pro jednoduchost jsou na něm jen 3 diody.

int LED[10] = {12,11,10,9,8,7,6,5,4,3};
 
void setup() {                
  for (int x=0; x< 10; x++) { 
     pinMode(LED[x], OUTPUT);
  }     
}
void loop() {  
  int led = analogRead(A0); //tímto potenciometrem budeme nastavovat LED
  int jas = analogRead(A1); //a tímto jas
  led = map(led, 0, 1023, 0, 9);
  jas = map(jas, 0, 1023, 0, 255);
  analogWrite(LED[led],jas);
  }  
 

 

Čas a arduino

Funkce millis()

Pokud chceme v našem programu pracovat s časem, můžeme použít dvě základní funkce. Millis() je jedna z nich. Do závorky se nepíší žádné parametry. Musí tam však být, aby program poznal, že jde o funkci. Tato funkce počítá milisekundy. Odpočítávání začíná se spuštěním programu. Když tedy vyvoláme: int cas = millis();, proměnná cas bude obsahovat počet milisekund od začátku programu. Podle manuálu Arduina v sekci References se funkce millis() přibližně po 50 dnech vynuluje (tzv. přeteče) a začíná od začátku. Vše si ukážeme na příkladu. Pro jeho pochopení si musíme vysvětlit matematickou operaci modulo. Používá se, když chceme zjistit zbytek po dělení dvou čísel. Je pro ni značka %. Tedy například 5%2=1 (5/2=2 zbytek 1), 20%3=2 (20/3=6 zbytek 2). Kód v příkladu nám bude každou sekundu blikat LED diodou.

 
void setup() {
  pinMode(13,OUTPUT);
}
 
void loop() {
  if((millis()%1000) == 0){
    digitalWrite(13,HIGH);
    delay(20);
  }
  digitalWrite(13,LOW);
}

Funkce delay()

Je to jedna z nejčastějších funkcí. Použijeme ji, pokud chceme, aby program na chvíli počkal. Do závorek se píše číslo právě v milisekundách. Jelikož jsme se s touto funkcí už setkali, nebudu ji dále popisovat.

Funkce micros()

Tato funce funguje stejně jako millis() jen s tou výjimkou, že zobrazuje čas v mikrosekundách. U micros() dojde k přetečení asi za 70 minut. Čas však nezobrazují po každé mikrosekundě, ale po mikrosekundách v násobcích 4 (u 16 MHz verze) a 8 (u 8MHz verze).

Funkce delayMicroseconds()

Obdoba funkce delay(), jen s tou výjimkou,že do této funkce, jak už název napovídá, zadáváme čísla v mikrosekundách.

Zvuky

Funkce tone()

Můžeme ji využít, pokud chceme arduino použít jako jednoduchý syntetizér. Na určeném digitálním pinu střídá 5V a 0V s určitou frekvencí. Můžeme ji zapsat dvěma způsoby. Buďto tone(pin,frekvence), nebo tone(pin,frekvence,trvání). Doba trvání se udává v milisekundách. Pokud ji neuvedeme, můžeme tón později v programu ukončit pomocí noTone(pin). Na vybraný pin připojíme repráček, piezzo bzučák nebo jack pro připojení repro soustavy. Doporučuje se připojit 100 ohmový resistor v sérii s repráčkem pro jeho ochranu. Vše si ukážeme na příkladu. Ukáži vám, jak oběma způsoby hrát přerušovaný tón a1. Jednu sekundu bude tón, jednu bude ticho.

void setup() {
}
 
void loop() {
  //1. způsob
  tone(12,440);
  delay(1000);
  noTone(12);
  delay(1000);
  
  //2.způsob
  tone(12,440,1000);
  delay(1000);
}

Jednoduchý klavír

Abychom si trochu vyzkoušeli, jak funkce tone() funguje, zkusíme si postavit jednoduchý klavír. Bude sestávat z 6 tlačítek, ke kterým přiřadíme frekvenci. Poté použijeme podmínku if k otestování, zda je tlačítko stisknuto. Když stisknuto je, budeme hrát příslušnou frekvenci. Pokud chcete trochu experimentovat, můžete například zde najít tabulku frekvencí jednotlivých tónů.

  int piny[6]={13,12,11,10,9,8}; //kde jsou tlačítka připojena
  int repro = 2; //pin, na kterém je připojen repráček
  int ton[6]={523,554,587,622,659,698};       //příslušná frekvence tlačítek
 
void setup() {
  for(int x = 0;x<6;x++){
    pinMode(piny[x],OUTPUT);
  }
}
 
void loop() {
for(int x = 0;x<6;x++){  
  if(digitalRead(piny[x]) == 1){
    tone(repro,ton[x]);
    delay(50);
    noTone(repro);   
  }}}
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

Schémata byla nakreslena v programu Fritzing.

Úkoly

Úkoly:
1. Vytvořte tento klavír pro celou oktávu. Například od c1 do h1 včetně půltónů.
2. Přidejte k prvnímu příkladu potenciometr, kterým měnte oktávu vašeho klavíru.

Arduino VI.

V tomto díle se podíváme, jak Arduino může pracovat s piezo elementem. Pomocí něj uděláme senzor klepání. Dále si vysvětlíme jak funguje relé a jeho připojení k Arduinu.

Řešení úkolů

Úkol 1 a 2

Úkolem bylo vytvořit klavír pro jednu oktávu a poté k němu přidat potenciometr k určení oktávy. Pro tento účel bylo asi nejvhodnější postupovat tak, jak bylo ukázáno v minulém dílu. Jen musíme tento klavír rozšířit. Přidáme i půltóny. Náš klavír bude tedy mít 12 tónu (C, Cis, D, Dis, E, F, Fis, G, Gis, A, Ais, H, His). Odkaz na tabulku frekvencí jsem uváděl v minulém díle. Uvedu zde pouze kód druhého příkladu. První příklad je stejný, jenom je proměnná oktáva trvale nastavená na nulu. Uspořádání tlačítek je na vás. Nejpraktičtější je si je seřadit stejně, jako na klavíru, nebo je nechat vzestupně, nebo sestupně v jedné řadě. Příklady zapojení můžete vidět na obrázcích.

 

int klavesy[12]={7,2,8,3,9,10,4,11,5,12,6,13}; 
//klávesy seřazené podle výšky tónu (frekvence)
int tony[4][12]= {{262,277,294,311,330,349,370,392,416,440,466,494},
                  {523,554,587,622,659,698,740,784,831,880,932,988},
                  {1047,1109,1175,1245,1319,1397,1480,1568,1661,1760,1865,1976},
                  {2093,2217,2349,2489,2637,2794,2960,3136,3322,3520,3729,3951}}; 
                   //frekvence tónů ve čtyřech oktávách
int piezo=49; //kde je připojen repráček
int oktava;
void setup() {
  for(int a=0; a<12; a++){
    Serial.begin(9600);
    pinMode(klavesy[a], OUTPUT);
  }
 
}
 
void loop() {
  int oktava = digitalRead(A0);
  oktava = map(oktava, 0, 1023, 0, 3);
  Serial.println(oktava);
   Serial.println( digitalRead(A0));
  for(int a=0; a<12; a++){
    int hodnota = digitalRead(klavesy[a]); //stisknuto = 1, uvolněno = 0
    if(hodnota == 1){
      tone(piezo,tony[oktava][a]);
      delay(40);
      noTone(piezo);
    }
    hodnota = 0; //na konci cyklu nastavíme proměnnou opět na nulu
  }
}

Piezo element

Piezo elementy jsou založeny na takzvaném Piezoelektrickém jevu. Je to schopnost materiálu při deformaci generovat elektrické pole, nebo naopak se při dodání elektrické energie deformovat. Nejznámějším materiálem s tou to vlastností je křemen. Na piezoelektrickém principu fungují piezo motory, piezo senzory, nebo piezo reproduktory. Konstrukce reproduktoru i senzoru je stejná a většinou se dá reproduktor použít i jako senzor a naopak. Jde o plíšek, na který je přitisknutý krystal. Ten je v případě senzoru chvěním plíšku deformován, v případě reproduktoru „buší“ do plíšku. Pro ukázku funkce piezo senzoru použijeme nápad ze stránky Arduina. Piezo senzor je zde použit jako detektor klepání na dveře. Když někdo zaklepe, po sériové lince se vypíše zpráva.

 
int citlivost = 60;
void setup() {
  Serial.begin(9600);
}
 
void loop() {
  int hodnota = analogRead(A0);
  if(hodnota > 60){
    Serial.println("Nekdo klepe!") ;
    delay(500); 
  }
  delay(100); 
}
 

Při použití v reálu je ještě potřeba si nastavit citlivost senzoru, aby klepání zaznamenal, ale aby ignoroval šum.

Relé a Arduino

Relé je spínač, který je ovládán elektrickým obvodem. Základem je elektrická cívka, která spojuje a rozpojuje kontakty. Můžeme se setkat s hodně druhy relé. Základními parametry jsou: jaké napětí je potřeba k sepnutí obvodu a jak velké napětí může být v řízeném obvodu. Dále rozlišujeme, zda je ovládaný obvod, když cívkou protéká proud otevřený, nebo uzavřený. V tomto případě potřebujeme k udržení jednoho stavu proud, u druhého nikoliv. Například když chceme, aby byl řízený obvod aktivní, musí cívkou procházet proud, když má být řízený obvod neaktivní, cívkou neprochází proud. Tento druh relé se jmenuje monostabilní. Druhým typem je relé bisabilní, kdy potřebujeme mít cívku aktivní pouze při změně logického stavu v řízeném obvodu. Dále se můžeme setkat s relé se spožděným sepnutím, se spožděným vypnutím atd.

Pro ovládání bistabilního relé potřebujeme dva piny Arduina (např. pin 1 a pin 2). Když chceme zapnout řízený obvod, nastavíme na prvním pinu logickou 1 a na pinu 2 logickou 0. Když ho chceme vypnout nastavíme na pinu 1 logickou 0 a na pinu 2 logickou 1. Když nechceme měnit stav relé, nastavíme na obou pinech stejnou logickou hodnotu (buď 0 a 0, nebo 1 a 1).

Pro ukázku jsem vybral monostabilní relé. Pomocí Arduina Vám ukáži, jak rozsvěcovat a zhasínat světlo. Pro práci s relé je vhodné vyrobit si modul se šroubovými kontakty pro rychlé připojivání. Vnitřní schéma jednoho druhu relé a modul vlastní výroby můžete vidět na obrázku.

 

Kód je zde velmi jednoduchý. Můžeme použít příklad Blink, se kterým jsme již pracovali. Najdeme ho v Arduino IDE v nabídce Examples. Na pin 13 pak připojíme jeden z vývodů cívky, druhý vývod připojíme k pinu GND.

 

Schémata byla nakreslena v programu Fritzing.

Úkol

1. Vytvořte program, který po zaklepání sepne relé, které například rozsvítí žárovku.

 

Arduino VII.

V dnešním díle se podíváme, jak pracovat s EEPROM pamětí, kterou má každé Arduino zabudovanou v sobě.

Řešení úkolu

int citlivost = 60;
void setup() {
  pinMode(12, OUTPUT); //pin, na kterém máme připojené relé
}
 
void loop() {
  int hodnota = analogRead(A0);
  if(hodnota > citlivost){
    digitalWrite(12,HIGH);
  }
  delay(100); 
}

EEPROM paměť

Tuto paměť obsahují všechny typy Arduina, jen je u různých modelů v různých kapacitách. Je integrována přímo v procesorech. Ve verzích s čipem Atmega8 a Atmega168 je to 512 bytů. Atmega328 má 1kB a Atmega1280 a Atmega2560 mají 4 kB. EEPROM je typ paměti, který nepotřebuje k uchování informace elektrický proud, tudíž nám data zůstávají v paměti dokud je nepřepíšeme. Uživatelské programy se ukládají na Flash paměť. Tato paměť také nepotřebuje elektrický proud k uchování infomace. Posledním typem paměti v Arduinu je SRAM. Uchovávají se na ní proměnné programu a při odpojení napájení se tato paměť vymaže (děkuji uživateli František Bocek za doplnění). Dle stránek Arduina vydrží EEPROM paměť minimálně 100 000 zápisů, což se může zdát hodně, ale při špatném naprogramování a zacyklení programu může dojít k poškození poměrně rychle. Podle serveru Hackaday paměť vydrží 1 200 000 přepsání. Je možné, že se výdrž později vyrobených pamětí prodlužuje, nebo se může lišit kus od kusu (jsou to však pouze moje domněnky). Při práci s pamětí pracujeme s jednotlivýmy byty. Jeden byte má osum bitů, proto do něj můžeme vepsat hodnoty od 0 do 255. Byty, se kterýmy se ještě nepracovalo jsou nastaveny na hodnotu 255.

EEPROM knihovna

Arduino pro základní operace (čtení/psaní) s touto pamětí používá knihovnu EEPROM.h, která je součástí Arduino IDE. Knihovnu nemusíme kromě příkazu pro vložení (#include <EEPROM.h>) nijak inicializovat. Pro práci používáme dva příkazy, a to EEPROM.read a EEPROM.write. Jak se s těmito příkazy pracuje si nyní ukážeme.

EEPROM.read

V kódu se používá syntaxe: EEPROM.read(adresa);, kdy adresa je proměnná, nebo číslo s minimální hodnotou 0 a maximální hodnotou 511/1023/4095 (dle verze procesoru). Nejčastěší je zřejmě použití, kdy získanou hodnotu nastavujeme, jako hodnotu proměnné: hodnota = EEPROM.read(adresa);. Můžeme ji použít i jako parametr nějaké jiné funkce, například: Serial.println(EEPROM.read(adresa));. Ukažme si použití EEPROM.read na příkladu.

#include <EEPROM.h>
 
int pamet = 4096; 
/* zde napište velikost vaší paměti v bytech.
Jelikož já jsem vlastníkem modelu s ATmega 2560,
je moje paměť 4 kB = 4096 B */
int adresa;
void setup()
{
  pinMode(13,OUTPUT);
  Serial.begin(9600);
  for(adresa = 0; adresa < pamet; adresa++){  
    Serial.print("Na bytu s adresou ");
    Serial.print(adresa);
    Serial.print(" je hodnota ");
    Serial.println(EEPROM.read(adresa));
  } 
  digitalWrite(13, HIGH); 
  //led se rozsvítí, až bude čtení dokončeno
}
 
void loop()
{

}

Pokud se vše povedlo bez komplikací, měl by vám Serial monitor vypisovat podobné zprávy, jako jsou na obrázku.

 

EEPROM.write

Zápis této funkce je obdobný, jako u předchozího příkladu, jen nám přibil navíc jeden parametr, kterým je hodnota. Syntaxe je tedy takováto: EEPROM.write(adresa, hodnota);, kdy pro parametr adresa platí stejná pravidla, jako u EEPROM.read. Jelikož pracujeme v rozsahu jednotlivých bytů, musí být hodnota mezi 0 a 255. V našem příkladě budeme stále dokola psát do bytů hodnoty od 0 do 255, dokud nebude kapacita paměti zcela zaplněna. Pro lepší kontrolu nad procesem zápisu si necháme posílat po sériové lince na jaký byte a jaká hodnota se právě zapisuje. Při bezproblémovém průběhu by se mělo zobrazit okno se stejnýmy zděleními, jako jsou na obrázku.

#include <EEPROM.h>
 
int pamet = 4096; //kapacita vaší EEPROM
int adresa;
int hodnota = 0;
 
void setup()
{
  Serial.begin(9600);
  pinMode(13,OUTPUT);
  for(adresa = 0; adresa < pamet; adresa++){  
    EEPROM.write(adresa, hodnota);
 
    Serial.print(adresa);
    Serial.print(":");
    Serial.println(hodnota);
    hodnota++;
    if(hodnota == 256
    ){
      hodnota = 0;
    }
    
  }  
  digitalWrite(13,HIGH);
}
 
void loop()
{
}

Pokud jste se divali na stránku Arduina do Examples, možná jste zde viděli příklad s názvem EEPROM clear. Toto ale není funkce. Je to pouze způsob, jak zformátovat paměť. Kód vypadá podobně, jako v tomto příkladu, jen je všude parametr hodnota nastaven na nulu.

Úkol

1. Napiště program, který rozloží číslo s maximálním rozsahem 16 bitů na dvě osmibitové a uloží je na EEPROM paměť.
2. Druhý program bude mít za úkol „sestavit“ z těchto dvou čísel číslo původní.

 

 

Arduino VIII.

V tomto díle si ukážeme, jak naše projekty uvést do pohybu. Představíme si klasické motory, krokové motory i servo motory.

Řešení úkolu

Úkol 1

#include <EEPROM.h>

int cislo = 500;

int adresa1 = 1;

int adresa2 = adresa1 + 1;

byte hodnota1;

byte hodnota2;

 

void setup(){

Serial.begin(9600);

if(cislo <= 255){

hodnota1 = cislo;

hodnota2 = 0; }

else{

hodnota1 = 255;

hodnota2 = cislo – 255; }

EEPROM.write(adresa1, hodnota1);

EEPROM.write(adresa2, hodnota2);

//kontrola – výpis přes sériovou linku

Serial.print(adresa1);

Serial.print(“ : „);

Serial.println(EEPROM.read(adresa1));

Serial.print(adresa2);

Serial.print(“ : „);

Serial.println(EEPROM.read(adresa2));

}

 

void loop(){}

Úkol 2

#include <EEPROM.h>

int adresa1 = 1;

int adresa2 = adresa1 + 1;

 

void setup() {

Serial.begin(9600);

Serial.print(adresa1);

Serial.print(„:“);

Serial.println(EEPROM.read(adresa1));

Serial.print(adresa2);

Serial.print(„:“);

Serial.println(EEPROM.read(adresa2));

}

 

void loop() {}

Klasický motor + popis výkonového členu ULN2003A

Prvním z představených je asi nejčastější typ motorů – DC motor. Můžeme se s ním setkat prakticky všude. Od dětských hraček, přes holící strojky, zubní kartáčky až po vrtačky. Jejich použití je vhodné tam, kde nepotřebujeme mít přesnou kontrolu nad otáčkami, nebo nad úhlem otočení. Pokud chceme mít alespoň nějaký přehled o rychlosti, musíme přidat nějaký senzor (optické senzory, enkódéry…). Samotná rychlost se pak reguluje buď analogově (velikostí napětí – například již zmiňovaná vrtačka), nebo digitálně (PWM…).

Jelikož většinou samotný mikrokontrolér neumožňuje generovat jiné napětí než 0 nebo 5 voltů, musíme použít PWM, nebo dokoupit převodník na analogový signál. Dalším problémem je napětí motoru. Pokud je méně než 5V, můžeme ho s vhodným rezistorem připojit přímo k Arduinu. Když však je napětí motoru větší, musíme pro připojení použít vhodný tranzistor, nebo výkonový člen. Já jsem se rozhodl pro účely našeho článku vybrat obvod ULN2003A, za jehož doporučení děkuji uživateli Aleš Hakl. ULN2003A je využitelný při demonstraci klasických i krokových motorů a jeho cena nepřesahuje 10 Kč. Dalším použitelným IC je ULN2803A, který obsahuje o jeden řídící „kanál“ navíc. Objema čipy můžeme ovládat motory až do 50 voltů. Nyní už ale k samotnému zapojení obvodu.

Budeme potřebovat:

  • zdroj napětí (dle vašeho motoru)
  • integrovaný obvod ULN2003A
  • Arduino
  • vodiče
  • motor
  • nepájivé pole (není nutné, ale zjednoduší práci)

Poté zapojíme Arduino dle obrázku.

 

Následující kód bude motor postupně roztáčet až do maxima. Po jeho dosažení se motor vypne a vše se opakuje znovu.

void setup() {

pinMode(12,OUTPUT);

Serial.begin(9600);

}

 

void loop() {

for(int a=0;a<256;a++){

analogWrite(12,a);

Serial.println(a);

delay(100);

}

}

Datasheet k ULN2003A ZDE.
Schémata byla nakreslena v programu Fritzing.

 

 

 

Krokové motory

Tyto motory jsou anglicky nazývané steppers. Narozdíl od klasických motorů nabízejí větší možnost řízení. Je to dáno jejich mechanickou konstrukcí – rotor je tvořen určitým počtem magnetických plošek (liší se druh od druhu). Druhou část, stator, tvoří vždy několik cívek. Obě tyto části můžeme vidět na obrázku. Jeden krok motoru má nejčastěji velikost 7,5° ale můžeme se setkat i s 1,8°, 15° nebo jinými. Rozlišujeme základní dva typy krokových motorů: unipolární a bipolární. V jejich ovládání je poměrně velký rozdíl, proto se jim budeme věnovat samostatně.

 

 

 

 


Unipolární

Prvním typem jsou takzvané unipolární motory. Z názvu vyplývá, že pro funkci motoru stačí jedna polarita napětí. Znamená to, že společný vodič je stále připojen zdroj stejné polarity. Jednotlivé kroky se pak ovládají postupným připojováním a odpojováním zbývajících vodičů ke zdroji proudu opačné polarity. Nejčastější typ tohoto motoru má šest vodičů. Jeho vnitřní schéma můžete vidět na obrázku. Můžeme se setkat i s motory s pěti vodiči. V tomto případě jsou vývody A a B spojeny (obrázek 2).

Příklad:
Pro roztočení motoru připojíme vodiče A a B na zdroj kladného napětí. Poté budeme připojovat k zápornému napětí vodiče A1,A2,B1,B2 (v tomto pořadí).

V jednu chvíli bude k záporu připojen vždy pouze jeden vodič. Motor na obrázku by se roztočil proti směru hodinových ručiček. Pokud budeme chtít motor roztočit opačným směrem, stačí vodiče připojovat k zemi v opačném pořadí. Vše zapojíme podle obrázku níže.

Na konci odstavce můžete vidět i ukázku kódu.

 

 

 

 

 

 

 

int piny[4] = {9,10,11,12};

int faze[4][4] = {{0,0,0,1},

{0,0,1,0},

{0,1,0,0},

{1,0,0,0}};

byte cekej=2;

 

void setup() {

for(int a=0 ; a<=3 ; a++){

pinMode(piny[a] ,OUTPUT);

}

}

 

void loop() {

for(int b = 0; b <= 3; b++){

for(int c = 0; c <= 3; c++){

digitalWrite(piny[c],faze[b][c]);

}

delay(cekej);

}

}

 

 

Bipolární

Druhým typem jsou motory bipolární. Z názvu vyplývá, že k ovládání bude potřeba obou polarit. Pro jejich řízení se používají tzv. H-Bridge (můstky). Ty se dají použít i pro řízení směru DC motoru. Můžeme je koupit již přímo jako integrovaný obvod, nebo si je sestavit z osmi tranzistorů. Pro buzení krokového motoru se použije dvakrát stejné zapojení, jako pro buzení DC motoru. Schéma jednoduchého můstku můžete vidět na obrázku 2. My však použijeme zapojení z tohoto webu. Najdete ho asi ve 3/5 stránky. Zapojení zde využívá kombinaci integrovaného obvodu ULN2803A, čtyř tranzistorů a osmi rezistorů. Pro ovládání tohoto zapojení můžeme použít stejný kód, jako pro unipolární motor. Výhodou je i to, že stačí odpojit jeden vodič a máme ovladač pro unipolární motor. Vše zapojte podle schématu. Kód můžete ponechat stejný jako v poslední části.


Zdroj obrázků: ZDE.

Servo

Tyto motory se používají, když chceme mít přesnou informaci o otočkách či úhlu. Některá serva nemají rozsah větší, než 180°. Používají se například v modelářství. Můžeme se však setkat i se servy lineárními. Tento typ najdete například ve stavebnici Lego Mindstorms. Ze servomotorů nejčastěji vedou tři vodiče: dva napájecí a jeden řídící. Ve většině případů jsou tyto motory řízeny impulzy o různé délce opakující se s určitou frekvencí. V sekci examples najdeme příklady pro práci se servem. Počet připojených serv je limitován pouze počtem vývodů Arduina (bez použití jiného IC). Ve videu na konci stránky naleznete zajímavé využití servo motorů.

#include <Servo.h>  // vložení knihovny pro práci se servem

 

Servo jedna;  //vytvoření objektu pro práci se servem s názvem jedna

int pos = 0;    // uchování pozice serva

 

void setup()

{

jedna.attach(9);  // servo je připojeno na Arduino pin 9

}

 

void loop()

{

for(pos = 0; pos < 180; pos += 1)  // servo se bude pohybovat od 0° k 180°

{

jedna.write(pos);              // nastaví servo na pozici pos

delay(15);                       // počká 15 ms

}

for(pos = 180; pos>=1; pos-=1)     // nyní se bude pohybovat od 180° k 0°

{

jedna.write(pos);

delay(15);

}

}

Schémata byla nakreslena v programu Fritzing.

 

 

 

 

 

 

 

 

 

 

 

 

 

Arduino IX.

V tomto díle si ukážeme, jak Arduino použít jako ISP programátor a s jeho pomocí programovat jiné čipy firmy Atmel.
Úvod

Arduino je jistě skvělá věc. Co když ale dojdeme do fáze, kdy nám nevyhovuje nějaký projekt dlouho vymýšlet a po tom, co ho konečně doladíme a dotáhneme do cíle, ho opět rozebrat, abychom mohli použít Arduino zase na něco jiného. Kvůli tomu umí Arduino pracovat jako ISP programátor. S jeho pomocí potom můžeme naprogramovat nejenom menší čipy řady ATtiny, ale i ATmega, na kterých je většina desek založena. Možností vytvářet klony Arduina s ATmega se ale v tomto článku nebudeme zabývat příliš podrobně.


Propojení Arduina a čipu.

Tato část je pro oba typy čipů stejná. Pro správné naprogramování nového čipu je potřeba propojit správné piny. Důležité je ale rozlišovat mezi porgramovacími piny Arduina a programovaného čipu. Na Arduinu potřebujeme najít piny MISO, MOSI, SCK a SS. Tyto vývody procesoru jsou ale na různých verzích Arduina různě propojeny. Vývody naleznete zde:

Model SS MOSI MISO SCK
UNO, Duemilanove 10 11 12 13
Mega (1280, 2560, ADK) 53 51 50 52

Druhým krokem je nalezení odpovídajících pinů na programovaném čipu. Je zde ale jedna obměna – místo pinu SS budeme hledat pin RESET. Pro jednoznačnost je propojení zobrazeno v následující tabulce:

Arduino

Programovaný čip

MISO

<—>

MISO

MOSI

<—>

MOSI

SCK

<—>

SCK

SS

<—>

RESET

Postup propojení čipu a Arduina je tedy následující (použit příklad s čipem ATmega168):

  1. Najdeme si datasheet vybraného čipu. (Pro ATmega168 jej nalezneme zde.)
  2. V něm si najdeme nákres daného čipu.
  3. Vyhledáme piny potřebné pro programování – na obrázku jsou barevně vyznačeny.
  4. Podle tabulky propojíme sobě odpovídající programovací piny (na obrázku červeně).
  5. Připojíme napájecí piny (na obrázku zeleně).
  6. Tímto je čip připraven k programování.

 

 

 

 

 

 

 

 

 

 

Čipy ATmega

Ke stavbě jednoduché desky založené na čipu ATmega (například ATmega328) je potřeba pouze Arduino (UNO, Mega…) sloužící jako programátor, vybraný čip a zdroj 5V napětí. Pro pokročilejší desku, pracující na vyšší frekvenci je navíc potřeba dva 22pF kondenzátory, jeden 10kOhm resistor a oscilátor. Ten má pro různé čipy různou frekvenci, která se dá najít v datasheetu daného čipu. Většinou to však bývá 16MHz. Poté stačí součástky zapojit podle jednoho z uvedených schémat.
Podrobný popis dalšího postupu naleznete zde: http://arduino.cc/en/Tutorial/ArduinoToBreadboard
Tento článek pojednává převážně o ATtiny a nebudeme se programováním ATmega hlouběji zabývat.

 

 

 

 

 

Čipy ATtiny

Pro účely tohoto návodu si k programování vybereme čip ATtiny85. Hned na začátek je nutno upozornit na to, že se jedná o „odlehčené“ verze čipů a nemůžeme tedy počítat s úplně stejnými vlastnostmi, jako u velkých „sourozenců“ z rodiny ATmega. Asi nejvýraznějším rozdílem je omezená knihovna funkcí. Funkce, které můžete při programování ATtiny použít můžete vidět v následujícím seznamu.

  • pinMode()
  • digitalWrite()
  • digitalRead()
  • analogRead()
  • analogWrite()
  • shiftOut()
  • pulseIn()
  • millis()
  • micros()
  • delay()
  • delayMicroseconds()

V obrázku můžete vidět, jaké důležité funkce jaký pin čipu má (rozmístění PWM, analogových vstupů, programovacích pinů…) a pod jakým číslem se na něj později v programu budeme dovolávat. Na cizojazyčných webech se můžeme setkat s pojmem pinout.

Nejsme však omezeni pouze na čip ATtiny85. Můžeme však použít jakýkoliv čip z této rodiny, pokud k němu nalezneme odpovídající modifikaci souboru boards.txt. V tomto souboru jsou uloženy informace o tom, jak se má při programování přistupovat k různým čipům a deskám. Nalezneme zde například jejich taktovací frekvenci, velikost paměti a jiné.

Software Arduino IDE však ve formě, kterou můžeme stáhnout na stránkách arduino.cc není vybaven instrukcemi, jak pracovat s čipy řady ATtiny (u ATmega je to jiné, protože na některých z nich jsou založené i klasické desky Arduino – některé modifikace je však také potřeba hledat). Tyto instrukce tedy musíme softwaru nějak přidat. Soubory, se kterýmy budeme v tomto článku pracovat naleznete zde: hardware.zip.

V této fázi máme dvě možnosti, jak naučit Arduino IDE s ATtiny pracovat. První možnost je nalézt složku, do které IDE ukládá uživatelské soubory, jako jsou vytvořené programy atd. V oficiální dokumentaci je nazývána sketchbook. Ta většinou bývá umístěna v Dokumentech (pro Windows) ve složce Arduino. Do této složky rozbalíme celý archiv hardware.zip. Nyní už nemusíme nic upravovat a můžeme se vrhnout na programování. Pro kontrolu by měl správně umístěný archiv vypadat takto:

Druhou možností je změnit tento soubor přímo ve složce, která obsahuje IDE. Tato složka může být kdekoliv, záleží na tom, kde jsme ji uložili při stahování. Její název je většinou arduino-cislo_verze (například arduino-1.0.3). Nyní nalezneme soubor boards.txt, který chceme modifikovat – ten zatím obsahuje pouze standartní verze Arduina. Měl by být umístěn zde umístěn zde: arduino-cislo_verze > hardware > arduino > boards.txt. Jelikož je to prostý text, můžeme ho otevřít i upravovat v libovolném textovém editoru. Zároveň otevřeme i stažený soubor boards.txt a jeho obsah zkopírujeme na konec prvního ze souborů. Text, který obsahuje informace o čipu ATtiny45 s vnitřním 1 MHz oscilátorem vypadá například takto:

attiny45.name=ATtiny45 (internal 1 MHz clock)

attiny45.bootloader.low_fuses=0x62

attiny45.bootloader.high_fuses=0xdf

attiny45.bootloader.extended_fuses=0xff

attiny45.upload.maximum_size=4096

attiny45.build.mcu=attiny45

attiny45.build.f_cpu=1000000L

attiny45.build.core=arduino:arduino

attiny45.build.variant=tiny8

Ještě však musíme IDE říct, jaké vývody jaký čip má a jak je používat. Tyto informace jsou součástí staženého archivu a nezneme je ve složce variants. V druhém okně otevřeme složku v počítači, ve které je umístěn soubor boards.txt. Zde nalezneme složku hardware a v ní variants. Poté zkopírujeme veškerý obsah složky variants ze staženého archivu (tj. složky tiny8 a tiny14) do složky variants v počítači. Tím je u konce i druhá cesta.

Jak vidíte, první možnost je praktičtější. Pro vrácení změn stačí smazat jednu složku a je po problému. V druhém případě se při stažení nové verze IDE změny nezachovávají a musíme pak soubory znovu měnit, kdežto složka Arduino v Dokumentech se s aktualizacemi nemění. Nyní už tedy máme připravenou jak stranu software, tak i hardware a můžeme přejít k samotnému programování.

 

 

 

Programujeme

Otevřeme si Arduino IDE a v nabídce tools vybereme verzi našeho Arduina (zatím ne programovaného čipu, ale programátoru). Poté z File > Examples otevřeme ArduinoISP a nahrajeme ho do Arduina. Pozor! Některé verze IDE mají v tomto skriptu špatně zadané delay(). U nejnovějších verzí IDE je tato chyba opravena, ale pokud máte stále nějakou starší verzi, najděte ve skriptu ArduinoISP funkci heartbeat() a zkontrolujte, jestli je v ní funkce delay() nastavena na 20ms. Pokud ne, učiňte tak. V této fázi je Arduino úspěšně nastaveno jako programátor. Pro nahrání kódu do ATtiny vybereme z nabídky Tools > Board verzi programovaného čipu (v tomto případě tedy ATtiny85 1MHz internal clock) a pro ověření funkčnosti zkusíme nahrát první kód. Nejjednodušší bude vyzkoušet příklad blink. Vše zapojíme podle schématu a otevřeme příkaz blink z Examples. Před samotným uploadem musíme ještě zmenit pin, na který je připojena LED. Ten musí mít číslo od 0 do 4. Zvolme si například 0. Nyní program nahrajeme do ATtiny stisknutím tlačítka upload, nebo klávesovou zkratkou ctrl + u.

int led = 0;

 

void setup() {

// initialize the digital pin as an output.

pinMode(led, OUTPUT);

}

 

void loop() {

digitalWrite(led, HIGH);

delay(1000);

digitalWrite(led, LOW);

delay(1000);

}

Tímto by mělo být vše jasné a už by nic nemělo bránit vlastní tvorbě.

 

Pásek z led

Nyní už se můžeme přesunout k vyzkoušení ATtiny v praxi. Jediné, co po něm budeme chtít je, aby neustále dokola blikal páskem led diod. Budeme potřebovat:

  1. Čip ATtiny
  2. LED diody – například 5 kusů
  3. Kosek drátu
  4. Zdroj 5V

Když už máme všechny potřebné součásti, můžeme se pustit do zapojování. Všechny anody ledek zapojíme do VCC ATtiny (a nebo všechny katody do GND). V prvním případě budou svítit všechny LED a vždy jedna bude zhasnutá, v druhém případě bude svítit vždy právě jedna LED. Zbývající nožičky připojíme každou k jednomu pinu. Kód pak může vypadat takto:

int ledky[] = {0,1,2,3,4}; //piny, na kterých jsou připojené led diody

int pocet = 5; //počet LED

int a = 0; //pomocná proměnná

int del = 100; //prodleva mezi blikáními

 

void setup() {

for(a = 0; a < pocet; a++){

pinMode(a, OUTPUT);

}

}

 

void loop() {

for(a = 0; a < pocet; a++){

digitalWrite(a, HIGH);

delay(100);

digitalWrite(a, LOW);

delay(100);

}

for(a = pocet; a >= 0; a–){

digitalWrite(a, HIGH);

delay(100);

digitalWrite(a, LOW);

delay(100);

}

}

Takto můžeme zapojit až 5 diod. Pokud byste chtěli zapojit více diod, můžete to udělat způsobem zvaným Charlieplexing. Pro 6 a 12 diod je zapojení zakresleno v tomto obrázku. Takto se dá s ATtiny ovládat až 24 LED bez použítí driveru! Vyžádá si to však úpravu kódu. Tu ale nechám na každém z vás.

Tip: Jak zjednodušit programování

Abychom nemuseli programovat čipy jenom v nepájivém poli, je dobré si spájet programovací „nástavec“, do kterého se čip připne. Když je čip zapojen do tohoto nástavce, jsou všechny potřebné piny spojené a nemusíme je tedy zapojovat stále dokola. Součástky potřebné ke stavbě:

  1. Univerzální plošný spoj
    • Hodí se v případech, kdy nechceme leptat vlastní plošné spoje.
    • Dá se sehnat ve více provedeních. (a – Všechny řádky jsou vodivě spojené, b – nic není vodivě spojené, c – body jsou spojené po třech a další)
    • Je běžně k sehnání: GME, Taciko, GES, TME
    • Pro účely naší stavby plně postačuje jednostranný vrtaný plošný spoj s vzájemně nepropojenými kulatými body – například tento.
  2. Kousek vodiče
  3. 2 x čtyřzdířkové dutinkové lišty
    • S těmi se už každý jistě setkal. Jsou to ty lišty, do kterých se na Arduinu zapojují veškeré vodiče.
    • Nám budou stačit dvě lišty se čtyřmi zdířkami.
    • Na obrázku programátoru níže vidíte pětizdířkové lišty. Jediný důvod rozdílu je, že jsem doma jiné nenašel. Zdířky navíc jsem připojil k V+ a GND (každou k jednomu pinu).
    • Dá se lehce sehnat, stačí se zeptat na Dutinkové lišty (Google, prodavač v místním obchodě se součástkami…)
  4. Patice na připojení ATtiny
    • Do této součástky se upne čip.
    • Dá se nahradit dalšími dvěmi dutinkovými lištami.
    • Ke koupi například ZDE.
  5. Oboustranný kolík
    • Slouží k propojení programátoru a Arduina.
    • Prodávají se v různých variantách (různá délka, dvojice, trojice…).
    • Nám stačí celkem osm jednotlivých kolíků (nebo různé kombinace – viz obrázek)
    • Může vypadat například takto.
  6. Pájka, cín

Pokud chcete stavět programátor pro Arduino UNO a podobné, návod naleznete například zde. Moje verze je určena pro Arduino MEGA. Pojďme se na ní nyní podívat. Prakticky veškeré součástky se nalézají na jedné straně desky. Na spodní straně, která není na obrázku vidět, je pouze propojení jednotlivých částí (cínem) a konektory pro zapojení do Arduina. Fialovou barvou ve schématu jsou naznačeny cínové spoje na spodní straně desky.

Schémata byla nakreslena v programu Fritzing.

Arduino X. – měření teploty

Dnes se podíváme, jak vytvořit uživatelsky definované funkce a jakými způsoby může Arduino měřit teplotu.
Při vymýšlení projektů typu „co mám dělat teď?“ nás jistě někdy napadla zapojení, ve kterých je potřebné zjistit teplotu okolí. Mohly by to být: meteostanice, termostaty, teploměry a podobné. Elektronických součástek, které mohou měřit teplotu, je ale celá řada a proto nelze napsat článek, který by je obsáhl všechny. Pro ukázkové účely tedy vybereme zástupce každé z hlavních skupin. Prvním z nich jsou ty, které s čipem komunikují digitálně, druhé analogově s lineárním průběhem a třetí analogově s jiným průběhem. Poslední skupinou teploměrů jsou ty, které mají některé z čipů ATmega zabudované přímo v sobě. Také si ukážeme, jak se dají v jazyce Wiring vytvořit funkce.

 

Vytváření uživatelských funkcí

S funkcemi jsme se v průběhu seriálu již setkali, byly jimi například funkce analogRead(), serial.println() a další. Tyto funkce však obsahuje jazyk Wiring již v samotném základu, čili existují bez přičinění uživatele. V některých případech by se však hodila možnost vytvořit si vlastní funkce. Patří mezi ně například situace, kdy se některá část kódu má opakovat stále dokola, ale nevyhovuje nám použití cyklu. Pomocí funkce můžeme tento kód „zabalit“ do jakéhosi softwarového balíčku a tím umožnit jeho vícenásobné používání.

Hned na začátek je nutno říct, že i funkce musí mít datový typ. Může to být typ int, double a další. Také se setkáme s doteď nezmíněným typem void. Ten se používá, pokud funkce nevrací žádnou hodnotu, jen provádí určité příkazy. Deklarace (nastavení) funkce musí být provedeno mimo tělo funkcí void loop() a void setup(). To, že je funkce deklarovaná, ještě neznamená, že bude probíhat automaticky. Pro vykonání příkazů funkce ji musíme v požadovaném místě kódu „zavolat“.

Příklad 1.

Našim cílem bude vytvoření jednoduché funkce, která změří hodnotu na A0, počká sekundu a sečte ji s novou hodnotou A0. Poté vše vypíše pomocí Serial.println(). Naše funkce nebude vracet žádnou hodnotu, bude tedy mít datový typ void.

Začneme „obalem“ funkce.

void mereni(){ //prázdné závorky jsou nutné, aby program věděl, že jde o funkci
   ...
}

Nyní přidáme funkci její funkčnost.

void mereni(){ 
   int x = analogRead(A0);
   delay(1000);
   int y = analogRead(A0);
   Serial.print("Merim: ");
   Serial.println(x+y);
   delay(1000);
}

Nyní příjde na řadu volání (provedení) funkce.

void setup(){
   Serial.begin(9600);
}
 
void loop() {
   mereni(); //volání funkce mereni()
}

Příklad 2.

Nyní si ukážeme, jak deklarovat funkci s parametry, která bude vracet určitou hodnotu. Parametr je vstupní informace, kterou předáváme funkci v závorkách. Názvy parametrů si můžeme zvolit a pomocí nich s daty v těle funkce pracovat stejně, jako s proměnnými. Pokud funkce dostává více parametrů, oddělují se čárkou. Nejjednodušším příkladem je součet dvou čísel typu int a vrácení jejich hodnoty (nevypíše, pouze vrátí hodnotu).

int soucet(int a, int b){ //říkáme funkci, že budeme pracovat se dvěma čísly (a, b) typu int
   return a+b; //slovo return je zde důležité, tím funkci říkáme, jakou hodnotu má vrátit
}

Následuje zavolání této funkce s parametry 20 a 50.

void setup(){
   Serial.begin(9600);
   Serial.println(soucet(20,50));
} 
 
void loop() {
}

Teď už se můžeme podívat na způsoby měření teploty pomocí Arduina.

 

Interní teploměry čipů

Hned na začátek je nutno upozornit, že přesnost těchto senzorů je značně nejistá. Jelikož jsou součástí pouzdra čipu, jsou snadno ovlivnitelné teplem, které při práci čipy produkují (výchylka 10 °C je zcela běžná). Někdy jsou však plně dostačující. K měření okolní teploty bez větších výchylek jsou vhodné jenom v případě, že bylo Arduino minimálně 10 minut nečinné. Hodí se ale k sledování teploty při náročných operacích (například když čipem protéká větší proud), kdy můžeme předejít poškození čipu včasným odstavením desky. Největší nevýhodou je, že ho neobsahují všechny čipy, které na Arduinu najdeme.
Podpora teploměrů v čipech:

ATmega8 Ne
ATmega8L Ne
ATmega8A Ne
ATmega16 Ne
ATmega168A Ano
ATmega168P Ano
ATmega328 Ano
ATmega328P Ano
ATmega1280(Arduino Mega) Ne
ATmega2560(Arduino Mega 2560) Ne
ATmega32U4(Arduino Leonardo) Ano

Pro vyzkoušení tohoto teploměru jsem použil Arduino Leonardo a kód, který je k nalezení zde.

long readTemp() {
  long result;
  // Read temperature sensor against 1.1V reference
  ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX3);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = (result - 125) * 1075;
  return result;
}
 
void setup() {
  Serial.begin(9600);
}
 
void loop() {
  Serial.println( readTemp(), DEC );
  delay(1000);
}

Výstupem jsou tisíciny °C. Výsledek pak tedy stačí vydělit 1000 a získáme naměřenou teplotu v °C.

 

Digitální teploměry

Druhou skupinou teploměrů jsou ty, které nám zasílají naměřené hodnoty digitálně. Bývají často nejpřesnější a na jednu sběrnici je jich možné připojit i více (záleží na typu). Pro ukázkové účely jsem vybral senzor DALLAS 18B20 od firmy Maxim Integrated. Ten komunikuje pomocí 1-Wire sběrnice, nepotřebuje externí napájení, rozsah hodnot má -55 až +125°C a má nastavitelné rozlišení 9-12 bitů. Každý senzor má vlastní unikátní 64-bitové číslo, které slouží k jeho identifikaci (podobně jako IP adresa u PC). Díky tomu je možné připojit i více těchto teploměrů na jeden datový vodič. Největší výhodou je, že pro Arduino existuje knihovna určená k práci s tímto teploměrem. Na obrázku vidíte pinout teploměru a schéma zapojení více senzorů na jednu sběrnici.


Pokud máme vše zapojeno podle schématu, nezbývá nám, než zprovoznit teploměr i na straně softwaru. Pro komunikaci po 1-Wire sběrnici budeme potřebovat knihovnu OneWire. Její dokumentaci i odkaz ke stažení nalezneme na oficiálních stránkách Arduina. Tato knihovna obsahuje i příklad (v Examples) pro připojení tohoto teploměru. Po stažení stačí rozbalit obsah knihovny OneWire do složky libraries a zapnout Arduino IDE (popř. restartovat). Poté v Examples rozklikneme OneWire a vybereme soubor DS18x20 Temperature. Ten nahrajeme do Arduina a otevřeme Serial monitor. Vypisovaný text by měl obsahovat nejenom naměřené hodnoty, ale i informace o teploměru (adresa atd.), což je pro běžné účely moc informací. Po prohlédnutí kódu a promazání výpisu zbytečných informací se ale dá výpis lehce přizpůsobit jen pro zobrazování teploty. Příklad výpisu vidíte níže:

ROM = 28 C9 9F BA 3 0 0 A1
  Chip = DS18B20
  Data = 1 94 1 4B 46 7F FF C 10 26  CRC=26
  Temperature = 25.25 Celsius, 77.45 Fahrenheit
No more addresses.

Po upravení může výpis vypadat například takto:

Temperature = 27.62 Celsius, 81.72 Fahrenheit

 

Analogové teploměry s lineárním průběhem

Další skupinou jsou teplocitlivé součástky, které na změnu teploty reagují změnou odporu. U této skupiny má změna lineární charakter. Například vždy při zvýšení teploty o 1 °C se změní odpor součástky o 100 ohmů, a to v celém měřitelném rozsahu. Pokud bychom přenesli závislost odporu na teplotě do grafu, výsledný obrazec by byla přímka (linea -> lineární průběh).

Pro prezentační účely jsem vybral teploměr LM35. Ten umí měřit teploty buďto v rozsahu +2 – +150 °C, nebo -55 – +150 °C (podle zapojení). V menším rozsahu výrobce uvádí přesnost 1/4 °C a ve větším přesnost 3/4 °C. Převod výstupního napětí je 10 mV/°C. Jeho popis nalezneme i na české wikipedii společně s doporučeným schématem pro zapojení. Pro demonstraci si vybereme lehčí zapojení s rozsahem hodnot nad 0 °C a jako zdroj použijeme 5V z Arduina. Výstup teploměru připojíme na A2. Pro získání výsledné hodnoty budeme potřebovat trochu matematiky: Arduino umí rozlišit 1024 analogových hodnot v rozsahu 0 až 5V. Nám tedy stačí převést naměřené hodnoty z rozsahu 0-1023 do rozsahu 0-500, abychom dostali skutečné napětí měřené v desítkách mV. To totiž odpovídá převodu 10 mV/°C. Tímto převodem získáme skutečnou teplotu ve °C.


Kód vypisující naměřenou teplotu vypadá takto:

void setup(void) {
  Serial.begin(9600);
}
 
void loop(void) {
  float temp = analogRead(A2);
 
  temp = map(temp, 0, 1023, 0, 500);
  
  Serial.print("Namereno: ");
  Serial.println(temp);
  delay(1000);
}

Analogové teploměry s nelineárním průběhem

Když tyto součástky nazývám teploměry, trochu jim lichotím. Jde o termistory, což jsou součástky, které se změnou teploty mění svůj odpor. Dělí se na pozitivní a negativní. U pozitivních odpor s teplotou vzrůstá. Nárůst je zde skokový, proto najdou více než při měření teploty využití spíše v automatizaci, kde je potřeba například sepnout obvod při dané teplotě. U negativních termistorů je grafem křivka.

Podívejme se ale na celý problém prakticky. Pro ukázku jsem vybral tento 10 kOhm termistor, jehož datasheet nalezneme zde. Ten zapojíme do děliče napětí společně s 10 kOhm rezistorem. Vývod připojíme na pin A0.

Napětí vycházející z děliče vypočteme následovně: Analogový vstup rozlišuje 1024 hodnot (0-1023). Vydělíme-li 5V/1024 získáme velikost jednoho „dílku“ stupnice ve voltech. Naměřená hodnota na A0 je tedy počet těchto dílků. Když vynásobíme velikost jednoho dílku naměřenou hodnotou, získáme skutečné napětí na A0.

Pro výpočet odporu termistoru použijeme dělič napětí. Přesněji řečeno vzorec z anglické wikipedie.

Kde Vin je 5V (výstup Arduina), Vout je naměřená hodnota napětí na A0. R1 je odpor termistoru, R2 je odpor rezistoru (u nás 10 kOhm). Funkce pro výpočet odporu termistoru by mohla vypadat takto:

float mereni(){
  int aread = analogRead(A0); 
  float V2 = (V1/1023) * aread; //U2 obsahuje hodnotu napětí na A0
  float R1 = ((R2*V1)/V2)-R2;
  
  return R1;
}

Poznámka: Když pokud se při zahřívání naměřená hodnota R1 zvětšuje, pravděpodobně je chyba v zapojení. Stačí však vyměnit termistor za rezistor a problém by měl být vyřešen.

Když už máme vypočítaný odpor, můžeme se podívat na výpočet teploty. Tu z odporu vypočteme pomocí následujícího vztahu:

Po vyvození T z předchozího vztahu získáme rovnost pro výpočet teploty.

Kde T je výsledná teplota, T0 je tabulková hodnota (většinou 25°C = teplota, při které je měřeno R0), B je také tabulková hodnota, která je k nalezení v datasheetu daného termistoru (ta se sice mírně mění s měnící se teplotou, ale pro účely základního měření nám bude postačovat jen jedna konstantní hodnota) a R1 je naměřený odpor. Ještě je třeba zmínit, že při počítání je nutno dosazovat teploty v kelvinech (K) a že log() je zápis pro výpočet přirozeného logaritmu. Funkce pro výpočet logaritmu není přímo v základu jazyka, ale naštěstí existuje v knihovně, která je do celého balíku zahrnuta. Pomocí příkazu #include vložíme na samý začátek kódu knihovnu math.h. Poté již budeme funkci log() moci použít.
Převodní vztah °C na K je následující: 0°C = +273,15K => 25°C = 298,15K

Vložení knihovny do skriptu:

#include <math.h> //zde se středník na konci řádku nepíše

Rozšíříme-li funkci mereni() o výpočet teploty, bude vypadat následovně:

float mereni(){
  int aread = analogRead(A0); 
  float V2 = (V1/1024) * aread; //U2 obsahuje hodnotu napětí na A0
  float R1 = ((R2*V1)/V2)-R2;
  float T = 1/((1/T0)+((1/B)*log(R1/R0))); // výstupem je teplota v Kelvinech
  float TC = T - 273.15;
  
  return TC;
}

Pokud všechny části kódu seskládáme dohromady výsledek bude vypadat následovně:

#include <math.h>
 
int R2 = 10000; //velikost odporu připojeného k děliči
float V1 = 5.0; //napětí z Arduina
float T0 = 298.15; //teplota v Kelvinech
float B = 4300; //tabulková hodnota
float R0 = 10000; //hodnota odporu termistoru při 25°C
 
 
float mereni(){
  int aread = analogRead(A0); 
  float V2 = (V1/1024) * aread; //U2 obsahuje hodnotu napětí na A0
  float R1 = ((R2*V1)/V2)-R2;
  float T = 1/((1/T0)+((1/B)*log(R1/R0))); // výstupem je teplota v Kelvinech
  float TC = T - 273.15; //převode teploty z K na °C
  
  return TC;
}
 
void setup(){
   Serial.begin(9600);
} 
 
void loop() {
  Serial.println(mereni());
  delay(1000);
}

Závěr

Pokud porovnáte hodnoty všech použitých měřících technik, mnohdy zjistíte, že se od sebe podstatně liší. Mělo by však platit, že při použití s Arduinem jsou nejpřesnější kalibrované digitální teploměry a poté kalibrované analogové teploměry (zde vznikají odchylky kvůli převodníku Arduina, který nemusí mít dostatečně přesnou stupnici). U termistorů a vnitřních teploměrů je přesnost různá a může se lišit typ od typu.

 

 

 

 

 

 

 

 

 

 

 

 

Arduino – pulsně šířková modulace (PWM) v C(++)

Pulse Width Modulation (PWM) lze přeložit jako pulsně šířková modulace. Jde o signál, kdy z pinu Vašeho AVR čipu, ať už je to Arduino nebo ne, vychází hodinový signál, který vyvolává hardware sám na pozadí a nijak neovlivňuje chod hlavního programu vašeho procesoru.

Tento pulsující signál se využívá za pomocí jednoduchého triku k různým úkonům. Nejčastěji udávaným příkladem použití PWM je pohaslá LED dioda, nebo dokonce její pomalé rozsvícení a zhasínání. Trik tohoto efektu je v hustotě po sobě rychle jdoucích signálů 1 a 0, které velmi rychle rozsvěcejí a zhasínají LEDku tak, že lidské oko vnímá až průměr času rozsvíceného a zhaslého. Jinak řečeno LEDka bliká tak rychle, že to není poznat, místo toho je ale pohaslá.

Stejný trik se využívá i u DC motorů, které jsou místo trvale sníženého napětí, vystaveny napětí normálnímu, ale v jednotlivých impulzech. To v konečném výsledku způsobí že DC motor se netočí tak rychle, jako kdyby byl napětí vystaven trvale, nicméně na své síle neztratí, což by se v případě menšího napětí stalo.

Poslední „trik”, který se s PWM používá je RC filtr, který díky časovému zpoždění změní střídání jedniček (5V) a nul (0V) na průměrné napětí, například 3.8V.

 

Průběh PWM signálu na pinu(zelená) dle nastavení OCR (červená) v závislosti na čítači (modrá).

Před tím, než si ukážeme jak tyto pulsy vyvolat, je třeba si říct alespoň něco málo o časovačích. Časovač (TIMER) funguje nezávisle na provádění kódu v procesoru. Jde o subsystém, který je ovládán pomocí registrů. Jedna z hlavních částí časovače je čítač (TCNT). Ten bývá 8 bitový nebo 16 bitový a podle toho umí nabývat hodnot 0 – 255 (8b) nebo 0 – 65535 (16b). Do čítače je každý tik uložena hodnota. Po dosažení maxima (nemusí tomu tak vždy být, ale to už je nad rámec tohoto článku) je tato hodnota vynulována, a počítá se znovu.

#include <avr/io.h>
#include <avr/interrupt.h>
 
volatile uint8_t count;
 
int main(void) {
                                    // nastavi prescaler => FCPU/64
    TCCR0B |= (1<<CS02)|(1<<CS00);  // na 16MHz => 16Mhz/256/1024 = 61.03515625
    TIMSK0 |= (1<<TOIE0);           // povoli Overflow Interrupt 
    TCNT0 = 0;                      // inicializuje citac
 
    DDRB |= (1 << PB5);             // na portu B nastavi 6. bit na vystupni mod
 
    count = 0;                      // inicializace globalni promenne
    sei();                          // povoli presuseni vyvolane casovacem
 
    while(1);                       // nekonecna smycka
    return 1;                       // toto nenastane, budme ale slusni
}
 
/* Toto je obsluzna rutina preruseni casovace TIMER0.
   CPU tuto rutinu samo pusti po preteceni citace */
ISR(TIMER0_OVF_vect) {
   count++;
   if(count == 61) {                // 61 kroku je potreba k casovani ~1 vteriny
      PORTB ^= (1 << PB5);          // invertuju hodnotu sesteho bitu
      count = 0;
   }
}

Ve skutečnosti, nemusí být časovač jen inkrementován a nemusí to být každý tik procesoru. Tiky lze ovládat a to dvěma způsoby. Je možné je zředit pomocí hodnoty řídícího registru (TCCR), kterým lze časovač úplně vypnout (výchozí stav), nebo nastavit tzv. prescaler (nevím jak toto slovo přeložit, raději to dělat nebudu). Tím lze nastavit, že zásah do čítače bude vykonán každý 8mý, 64tý, 256tý, nebo 1024tý tik. Tiky lze také generovat externím zdrojem. Díky tomu, lze získat „přesný” čas bez ohledu na kód probíhající v CPU. Časovač navíc funguje v několika módech, pro naše účely je rozdělíme do dvou druhů. V prvním případě je vyvoláno přerušení, to lze snadno obsloužit naší vlastní funkcí. V druhém případě jde o PWM. Díky němu můžeme přes registr vysílat PWM signál na příslušném pinu bez toho, aby jsme se o jeho průběh (nahazování jedničky, resp nuly) museli nějak starat.

#define F_CPU 16.0E6
 
#include <avr/io.h>
#include <util/delay.h>
/*
    Tt = 1 / ( FCPU / prescaler) (pokud prescaler používá FCPU)
    Tp = Tt * 255
    Ton = Tt * OCR
    Toff = Tp - T1
 
    Vrc = (OCR / 255) * 5v
 
    Tt = 1 / (1MHz / 1024) = 1 / 976.5625 = 0.001024 s
    Tp = 0.001024 * 255 = 0.26112 s
    Ton = 0.001024 * 64 = 0.065536 s
    Toff = 0.26112 - 0.065536 = 0.195584 s
 
    Tt = 1 / 1MHz = 1us
    Tp = 255 us
    Ton = 64 us
    Toff = 255 -64 = 191us
 
    Vrc = 64 / 255 * 5 = 1.25
*/
 
int main(void) {
    uint8_t pulses = 0;
              
    TCCR2A |= (1<<WGM20)|(1<<WGM21);// Rychlé PWM
    TCCR2A |= (1<<COM2A1);          // práce s registrem OC0A dle módu PWM
    TCCR2B |= (1<<CS20);            // bez škálování
 
    DDRB |= (1 << PB3);             // nastaví OCR2A (PB3) pin jako výstupní
 
    while(1) {
        for(pulses = 0; pulses < 128; pulses++) {
            OCR2A = pulses;         // parametry vysílaného signálu
            _delay_ms(20);
        }
 
        for(pulses = 128; pulses > 0; pulses--) {
            OCR2A = pulses; 
            _delay_ms(20);
        }
 
    }
    return 1;
}

Celé kouzlení s PWM tedy spočívá v nastavení časovače: mód pro PWM, prescaler, práce s čítačem a nakonec v nastavení příslušné hodnoty do registru, který vyvolá PWM na pinu s danou hustotou kladného napětí 5V, viz kód.

Detailnosti a hlavně možnosti Vašeho MCU lze dočíst v kvalitní a podrobné dokumentaci, kterou výrobce k čipům uvolňuje. K článku jsou také připojeny zdrojové kódy pro USBtiny zapojení, které je založeno na čipu ATtiny2313A, jehož cena v GM včetně součástek je kolem 100 Kč s tím, že pokud nechcete používat USB komunikaci a stačíte si s taktem 1MHz, asi polovinu součástek vůbec nepotřebujete. Vlastně stačí jen čip, odpor a jeden kondenzátor 😉

Odkazy v textu:

http://dicks.home.xs4all.nl/avr/usbtiny/

Přiložené soubory:

Kód pro Arduino Uno           Kód pro USBtiny

Arduino – programování v čistém C(++)

O Arduinu bylo napsáno mnoho hello world článků, většina z nich ale ukazuje zdrojový kód napsaný v jazyku Wiring, který byl vyvinut pro snazší práci s Arduinem. Já tímto článkem půjdu proti proudu a onen hello world ukážu v čistém C.

Ve skutečnosti nejde o programovací jazyk, ale o knihovnu v C++, která díky různým technikám velmi usnadňuje práci s arduinem. Uživatelé tak programují v C++ a ani o tom neví. Protože jde ale o procesory, které mají proti klasickým PC velmi málo paměti a v praxi do nich uživatelé možná budou chtít implementovat rozsáhlou a složitou funkcionalitu, hodí se znát, jak obejít knihovnu, díky které výsledná „binárka” bobtná. Navíc Arduino není jedinou deskou s tímto procesorem, a tak se může stát, že knihovna Wiring na jinou desku, resp. jiný procesor nebude prostě připravená.

Jeden ze základních příkladů, takovou avrkovou hello world aplikací je blikání integrované ledky na pinu 13. Kód v „jazyce” Wiring vypadá takto:

void setup() {
  // nastavení digitálního pinu výstup výstup
  // pin 13 je na většině desek Arduina připojen na LED diodu
  pinMode(13, OUTPUT);
}

void loop() {
  digitalWrite(13, HIGH);   // zapne LED diodu
  delay(1000);              // počká jednu sekundu
  digitalWrite(13, LOW);    // vypne LDE diodu
  delay(1000);              // počká jednu sekundu
}

Pokud bychom tento kód chtěli napsat v čistém C, vypadal by takto:

#include <avr/io.h>             // definice registrů DDRB, PORTB a pinů PBn

#define F_CPU 16.0E6            // pro potřeby časování je třeba nastavit
                                // frekvenci procesoru
#include <util/delay.h>         // práce s časováním - funkce _delay_ms

// _delay_ms lze volat s maximální hodnotou 262.14 / F_CPU v MHZ, proto
// vytvoříme funkci, která bude čekat celou vteřinu

void _delay_s(const unsigned char sec){
    unsigned char i = 0;        // v C++ by mohla být definice ve for cyklu
    for (i = 0; i < sec*10; i++){
        _delay_ms(100);
    }
}

int main (void) {
    DDRB |= (1 << PB5);         // nastaví bit5 na portu B (pin 13) na výstup

    while (1) {
        PORTB |= (1 << PB5);    // nastaví bit5 na portu B na 1 (zapne LED)
        _delay_s(1);            // počká jednu vteřinu


        PORTB &= ~ (1 << PB5);  // nastaví bit5 na portu B na 0 (vypne LED)
        _delay_s(1);            // počká jednu vteřinu
    }

    return 1;
}

Jak je z kódu zřejmé, jde vlastně o totéž. Na rozdíl od Wiring varianty však C varianta pracuje přímo z registry procesoru, ty mohou být na různých čipech odlišné. Když bychom se však podívali do zdrojových kódů knihovny Wiring, našli bychom tam funkce, které dělají totéž, jen s omáčkou, která se stará o univerzálnost řešení.

Oba kódy přímo či nepřímo vyžadují knihovnu avr-libc, která je základní free knihovnou pro mikroprocesory AVR na kterých je Arduiono postaveno. Knihovna obsahuje to nejdůležitější co by mohl programátor AVR procesorů potřebovat. Najdeme v ní podporu pro práci s pamětí RAM i EEPROM, knihovnu stdio, stdlib, string i math a také knihovny pro časování, obsluhu přerušení nebo CRC výpočty.

Co ale v knihovně nenajdete jsou implementace kontejnery a iterátory, výjimky a žádné jiné třídy. C++ je v tomto směru jen otázkou syntaxe. Můžete tedy psát třídy, v nich používat identifikátor this a bez varovných hlášení kompilátoru použít například konstrukci (for int i = 0; i < 200; i++). Další a především podrobnější informace jsou k nalezení na stránkách projektu.

K článku je připojen i Makefile, který je jednoduší variantou uvedenou právě na stránkách avr-libc v sekci Demo projects. Ten obsahuje pravidla pro kompilaci i flashování aruduina. Nahrání nového firmware (flashování) do vašeho procesoru lze provádět různými technikami. Budu předpokládat že jste majiteli Arduina, a proto můžete použít program [avrdurde]. Dnešní Makefile i zdrojový kód je vytvořen pro Arduino Uno, bude ale fungovat i na jiných procesorech typu AVR. Proto pokud máte jiné arduino, je třeba zkontrolovat schéma zapojení, kde se nalézá ona LED dioda a případně upravit port ve zdrojovém kódu. A také je nutné před kompilací nastavit správný typ procesoru. Samotný proces kompilace a flashování lze provést jedním:

$ make blink.flash

V příštím článku se podíváme na PWM. Jako alternativu přidám i kód pro jiný AVR čip, který lze u nás pořídit se vším všudy do 100 korun. K jeho flashování už ale potřebujete programátor, který je různě drahý.

 

 

You must be logged in to post a comment.