Blikáme jemně: digitálně – analogový převodník

Už jsme si zablikali, tak co si teď ukázat něco dalšího? Co třeba neblikat tak natvrdo, ale tu LEDku tak jako pomalu rozsvěcet…

Pokud je blikání LEDkou obdoba Hello world, tak je tahle úloha obdobou „PRINT 1+1“. Pokud jste si někdy hráli s Arduinem, tak víte, že LEDka je připojená na digitální výstup, který jaksi nemá nic jiného než „plný jas – tma“, a že se tedy pomalé rozsvěcení řeší pomocí PWM.

PWM

neboli Pulsně-šířková modulace (Pulse Width Modulation) je způsob, jak na binárním výstupu (0 / 1) nasimulovat analogový signál (0 .. 1). V té „správné“ podobě se používají digitálně-analogové převodníky (DAC), buď integrované, nebo v jednoduché podobě R-2R sítě, kde vícebitový digitální signál převádíme na analogový. Pokud je situace vhodná, lze použít ale jednoduššího způsobu, a tím je právě PWM.

Princip PWM je jednoduchý: mějme vstupní hodnotu, řekněme osmibitovou, a nazvěme si ji D. K ní si uděláme čítač hodinových pulsů, rovněž osmibitový, který bude počítat od nuly k 255 a pak znovu od nuly. Dokud je hodnota čítače menší než D, bude na (jednobitovém) výstupu 1, jakmile je hodnota vyšší než D, bude na výstupu 0. Jinými slovy: pokud máme hodiny s frekvencí f, bude na výstupu obdélníkový signál s frekvencí f/256, který má ale různou střídu, tedy dobu log. 1 a log. 0. Kdybychom si ten interval rozdělili na 256 částí, tak signál bude po D částí v log. 1 a po (256-D) částí v log. 0. Mění se tzv. plnění (duty).  Pokud je frekvence f dostatečně vysoká (a co je „dostatečně“, to závisí na okolnostech), dá se na signál nahlížet tak, jako by se jeho hodnota měnila spojitě mezi 0 a 1 po 256 krocích. Z definice vyplývá, že pokud D=0, tak je na výstupu stále 0 (0/256), pokud D=255, je na výstupu 255x log. 1 a 1x log. 0 (255/256), tedy 99,6 % Pokud chceme mít maximální plnění 100 %, pak je potřeba buď zvětšit velikost D o 1 bit, nebo zkrátit čítač o 1 (tedy nejvyšší hodnota bude „11111110“).

Pokud jde o blikání LED, je vhodná frekvence taková, která je větší než je lidské oko schopno rozpoznat, tj. nějakých 24 Hz. Při osmibitovém PWM pak musí být vstupní frekvence alespoň 24 * 256 = 6,144 kHz. V praxi se používají frekvence okolo 100 kHz. Při řízení servomotorů je frekvence PWM signálu 50 Hz, tedy vstupní frekvence pro osmibitový převodník bude 50 * 256 = 12,8 kHz. Pokud budeme generovat audio signál, kde je nejvyšší frekvence okolo 22 kHz, a použijeme osmibitový PWM, musíme k vytváření signálu použít frekvenci 5,632MHz.

Asi už není, co víc k tomu dodat, takže zde je kód čtyřbitového PWM:

Je v něm víceméně doslova zapsán algoritmus, popsaný v předchozích odstavcích. Udělal jsem si i druhou architekturu, která implementuje zkrácení čítače o 1:

a s malou úpravou je možné obojí nadefinovat jako generickou entitu s proměnnou šířkou:

Ovládání LED pomocí PWM

Vytvoříme si zapojení blink2, které bude podobné předchozímu, ale upravené. Použijeme čtyřbitový PWM. Mnohabitový dělič hodinového signálu 50 MHz zůstane, z něj si vygenerujeme signál „lfo“ (neboli „nízkofrekvenční oscilátor“), a tímto signálem budeme budit čítač, který bude postupně čítat 0..15. Tento signál pak budeme posílat do PWM k převodu na „analogovou hodnotu“. Jako hodiny pro PWM můžeme použít libovolný kmitočet, vyšší než „lfo * 16“ a vyšší než výše zmíněných 6,1 kHz. Zde se přímo nabízí poslat tam rovnou hodinový signál 50 MHz, ona to LED zvládne…

Všimněte si, že tentokrát obsahuje zapojení všechny tři LED, které na kitu jsou. Použiju obě architektury, jak kanonickou, tak vylepšenou s plněním do 100 %, jednu připojím na led3 (pin číslo 3), druhou na led9 (pin číslo 9), prostřední LED (pin 7) nastavím do 1 (a protože jsou LED zapojené na log. 1, znamená to, že bude zhasnutá).

V zapojení dělím 50 MHz mnohabitovým čítačem „counter“, z jeho 23. bitu odebírám signál „lfo“. Ve druhém procesu počítám pulsy na signálu „lfo“ a měním podle nich hodnotu „v“ (0 – 15). Vytvářím si dvě instance entity PWM. Všimněte si, že jsem nezadával do kódu definici komponenty, místo toho vytvářím instance přímo přes „entity work.PWM“ a vybírám architekturu.

Až budete testovat, neudělejte stejnou chybu jako já: Udělal jsem si nový projekt, zapomněl jsem, že jsem si nenastavil přiřazení signálu pinům, a pak jsem se velmi divil, že zapojení nefunguje!

A protože jsou, jak jsem už zmínil, LED připojeny na log. 1, bude se zapojení chovat obráceně, tj. místo rozsvěcení bude pohasínat. Nejjednodušší změna je nastavit v<=v – 1;

Sigma-Delta

Druhá metoda digitálně-analogového převodníku, nazvaná „sigma-delta„, pracuje na jiném principu: snaží se nalézt stejný poměr počtu 1 a 0, jaký odpovídá poměru (D / 2N), kde N je šířka převodníku v bitech. Vnější rozhraní zůstává stejné jako u PWM, tedy hodiny, vstupní vektor a výstupní jednobitový signál. Výstupem sigma-delta převodníku je signál, který obsahuje pulsy nestejné délky, ale ve výsledném součtu odpovídá poměr času v log. 1 ku času v log. 0 požadovanému poměru. Algoritmus je jednoduchý: K čítači o dané šířce N se přičítá hodnota D. Pokud došlo k přenosu, je na výstup poslána log. 1 a od čítače se odečte hodnota 2N, jinak je na výstupu log. 0.

Ukázkový čtyřbitový sigma-delta převodník jsem napsal takto:

Zase platí, že pro hodnotu „1111“ není výsledek ideálních 100 %, ale jednou za 16 cyklů je nastavena 0.

Nevýhodou PWM i sigma-delta je to, že signál obsahuje parazitní „nosnou“ frekvenci, a pro další použití je třeba za výstup zapojit dolní propust, která tuto frekvenci odfiltruje. Sigma-delta modulace má ve výsledném signálu tuto parazitní nosnou ale mnohem vyšší a s různými frekvencemi, které se skládají do vysokofrekvenčního šumu, což může být někdy výhodnější (např. vyšší odstup těchto frekvencí od signálu, takže se lépe odfiltrovává). Viz teorie.

Když si zkusíte přidat další převodník pro třetí LED, můžete vidět, jaký je rozdíl mezi PWM a sigma-delta. Já okem pozoruju drobný rozdíl v oblasti nízkých hodnot – zdá se mi, že sigma-delta dokáže líp prokreslit nízkou intenzitu světla.

Převedení SDM na generickou podobu opět nechám na vás. Na závěr tradiční testbench: