IoT neboli Internet věcí je dnes velmi populární pojem (podobně jako před časem byl sémantický web) a jde tedy o pojem velmi široký. My budeme jako IoT vnímat přístroje a aplikace, které nemají charakter koncových zařízení. Čeho se tento pojem týká, zjistíte velmi snadno při nákupu těchto přístrojů, jelikož u nich někde najdete nenápadné upozornění, že přístroj není koncovým zařízením a může vyžadovat odbornou montáž. Tyto přístroje obvykle poznáte podle toho, že nemají vypínač. A nyní nemáme na mysli ATX-zdroje, kde je vypínač pouhá dekorace, kterou je třeba delší dobu držet, nežli se přístroj rozmyslí, zda příkazu uposlechne, ale přístroje, které se opravdu dají vypnout pouze odpojením napájení.

Mezi tyto přístroje patří například Raspberry Pi, což byl původně výukový model počítače, na kterém se měli žáci učit programovat. Tento přístroj je však dostatečně výpočetně výkonný, aby se na něm dal spustit některý ze systémů UNIXového typu a lze jej podle toho také používat. Dalším typem představitelů jsou destičky typu Arduino. I to jsou stroje, které měly sloužit k výuce programování, kybernetiky a automatizace. A právě na tyto dva typy představitelů zaměříme svou pozornost. Nežli si o nich ale začneme povídat, je opět potřeba drobný úhybný manévr.

Robot rizeny Raspberry pi napajeny z powerbanky
Takto například může vypadat počítač, ze kterého se dají promítat slidy o hodině. Kromě promítání slidů umí například jezdit, při čemž se pokouší nehavarovat do překážek.

Kutilský koutek

Jelikož si budeme povídat o přístrojích sloužících k automatizaci, musíme si říci něco málo o kutilství. Nyní je i domácí kutilství (stejně jako téměř vše ostatní) přísně regulovanou činností a k práci s elektrospotřebiči je třeba absolvovat zkoušky dle vyhlášky 50/1978. Bez této kvalifikace člověk nesmí zasahovat do elektrospotřebičů. My si tedy smíme o práci s elektřinou pouze povídat (dokud nezískáte příslušnou kvalifikaci), ačkoliv následující text může naznačovat, že bychom s elektřinou skutečně pracovali.

Přístroje, které jsou předmětem našeho zájmu, nepracují s napětím vyšším nežli 5 V (neseženete-li si USB-nabíječku, jejíž zem má proti skutečné zemi napětí 48 V, jako se před časem podařilo mně). Při 5V napětí nehrozí elektrický šok (kdežto zmíněných 48 V je už něco trochu jiného). Jakýkoliv přístroj připojený k elektrické síti je především zdrojem tepelné energie, na což je potřeba dát pozor. Neodborně připojené přístroje mohou snadno způsobit požár.

Po těchto upozorněních již přistoupíme k odborným tématům. Jelikož motivací pro práci s Internetem věcí je automatizace, potřebujeme z přístrojů, které umíme ovládat, nějak dostat informaci ven (to je u běžného počítače problematické). Toto se děje pomocí tzv. pinů. Pin pro nás v tuto chvíli nebude číslo ovládající kartu (ať už platební nebo telefonní), ale drátek čnící z destičky, ke kterému se očekává připojení nějakého přístroje. Těmito piny právě destičky jsoucí teď v centru našeho zájmu komunikují se světem. Svět pro ně sestává z přístrojů, kterým pomocí těchto pinů posílají vhodným způsobem proud. Některé piny jsou napájecí, jiné jsou zemnicí, většina jich však tvoří GPIO, tedy General Purpose Input/Output. Jde tedy o drátky, které mohou reprezentovat vstup nebo výstup. Vstup či výstup může být buďto analogový, kdy v jednotlivých krocích (řekněme 1 024) zvyšujeme napětí od nuly po stanovenou mez (v případě TTL 3.3 V). Vstup či výstup může být též digitální, což znamená, že přijmeme hodnotu 0 (odpovídající nejvýše několika stům milivoltům) nebo 1 (odpovídající alespoň stovkám milivoltů). Naše přístroje tedy budou komunikovat tak, že buďto z jednotlivých pinů čtou údaje, nebo na ně údaje zapisují. Tyto údaje si pak přečte někdo další (kdo je k tomu pinu připojený), případně nám je někdo (opět připojený) po tom pinu posílá.

Aby ve věcech nebyl náhodou pořádek, obvykle existuje více druhů číslování pinů (alespoň dva). Jeden odkazuje k číslování výrobce čipů (v pořadí, ve kterém piny lezou ven), druhý (přibližně stejně častý) systém se opírá o polohu na finální destičce (na kterou jsou piny vyvedeny). Tato číslování spolu obvykle mají jen velmi málo společného a je tudíž potřeba dát pozor, o jaké číslování se jedná!

Raspberry Pi

Jak jsme již uvedli, jde o počítač uvězněný na destičce o rozměrech přibližně 10 x 8 cm osazený řádově stovkami MB RAM (až nižšími jednotkami GB) se zásuvnou microSD kartou sloužící místo hard-disku, s obvyklými konektory (USB, HDMI, RJ45) o ceně v řádu desítek Euro. Jako CPU zde slouží některý z ARMů. Samotný modul se napájí z MicroUSB portu a destička může mít příkon až k 10 W (což je příkon běžné páječky). K napájení je proto potřeba mít USB zdroj schopný dodávat alespoň 2 A (pro některé destičky stačí méně, ale zase ne méně nežli 1,5 A). Použijeme-li zdroj s nedostatečným výkonem, bude se nám stroj nepředvidatelně restartovat (obvykle v okamžicích náporu na výpočetní výkon, tedy zrovna když ho používáme). Nejjednodušší využití takového přístroje spočívá v instalaci některého z UNIXových systémů (v případě Raspberry Pi konkrétně Raspbiana či FreeBSD) a následně člověk může pracovat tak, jak se naučil na hodinách UNIXu. Můžete tedy pracovat s UNIXovým shellem. Chcete-li však programovat Internet věcí, obvykle se to namísto v shellu dělá v Pythonu.

