Kity, Bity, Neurony

Martin Malý

Vydavatel:

CZ.NIC, z. s. p. o.

Milešovská 5, 130 00 Praha 3

Edice CZ.NIC

www.nic.cz

1. vydání, Praha 2025

Kniha vyšla jako 35. publikace v Edici CZ.NIC.

© 2025 Martin Malý

Toto autorské dílo podléhá licenci Creative Commons BY-ND 4.0 (https://creativecommons.org/licenses/by-nd/4.0/). Dílo však může být překládáno a následně šířeno v písemné či elektronické formě, na území kteréhokoliv státu, za předpokladu, že nedojde ke změně díla a i nadále zůstane zachováno označení autora a prvního vydavatele díla, sdružení CZ.NIC, z. s. p. o. Překlad může být šířen pod licencí CC BY-ND 4.0.

Tato kniha vyšla v Edici CZ.NIC. Chcete přispět na vznik dalších? Darujte libovolnou částku na dar.nic.cz/kniha-kity

Edice CZ.NIC je jednou z osvětových aktivit sdružení CZ.NIC, správce české národní domény.

ISBN 978-80-88168-85-0 (tištěná verze)

ISBN 978-80-88168-86-7 (ve formátu PDF)

ISBN 978-80-88168-87-4 (ve formátu EPUB)

— Martin Malý

Kity, Bity, Neurony

— Edice CZ.NIC

Předmluva vydavatele

Předmluva vydavatele

Milá čtenářko, milý čtenáři,

Vámi otvíraná kniha, nazvaná Kity, bity, neurony, představuje již šestou publikaci Martina Malého vydávanou v Edici CZ.NIC. Autor se tentokrát zamýšlí nad dynamickým vývojem v celém „oboru bastlení“ – domácího kutilství. Ačkoliv se podle autora někteří čtenáři dříve dožadovali návratu k tranzistorům, kniha se místo nostalgie soustředí na to, co se ve světě hobby elektroniky objevilo relativně nedávno.

Cílem autora bylo ukázat nové možnosti domácího kutilství, představit zajímavé oblasti a být užitečným průvodcem v domácím bastlení zvláštnímu druhu člověka kutilu elektrotechnickému. Martin Malý se v knize postupně věnuje v jednotlivých kapitolách softwaru a hardwaru, modulům, praktickým aplikacím a v neposlední řadě umělé inteligenci a neuronovým sítím. Jako bonus si čtenář může postavit třeba bezdotykovou lampičku ovládanou gesty.

Kniha vzdává hold domácímu kutilství, které autor rehabilituje jako umění vytvořit něco vlastníma rukama, s maximem kreativity a radosti z objevování. Bastlení je totiž nutné vnímat ne jako způsob jak získat hotové bezchybné řešení, ale jako kreativní proces učení a radosti z řešení problémů. A právě radost z tvoření a touha porozumět všudypřítomným technologiím představují základní vlastnosti kutilského člověčenství. Přejeme vám příjemné čtení a neutuchající touhu stavět, objevovat a žít.

Jaromír Novák, CZ.NIC
Praha, 25. listopadu 2025

Poděkování

Poděkování

Když jsem psal poděkování do své první knihy, netušil jsem, že jednou budu psát poděkování do knihy šesté. Ale stalo se to, a to především díky mnoha skvělým lidem.

V první řadě děkuji lidem, kteří tuto knihu v Edici CZ.NIC připravili. Jmenovitě pak paní Kateřině Slavíkové, bez níž by tyto knihy ani nevznikaly. Na počátku je vždycky její telefonát s nenápadnou otázkou „…a nechcete zase něco napsat?“ Nedokážu odmítnout!

Děkuji lidem, kteří bastlení považují za radost, ne za výsadu, a kteří mi pomohli radou, tipem, námětem, nebo jen svým pozitivním příkladem. Pro mě jsou duší českého bastlení. Za všechny jmenuji Michala Ševčíka, Petra Šrámka, Martina Kiklhorna, Juraje Michálka, Konstantina Lásku, Oldřicha Horáčka, Martina Wolkera, Martina Kocourka, ale kdybych chtěl být spravedlivý, tak bych musel jmenovat všechny ty lidi, co znám z Twitteru (nyní X) jen přezdívkami a podle jejich profilových fotografií.

Úplně nejvíc pak děkuji vám všem, kteří moje knihy čtete a kupujete. Vždycky mě potěší, když se ke mně někdo hlásí a říká: „Jé, já četl vaši knížku!“ – a co teprve když je z oboru, kde bych to moc nečekal. Díky za tahle milá potěšení!

Speciální poděkování za toleranci a trpělivost patří mojí partnerce Lence.

Díky!

Předmluva

Předmluva

Napsal jsem pět knih o elektronice. Když jsem dopsal první, věděl jsem, že bude mít pokračování o mikroprocesorech a stavbě vlastních počítačů. Když jsem psal druhou, věděl jsem, že bude muset být třetí, o FPGA. A pak jsem myslel, že už jsem napsal všechno, co jsem chtěl o elektronice napsat…

Jenže díky vám, čtenářům, vzniklo i speciální „školní“ pojednání o Micro:bitu, a když jsem ho dopisoval, přišly nové modely ESP32, spousta konstrukcí, a bylo jasno: další kniha musí být o ESP32!

I po páté knize jsem si říkal, že už asi nebudu mít o čem psát, ale obor jde rychle dopředu. Nemyslím elektroniku, tam je to nepochybné; myslím „obor bastlení“, domácího elektronického kutilství. Když se mi opět ozval vydavatel s tím, jestli nechci napsat další knihu, tak jsem se zamyslel: o čem by měla být?

Někteří navrhovali vrátit se k tranzistorům. Jiní navrhovali rádio. Obojí jsou zajímavé oblasti. Ano, uznávám, že „bastlení“ s tranzistory má svoje kouzlo, i když leckdy nostalgické: vůně pálené kalafuny, olověná pachuť na jazyku, tranzistory s dlouhými nožičkami rozkročené nad změtí drátků, v lepším případě nad deskou plošných spojů, měření, nastavování pracovního bodu zesilovače, vinutí cívek („viňte 624 závitů vodičem 0,1 mm a každou vrstvu proložte papírem. U závitu 218 udělejte odbočku. Na cívku naviňte 12,5 závitu lakovaným vodičem 1 mm“ – pamatujete?) a oživování toho všeho… Tranzistory mi voní zažloutlými listy knih, které jsem četl a miloval jako kluk, ale svět se za těch skoro padesát let posunul. Když dnes postavíte rádio tak, jak se stavělo „tenkrát“, moc toho k poslouchání nechytíte. Většina vysílání je už FM nebo DAB+ a to je už daleko za „tranzistorovým“ obzorem. Samozřejmě si můžete postavit přijímač s FM i DAB, kde bude anténa, trocha bižuterie a jeden integrovaný obvod, co se o všechno stará, ale zas tam chybí ta tranzistorová romantika.

Nakonec jsem si říkal, že tranzistory jsou „nyní již nestárnoucí“ a vrátit se k nim mohu kdykoli. A když jsem se rozhlížel, co se ve světě hobby elektroniky děje, tak mi došlo, že se musím trošku vrátit ke konceptu první trilogie: základní principy, ukázky zapojení, různé možnosti, novinky, techniky.

Tato kniha je věnovaná věcem, které se objevily v bastlířském světě relativně nedávno. Rozdělil jsem ji do čtyř hlavních částí: software, hardware, moduly a AI, respektive neuronové sítě.

V oblasti software se objevují nové jazyky, které v některých situacích nabourávají téměř absolutní dominanci C/C++. Kromě Pythonu a jeho variant pro MCU jde třeba o skriptovací jazyk Lua, který se hodí pro psaní různých pluginů a uživatelských kódů, nebo o „bare metal“ verzi Rustu, což je jazyk s velmi pomalou učící křivkou, ale na konci jste odměněni velmi bezpečnými programy, protože vás už samotný překladač chrání od konstrukcí, ve kterých by mohlo docházet k problémům. Zařadil jsem i nový jazyk Zig, který je zajímavou alternativou k C a zároveň s ním dokáže skvěle koexistovat. Popíšeme si i principy LLVM, který se stal základem mnoha překladačů.

Hardwarová část obsahuje seznámení s Raspberry Pi Pico 2, s velmi levným MCU CH32V003, se zajímavým duálním Milk-V Duo, a přidal jsem i novou generaci ESP32. Když se na tyto obvody podíváte s odstupem, uvidíte, že je jedna věc spojuje, a to je architektura RISC-V. Tato modulární architektura, odvozená ze známé architektury MIPS, je open-source, takže ji výrobci čipů mohou používat ve svých zařízeních bez nutnosti platit licenční poplatky. To spolu s bohatými možnostmi přizpůsobení z ní dělá zajímavou a perspektivní alternativu například k ARM. Proto jsem velkou část věnoval popisu této architektury.

Ve třetí části se budu věnovat praktickým věcem, u kterých jsem si říkal, že by měly zaznít. Například jak ve vlastních konstrukcích vyřešit napájení přes stále populárnější USB-C, jaké zvolit čidlo a jaké jsou možnosti, a popisu některých projektů, které jsou zajímavé i jako inspirace k vlastní tvorbě.

A poslední část knihy věnuji neuronovým sítím. Je bez debat, že tato technologie bude v dalších letech téměř všude, a díky rozvoji elektroniky bude stále častěji dostupná i pro domácí hobby projekty. Mnoho čipů už dnes nabízí různé „AI akcelerátory“ a koprocesory, proto jsem zařadil tuto sekci. Popíšeme si základní principy neuronových sítí (perceptron, vícevrstvé sítě, backpropagation, učení), jejich použití v mikrokontrolérových zařízeních (kvantizace sítě pro malé procesory), používané knihovny a příklad toho, jak spustit na malém jednočipu vlastní neuronovou síť.

Dlouhé zdrojové kódy k příkladům a užitečné odkazy najdete na https://kbn.elektroniche.cz

1 Chvála bastlení

1 Chvála bastlení

V této knize vzdávám hold domácímu kutilství, zaměřenému na elektroniku. Rukopis dokončuji na podzim roku 2025, a říkám si, že je to docela dobrá příležitost podívat se na „posledních sto let s elektronikou“ očima domácích kutilů. I proto jednotlivé části knihy oddělují historická intermezza, popisující jednotlivá čtvrtstoletí, nejprve s elektronkami, pak s tranzistory, poté s integrovanými obvody, dnes s jednočipovými mikrokontroléry.

Pro podobné činnosti se vžilo označení „bastlení“, které je trochu pejorativní, ale já bych ho rád alespoň pro tuto knihu rehabilitoval.

„To je ale zbastlené,“ říkávali starší a kroutili hlavou nad poličkou, která se mírně nakláněla doleva. V jejich hlase bylo znát zklamání a slovo „zbastlit“ znělo z jejich úst jako obžaloba. Jako když řekneme, že je něco odfláknuté, nedodělané, provizorní. V běžné řeči se bastlení stalo synonymem pro provizorní řešení, hala bala, nakřivo, polorozpadlé, podepřené kusem kartonu a zafixované izolepou.

Jenže pak je tu ještě jiné bastlení. To, které znamená pravý opak. Bastlení jako umění vytvořit něco vlastníma rukama, s minimem prostředků, ale s maximem kreativity. Bastlení jako proces objevování, učení se a radosti z tvoření.

Každý bastlíř to zná, ten moment, kdy se v garáži nebo u pracovního stolu rodí něco nového. Není to proto, že by to nutně potřeboval. Není to proto, že by si to nemohl koupit hotové. Je to proto, že chce pochopit, jak věci fungují. Chce jim dát něco ze sebe. A především si chce užít tvorbu.

Bastlení je jako jazz. Můžete poslouchat dokonale nahranou studiovou skladbu, nebo se můžete posadit k pianinu a začít experimentovat. Bude to zpočátku skřípat, některé tóny nebudou sedět, ale bude to vaše. A časem, s každým dalším pokusem, s každou další hodinou strávenou učením a zkoušením, se začne rodit něco jedinečného.

V době, kdy máme všechno na dosah ruky, kdy stačí několik kliknutí k objednání prakticky čehokoliv, může bastlení působit jako přežitek. Proč trávit hodiny stavbou vlastního teploměru, když si můžeme koupit profesionální meteostanici? Proč pájet vlastní zesilovač, když jsou k dispozici špičkové audio systémy? Proč programovat vlastní domácí automatizaci, když existují hotová řešení?

Odpověď je jednoduchá: Protože bastlení není způsob, jak mít systém pro automatizaci, meteostanici nebo osvětlení. Podstatný je proces, ta zvláštní magie, která se děje, když vezmete do ruky pájku, když poprvé připojíte nový senzor, když váš vlastnoručně napsaný program konečně udělá přesně to, co jste chtěli. Nebo když něco nefunguje a vy musíte přijít na to proč. Bastlení je radost z řešení problémů a uspokojení z překonávání překážek.

Bastlení je také komunitní věc. Spojuje lidi, kteří si navzájem pomáhají, sdílejí své zkušenosti, radí se a inspirují se. Bastlení jsou i večery strávené na internetu hledáním řešení zdánlivě neřešitelného problému, ale i nadšení, když konečně najdete někoho, kdo řešil něco podobného. Je to sdílená radost z úspěchu i společném učení se z neúspěchů.

V době, kdy se věci stávají stále více uzavřenými a nepřístupnými běžnému člověku, kdy jsou naše zařízení černými skříňkami, do kterých nemůžeme nahlédnout, je bastlení aktem svobody. Je to způsob, jak si zachovat kontrolu nad technologiemi, které nás obklopují. Jak jim porozumět, jak je přizpůsobit našim potřebám, jak je učinit opravdu našimi.

Takže až příště někdo řekne, že něco je „zbastlené“, možná je čas se zamyslet. Možná je čas připomenout, že bastlení je ve skutečnosti projevem té nejvyšší péče a lásky k řemeslu. Je to způsob, jak věcem vdechnout duši, jak jim dát příběh. A především je to způsob, jak zůstat zvídavými dětmi v těle dospělých, jak si zachovat radost z objevování a tvoření.

Protože bastlení není jen sestavování elektroniky. Je to svoboda tvořit, odvaha experimentovat a radost z poznávání. Bastlení v nás otevírá to nejlepší, co v nás je: tvořivost, zvídavost a nekonečnou touhu učit se nové věci.

A možná právě proto si zaslouží, abychom ho psali s velkým B.

2 Software

2 Software

2.1 Mikrokontroléry nejsou jen C/C++ aPython

Embedded vývoji (programování vestavěných systémů) tradičně dominuje jazyk C/C++. Je zpovahy nízkoúrovňový amá malou režii. Vsoučasnosti však existují imodernější alternativy zaměřené na vyšší spolehlivost, produktivitu či lepší správu paměti, které můžete použít na platformách jako Arduino (AVR), ESP32 (Xtensa/RISC-V), RP2040 (ARM Cortex-M0+) nebo RP2350. Představíme si dva takové jazyky, Nim aFORTH, zpohledu jejich současného využití vtakových zařízeních.

Vdalších kapitolách si podrobněji probereme jazyky Lua aZig. Jeden znich je vhodný pro aplikace, kde chceme dát možnost uživatelům psát vlastní bezpečné skripty aprovádět je přímo na zařízení, druhý je zajímavou alternativou kC, která přidává nové vlastnosti, ale nerozbíjí kompatibilitu.

Taky se budeme věnovat toolchainům, tedy řetězcům nástrojů, které jsou spolu provázané azpravidla jeden nástroj používá výstup druhého. Typicky jde ořetězec snavazujícími komponentami: překladač do nižšího jazyka → překladač do objektového kódu → spojovací program (linker). Ikdyž se volají třeba jedním příkazem, tak tam stále někde vpozadí je spousta nástrojů…

2.1.1 Nim

Nim (dříve Nimrod) je vyšší programovací jazyk, který přináší do systémového programování syntaktickou lehkost podobnou Pythonu, ale kompiluje se do efektivního nativního kódu (přes C/C++, nebo přímo). Oficiálně je prezentován jako „staticky typovaný kompilovaný systémový programovací jazyk“, který kombinuje osvědčené koncepty zPythonu, Ady aModuly-2. Je to jazyk multiparadigmatický: podporuje imperativní strukturovaný styl, funkcionální prvky (vyšší funkce, lambda výrazy), objektově orientované programování (dědičnost, metody) imetaprogramování pomocí maker.

Nim je navržen sohledem na čitelnost aexpresivitu kódu: syntaxi má podobnou Pythonu (výrazný rys je např. odsazovací bloková struktura místo složených závorek), ale zároveň nabízí nízkoúrovňové konstrukce (např. ukazatele, bitovou aritmetiku), potřebné pro systémové programování. Díky této kombinaci je Nim někdy označován za jazyk, který propojuje skriptovací jazyky avýkonné kompilované jazyky.

Hlavní rysy jazyka

Nim klade důraz na efektivitu kódu aflexibilní správu paměti. Výchozí implementace překládá Nim do jazyka C/C++ (případně do Javascriptu pro web), jedná se tedy otranspiler. Zkompilované programy nevyžadují žádný virtuální stroj ani runtime prostředí nebo knihovny. Výsledkem je nativní samostatný spustitelný soubor.

Nim nabízí několik režimů správy paměti. Tradičně používal garbage collector (nepřetržitý běhový GC, podobně jako Go nebo Java), ovšem novější verze zavedly deterministickou správu paměti pomocí destruktorů apřemisťovací sémantiky, inspirovanou C++ aRustem. To znamená, že vmoderním Nimu (od verze 1.4) můžete využít tzv. ARC (automatic reference counting) nebo ORC, tj. automatické počítání referencí na objekt spředvídatelným uvolňováním objektů ve chvíli, kdy už na ně neexistuje žádný odkaz. Pro MCU je to zásadní, protože Nim umí pracovat zcela bez garbage collectoru. Stačí přepnout režim (--gc:arc nebo --gc:none při kompilaci). Vrežimu --gc:none je odpovědnost za uvolňování paměti plně na programátorovi (podobně jako vC), nicméně díky tomu můžete využít Nim ivsystémech sextrémně malou pamětí. Ale isgarbage collectorem se Nim snaží být šetrný. ARC dealokuje paměť průběžně anemá pauzy, tzv. stop-the-world, jako jiné garbage collectory.

Silnou stránkou Nimu je jeho systém maker. VNimu můžete psát makra, která pracují přímo se syntaktickým stromem (AST) programu. Tím můžete vjazyce definovat nové konstrukce, doménově specifická rozšíření apod., aniž by se měnila syntaxe jazyka (makra vNim využívají stávající syntaxi, která je dostatečně flexibilní). To je výhodné třeba pro generování ovladačů zpopisu periferie. Lze si nadefinovat makra, která na vstupu dostanou popis periferie avygenerují potřebné konstanty apřístupové funkce.

Nim má moderní typový systém sinferenčními schopnostmi (mnohé proměnné nemusí mít explicitně uvedený typ, odvodí se), podporuje tuples (n-tice), generika (šablony) isum types (sjednocené datové typy podobné variantám/algebraickým typům). Například zpracování chyb může Nim řešit jak výjimkami, tak pomocí sum typů (třeba návratová hodnota může být Result[T, Error] podobně jako vRustu).

Nim je velmi dobře kompatibilní sjazyky C/C++. Protože kompiluje do jazyka C, tak je snadné volat zkódu vNim libovolnou funkci vC nebo využít existující knihovnu. Typy můžete přebírat automaticky avolání je bez režie. Můžete přímo zahrnout hlavičkový soubor od výrobce (např. mapu registrů pro specifickou periferii) apřistupovat kněmu zNim.

Vpodstatě platí, že jakákoli platforma, která má překladač C, je podporována Nimem. Nim je vtomto skutečně univerzální. Může generovat kód pro AVR, ARM, ESP32, cokoliv, pokud ktomu existuje odpovídající překladač C.

Runtime aknihovny

Výsledné spustitelné soubory vNimu jsou typicky malé asamostatné. Standardní knihovna je poměrně bohatá (obsahuje například moduly pro datové struktury, formátování textu, síťovou komunikaci atd.), ale vmikrokontroléru by se použila minimálně nebo vůbec. Základní runtime Nimu může obsahovat podporu pro garbage collector (pokud je povolený), případně několik pomocných rutin (např. pro aritmetiku nad velkými celými čísly, pokud jste ji použili). Lze ho však výrazně omezit. Vhodnou konfigurací překladače (pomocí konfiguračních souborů .nims) můžete vypnout generování výpisu zásobníku, odkazů pro ladění atd., aušetřit další paměť. Vextrémním případě (ARC/žádný GC, vypnutý debug) se velikost programu blíží holému kódu vC, potřebuje pouze základní věci jako funkce memset/memcpy (aity si může případně sám vygenerovat).

Existují projekty, napsané vNimu pro osmibitový AVR spouhými 2 kB RAM. Samotné jádro Nimu vnich zabírá jen jednotky kilobajtů. Pro 32bitové MCU (ARM, ESP32) nejsou zdroje tak kritické, takže je možné použít ikomfortnější správu paměti (ARC). Ta přidá nějaký kód navíc (např. destruktory apočítadla referencí ke každému alokovanému objektu), ale stále jde orelativně malou režii vdesítkách kB.

Žádné externí závislosti, kromě standardní knihovny céčka (pokud je využita pro volání malloc atd.) nejsou nutné.

Ekosystém

Nim má aktivní komunitu, ačkoli menší než populárnější jazyky. Distribuován je svlastním balíčkovacím manažerem Nimble, kde můžete najít množství knihoven od webových frameworků po utility. Pro vývoj sMCU není zatím moc specializovaných knihoven, ale existují zajímavé projekty:

• Nesper: balíček pro oficiální ESP-IDF (Espressif IoT Development Framework), ve kterém můžete psát firmware pro ESP32 vNim avyužívat všech funkcí wifi, Bluetooth atd. (viz projekt elcritch/nesper na GitHubu). Nesper demonstruje silnou stránku Nimu, totiž plnou kompatibilitu sexistujícími API vC. Kód vNesperu volá funkce knihovny od Espressif bez jakéhokoli přidaného kódu, jen strochou syntaktického cukru.

• CMSIS/NXP vNimu: díky snadnému importu hlavičkových souborů zC můžete vNim rychle získat definice registrů pro ARM MCU (CMSIS) apracovat snimi. Někteří vývojáři sdíleli .nim soubory vygenerované ze SVD popisů.

• Existuje např. iprojekt využívající Nim vmalé satelitní platformě (CubeSat), kde byl vybrán díky nabízené kombinaci výkonu avysoké abstrakci při analýze dat.

Překladač Nimu je velmi rychlý apodporuje iinterpretaci NimScriptu. To se využívá při konfiguraci. Co se týče IDE, existují pluginy pro VSCode, JetBrains IDE adalší, spodporou syntaxe azákladního doplňování. Kód můžete ladit na úrovni vygenerovaného C, tedy ladit výsledný program pomocí gdb jako běžný program vC (je to málo komfortní, ale možné). Pro běžný vývoj pro mikrokontroléry se Nim integruje například do PlatformIO.

Ekosystém knihoven pro periferie není vNimu centralizovaný. Vývojář typicky využije existující knihovnu vC. Nim se často označuje za „hostovaný jazyk“ (hosted language), to znamená, že se při některých nízkoúrovňových operacích spoléhá na hostitelský jazyk, typicky céčko. To ale vkontextu malých zařízení nevadí, spíš to usnadňuje integraci se stávajícími vývojovými balíky pro jednotlivé platformy.

Celkově je ekosystém Nimu pro vývoj jednočipových aplikací zatím skromný, ale díky kompatibilitě sC není třeba vynalézat kolo. Kdokoli, kdo zvládne zkompilovat projekt vC pro daný mikrokontrolér, může totéž udělat sprojektem vNimu. Nim je tak pro MCU spíše „toolbox“, který využívá existující nástroje. Jeho výhodou je, že není omezen architekturou.

Vhodné typy mikrokontrolérových projektů

Nim se hodí pro projekty, kde je požadována vyšší abstrakce aproduktivita, než nabízí C, ale současně je potřeba zachovat relativně nízkou režii apřístup khardware. Některé scénáře:

• Hobby aIoT projekty na výkonnějších MCU: Například ESP32 má desítky až stovky kB RAM, ato je dostatečné pro běh Nimu sARC. Nim umožní rychle vyvinout aplikaci (např. čidlo sweb serverem) smnohem menším množstvím nutného kódu než při psaní včistém C/C++. Jako programátor můžete využít vyšší datové struktury, generické funkce, serializaci JSON apod. bez velkých starostí opaměť, protože ARC se postará ojejí správné uvolnění.

• Prototypování algoritmů: Nim svou syntaxí podobnou Pythonu láká krychlému psaní algoritmů, které pak běží nativně. Pokud vyvíjíte třeba zpracování signálu nebo řídicí algoritmus pro ARM Cortex-M4, vNimu ho napíšete téměř jako pseudokód, ale výsledek poběží svýkonem C. Makra umožní vkládat ladicí výstupy, generovat opakující se části atd.

• Vestavěné aplikace skomplexní logikou: Stavíte např. datalogger, který komunikuje přes různé protokoly, ukládá data na SD kartu, reaguje na události. VNimu můžete takový firmware strukturovat modulárně (použít objekty pro abstrakce zařízení), využít výjimky pro chybové stavy atd. Zjednoduší to kód oproti C, kde by se muselo ručně kontrolovat každé volání funkce (vNimu lze použít try/except podobně jako vPythonu, ale sminimální režií).

• Multiplatformní logika: Pokud část kódu má běžet ina PC ina MCU (např. nějaká knihovna sdílená mezi firmware asimulačním modelem na PC), tak Nim je výborná volba. Stejný zdrojový kód můžete zkompilovat do JavaScriptu (pro webovou simulaci), do nativní aplikace ido firmware (přes C). Nemusíte psát výrazně odlišný kód pro různá prostředí.

Omezení tu samozřejmě jsou. Nim není ideální pro úplně nejmenší osmibitové mikrokontroléry spár kB paměti, pokud bychom chtěli využívat komfortní funkce (dynamické řetězce, haldy). Sice se dá itam nasadit Nim (spřepínačem --gc:none), ale prakticky byste museli psát kód sice vNimu, ale „jako vC“, takže by výhoda jazyka zčásti padla. Pro 32bitové MCU sdesítkami kB paměti už ale Nim pohodlně funguje.

Další omezení je menší komunita. Na problém možná nenajdete odpověď tak rychle jako uC či Arduina. Také nástroje (ladění, trasování) nejsou tak vyspělé. Neexistuje ekvivalent JTAG debuggeru, který by byl integrovaný přímo sjazykem Nim. Používají se standardní nástroje pro C, ale to může být někdy nepohodlné kvůli odlišnostem.

Ukázka „Hello World“

Připomeňme si, že Nim můžete spustit ina Arduino UNO (ATmega328P), které má pouhých 2 kB RAM. Kompilátor to zvládne díky možnosti vypnout runtime apřizpůsobit se dané architektuře. Konfigurační soubor pro překlad může vypadat např. takto:

# config.nims– nastavení proAVR

switch("os", "standalone") # žádný OS

switch("cpu", "avr") # cílová CPU architektura

switch("gc", "none") # žádný garbage collector

switch("stackTrace", "off") # nevkládat stack trace info

switch("lineTrace", "off") # nevkládat debug info ořádcích

switch("passC", "-mmcu=atmega328p") # parametry proavr-gcc (překlad proMCU)

switch("passL", "-mmcu=atmega328p") # parametry prolinker

Takto zajistíme, že Nim vygeneruje C kód pro AVR apoužije pro kompilaci AVR-GCC. Samotný kód vNimu pak může přímo manipulovat registry MCU. Např. rozblikání LED na pinu 13 (Arduino UNO) by šlo takto:

const DDRB* = cast[ptr uint8](0x24) # Data Direction Register B (ATmega328P)

const PORTB* = cast[ptr uint8](0x25) # Port B Data Register

proc delay_ms*(ms: int) =

## jednoduchá prodleva pomocí smyčky

for iin 0 ..< ms*1000: discard # (na16MHz CPU ~ orientační čekání)

# Inicializace– nastav PB5 (arduino pin13) jako výstup

DDRB[] = DDRB[] or 0b0010_0000

while true:

PORTB[] = PORTB[] xor 0b0010_0000 # přepni bit LED

delay_ms(500)

Výše uvedený kód je ilustrační. Ukazuje přístup kpaměťovým adresám (pomocí cast[ptr uint8]) anekonečnou smyčku blikání. Přeložený program můžete nahrát do Arduina standardním postupem (např. pomocí avr-objcopy převést na .hex anahrát pomocí avrdude). Je tu hezky vidět, že Nim je syntakticky mnohem stručnější než ekvivalent vC (není třeba psát datové typy uliterálů, cyklus lze udělat pythonovským zápisem atd.), apřitom výsledek po překladu je velmi podobný strojovému kódu.

Dostupná literatura aonline zdroje

• Oficiální příručka Nim: dokumentace na nim-lang.org obsahuje manuál popisující jazyk astandardní knihovnu. Pro vývoj elektroniky jsou důležité hlavně kapitoly osprávě paměti aintegraci sC.

• Kniha „Nim in Action“ (Dominik Picheta, Manning 2017): úvod do jazyka apraktické projekty. Ikdyž není zaměřena přímo na MCU, tak pokrývá podrobně volání kódu vC avýkonové aspekty.

• Nim community forum (forum.nim-lang.org): aktivní fórum, kde najdete vlákna opoužití Nim na ESP32, Arduino adalších. Často tam přispívají samotní tvůrci jazyka.

• Článek „nim for embedded software development“ (na Dev.to): zkušenosti vývojáře spoužitím Nim pro MCU, včetně ukázky nastavení pro AVR.

• Repozitář Awesome Nim: komunitní seznam knihoven aprojektů (GitHub nim-lang/awesome-nim), který zmiňuje ivyužití Nimu pro elektroniku.

2.1.2 Forth

Forth je nestárnoucí klasika mezi programovacími jazyky pro systémy smalými procesory. Jde ozásobníkově orientovaný jazyk azároveň jednoduché interaktivní vývojové prostředí, který navrhl v60. letech Chuck Moore akterý byl hojně využíván v70. až 90. letech vprůmyslových vestavěných aplikacích. Paradigma Forthu je ojedinělé: je to konkatenativní (skládající) jazyk, kde se program skládá zposloupnosti slov (tokenů), které operují nad společným datovým zásobníkem. Forth nezná klasické proměnné adatové typy vběžném smyslu (vše jsou jen čísla na zásobníku), nemá syntaktická omezení (řídicí struktury používají speciální slova). Můžeme ho označit za procedurální jazyk bez kontroly typů (přesto se dá ve Forthu definovat např. oddělený zásobník pro desetinná čísla atd., ale to je implementační detail).

Důležitou vlastností je, že Forth typicky běží sinteraktivním interpretem, je tedy zároveň vývojovým prostředím (IDE), kde uživatel může za běhu systému zadávat příkazy, zkoušet funkce atd.

Forth je výrazně odlišný od mainstreamových jazyků. Je postaven na RPN (obrácená polská notace, reverse polish notation), kde se zapisují nejprve operandy, aza ně operace. Všechny operace berou parametry ze zásobníku avýsledek ukládají zpět. Např. součet 2 a3 se zapíše jako 2 3 + (kde „plus“ je slovo, které vezme dvě čísla ze zásobníku, sečte avýsledek uloží opět na zásobník).

Ve Forthu neexistuje syntaktický rozdíl mezi „jazykem“ a„vestavěnými funkcemi“, protože celé prostředí Forthu je definováno souborem slov (včetně řídicích struktur jako IF..ELSE..THEN, smyček DO..LOOP atd.). Uživatel může za běhu definovat nová slova (vlastní funkce), ata se okamžitě stávají součástí jazyka. Forth je tedy extrémně flexibilní arozšiřitelný; zkušený programátor si může přizpůsobit celé prostředí podle potřeby. Zjiných jazyků má blízko snad jen kPostScriptu (který je také zásobníkový) nebo modernějším jazykům jako Factor, ale vmnoha ohledech je Forth skutečně unikátní.

Hlavní rysy jazyka

• Interaktivnost: Forth typicky běží na cílovém zařízení jako interpret, ke kterému je možné se připojit (např. přes sériovou linku) azadávat příkazy. Okamžitě po zadání příkazu je vidět výsledek. To urychluje vývoj aladění; nepotřebujete plný debugger, stačí konzole. Proto se Forth používá často ijako zabudovaný monitor vprůmyslových zařízeních.

• Kompilace ainterpretace: Forth používá tzv. threaded code, kde se nové slovo (funkce) kompiluje jako sekvence volání jiných slov. Kompilace je velmi rychlá aprobíhá přímo na zařízení (tzv. self-hosted). Zpohledu uživatele se střídají dva režimy: interpretation state (příkazy se ihned vykonávají) acompile state (příkazy se místo vykonání kompilují do definice nového slova). Přepnutí do compile state nastane po zadání slova : (dvojtečka, tedy začátek definice slova) azpět do interpretace se přejde po ; (středník, konec definice). Tato dualita dává Forthu schopnost definovat slova za běhu ahned je volat.

• Extrémní efektivita anízké nároky: Implementace Forthu jsou velmi malé. Jednoduché jádro Forthu (interpreter + kompilátor + základní slovník) se vejde do několika kilobajtů paměti. Například AmForth pro mikrokontroléry AVR8 potřebuje jen ~8‒12 KB flash a~200 bajtů RAM pro běh základního systému. Na druhou stranu Forth nemá komfortní automatickou správu paměti, vše musíte udělat ručně (ale vmalých MCU to nevadí, tam paměťovou haldu často nepotřebujete vůbec).

• Jednoduchost běhového prostředí: Klasický Forth nepotřebuje žádný operační systém ani volání služeb. Může běžet přímo od resetu MCU jako holý firmware. Implementuje si často ivlastní miniaturní operační systém (např. jednoduchý plánovač úloh, souborový systém vpaměti atd.) Mnohé implementace Forthu také podporují multitasking (kooperativní nebo preemptivní) uvnitř sebe sama, ibez podpory ze strany OS. To znamená, že jediné, co musíte na MCU zajistit, je nastavení ukazatele zásobníku askok na start Forth VM.

• Přenositelnost astandardizace: Forth byl formalizován vANSI standardu (ANS Forth 1994, později Forth 200x). Díky tomu existuje množství implementací, které jsou do velké míry kompatibilní. Programy napsané vmezích standardu půjde zprovoznit na různých systémech sminimem úprav. Pro MCU se ale často používají podstandardní implementace (např. minimální jádro bez některých složitých slov kvůli úspoře paměti).

Zhlediska programování jednočipových zařízení je Forth atraktivní tím, že je to samostatné prostředí: když do zařízení nahrajete Forth, získáte tím interaktivní konzoli, pomocí níž můžete zařízení řídit iprogramovat. Historicky se Forth využíval třeba vastronomii (ovládání teleskopů), průmyslové automatizaci, dopravních systémech atd., kde technik mohl přes terminál komunikovat se zařízením amonitorovat jeho stav vreálném čase přímo pomocí slov ve Forthu. Mohl si případně rovnou nadefinovat nová, vyzkoušet je aupravit tak fungování celého stroje. Například Open Firmware (boot ROM standard ustanic Sun, Apple atd.) byl postaven na Forthu. Uživatel mohl při startu vstoupit do prostředí Forthu apracovat přímo shardware.

Runtime aknihovny

Forth má minimální nároky. Pojem „runtime“ se zde překrývá s„celým jazykem“, protože interpret Forthu je zároveň runtime. Jen pár kilobajtů FLASH astovky bajtů RAM stačí na plně funkční systém sinterpretem. Například Mecrisp-Stellaris, populární Forth pro ARM Cortex-M, má velikost kolem 20 kB, ato včetně řady užitečných rozšíření (matematická slova, assembler atd.). Implementace FlashForth či amForth pro AVR se vejdou do 8 KB. Díky tomu není problém nasadit Forth ina malé 8bitové MCU. Forth nepotřebuje žádné externí knihovny, veškerá funkcionalita je buď vzákladním slovníku, nebo se dá dohrát přímo ve Forthu.

Minimalistická povaha Forthu znamená ale absenci některých komfortních prvků. Například nemá vestavěný debugger akladění se používá právě interaktivnost (můžete si ručně procházet zásobník azjišťovat hodnoty). Neexistuje ochrana paměti, takže špatně napsané slovo může přepsat libovolné místo vpaměti zařízení. Také neexistuje standardní knihovna funkcí, jako je vC. Pro cokoliv složitějšího si programátor musí buď napsat vlastní kód, nebo zavolat cizí kód (pokud to implementace dovolí). Některé moderní Forthy však integrují ivolání C funkcí či inline assembler pro kritické úlohy.

Ekosystém

Forth jako takový nemá centralizovaný ekosystém knihoven (žádný „Forth Package Manager“). Výměna kódu probíhá spíše komunitně. Existují sbírky užitečných rutin (např. implementace protokolu I2C včistém Forthu, ovladače displejů atd.), ale ne vpodobě snadno instalovatelných balíčků. Vpraxi si mnoho programátorů píše značnou část kódu na míru aplikaci.

Co se týče vývojového prostředí, tak platí, že typický pracovní postup je připojit se terminálem kzařízení, vtextovém editoru mít připravený zdrojový kód (sada definovaných slov), aten pak poslat přes terminál do zařízení kinterpretaci. Některé implementace (např. Mecrisp) podporují iuložení zdrojového textu vpaměti zařízení pro budoucí editaci. Jinak je možné programy do zařízení nahrávat ibinárně, tzv. cross-compiling, kdy kód ve Forthu zkompiluje hostitelský počítač avýsledný kód se nahraje do zařízení. Tato metoda je méně interaktivní, ale vhodná pro produkční nasazení (výsledkem je firmware, který už neobsahuje interaktivní konzoli, pokud nechceme).

Existuje mnoho různých implementací Forthu pro mikrokontroléry:

• amForth– open-source Forth pro AVR (ATmega), běží přímo vMCU, nabízí ipřerušení amultitasking.

• Mecrisp-Stellaris– moderní Forth pro ARM Cortex-M, velmi populární díky výkonnosti aaktivnímu vývoji. Podporuje iARMy jako MSP430 amá iRISC-Vvarianty (Mecrisp-Quintus).

• FlashForth– další Forth pro AVR aPIC.

• eforth– jedná se spíše okoncept minimálního Forthu, který byl portován na mnoho architektur (včetně 8051, Z80 atd.).

• Komerční verze Forthu– firmy jako Forth, Inc. či MPE nabízí komerční implementace Forthu spodporou pro konkrétní platformy (např. Green Hills nabízí Forth pro ARM sintegrací sjejich toolchainem apod.). Ty často přidávají iintegraci sC (možnost volat C funkce zForthu anaopak).

Za zmínku stojí, že Chuck Moore navrhl ispecializované procesory optimalizované pro Forth (např. novější čipy GreenArrays). Tyto procesory prakticky vykonávají Forthovská slova vhardwaru.

Kromě terminálu nepotřebujete mnoho. Pro zvýšení komfortu existují editory, které dokážou posílat slova do zařízení klávesovou zkratkou, zvýrazňují syntaxi atd., ale vzásadě postačí libovolný seriálový terminál (TeraTerm, screen, minicom…)

Vhodné typy projektů smikrokontroléry

Forth byl vminulosti hojně využíván vcelé řadě projektů, především tam, kde bylo nutné rychle aefektivně komunikovat shardwarem azároveň mít možnost ladit software vreálném čase. Typickým příkladem jsou laboratorní aprůmyslová zařízení, například řízení teleskopů, spektrometrů nebo výrobních strojů. Inženýři zde mohli psát Forthové skripty pro konfiguraci či kalibraci zařízení aokamžitě je spouštět. Pokud bylo třeba provést změnu, stačilo upravit kód na místě anahrát ho za běhu, často bez nutnosti restartovat zařízení. Tato úroveň flexibility je uklasického postupu, kdy se kód píše vC, následně překládá anahrává do zařízení, prakticky nedosažitelná.

Forth se osvědčil ive vestavěných řídicích systémech, kde se často mění požadavky. Díky němu bylo možné program upravovat přímo vterénu. Například uautonomních robotů bylo možné nahrát nový navigační algoritmus přímo do běžícího systému bez zásahu do bootloaderu. Ve 20. století stímto přístupem experimentovala iNASA, když v80. letech zkoušela skriptování palubních počítačů pomocí Forthu právě kvůli možnosti úprav „za pochodu“. Přesto se ve větším měřítku prosadily spíše jiné jazyky, například interpretovaný BASIC.

Další oblastí, kde Forth nacházel uplatnění, byly projekty sextrémně omezenou pamětí. Například na osmibitových mikrokontrolérech bylo díky Forthu možné vytvořit interaktivní firmware, protože plnohodnotný interpret Forthu se vejde už do 4 kB flash paměti. Naproti tomu interpreter Pythonu se do takto malého prostoru nevejde. Proto se Forth dříve často objevoval vhobby projektech, zatímco dnes tuto roli na výkonnějších MCU částečně převzal MicroPython.

Forth byl aje také cenným nástrojem pro vzdělávací účely aexperimentování. Díky dostupnosti implementací pro PC, jako je GForth, si studenti mohou snadno vyzkoušet návrh jazykových konstrukcí alépe pochopit fungování procesoru. Při programování MCU zase nutí Forth programátora uvažovat nad optimalizací aefektivním využitím paměti, protože ruční správa zásobníku vyžaduje důkladné přemýšlení otom, jaké hodnoty se kde nachází.

Na druhou stranu jsou programy ve Forthu často obtížně srozumitelné (tzv. „write-only language“), pokud nejsou dobře okomentované. Údržba velkých projektů ve Forthu je náročná, zejména pro nové členy týmu. Dnes, vdobě velkých týmů amnožství knihoven, je Forth marginální avětšina vývojářů preferuje C/C++ ipřes jejich nevýhody, protože ekosystém aknow-how jsou rozšířenější. Další limit Forthu je výkon. Ikdyž je celkově velmi úsporný, samotná interpretace slov přidává režii (tradiční nepřímá skoková interpretace). Na moderních MCU to obvykle nevadí (200 ns na instrukci není problém, když cyklus MCU je ~10 ns), ale pro hrubý výpočetní výkon (třeba zpracování signálu) se Forth nepoužívá, tam nastupuje spíše C soptimalizacemi vassembleru.

Najdete implementaci Forthu téměř pro každý mainstreamový MCU. Například pro Arduino UNO (ATmega328) je amForth či FlashForth, pro ESP32 existují porty Mecrisp (běží na ESP32-C3 RISC-V, adokonce ina původním Xtensa jádru vrežimu spolupráce sFreeRTOS), pro RP2040 (Raspberry Pico) byl portován Mecrisp-Stellaris. Mnohé implementace jsou open-source avolně dostupné, takže omezení je spíše vmenší komunitě (například vČR se Forthu věnuje jen hrstka nadšenců).

Ukázka „Hello World“

Blikání LED je tradiční první krok uvětšiny jazyků pro MCU. UForthu se jím navíc demonstruje interaktivita jazyka. Představme si například, že máme Arduino snahraným Forthem (FlashForth). Po spuštění se vterminálu objeví prompt, např. ok> (označuje, že systém je připraven přijímat povely).

Nejprve je třeba nastavit pin LED (Arduino UNO pin 13, což je port B5) jako výstup. Ve Forthu to jde buď použitím již definovaných slov, nebo zapsáním do registrů. FlashForth poskytuje slova jako DDRB aPORTB pro přístup kregistrům portu B. Takže bychom mohli zadat:

binary \ přepni dobinární soustavy pročitelnost bitů

00100000 DDRB c! \ nastav bit 5 vregistru DDRB (datový směr) - tím je PB5 výstup

Systém odpoví ok, pokud vše proběhlo vpořádku. Teď můžeme ručně rozsvítit azhasnout LED:

00100000 PORTB c! \ nastavení bitu 5 vPORTB na1 (LED on)

00000000 PORTB c! \ smazání bitu 5

Ve FlashForth je dokonce definováno slovo bis! (bit set) abic! (bit clear) pro nastavování jednotlivých bitů, takže by šlo psát PORTB 5 bis! pro rozsvícení aPORTB 5 bic! pro zhasnutí.

Teď vytvoříme nové slovo, které bude periodicky blikat LEDkou:

: blink \ definice slova blink

begin

PORTB 5 bis! 500 ms \ zapni LED, čekej 500 ms

PORTB 5 bic! 500 ms \ vypni LED, čekej 500 ms

again ; \ opakuj donekonečna

Po zadání této definice interpret odpoví ok. Nyní stačí spustit blink aLED začne blikat. Program běží uvnitř systému adá se kdykoli přerušit (např. klávesou Ctrl+C vněkterých implementacích) aupravit definici slova blink za běhu.

Zpříkladu je vidět, že Forth dovoluje velmi rychle iterovat: můžeme zkusit různé periody, můžeme definovat třeba : on PORTB 5 bis! ; a: off PORTB 5 bic! ; pro pohodlné ruční ovládání LED atd. Vše bez nutnosti překládat firmware externím překladačem.

Dostupná literatura aonline zdroje

• Knihy: Starting Forth (Leo Brodie)– klasická kniha (1981) výborně vysvětlující základy Forthu zábavnou formou, dostupná online jako PDF. Thinking Forth je navazující kniha stejného autora ofilozofii návrhu programů ve Forthu (jak psát kód, který je srozumitelný audržovatelný). Tyto knihy jsou idnes relevantní aoblíbené.

• Standardy adokumentace: ANS Forth 2012 standard– definice jazykových slov, ke stažení zwebu forth-standard.org. Dále dokumentace konkrétních implementací: např. Mecrisp-Stellaris manual (popis rozšíření Mecrisp Forth), FlashForth User Guide atd.

• Komunitní weby afóra: comp.lang.forth (Usenet, dnes dostupný např. přes Google Groups) je historické diskusní fórum smnožstvím informací. Existuje Forth Interest Group (FIG) ajejí publikace– FIG měl web forth.org, kde najdete archiv materiálů. Také subreddit r/Forth sdružuje nadšence (ikdyž malý).

• Moderní tutoriály: Některé blogy (wellys.com) popisují krok za krokem, jak zprovoznit Forth na zařízení ajak psát programy.

• Konference aworkshopy: Mezinárodní konference EuroForth sdružuje akademiky iprůmysl kolem Forthu ajejí sborníky jsou volně dostupné. Občasné workshopy (např. ForthDays) jsou někdy zveřejněné online.

2.1.3 Zig

Nejspíš jste slyšeli oRustu ajeho přísném správci paměti, možná znáte Go sjeho jednoduchostí. Ale co kdyby existoval jazyk, který má rychlost C, bezpečnost moderního jazyka, apřitom se nezříká nízkoúrovňové kontroly? Přesně to je Zig: pragmatický jazyk navržený tak, aby vylepšil C, aniž by ho úplně nahradil.

Zig vznikl kolem roku 2015 jako projekt Andrewa Kelleyho, který chtěl jazyk jednoduchý na pochopení, rychlý na spuštění ahlavně spolehlivý. Na rozdíl od Rustu, který vás nutí myslet vurčitém paradigmatu, zůstává Zig blízko hardwaru adává vám kontrolu, když ji potřebujete. Přitom ale odstraňuje některé nebezpečné prvky céčka, jako jsou nedefinované chování nebo skryté alokace paměti.

Pro vývoj elektroniky je Zig zajímavý zejména proto, že nabízí kompilaci pro malé mikrokontroléry bez zbytečného balastu vběhovém kódu. Žádný garbage collector, žádné skryté alokace, ale přesto má bezpečnější práci spamětí než čisté C. Navíc má vynikající interoperabilitu scéčkovým kódem, takže můžete postupně přecházet nebo kombinovat oba jazyky.

Instalace aprvní kroky

Zig si stáhnete zoficiálních stránek jako jediný statický binární soubor. Na Linuxu amacOS ho rozbalíte do libovolného adresáře apřidáte do PATH. Na Windows funguje podobně, nepotřebujete žádný složitý instalátor, žádné závislosti.

# Stažení arozbalení

wget https://ziglang.org/download/...

tar -xf zig-...

export PATH=$PATH:/path/to/zig

První program vypadá očekávatelně:

const std = @import("std");

pub fn main() !void {

std.debug.print("Ahoj, světe!\n", .{});

}

Uložte jako hello.zig aspusťte příkazem zig run hello.zig. Zig zkompiluje aspustí program vjediném kroku. Pro finální sestavení použijete zig build-exe hello.zig.

Vtomto příkladu vidíte už teď několik zajímavostí. Funkce main má návratový typ !void– to znamená, že může buď nic nevrátit, nebo skončit schybou. Symbol @import je vestavěná funkce (poznáte je podle @), která importuje modul. Astd.debug.print používá formátovací řetězec podobný printf, ale bezpečnější.

Základní rozdíly proti C

Zig se na první pohled podobá C, ale pod povrchem jsou významné rozdíly. Začneme utoho nejviditelnějšího, totiž usyntaxe proměnných afunkcí.

const x: i32 = 42; // konstanta, typ se může vynechat

var y: i32 = undefined; // proměnná, počáteční hodnota

var z= @as(f32, 3.14); // explicitní přetypování

fn fibonacci(n: u32) u32 {

if (n <= 1) return n;

return fibonacci(n - 1) + fibonacci(n - 2);

}

Klíčové slovo const znamená skutečnou konstantu, tedy hodnotu, kterou nemůžete změnit. Slovo var označuje proměnnou. Podobně undefined říká, že hodnotu zatím neznáte anastavíte ji později. Ale musíte ji nastavit před prvním použitím, jinak kompilátor protestuje.

Typy píšete za dvojtečku, ale často je můžete vynechat. Zig má explicitní typy jako i32 (32bitové signed), u8 (8bitové unsigned) nebo f64 (64bitové float).

Funkce se definují pomocí fn, návratový typ píšete na konec deklarace. Pokud funkce nic nevrací, použijete void. Pokud může skončit schybou, přidáte ! před typ, jako !void nebo !i32.

Práce spamětí

Jedna znejvětších výhod Zigu oproti C je explicitní práce spamětí. Nemá žádné skryté alokace, ale přitom je bezpečnější než malloc afree.

const std = @import("std");

const Allocator = std.mem.Allocator;

fn prace_s_pameti(allocator: Allocator) !void {

// Alokace pole

const pole = try allocator.alloc(i32, 100);

defer allocator.free(pole);

// Naplnění daty

for (pole) |*prvek, index| {

prvek.* = @intCast(i32, index);

}

// Dynamický seznam

var seznam = std.ArrayList(i32).init(allocator);

defer seznam.deinit();

try seznam.append(42);

try seznam.append(24);

}

Všimněte si klíčového slova defer. Říká „proveď tohle na konci funkce“. Je to podobné jako finally vjiných jazycích. Napíšete defer allocator.free(pole) hned po alokaci anemusíte myslet na uvolnění paměti ve všech možných cestách zfunkce.

Další důležitá věc: všechny alokace jsou explicitní. Předáváte allocator jako parametr, takže vždy vidíte, kde se paměť alokuje. Pro MCU můžete použít statický alokátor nebo alokátor sfixní velikostí. Nečeká vás tak žádné překvapení svyčerpáním haldy.

Chyby ajejich zachytávání

Zig má elegantní systém pro práci schybami. Místo výjimek nebo návratových kódů používá typ union soperátorem !.

const FileError = error{

NotFound,

PermissionDenied,

OutOfMemory,

};

fn otevri_soubor(jmeno: []const u8) FileError!u32 {

// Simulace chyby

if (jmeno.len == 0) {

return FileError.NotFound;

}

return 42; // handle souboru

}

fn pouzij_soubor() !void {

const handle = try otevri_soubor("test.txt");

// Pokračování jen přiúspěchu

std.debug.print("Soubor otevřen: {}\n", .{handle});

}

Klíčové slovo try automaticky propaguje chybu nahoru. Pokud otevri_soubor vrátí chybu, funkce pouzij_soubor okamžitě skončí stou samou chybou. Je to podobné jako operátor ? (otazník) vRustu, ale jasnější na čtení.

Můžete také zachytit konkrétní chyby:

fn bezpecne_otevri(jmeno: []const u8) void {

const handle = otevri_soubor(jmeno) catch |err| switch (err) {

FileError.NotFound => {

std.debug.print("Soubor nenalezen\n", .{});

return;

},

else => {

std.debug.print("Jiná chyba: {}\n", .{err});

return;

},

};

std.debug.print("Úspěch: {}\n", .{handle});

}

Tento systém vás nutí explicitně řešit chyby, ale není tak striktní jako Rust. Můžete použít catch unreachable, pokud víte, že chyba nemůže nastat.

Generické programování

Zig má zajímavý přístup ke generickému programování. Místo šablon, jako má C++, používá comptime, tj. kód, který se vyhodnotí během kompilace.

fn maximum(comptime T: type, a: T, b: T) T {

return if (a> b) aelse b;

}

fn vytvor_pole(comptime T: type, comptime velikost: usize) [velikost]T {

return [_]T{0} ** velikost;

}

// Použití

const max_int = maximum(i32, 10, 20);

const max_float = maximum(f32, 1.5, 2.7);

const pole_cisel = vytvor_pole(i32, 100);

Klíčové slovo comptime říká, že parametr nebo proměnná se vyhodnotí během kompilace. Zajímavý je type, to je speciální typ pro typy, který můžete předávat jako parametr.

Comptime je ale mnohem mocnější nástroj. Můžete například generovat struktury nebo funkce na základě konfigurace:

fn ConfigStruct(comptime config: Config) type {

return struct {

hodnota: if (config.use_float) f32 else i32,

pub fn nova_hodnota(self: *@This(), val: @TypeOf(self.hodnota)) void {

self.hodnota = val;

}

};

}

Propojení sC

Jednou znejvětších výhod Zigu je bezproblémová práce skódem vC. Můžete volat funkce, napsané vC, používat struktury zC, adokonce kompilovat céčkové zdrojové kódy.

// Import C hlavičky

const c = @cImport({

@cInclude("stdio.h");

@cInclude("stdlib.h");

});

pub fn main() !void {

// Volání C funkce

_ = c.printf("Hello zC: %d\n", 42);

// C malloc/free

const ptr = c.malloc(100);

defer c.free(ptr);

}

@cImport automaticky parsuje hlavičky *.h avytváří takzvané bindings pro Zig. Všechny funkce akonstanty ze zdrojových kódů ahlaviček vC jsou dostupné pod jmenným prostorem c. Typy se automaticky převádí, takže int zC je c_int vZigu.

Můžete také exportovat funkce vZigu pro C:

export fn zig_funkce(x: c_int) c_int {

return x * 2;

}

// Vhlavičce C:

// int zig_funkce(int x);

Klíčové slovo export vytvoří funkci, kompatibilní svolací konvencí céčka. To je užitečné pro postupnou migraci zC nebo pro vytváření knihoven.

Zig aMCU

Zig kompiluje do malého aefektivního kódu bez zbytečného kódu navíc. Při vývoji pro mikrokontroléry to rozhodně oceníte. Podívejme se na příklad pro ESP32-C3.

Nejprve vytvoříme soubor build.zig:

const std = @import("std");

pub fn build(b: *std.build.Builder) void {

const target = std.zig.CrossTarget{

.cpu_arch = .riscv32,

.os_tag = .freestanding,

.cpu_model = .{ .explicit = &std.Target.riscv.cpu.generic_rv32 },

};

const exe = b.addExecutable("esp32_app", "src/main.zig");

exe.setTarget(target);

exe.setOutputDir("build");

exe.install();

}

Pak hlavní kód:

const std = @import("std");

// Minimální obsluha kritické chyby

pub fn panic(msg: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {

_ = msg;

_ = stack_trace;

while (true) {}

}

// GPIO registry proESP32-C3

const GPIO_BASE: u32 = 0x60004000;

const GPIO_OUT_REG: *volatile u32 = @ptrFromInt(GPIO_BASE + 0x04);

const GPIO_ENABLE_REG: *volatile u32 = @ptrFromInt(GPIO_BASE + 0x20);

pub fn main() !void {

// Aktivace GPIO pin 8 (vestavěná LED)

GPIO_ENABLE_REG.* |= (1 << 8);

// Blikání LED

while (true) {

GPIO_OUT_REG.* |= (1 << 8); // LED on

delay_ms(500);

GPIO_OUT_REG.* &= ~(1 << 8); // LED off

delay_ms(500);

}

}

fn delay_ms(ms: u32) void {

// Jednoduchá smyčka (proreálné nasazení použijte timer)

var i: u32 = 0;

while (i< ms * 1000) : (i+= 1) {

asm volatile ("nop");

}

}

Všimněte si volatile pointerů: říkají kompilátoru, že hodnota se může změnit zvenčí, takže nesmí optimalizovat přístupy aspoléhat na to, že „hodnotu už zná“. @ptrFromInt převádí celé číslo na pointer bezpečným způsobem.

Pro RP2350 sjádrem ARM změníte jen target (asamozřejmě konkrétní práci sGPIO):

const target = std.zig.CrossTarget{

.cpu_arch = .arm,

.os_tag = .freestanding,

.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m33 },

};

Pokročilé funkce

Zig má několik užitečných pokročilých funkcí. Jedna znejpraktičtějších jsou struktury packed struct pro práci sregistry:

const StatusRegister = packed struct {

enable: bool,

ready: bool,

error: bool,

_reserved: u5,

mode: u8,

pub fn from_u16(value: u16) StatusRegister {

return @bitCast(StatusRegister, value);

}

};

// Použití

const reg_value: u16 = read_register(0x100);

const status = StatusRegister.from_u16(reg_value);

if (status.ready and !status.error) {

// Pokračování...

}

Konstrukce packed struct zaručuje konkrétní rozložení vpaměti. @bitCast bezpečně převádí mezi typy stejné velikosti.

Další užitečná funkce jsou anonymous structs pro dočasné struktury:

fn nastav_config(config: struct { frequency: u32, enable: bool }) void {

// Implementace...

}

// Volání

nastav_config(.{ .frequency = 1000, .enable = true });

Využijete ivektorové operace pro rychlé zpracování dat:

fn zpracuj_data(vstup: []const f32, vystup: []f32) void {

std.debug.assert(vstup.len == vystup.len);

const Vec4 = @Vector(4, f32);

var i: usize = 0;

while (i+ 4 <= vstup.len) : (i+= 4) {

const chunk: Vec4 = vstup[i..i+4][0..4].*;

const result = chunk * @splat(4, @as(f32, 2.0));

vystup[i..i+4][0..4].* = result;

}

// Zpracování zbytku pojednom

while (i< vstup.len) : (i+= 1) {

vystup[i] = vstup[i] * 2.0;

}

}

@Vector vytváří vektory pro SIMD, které kompiler automaticky přeloží na vektorové instrukce procesoru, pokud jsou kdispozici.

Testování aladění

Zig má vestavěnou podporu pro testování. Testy píšete přímo do zdrojového kódu:

const std = @import("std");

const testing = std.testing;

fn factorial(n: u32) u32 {

if (n <= 1) return 1;

return n * factorial(n - 1);

}

test "factorial test" {

try testing.expect(factorial(0) == 1);

try testing.expect(factorial(1) == 1);

try testing.expect(factorial(5) == 120);

}

test "memory allocation" {

var gpa = std.heap.GeneralPurposeAllocator(.{}){};

defer _ = gpa.deinit();

const allocator = gpa.allocator();

const array = try allocator.alloc(i32, 10);

defer allocator.free(array);

try testing.expect(array.len == 10);

}

Testy spustíte příkazem zig test soubor.zig. Zig automaticky najde všechny funkce začínající na test aspustí je.

Pro ladění můžete použít std.debug.print nebo @breakpoint(). VMCU ale často používáte jen UART nebo RTT pro výstup ladících informací.

Proč Zig namikrokontroléru?

Hlavní důvody jsou jasné: dostáváte rychlost akontrolu C sbezpečností moderního jazyka. Interoperabilita sC znamená, že můžete postupně migrovat existující projekty nebo používat stávající knihovny. Comptime systém dovoluje psát generický kód. Aexplicitní správa chyb vás nutí myslet na krajní situace.

2.2 Lua: skriptování promikrokontroléry

Existuje ověřený anenáročný nástroj, ato je právě Lua.

2.2.1 Úvod doLua

Kdy vmikrokontroléru použít C/C++ akdy Lua?

2.2.2 Základy programování vLua

První kroky: Instalace aspuštění Lua interpretu

winget search lua

winget install DEVCOM.Lua

lua

Měli byste vidět něco jako:

>

print("Ahoj, světe!")

Proměnné adatové typy

end

Operátory

Řízení toku programu

Podmínka

else

end

Cykly

Tabulky

Vytváření tabulek

Asociativní tabulky (mapy/slovníky)

}

