Na počátku všeho byl bit. Všechno povstalo skrze něj. V něm byl život a ten život byl světlem firmwarů. – Bible bastlířská, verš první.
V dnešním pokračování seriálu o programování elektroniky se vrátíme na úplný začátek. Namísto psaní kódu se podíváme na to, jak ve své podstatě vypadá několik jednoduchých i docela komplexních digitálních signálů, které ve svých programech vytváří každý bastlíř.
Jedna věc je totiž napsat třeba příkaz tone(10, 1000, 100), který vytvoří 100ms pípnutí s frekvencí 1 000 Hz na reproduktoru připojeném k pinu 10, jenže druhá věc je pochopit, jak takový signál skutečně vypadá, tedy co jsme to opravdu tímto příkazem vytvořili na elektrické – logické úrovni.
Logický analyzátor
Pomůže nám v tom levný analyzátor signálu z eBaye, který seženete zhruba za stokorunu. Už jsme si jej v našem seriálu vyzkoušeli loni v záři, když jsme pomocí něj sledovali bity tekoucí z mikrokontroleru do laserového blikátka.
Čínský klon kompatibilní se softwarem Logic od amerického Saleae
Jedná se o laciné klony kalifornských analyzátorů Saleae, takže stačí stáhnout jejich bezplatný analytický software Logic pro Windows, MacOS a Linux, připojit krabičku skrze USB k počítači a na druhé straně sjednotit země – připojit pin GND na krabičce s GND obvodu, který budeme sledovat.
Mějte na paměti, že kupujete čínský padělek, který je sice mnohonásobně levnější, ale poškozuje amerického výrobce, kterému se to nelíbí. Firma Saleae tedy dlouhodobě hrozí, že padělky z eBaye v aplikaci zablokuje, zatím to však neudělala. Snad z dobré vůle, analyzátory za pár dolarů si totiž nakoupila hromada začínajících bastlířů, kteří zpočátku nechtějí investovat do mnohem dražších hraček.
Krabička je osmikanálová, takže zvládne paralelně sledovat až osm různých digitálních signálů. Pojďme si to rovnou vyzkoušet na tom nejjednodušším možném příkladu.
Napíšu si primitivní program pro Arduino Uno, který rozbliká jeho vestavěnou LED. Ta je připojená k pinu číslo 13, takže kód, který ji vždy rozsvítí na 100 ms a pak na stejnou dobu zase zhasne, by vypadal takto:
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH);
delay(100);
digitalWrite(13, LOW);
delay(100);
}
LOW představuje logickou nulu (bit s hodnotou 0) a HIGH zase logickou jedničku (bit s hodnotou 1). Z elektrického hlediska se při HIGH na pinu 13 nastaví napětí ideálně na 5 V, což je pracovní napětí desky Arduino Uno, no a při LOW se zase sníží na 0 V. LED dioda začne blikat.
My se nyní na tento signál podíváme v programu Logic. Nejprve vybereme jeden z osmi kanálů na analyzátoru a připojíme jej právě na pin 13 na Arduinu. V prohlížeči Logic pak už jen stačí klepnout na tlačítko Start a program začne po určitý čas nahrávat digitální signál stanovenou rychlostí. Klon se sice chlubí rychlostí až 24 MHz, ve skutečnosti však oproti americkému originálu zvládne spíše 8-12 MHz, což ale pro běžné experimenty stačí.
Výsledek by měl vypadat zhruba takto:
Pulzující napětí mezi HIGH (5 V) a LOW (0 V) na pinu 13, jak jej zachytil logický analyzátor
Jak vidno, logický analyzátor převedl pulzující napětí zpět na digitální logiku, takže krásně vidíme, kdy LED svítila (HIGH = 1) a kdy zhasla (LOW = 0). Kolečkem myši si zároveň můžeme libovolně přibližovat, což nám pomůže v dalších ukázkách, kdy vše mnohem zrychlíme a půjde o každý detail.
Logic toho umí ale mnohem více. Když najedu myší na obdélník pulzu, zobrazí se mi jeho přesná délka. Ale nejen to, jelikož jsme vytvořil signál, který s určitou frekvencí rozbliká LED, Logic mi tuto frekvenci spočítá – odhaduje ji na cirka 5 Hz.
Když najedu ukazatelem myši na pulz, zobrazí se mi jeho údaje a frekvence 5 Hz
Je to správně? Jedno bliknutí se skládá ze 100ms světla a 100ms tmy, celý blik tedy trvá 200 ms a za jednu sekundu se jich odehraje pět. Pět pulzů za sekundu = 5 Hz. Je to správně.
Fajn, to by pro začátek stačilo. V další kapitole zachytíme mnohem zajímavější signál. Podíváme se, co se ve vodičích odehrává, když se pokusíme změřit vzdálenost pomocí oblíbeného ultrazvukového dálkoměru HC-SR04!
Ultrazvukový dálkoměr HC-SR04 patří k nejoblíbenějším a nejefektnějším senzorům každého začínajícího bastlíře. Pokud stavíte robota, pomůže vám měřit vzdálenost překážky, před kterou se má robot vyhnout, anebo jej můžete použít k něčemu mnohem praktičtějšímu.
Třeba k měření zásob dešťové vody ve skruži. HC-SR04 bude průběžně měřit vzdálenost vodní hladiny od horního okraje skruže, takže zásoby vody zjistíte primitivním výpočtem objemu válce.
Ultrazvukový dálkoměr HC-SR04 a zapojení s na nepájivém poli s prototypovací destičkou Pro Micro a logickým analyzátorem, který bude nahrávat dění na pinech TRIG (5) a ECHO (6)
Ultrazvukový dálkoměr má dva logické piny TRIG a ECHO. Na pinu TRIG (trigger = spoušť) nejprve nastartujeme měření. Podle dokumentace senzoru (PDF) musíme vytvořit kratičký pulz o délce 10 mikrosekund. Pokud připojíme TRIG třeba na pin číslo 5, mohlo by to vypadat takto:
digitalWrite(5, HIGH);
delayMicroseconds(10);
digitalWrite(5, LOW);
Jakmile tento pulz dorazí do dálkoměru, vyšle sérii kratičkých ultrazvukových pulzů a bude čekat, dokud se neodrazí od nějaké překážky zpět, aby je mohl zachytit. Pokud k tomu dojde, dálkoměr vyšle elektrický pulz na pinu ECHO a to o délce, která odpovídá době letu ultrazvukového pulzu.
Pokud pin ECHO připojíme k Arduinu na pin 6, můžeme na tento příchozí signál počkat a změřit jeho délku v mikrosekundách pomocí vestavěné funkce pulseIn, kterou zavoláme ihned po vyslání iniciačního pulzu:
long doba = pulseIn(6, HIGH, 1e5);
Parametr HIGH funkci říká, že má počkat, až se na pinu 6 objeví logická 1 a poslední parametr 1e5 (tedy 100 000) představuje maximální dobu čekání v mikrosekundách. Je volitelný a pokud jej nepoužijeme, bude Arduino čekat ve výchozím stavu celou sekundu a blokovat program.
Fajn, pojďme se nyní na tuto legraci podívat optikou logického analyzátoru, který nyní bude paralelně měřit dva signály, takže použijeme dva kanály. Jeden vodič připojíme třeba na nepájivém poli k pinu TRIG a druhý k pinu ECHO.
Výsledek by měl vypadat zhruba takto:
Analyzátor nejprve zaznamenal iniciační pulz na pinu TRIG. Krátce poté dálkoměr vytvořil na druhém pinu ECHO pulz o délce, která odpovídá letu ultrazvuku k překážce a zpět.
Jak vidno, na kanálu 0 jsme nejprve nahráli iniciační pulz. Podle Logicu má ale délku 14 mikrosekund! Jak je to možné? Jednoduše proto, že funkce digitalWrite má svoji režii, takže než stačila přepnout stav na pinu zpět na logickou nulu, uběhlo několik dalších us. Kdybychom chtěli docílit vyšší přesnosti, namísto digitalWrite použijeme instrukci pro přímou změnu registrů na čipu, které řídí stavy na jednotlivých GPIO.
Dálkoměru je to ale jedno, stačil mu prostě pulz, který měl délku alespoň 10 us. Krátce poté jeho emitor vyslal osm kratičkých ultrazvukových vln, což samozřejmě nevidíme, vidíme však výsledek měření na pinu ECHO, který jsme nahrávali na kanálu 1.
A takto vypadá schéma signálu podle dokumentace senzoru. V mezeře mezi 10us pulzem na pinu TRIG a pulzem na pinu ECHO se tedy odehrává samotné ultrazvukové měření.
Pulz má podle Logicu délku 0,5422 ms (tedy 542,2 us), což zhruba odpovídá i tomu, co změřila funkce pulseIn(). Mimochodem, tato funkce dobře měří co nejkratší časové úseky. Čím delší pulz, tím i větší odchylka měření.
Zbytek je už práce pro absolventy prvního stupně základní školy. Pokud ultrazvuk letěl k překážce a zpět 542 us, stačí čas podělit a zjistíme, že zvuk letěl k překážce 271 us.
Podle kalkulačky na weather.gov se zvuk při teplotě 23 °C šíří rychlostí 344,89 m/s. Za 1 us uletí 0,034489 cm. Náš změřený čas tedy odpovídá vzdálenosti okolo 9,3 cm. A ano, zhruba ve vzdálenosti 9-10 cm jsem se snažil podle pravítka udržet svoji dlaň.
Takto tedy vypadá digitální komunikace ve vodičích dálkoměru a v příští kapitole se podíváme, co se děje ve vodičích, když rozsvítím RGB LED odstínem vínové červené!
Modul RGB LED má čtyři piny. Zem (GND) a tři základní kanály R (červená), G (zelená) a B (modrá). A stejně jako v modelu RGB i zde skládáme výslednou barvu nastavováním jasu každé z barevných složek.
Modul RGB LED s ochrannými rezistory, takže nemusím do 5V obvodu připojovat další, a opět celý obvod s připojeným logickým analyzátorem. Tentkorát budu nahrávat tři kanály-
Jak už jsme si v našem seriálu ukázali mnohokrát, jas LED můžeme nastavit pomocí pulzně-šířkové modulace (PWM), kdy bude LED velmi rychle blikat konstantní frekvencí a my budeme vzájemně měnit délky fáze svitu a tmy. Když bude fáze tmy delší než fáze světla, náš nehorázně pomalý mozek si to vyloží jako snížení jasu světla a naopak.
Základní práce s PWM je na Arduinu velmi jednoduchá. Jednotlivé kanály RGB LED stačí připojit k pinům Arduina, které podporují PWM – třeba 3, 5 a 6, a pak namísto funkce digitalWrite použijeme analogWrite.
Kdybychom chtěli rozsvítit RGB LED červenou barvou, nastavíme maximální jas na kanálu R a kanály G a B zhasneme. Na osmibitové škále (jas vyjádřený hodnotou 0 až 255) by to vypadalo takto:
analogWrite(3, 255);
analogWrite(5, 0);
analogWrite(6, 0);
Fajn a teď ten slíbený vínový odstín. Jsem pouze jednoduchý chlap, který rozezná tři základní barvy, a tak jsem si na pomoc vzal Google. Vínová má hromadu variant, mně se ale zalíbila ta s hodnotami jednotlivých kanálu 133, 39 a 78:
analogWrite(3, 133);
analogWrite(5, 39);
analogWrite(6, 78);
Pokud bude mít RGB LED jednotlivé kanály dostatečně maličké, nebo ji překryjeme nějakým difuzérem (mléčný plast aj.), měli bychom vidět krásnou světle-vínovou. Já bych tedy řekl prostě růžovou, ale budiž.
Červená subdioda, zelená subdioda, modrá subdioda a konečně složená vínová
Tak a teď se už pojďme konečně podívat, jak to celé vypadá v logickém analyzátoru na počítači. RGB LED má tři logické vodiče, na nepájivém poli k nim tedy připojíme tři kanály analyzátoru a nahrajeme si pár milisekund aktivity.
Výsledek bude vypadat zhruba takto:
Nejvyšší jas má první červený kanál. Druhý zelený kanál má naopak nejnižší jas. Poslední modrý kanál je na tom o něco lépe. Výsledkem je vínová barva doslova vyblikaná třemi maličkými R, G a B diodami.
Tak toto je světlá vínová, dámy a pánové! V časových osách můžete krásně vidět, že největší jas má červená LED. Která svítí zhruba polovičním jasem (133), takže úseky HIGH a LOW jsou zhruba stejně dlouhé. Zelená LED má nejnižší jas (39), takže úsek HIGH, během kterého LED svití, je velmi krátký. A nakonec tu máme modrou LED, která svítí dvakrát jasněji než zelená (78) a je to patrné i z nahraného signálu. Její úseky HIGH jsou dvakrát delší než v případě zelené LED.
Takhle tedy vypadá signál RGB LED a v příští kapitole se podíváme ještě na jednu pulzující legraci. Tentokrát to ale nebude blikající dioda, ale vibrující reproduktor, který vygeneruje tón.
Když bouchnete do stolu, ozve se rána. Když budete bušit do stolu velmi rychle po sobě, jednotlivé rány se nám slijí podobně jako u blikající diody ve spojitý tón s určitou frekvencí. Reproduktor funguje úplně stejně, namísto bouchnutí do stolu se ale rána vytvoří velmi rychlým kmitem membrány, která způsobí slabou rázovou vlnu – zvuk. A my uslyšíme prasknutí.
Rychlým praskáním po sobě vytvoříme spojitý tón s určitou frekvencí. A čím větší rázovou vlnu membrána vytvoří, tím bude tón hlasitější. To je celé.
Malý reproduktor připojený na pin 9 prototypovací desky
Abychom toto praskání nemuseli vytvářet ručně, Arduino má vestavěnou funkci tone, která jej vygeneruje sama. Na nás zbude zvolit pin, na kterém je připojený jednoduchý piezoměnič (buzzer), nebo slabý reproduktor, který dokáže i bez zesilovače rozvibrovat přímo logický pin Arduina.
Následující kód nejprve pípne na frekvenci 500 Hz, pak na 1 000 Hz a nakonec na 1 500 Hz a každý blok bude mít délku 500 ms. Reproduktor bude připojený na pinu 9:
tone(9, 500);
delay(500);
tone(9, 1000);
delay(500);
tone(9, 1500);
delay(500);
noTone(9)
A jak to vypadá v logickém analyzátoru? Tentokrát budeme muset hodně rolovat kolečkem. Jednotlivé pulzy jsou totiž kratičké a celá sekvence má délku 1,5 sekundy. Z grafu je nicméně krásně vidět, jak nám postupně roste hustota elektrických pulzů pohybujících membránou, a tedy i frekvence tónu z 500 Hz na 1,5 kHz.
Výsledek bude vypadat zhruba takto:
Signál má délku 1,5 sekundy a s frekvencí až 1,5 kHz se nám už celý nevejde do záběru. Tady ale vidíte postupný přechod mezi frekvencemi 500 Hz, 1 000 Hz a právě 1 500 Hz.
A ještě s přiblížením na jednotlivá praskání při 1,5 kHz. Frekvenci potvrdil i analyzátor.
V poslední kapitole se konečně podíváme na jeden z nejpopulárnějších komunikačních protokolů senzorové elektroniky – sběrnici I2C – a ukážeme si, co se ve vodičích děje, když z jednoho Arduina do druhého pošleme tři bajty s hodnotou 255, 0 a 170.
Se sběrnicí I2C/TWI se už setkal každý bastlíř, ke komunikaci ji totiž používá většina všemožných čidel – třeba ty meteorologické, menší displeje aj. Sběrnice I2C má dva logické vodiče SDA a SCL. Zatímco vodičem SDA tečou samotná data – bity, SCL slouží jako časovač, který připojeným zařízením říká, kdy mají jednotlivé bity zapisovat (tedy kdy mají nastavovat na pinu SDA HIGH, anebo naopak LOW) a kdy je mají také číst.
Časový signál SCL je tedy sled pulzů, jehož frekvence určuje komunikační rychlost. Čím rychleji bude tikat, tím rychleji budou připojená zařízení data číst a zapisovat. Naprosto laicky řečeno, když dorazí na vodiči SCL pulz třeba do teploměru, ten si řekne: „Aha, dorazil pulz, takže mám přečíst hodnotu bitu na vodiči SDA.“ A přečte ji.
Schéma přenosu zprávy o velikosti jednoho bajtu, kterému předchází 7b adresa zařízení
Oproti předchozím signálům, kde zvýšené napětí HIGH na pinu představovalo automaticky logickou jedničku, je to ale v případě I2C naopak. Namísto na HIGH se ve skutečnosti čeká na LOW, takže když na sběrnici zrovna neprobíhá žádná komunikace, je na vodičích SDA a SCL nastaveno opravdu HIGH a voltmetrem bychom tedy na běžném Arduinu změřili zhruba napětí 5 V.
Proč tomu tak je? Má to své výhody. I2C totiž díky tomu může být teoreticky odolnější. Na vodičích je prostě stále zvýšené napětí a teprve když klesne, něco se děje.
Spojení dvou destiček Pro Micro (čip ATmega32u4) pomocí sběrnice I2C
Komunikaci na I2C v Arduinu zpravidla zastřešují knihovny konkrétních čidel, my si ale vyzkoušíme přímo vestavěnou knihovnu Wire, která se o to stará. Pomocí vodičů SDA, SCL a společné země (GND) propojíme dvě Arduina. Jedno bude sloužit jako hypotetické čidlo, které bude poslouchat na I2C adrese 8, a když zachytí požadavek na data, odešle tři bajty: čísla 255, 0 a 170. No a druhé Arduino si každou sekundu od toho prvního vyžádá tři bajty, které vypíše do sériové linky. Budou to ta naše čísla 255, 0 a 170.
Proč jsem vybral zrovna tyto hodnoty? Protože je v logickém analyzátoru snadno poznáme. Zatímco číslo 255 je složené z osmi logických jedniček, 0 z logických nul a v případě čísla 170 se zase nuly střídají s jedničkami. V grafu bychom tedy měli na první pohled rozeznat, který sled bitů představuje které číslo.
Kód na Arduinu, které si pomocí sběrnice I2C každou sekundu vyžádá 3 bajty od druhého Arduina na I2C adrese 8:
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(9600);
}
void loop() {
Wire.requestFrom(8, 3);
while (Wire.available()) {
uint8_t b = Wire.read();
Serial.println(b);
}
delay(1000);
}
Kód druhého Arduina, které při požadavku na sběrnici I2C odešle tři bajty s hodnotami 255, 0 a 170:
#include <Wire.h>
void setup() {
Wire.begin(8);
Wire.onRequest(pozadavek);
}
void pozadavek() {
uint8_t data[3] = {255, 0, 170};
Wire.write(data, 3);
}
void loop() {
delay(100);
}
Tak, teď zapojíme obě Arduina ke zdroji napětí, počkáme, až se v sériové lince začnou vypisovat naše hodnoty a zkusíme si v logickém analyzátoru nahrát pár sekund komunikace na pinech SDA a SCL.
Výsledek bude vypadat zhruba takto:
Logic není jen hloupý zobrazovač signálu. Nabízí také dekodér hromady elektrických protokolů včetně I2C. Takhle tedy vypadá odpověď druhého Arduina, které odesílá tři bajty 255, 0 a 170, které dekodér snadno rozpoznal.
V kanálu 1 můžete krásně vidět tikot časovače SCL, který během datové komunikace pulzuje s konstantní frekvencí 100 kHz. Oběma krabičkám říká, kdy mají zapisovat a číst bity. Všimněte si také, že před započetím komunikace je na obou vodičích opravdu logická 1 (HIGH). Teprve snížení na LOW dává všem krabičkám tušit, že se začne něco dít.
V první části probíhá komunikační režie, požadavek na data od zařízení s nastavenou I2C adresou atp. Nás však zajímá druhá část, kde jsou patrné hodnoty čísel 255, 0 a 170. Uprostřed je to blok jedničkových bitů čísla 255, pak blok nulových bitů a tedy 0, no a nakonec se nám prostřídá osm jedničkových a nulových bitů čísla 170.
Odesílání bajtu s hodnotou 170 a frekvence časovače SCL, který se drží 100 kHz
Podobný rej bitů byste mohli sledovat i u sběrnice SPI, která má vedle časovače vodiče pro každý směr komunikace, a samozřejmě i u běžné sériové linky, která se od těch předchozích liší zase v tom, že žádný časovací signál nemá, takže si musí obě strany poradit bez dirigenta.
Takto tedy ve vší stručnosti vypadají základní typy digitálních signálů. Podobný logický analyzátor za tu drobnou investici rozhodně stojí, začínající bastlíř totiž s jeho pomocí pochopí, co se v nitru opravdu odehrává, a proč jednotlivé protokoly potřebují tolik všemožných vodičů.
Tento článek je součástí balíčku PREMIUM+
Odemkněte si exkluzivní obsah a videa bez reklam na devíti webech.
Vyzkoušet za 1 Kč
Nebo samostatné Živě Premium