Python je programovací jazyk připomínající Járu Cimrmana. Ten prý vypadal jako sopka, která postupem času zavalila samu sebe. Python je na tom úplně stejně. Jeho hlavní výhodou je, že má wrappery kolem množství knihoven, takže nechceme-li seriosně programovat, ale jen lepit kusy kódu k sobě, je přesně tím, co hledáme. Nevýhody jsou vše ostatní. Jako každý interpretovaný jazyk je pomalý (asi 100x pomalejší nežli C#) a mezi programovacími jazyky patří k těm podivnějším. Stručně řečeno, je to něco jako Javascript bez typových konverzí. Místo složenými závorkami se bloky označují indentací. Řádky začínající stejným počtem mezer patří k sobě, řádky s větším množství mezer značí vnořený blok, řádek začínající menším množstvím mezer nežli řádek předchozí, značí konec alespoň jednoho bloku. Kolik bloků právě skončilo, se pozná podle toho, kterému bloku nad námi odpovídá náš počet mezer. Jinak je to obvyklý programovací jazyk, tedy jsou v něm funkce, proměnné, řídicí struktury if a while a objekty (poněkud avantgardně implementované). Toto by mělo průměrnému programátorovi stačit.


Takhle to vypada
Raspberry Pi. Zleva verze Zero (na které nefungují Windows, tedy tento model pro nás není vhodný), 3A, 3B+ (v plastikovém krytu). Leží na parketách obvyklé (tedy asi 6cm) šíře.

Hlavní výhodou Raspberry Pi (a přístrojů z této famílie) je 40pinový ježík připomínající konektor IDE, ke kterému tzv. kšandou připojujeme IDE-disky. Tento ježík má náhodou stejné rozměry (a kšandu na něj tudíž lze narazit), jde ale o 40pinové GPIO (kde některé piny mají zvláštní roli, jiné jsou obecné GPIO). Raspbian se od ostatních Linuxových distribucí liší právě tím, že má hned v základní verzi zabudovánu podporu pro toto GPIO, které tak můžeme používat. Například ve zmíněném Pythonu. To bychom to ovšem nebyli my, aby se v pravou chvíli neobjevilo Visual Studio. A ta chvíle právě přišla:

Raspberry Pi a Visual Studio

Raspberry Pi je poměrně bohatá rodina přístrojů, do které patří několik modelů. Například Raspberry Pi Zero, 2 (potažmo 2A), 2B, 3 (potažmo 3A), 3B, 3B+ a 4. Ačkoliv jde o jednu rodinu, přístroje se liší například hlavním procesorem. Pro některé procesory (konkrétně a alespoň ty osazované na Raspberry verzí 2 a 3) existuje operační systém jménem Windows 10 IoT Core. Dávejte pozor, protože například pro verzi 3B+ sice tento systém existuje, ale v experimentální verzi (která se už asi rok neupdatovala a její budoucí osud lze považovat za nejasný). V této experimentální verzi plno věcí nefunguje (například WiFi, kterou model 3B+ má). Jak je to s fungováním WiFi na verzi 3A (která nemá konektor RJ45, který spolu se čtveřicí USB-portů tvoří rozdíl mezi verzemi A a B), bude potřeba teprve zjistit. Jasné však je, že pro verze 3A a 3B+ je třeba instalovat různé verze Windows 10 IoT Core (verze z 3B+ na 3A nebootuje). Windows 10 IoT Core můžete nainstalovat na microSD kartu například instalátorem k tomuto účelu připraveným jménem Windows Assessment and Deployment Kit.

Windows 10 IoT Core mají s těmi Windows, které znáte, jen velmi málo společného. Jde o systém úplně jiný (není tam ani Notepad, ani Paintbrush, ani Minesweeper, ani Solitaire a ani žádná jiná z vlajkových lodí provázejících nás Windows od nepaměti). Systém je navržen pro přístroje bez displayů a klávesnic. Je tedy možné jej vzdáleně administrovat (na portu 8080 běží webové rozhraní, ke kterému se lze přihlásit a tak stroj spravovat) a je možné k němu otevřít ssh (na port 22, kde ovšem místo osvědčeného UNIXového shellu máme vylevněný command.com). Klávesnice, myš a monitor však je taktéž podporován a má jisté výhody, když tyto periferie připojíme. Sice si nezahrajeme Miny ani Patience (pokud si je sami neimplementujeme), ale dostaneme se do lokálního administračního rozhraní (se kterým je trochu větší legrace nežli s tím vzdáleným). A kde jsou Windows (byť IoT Core), tam strká pracky Visual Studio.

Není tudíž asi překvapivé, že i tyto přístroje (nainstalujeme-li na ně Windows 10 IoT Core) můžeme programovat ve Visual Studiu. Tentokrát musíme v Installeru zakliknout podporu Universal Windows Applications. Pak budeme schopni vytvářet aplikace běžící jak u nás, tak na Raspberry. Visual Studio je pořád stejné, C# také, jen vstup a výstup je zase jiný (a ukážeme si jej na příkladu). Tentokrát ted vytvoříme Blank App (Universal Windows).

Create project

Podobně jako když jsme vyvíjeli aplikace pro Android, můžeme ve Visual Studiu aplikaci uploadovat do Raspberry a dokonce tam vzdáleně ladit. A v případě, že bychom s tím měli problémy, můžeme zkusit ladit lokálně (proč jinak by se dotyčná platforma jmenovala Universal Windows Application). Ladění nám lokálně půjde do chvíle, kdy si začneme hrát s GPIO (to obvykle lokálně přítomné nemáme).

Nyní se tedy opět pustíme do příkladů. Začneme tím, že i nově vytvořenou aplikaci lze spustit. Toto je vhodné si vyzkoušet, abyste zjistili, co vám případně brání v úspěšném spuštění aplikace. Vytvořte tedy novou aplikaci a spusťte ji na vzdáleném zařízení.

Vytvořit aplikaci nebude těžké. Spustit ji bude obtížnější. Přesněji obtížnější to bude, chcete-li ladit na vzdáleném hardwaru. Ne nadarmo se typ aplikace jmenuje Universal Windows Application, ladit ji tedy můžete i lokálně. Chcete-li však ladit jinde, je třeba toto nastavit. Konkrétně chceme-li ladit na Raspberry Pi, které má jako CPU některý z famílie ARMů, je třeba ve Visual Studiu přenastavit obsah v liště popisující spouštění a ladění (sestávající ze tří okének obvykle obsahujících stringy Debug, x86Device. Spouštět sice stále můžete ladicí verzi (tedy slovo Debug můžete ponechat). Místo x86 už ale nastavíte ARM, protože Raspberry Pi nemá CPU intelské famílie ale ARM, jak jsme si již řekli a namísto Device nastavíte Remote Machine. Nastavení je pak zapotřebí dokončit v Project -> Properties. Tam v tabu Debug musíme nastavit jméno nebo IP adresu dotyčného přístroje do položky Remote Machine. Dále je třeba v nastavení zapnout Developer mode. O ten se nemusíme až tolik starat. Jen si necháme vytvořit Universal Windows Application, Visual Studio se nás rovnou při každém startu (dokud to tak nenastavíme) bude vyptávat, v jakém (vývojářském) režimu má být. Tam tedy naklikáme Developer mode.

Nastaveni vzdaleneho ladeni

Ostatní nastavení (projektu) nehraje až takovou roli. Některé tutoriály radí změnit i  Authentication Mode na None, případně do Remote machine za adresu (či jméno) přidat dvojtečku a číslo portu (8116). Někteří zase říkají, že bez spuštění remote debuggeru na dotyčném zařízení (ve webovém interfacu od Raspberry v sekci Debug) zapnout (tlačítkem vpravo dole) debugger. Autorovi textu se jako jediná důležité věc rozhodující o úspěchu či neúspěchu uploadu a následného spuštění jeví připojení k Internetu. S připojením funguje jakékoliv nastavení zmíněných položek, bez připojení pak nefunguje nic. Toto je poněkud zvláštní, protože přístroje provozující Windows 10 IoT Core tak musejí být při každém nahrávání programů připojené k Internetu. To vypadá jako významné bezpečnostní riziko. Po uploadu (přesněji po ukončení ladění) však již lze spojení odpojit.

Máme-li prázdnou aplikaci spuštěnu, vidíme, že aplikace pro Universal Windows Platform vypadají poněkud jinak nežli ostatní aplikace. S tím souvisí také to, co jsme již viděli na Androidu, a to velmi opatrná práce s vybavením. Konkrétně a například proces opět ani nesmí hledat data na filesystemu (potažmo na microSD-kartě). Svůj majetek musí mít aplikace přibalený u sebe. Chceme-li tedy pracovat se souborem, musíme říci, že aplikace bude přistupovat do filesystemu. Nechceme-li toto nastavovat, musíme využít resourcy, tedy potřebné soubory, se kterými budeme pracovat, přibalit do projektu. Toto uděláme hned ve druhém příkladu (kde nám bude aplikace vyhrávat). Příklady však teprve začnou a je třeba postupovat od začátku (hrát si teprve budeme).

Máme-li naklikaný prázdný projekt (který jsme před chvíli úspěšně spustili), zdrojový kód, který budeme modifikovat, najdeme v souboru MainPage.xaml.cs. Ten najdeme v Project Manageru pod souborem MainPage.xaml. Chceme-li formulář a designera, otevřeme MainPage.xaml. V designeru se kliká způsobem, který znáte z Windows Forms Applications. Časem se všimněte, že prvky na formuláři se také chovají způsobem, na který jsme zvyklí. Tedy textový obsah se skrývá pod wrapperem Text, tlačítko je stále instance třídy Button,... Taktéž si ale všímejte, že některé prvky jsou jiné!

Příklad 1: V designeru naklikejte na formulář tlačítko, tedy prvek typu Button a místo pro zobrazování textu typu TextBlock (který tu zastupuje prvek Label, který znáte z Windows Forms Applications. Tlačítko pojmenujte cudlik, textové políčko pojmenujte natext a nechte tlačítku vygenerovat ovladač události (ten s defaultním jménem cudlik_Click). Tento ovladač nastavte takto:

 private void cudlik_Click(object sender, RoutedEventArgs e)
 {
         natext.Text = "Buch!";
 }
Příklad spusťte a obdivujte, jak stále všechno funguje stejně, jako jste zvyklí z Windows Forms Applications (jen ty prvky se jmenují občas jinak).

Příklad 2: Jako Asset přidejte soubor jménem Brahms.mp3, příklad laďte na stroji se sluchátky nebo reproduktorem. Povšimněte si, že Raspberry Pi má port na sluchátka. Tím se na vás případně bude linout zvuk. Zvuk přes HDMI ve Windows 10 IoT Core na Raspberry Pi není podporován aspoň zatím). Týž ovladač události jako v minulém příkladu nyní definujte takto:

private async void cudlik_Click(object sender, RoutedEventArgs e)
{
    StorageFolder Folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
    Folder = await Folder.GetFolderAsync("Assets");
    StorageFile sf = await Folder.GetFileAsync("Brahms.mp3");
    MediaElement PlayMusic = new MediaElement();
    PlayMusic.SetSource(await sf.OpenAsync(FileAccessMode.Read), sf.ContentType);
    PlayMusic.Play();
}
Tentokrát (provádíme-li pokus na Raspberry Pi nebo počítači bez reproduktorů) je třeba připojit sluchátka. Všimněte si, kolik práce dá přehrát uložený zvuk. V příkladu vidíte přístup k vlastním Assetům (prvních 5 řádků). Následuje spuštění vyhrávání (volání metody Play). Taktéž si všimněte klíčových slov asyncawait. První klíčové slovo používáme jako modifikátor funkce, která použije to druhé klíčové slovo. To druhé klíčové slovo znamená, že se má volání provést asynchronně, tedy nemá se čekat na jeho výsledek. Ještě přesněji klíčové slovo async v definici funkce říká, že se nemá čekat na výsledek našeho volání, jelikož si spustíme asynchronní funkci.

Příklad 3: Formulář s tlačítkem a textovým prvkem se nám osvědčil, tak ho využijeme i nyní. Opět jen modifikujeme ovladač kliknutí na tlačítko:

private void cudlik_Click(object sender, RoutedEventArgs e)
{
    MediaElement mediaElement = new MediaElement();
    var synth = new SpeechSynthesizer();
    //var voices = SpeechSynthesizer.AllVoices;
    //synth.Voice = voices.First(x => x.Gender == VoiceGender.Female);
    Windows.Media.SpeechSynthesis.SpeechSynthesisStream stream = await synth.SynthesizeTextToStreamAsync("Good-bye world!");
    mediaElement.SetSource(stream, stream.ContentType);
    mediaElement.Play();
}
Vidíme, že zvukový výstup je pomalu jednodušší, nežli přístup k vlastním souborům. Zakomentované řádky je možné odkomentovat, tím se nastavují vlastnosti hlasu loučícího se se světem.

Příklad 4: Ke GPIO 2 (tedy 3. pinu) připojíme výstup senzoru přiblížení (magnetického čidla, které hlásí, zda je poblíže něj magnet, podrobnosti jsou v následující sekci u Arduina). Prvek TextBlock se nám nyní výrazně hodí:

using Windows.Devices.Gpio;
...

namespace priklad{
    public sealed partial class MainPage:Page
    {   GpioController gpio = GpioController.GetDefault();
        GpioPin MyPin;
        public MainPage()
	{   this.InitializeComponent();
	    MyPin=gpio.OpenPIN(2);
	
            try
            {
                MyPin.SetDriveMode(GpioPinDriveMode.Input);
                MyPin.SetDriveMode(GpioPinDriveMode.InputPullUp);
            }
            catch (Exception)
            {
                MyPin.SetDriveMode(GpioPinDriveMode.Input);
            }
            MyPin.DebounceTimeout = TimeSpan.FromSeconds(0.5);
            MyPin.ValueChanged += MyValueChanged;
            MyValueChanged(MyPin, null);

        }

        private void write(string what,bool alm)
        {   IAsyncAction task = Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {   natext.Text = what;
                natext.Foreground = new Windows.UI.Xaml.Media.SolidColorBrush(alm?Windows.UI.Colors.Red:Windows.UI.Colors.White);
                
            });
        }
        public void MyValueChanged(GpioPin sender, GpioPinValueChangedEventArgs e)
        {   if (sender.Read() == GpioPinValue.High)
                write("Prichazi proud!",true);
            else 
		write("Jsme na suchu!",false);
        }
    }
}
Nechali-li jsme si na formuláři tlačítko s nastaveným ovladačem kliknutí, musíme samozřejmě tento ovladač nechat definovaný (ale to je snad jasné).

Na tomto příkladu si všimněte práce s GPIO. Jeden pin reprezentuje objekt třídy GpioPin. Tento pin musíme otevřít (což děláme v konstruktoru třídy MainPage). Musíme říct, do jakého režimu se má nastavit. My se jej pokoušíme nastavit do režimu, kdy jako nepřipojený bude hlásit, že jím proud teče. Pokud tento režim nevyjde (přijde výjimka), řekneme jen, že je to pin vstupní. Při startu si tedy pin zinicializujeme a nastavíme mu ovladač změny (funkce MyValueChanged). Změní-li se napětí na dotyčném pinu, objeví se údaj o tom v textovém prvku. Aby se údaj o tom, v jakém stavu pin je, objevil hned na začátku (a nemuselo se čekat na změnu), dotyčný ovladač rovnou explicitně zavoláme.

Ovladač události vyvolá pozaďové vlákno. Pro to platí tatáž omezení, jako jsme viděli dříve (například na Androidu). Tedy toto vlákno nesmí zapisovat do formuláře. My však právě do formuláře zapsat potřebujeme. Proto to neděláme přímo, ale voláme si na to funkci write, která tuto změnu provede asynchronně. Samozřejmě bychom tuto změnu mohli asynchronně nechat provést rovnou v ovladači události, ale kód by začal být lehce nepřehledný (dělali bychom tam dvakrát totéž).

Cvičení: Ke kafomatu vyrobte juke-box. Pokud již juke-boxy nepamatujete, jde o přístroj, do kterého se hodila mince a za tuto minci si člověk mohl nechat zahrát vybranou skladbu. Juke-boxy kdysi obsahovaly gramofon a množství desek, z nichž si platící mohl vybrat. Dnes takovýto přístroj implementujte s využitím Raspberry Pi. Juke-box pak můžete postavit vedle kafomatu. Zatímco kafomat ničí naše žaludky, Juke-box bude ničit naše uši. A oba to dělají za (naše) peníze. :-)