Práce stabulkami

Procházení tabulky

Tabulky jako objekty avnořené tabulky

Praktický příklad smikrokontrolérem

Funkce

Definice funkcí

Vícenásobné návratové hodnoty

Praktický příklad

Anonymní funkce aclosures

Praktický příklad

Variadické funkce (sproměnným počtem argumentů)

Ošetřování chyb vLua

Ošetření chyby

Rozdíl mezipcall axpcall

Co se děje, když chráněná hranice chybí

Konstrukce assert, návratové kódy avlastní protokol

Moduly abalíčky

Vytvoření jednoduchého modulu

Použití modulu

Praktický příklad

2.2.3 Lua naESP32 adalších platformách

Příprava prostředí: Jak dostat Lua domikrokontroléru

Rychlý start sArduino IDE

2.2.4 Komunikace meziC/C++ aLua

Volání funkcí C/C++ zLua

Princip práce se zásobníkem Lua

Volání funkcí vLua zC/C++

Obsluha chyb: lua_pcall, luaL_error a„dlouhý skok“

Bezpečný vstupní bod vLua

Bezpečné volání cizích callbacků

Shrnutí

Rozdíl mezilua_ aluaL_

Vyzvedávání hodnot ze zásobníku

Zapisování hodnot dozásobníku

Registrace knihovny funkcí

Reference aregistry

Chybová hlášení

Shrnutí podle účelu

2.2.5 Optimalizace apraktické tipy

Každý bajt se počítá

Minimalizujte vytváření nových objektů vesmyčkách

Správa paměti agarbage collection (GC)

Jak zjistit, co je pomalé

Základní bezpečnost

Testování aladění

2.2.6.Práce se souborovým systémem: Ukládání skriptů akonfigurací