Jak vidíte, Universal Windows Platform se chová do jisté míry specificky, ale C# je pořád stejný, Visual Studio je pořád stejné a řada různých temných omezení je stále stejná. Tomu jsme celou dobu říkali principy a pokoušeli jsme se na ně soustředit. To ostatní, co se v různých jazycích liší, označujeme jako anomalie a na ty začne být čas soustředit se buďto na pokročilých kurzech, anebo samostatně po studiu, až zjistíte, ve kterém prostředí zkusíte strávit zbytek života. Na anomaliích je nepříjemné, že si na ně člověk zvykne a v ostatních jazycích mu chybějí. Proto jsme se dosud pokoušeli soustředit na principy.

Arduino a jeho rodina

Arduino je poměrně levné prostředí osazené zpravidla nějakým microcontrolerem, které bylo původně navrženo k výukovým účelům. Proto existuje mnoho výukových sad (za drahé peníze). Jelikož jsem názoru, že pro práci s elektřinou jsou potřeba zkoušky dle zmíněné vyhlášky 50/1978 Sb., není mi úplně jasné, jak mají výrobci těchto sad ošetřenu odpovědnost za škody vzniklé nekompetením použitím těchto výukových sad. Výhodou Arduina je, že má poměrně slušnou podporu a také technické vybavení čítající několik digitálních i analogových vstupů (GPIO), 5V napájení, 3.3V napájení a několik zemnicích pinů. Přístroj se napájí také pomocí nějakého USB konektoru a tímto konektorem se též dá programovat (přesněji tudy se do něj dá nahrát program). Taktéž je Arduino poměrně stabilní. Nevýhodou je však cena. Jelikož jde o dominantní nástroj sloužící ve výuce, o Arduina na trhu se přetahujeme s množstvím žáků. Existují však i další přístroje, které dovedou udělat podobnou práci (nechceme-li využívat všechny schopnosti Arduina). Výhodou jiných přístrojů je, že je lze programovat týmž studiem jako Arduino (jen je potřeba postahovat jiné knihovny) a některé vývojové destičky mají oproti Arduinu zabudované prvky pro síťovou komunikaci (na což Arduino potřebuje shield). Takovou destičkou je například NodeMCU od Wemos. NodeMCU je destička, na které většinu místa zabírá ESP8266, což je mikrokontrolér s připojenou WiFi (a několika piny včetně pinu napájecího, zemnicího, jednoho analogového GPIO a také několika digitálních GPIO pinů).

Takhle to vypada
Přístroje programovatelné Arduino Studiem. Zleva: Arduino (schované pod LCD shieldem), LoLin a D1 mini. Všimněte si společné malé destičky s wifi anténou na dvou přístrojích vpravo (to je ESP8266). Pravý přístroj je v tuto chvíli DarwiKuk. Parkety mají stále šířku kolem 6 cm.

Arduino a destičky z jeho famílie se programují pomocí Arduino Studia. Toto studio je výpočetně výrazně méně náročné, nežli všechna dosud předvedená studia. Správa projektů je tu poněkud jednodušší. Projekt je reprezentován adresářem a jemu příslušející zdrojáky jsou všechny v něm obsažené soubory s koncovkou ino. Další výhodou je, že Arduino Studio používá jako překladač g++-avr, tedy GNU C++ pro AVR. Tento překladač tedy implementuje podmnožinu C++, které znáte. Konkrétně fungují funkce, proměnné, základní řídicí struktury, objekty, konstruktory, destruktory a přetěžování funkcí. Naopak nefungují například výjimky nebo šablony. A knihovní funkce, na které jste byli zvyklí, také nefungují. Nicméně jsou nahrazené jinými funkcemi. Ostatně řada z těch funkcí, které znáte, nyní nemá dobrý smysl. Těžko využijete například funkci printf na stroji bez displaye. Základní komunikace (pro účely ladění) probíhá po USB. Co vám destička hlásí, můžete sledovat Serial Monitorem (který vypisuje jednotlivé znaky po seriovém portu přicházející) nebo Serial Plotterem (který vykresluje přicházející hodnoty). Oba jsou k dispozici v menu Arduino Studia (konkrétně v menu Tools). Seriový port nás provází odjakživa a jistě jste se o něm učili (duplexní asynchronní přenos, jedním drátem se vysílá, druhým přijímá). Komunikace po seriovém portu může probíhat různými rychlostmi. Dnes rozumně používaná rychlost je 115 200 bps (není to mnoho, ale většina přístrojů ji zvládá a pro účely ladění i běžného přenosu dat z levných měřicích přístrojů bezpečně postačuje).

Arduino Studio

V tomto studiu budeme používat vlastně jen první dvě ikony. První zkompiluje projekt, druhá zkompiluje (pokud se zdrojové texty změnily) a nahraje do destičky. Port (ke kterému máme destičku připojenu) musíme nastavit v menu Tools intuitivně pojmenovanou položkou Port.

Program vytvořený v tomto studiu, jak vidíte, nemá funkci main, ale je osazen dvěma (jinými) funkcemi, a to setuploop. První funkce se spustí po startu destičky (a vykoná se jednou od začátku do konce). Jen doběhne, spustí se funkce loop, která se, pokud někdy doběhne, ihned spustí znovu od začátku. Programování těchto přístrojů tedy vypadá úplně jinak nežli programování aplikací pro mobilní telefony. Zatímco tam jsme měli událostmi řízené programování, tady jsou události jen dvě (start systému, který spustí funkci setup a dokončení běhu nějaké funkce, což spustí funkci loop). Jsme tedy zpět u toho programování, ke kterému vás vedli v prvním ročníku: Obstarejte si údaje, spočítejte, co chcete a vypište výsledek. A znovu.

Tyto přístroje například lze použít jako jednoduchý zabezpečovací systém, který hlídá, zda se na nějakém území neděje něco podezřelého - například jestli tam nikdo neprochází či jestli někdo neotevřel okno či dveře, které má systém pod dozorem. Tento zabezpečovací systém pak může poslat seriovým portem údaje do počítače (který je vyhodnotí a například zavolá majiteli, že má škodnou v revíru - nebo dokonce destička sama může nařídit siréně, ať se rozkvílí a lupiče svým kvilem vypudí). Anebo může údaje poslat pomocí WiFi (zavolat si na server). Poněkud příjemnější použití můžeme vidět například na stroji DarwiKuk. Tento přístroj navrhl kolega Rubeš, člen spolku Darwiniana k usnadnění pěstování dravých rostlin. Masožravé rostliny jsou mezi těmi běžně doma pěstovanými nadprůměrně náročné. Jelikož řadě lidí hynou, kolega Rubeš navrhl a implementoval přístroj, který sleduje vybrané meteorologické jevy. DarwiKuk bude jedním z našich příkladů, k čemu lze Arduino Studio použít. Nicméně my jsme zatím s programováním na začátku a zajímá nás, jak to celé funguje.

K programování těchto zařízení existuje mnoho tutorialů (různých kvalit), kde obvykle zanikají principy. O těch si nyní zkusíme chvíli povídat. Využijeme toho, že jazyk samotný (tedy omezenou verzi C++) již znáte a můžeme se zcela soustředit na vstup a výstup. Ten je reprezentován především analogovým a digitálním vstupem a výstupem. Abychom mohli provozovat tento vstup a výstup, potřebujeme nějaký pin. My využijeme destičku WeMos D1 Mini (což je, jak vidíme, ESP8266, tedy počítač velikosti pecky vybavený WiFi anténou, připájený na destičku, která má trochu zvětšit piny - a také na cestu strká různé představné odpory). Programujeme-li konkrétně tuto destičku, musíme pro ni instalovat podporu ESP8266 tak, že v menu File vybereme položku Preferences a v tabu Settings vyplníme do položky Additional Boards Manager URLs: adresu http://arduino.esp8266.com/stable/package_esp8266com_index.json Dále musíme nastavit, že kompilujeme pro tuto destičku. Tedy v menu Tools vybereme položku Board a v podmenu vybereme položku Boards manager... Tam (pomocí okénka vpravo nahoře) necháme najít ESP8266, klikneme Install a chvíli počkáme, až se stáhnou příslušné knihovny. No a nyní už se můžeme pustit do toho.

Připomeňme si, že chceme manipulovat se vstupem a výstupem, a to analogovým a digitálním. Abychom si demonstrovali digitální výstup, použijeme pin 2, který má tu výhodu, že je připojený k LED, která umí krásně modře svítit. Že jsme úspěšně zapsali, tedy poznáme podle toho, že se tato dioda rozsvítí nebo naopak zhasne. Necháme ji tedy pro své pobavení blikat ve vteřinových intervalech.

Příklad 1: Blikání diodou

#define LED_PIN 2 // GPIO02 neboli D4 pripojene k LED

void setup() {
  // put your setup code here, to run once:
  pinMode(LED_PIN,OUTPUT);//Zinicializujeme jako vystupni
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(LED_PIN,LOW);//rozsvit
  delay(1000);
  digitalWrite(LED_PIN,HIGH);//zhasni
  delay(1000);
}
V tomto příkladu ve funkci setup inicializujeme GPIO 2 na destičce označený jako D4 jako výstupní (tím říkáme, že na něj budeme zapisovat). Ve funkci loop to pak také děláme. Tato funkce rozsvítí LED, vteřinu počká, zhasne a opět vteřinu počká. Když tato funkce skončí, spustí se ihned znovu. Proto nám dioda bliká.

Příklad 2: Načítání digitálního vstupu
Chceme-li načítat, potřebujeme něco, co nám data pošle. Například senzor otevření dveří. To je ve skutečnosti magnetický senzor, který zjišťuje, zda je k němu přiblížen magnet. Senzor je přilepený na futro u dveří, magnet je přilepený u něj na dveřích, otevřou-li se tyto, magnet se vzdálí. Úplně stejně bychom z technického hlediska pracovali například s PIR-senzorem (jen by se nejspíše lišilo napájení, PIR-senzor obvykle potřebuje 5V napájení, senzor otevírání dveří naopak jen 3V). Ovšem oba senzory jen odpovídají na otázku: "Vidíš něco zajímavého?"

#define vstup D1
void setup()
{ Serial.begin(115200);
  pinMode(D1,INPUT_PULLUP);//je-li pin odpojený, má hlásit HIGH
  //pinMode(D1,INPUT);//alternativa, kdy pri odpojeni nevime, co se stane
}

void loop()
{ Serial.println(digitalRead(D1));
  delay(100);// opet delame 10 mereni za sekundu
}
Tentokrát si můžeme výstup nechat zobrazit pomocí Serial plotteru (anebo Serial monitoru).

Příklad 3: Načítání analogového vstupu
Analogový vstup si můžeme demonstrovat například na čidle zalití či deště (také bychom podobně mohli využít odporový teploměr, tedy čidlo, kterému se s teplotou mění odpor, ovšem tyto analogové teploměry nebývají moc kvalitní). Měřák zalití (který také kvalitou zrovna neoplývá, ale aspoň je levný) funguje buďto také odporově (kdy k jedné elektrodě připojíme napětí a na druhé koukáme, jaké napětí na ni dorazí skrz zpravidla špinavou a tedy slušně vodivou vodu), nebo kapacitně (zkusí si nabít okolí a podle toho, jakou kapacitu okolí má, usoudí, kolik vody v okolí je). Každopádně tedy má smysl uvažovat o tom, že toto čidlo nebude digitální, ale analogové.

#define VSTUP A0  //jediny analogovy vstup
void setup()
{ Serial.begin(115200);
}

void loop()
{ Serial.println(analogRead(VSTUP));//precteme a vypiseme po seriaku
  delay(100);// po mereni pockame 100 ms
}

Výstup je vhodné si zobrazit Serial plotterem.

Analogový výstup bychom mohli využít například k roztáčení motoru (kdybychom chtěli přibližně řídit rychlost dotyčného motoru, jinak pro pohon motoru postačí digitální výstup, ale nejspíše budeme potřebovat relé nebo transistor, protože motor má příkon, který pomocí GPIO proti zemi nejsme schopni pokrýt). Řešení si jistě dovedete představit podle výše uvedených tří příkladů. My postoupíme dál, a to k využití advancovanějších měřáků. Jako příklad nám poslouží

Příklad 4: Darwikuk.
Zdrojové texty jsou na webu (a jsou dílem kolegovým, tak je sem nebudu kopírovat). Všimněte si, že tam připojujeme měřáky zjišťující teplotu, tlak, vlhkost a osvětlení. K tomu účelu jsme připojili dvě destičky celkem čtyřmi dráty (a ještě k tomu jsme ty destičky připojili k sobě). Jak tedy celý tento systém funguje?

Začneme menší kontrolní otázkou. Nalistujte ve zdrojovém kódu funkci hodnotaMereni a důkladně si rozmyslete, co dělá. Velmi výrazně se vám k tomu mohou hodit třídicí algoritmy probírané v prvním ročníku. Všimněte si též, že kolegovy zdrojové texty jsou napsané velmi kultivovaně a také jsou dobře okomentované.

Myšlenkově nejnáročnější část softwaru jsme již prošli (v minulém odstavci) a přejdeme k hardwaru. Zúčastněné senzory (BME280 a TSL2561) nejsou ani analogové měřáky a ani měřáky digitální (v tom smyslu, jak jsme si řekli). Ve skutečnosti jsou to digitální přístroje podporující komunikaci pomocí I2C (o čemž jste se učili v Principech počítačů). I2C jste probírali jako sběrnici (protože se dá řetězit). Název je zkratka Inter Integrate Communication, což odkazuje k tomu, že jde o protokol pro komunikaci mezi integrovanými obvody (tedy mezi přístroji majícími základní inteligenci). I2C je protokol typu otrokář - otrok a funguje se čtyřmi vodiči. Otrokář poskytuje napájení a zem (k čemuž potřebuje dva vodiče) a bubnuje (po třetím vodiči). Bubnuje-li otrokář levou rukou, po čtvrtém (datovém) vodiči může poslat bit svého požadavku. Bubnuje-li otrokář pravou rukou, může otrok poslat bit odpovědi. Je asi jasné, že "bubnování" je realizováno napětím (potažmo jeho absencí) ve vodiči (tedy jednou rukou bubnujeme, pokud je vodič pod napětím, druhou pokud je vodič uzemněný). Po datovém vodiči tedy formálně probíhá synchronní seriová komunikace.

Nyní je jasné, proč stačí čtyři vodiče, ačkoliv přenášíme analogové informace (a ještě ke všemu hned čtyř druhů). Otázkou ještě je, jak to, že přístroj funguje, když jsou k těm čtyřem vodičům připojené dvě destičky současně. I na to přináší odpověď specifikace I2C. Každý otrok totiž má adresu. Otrokář v rámci requestu řekne adresu otroka, se kterým se baví, a tento otrok také začne odpovídat. Jelikož BME280 má jinou adresu (a celkově jiné detaily protokolu pro komunikaci) nežli TSL2561, tyto dvě destičky si nepřekážejí. Ale kdybychom zkusili dvakrát připojit stejnou destičku, byl by vážný problém.

Toto je užitečné věděti, abychom chápali, jak svět kolem nás funguje (a nepřipadali si jak v pohádce, když naše životy ve skutečnosti řídí mocné vědy přírodní). Pro samotné využití to však není nutné. Samotná komunikace (jak vás mohlo napadnout) probíhá tak, že voláme funkce z nějaké knihovny. V tomto případě jde o funkce z knihoven od společnosti Adafruit, které jsou navržené právě na komunikaci s těmito destičkami. My si tedy jen řekneme "dej sem teplotu" a příslušná funkce nám ji přes I2C vybubnuje.

Cvičení: Navrhněte kafomat. Začněte třídičkou mincí, která bude IR-čidlem sledujícím přiblížení určovat, kterou dírou vhozená mince propadla (a příslušnou hodnotu započítá). Pokračujte tím, že motor bude vhodnou dobu prskat (horkou) vodu, dokud jí neproteče dostatek. Jak byste řešili dávkování prášku? Přeci stejně jako padání kelímků. A pokud se vám nepodaří nic z předešlého, navrhněte pro kafomat alespoň teploměr, který bude zjišťovat, jakou teplotu má vyráběné kafe. Anebo možná raději navrhněte teploměr, který bude měřit teplotu kupujících. Bude-li mít zákazník teplotu přes 37,5 stupně, je podezřelý, že má dnes velmi populární SARS verze 2.0 (který nám zrušil výuku) a je třeba jej upozornit, že nedodržuje karanténu (ať si připraví tři míče na pokutu).
Nápověda: Na měření teploty zákazníka můžete zkusit použít nějaký infračervený (a tedy bezkontaktní) teploměr. Teploměr, na který by bylo potřeba sahat, u kafomatu být nemůže, protože by ještě infekci šířil! Taktéž nezapomeňte, že samotný kafomat musí připomínat pevnost. Jinak si k němu budou pobudové chodit jako k bankomatu.


otevreny kafomat     automaticke rozmenovadlo
Takto vypadají dnes běžně používané kafomaty. Dokážete navrhnout něco lepšího?

Cvičení: Navrhněte a implementujte robotický vysavač, přesněji robota uklízeče. Takového, který dokáže uklidit nepořádek, co každou chvíli nadělá váš kafomat z minulé úlohy. Z toho se poměrně nepochybně bude sypat černý intenzívně barvící prášek, sušené mléko a umělé sladidlo. Aby toho nebylo málo, každou chvíli z něj také jistě vyšplíchne voda - v lepším případě čistá, obvykleji však s rozpuštěným práškem černé barvy.

Tímto končí naše exkurze do světa internetových a mobilních aplikací. Vidíte, že jde o svět v poslední době se prudce rozvíjející. A být součástí takového světa bývá velkou výhodou.

Děkuji za pozornost, dál už musíte sami. Mnoho úspěchů.