SVETELEKTRO

14. januára 2012   Verzia pre tlač Verzia pre tlač

PWM pomocou AVR mikrokontroléra


petoknm

Vysvetlenie princípu PWM, realizácia pomocou OZ alebo mikrokontroléra

Dlho som si kládol otázku ako kontrolovať výkon rôznych zariadení pomocou mikrokontrolérov. Áno, vedel som ako spínať zariadenia on/off pomocou napr. tranzistora, MOSFETu alebo relé. Nebolo to ,ale podla mojích predstáv. Potreboval som napríklad kontrolovať jas LED-ky alebo výkon motora ,ale plynulo od 0-100%, nie len on/off. Na to sa perfektne hodí pulzne šírková modulácia. Táto metóda je akýmsi Digital-To-Analog konvertorom.To znamená, že sa pomocou digitálnej kontroly pinu (0 a 5V), dokážu vytvoriť napätia v tomto rozsahu (0 až 5V).

Táto metóda kontroly výkonu zariadenia je používaná najmä na riadenie rýchlosti motorov, na kontrolu jasu žiaroviek, LED, na výrobu zvukového signálu alebo iných signálov na kontrolu UPS, meničov napätia a pod.

Princíp
Mikrokontroléry dokážu spínať svoje piny buď k zemi alebo k napájaciemu napätiu. Tým sa vytvorí stále napätie 0 alebo 5V(3.3V). Ale ak mikrokontrolér bude tieto stavy rýchlo striedať a na takýto výstup dáme filter vysokých frekvencii, tým sa zbavíme kolísania napätia a na výstupe dostaneme napätie niekde medzi 0-5V. Toto napätie závisí od šírky tohto pulzu v porovnaní so svojou periódou.
Chceme aby náš mikrokontrolér vytvoril napätie napríklad 1V. To je 1/5 napájacieho napätia a tým pádom šírka pulzu musí byť 1/5 periódy=20%. Čiže naprogramujeme náš uPC ,aby svoj pin priviedol na 5V napríklad na 1ms a potom ho necháme uzemniť tento pin na 4ms (1ms+4ms=5ms=1 perióda). Takýto priebeh by na osciloskope vyzeral približne takto:

Potom by sme pridali rezistor a kondenzátor, aby sa toto napätie ustálilo a tým dostaneme jeho priemer:

Výsledné napätie:

Náhoda? Ani zďaleka.
Ak chcete vytvoriť nejaké napätie, tak môžete použiť tento jednoduchý vzorec ,ktorý vám teraz vysvetlím:
U_out=t_on/t_p *U_in
t_on/t_p je strieda, čiže pomer času t_on počas ktorého má pin napájacie napätie k času celej periódy t_p(t_p=t_on+t_off), často vyjadrený v percentách. V predchádzajucom prípade to bolo 20%=0.2=1ms/(1ms+4ms)=1ms/5ms
U_in je napájacie napätie mikrokontroléra, ale nejaké iné napätie, ktoré sa strieda so zemou, aby sa vytvoril analógový signál, niekedy označované ako U_max
Čiže ak chcem napríklad 3.3V z 5V pomocou PWM ,tak si dosadím to čo poznám a zistím akú striedu mám použiť (D znamená strieda)
3.3V=D*5V
D=3.3V/5V=0.66=66%

Hodnoty súčiastok som trochu zmenil:

A tu môžete vidieť priebeh nabíjania a vybíjania kondenzátora:

t_p=100μs

D=0.66=66%

Výroba PWM:

PWM signál sa dá vyrobiť veľmi jednoducho. Analógovo sa to dá dosiahnuť tým , že budeme porovnávať trojuholníkový signál alebo pílu k nejakému inému napätiu. A keď signál presiahne toto napätie, tak komparátor bude mať na svojom výstupe PWM signál so striedou nepriamo úmernou k porovnávaciemu napätiu. Ukážka na príklade:

Toto je jednoduchý generátor trojuholníkového signálu:

A výstup druhého operačného zosilňovača vyzerá nejako takto:

Potom k tomuto výstupu pridáme komparátor, ktorý neustále porovnáva napätie tohto trojuholníkového signálu so stálym napätím na jeho invertujúcom vstupe, ktoré sme získali napäťovým deličom pomocou dvoch rezistorov R6, R7:

Ak je toto napätie presne 6V, tak ak trojuholníkový signál prekročí túto hodnotu, tak na výstupe tretieho operačného zosilňovača sa objaví 11V (napájacie napätie je 12V ,ale nie je možné dosiahnuť kvôli poklesu napätia cez polovodičový prechod, ako napr. u diód). Ale pokiaľ je hodnota troj. sig. nižšia ako stále napätie na neinvertujúcom vstupe komparátora ,tak je na výstupe približne 1V(ten istý problém, komparátor chce dosiahnuť 0V ale kvôli poklesu napätia to nejde, takže to bude trochu viac nez 0V). Tu možno vidieť trojuholníkový signál, porovnávacie napätie a výstup komparátora:

Trojuholníkový signál je modrý, porovnávacie napätie je žlté a výstup komparátora je červený. D=50%
Keď sa teraz toto porovnávacie napätie zvýši znamená to ,že to bude pretínať troj. sig. na vyššom mieste čiže výstup komparátora bude mať menšiu striedu a tým sa do zariadenia dostane menej energie a má tým menší výkon:

Iba som zmenil hodnotu R6 z 10k na 5.6k to zvýšilo porovnávacie napätie z 6V na 7.68V. A ako vidíte zmenšila sa šírka pulzu v porovnaní k jej perióde. D<50%

Tak isto to funguje ked znížim porovnávacie napätie. Bude sa pretínať s troj. sig. na nižšom mieste čiže strieda sa zvýši. R6=10k, R7=5.6k. D>50%:

To je všetko čo sa týka analógového spôsobu generovania PWM signálu. Ak chcete, tak na výstup môžete pripojiť MOSFET a riadiť tým príkon motorov alebo žiarovky… R6 a R7 môžete nahradiť potenciometrom ,ale pamätajte, že porovnávacie napätie musí byť blízko napätia trojuholníkového signálu, aby ste dostali nejaký PWM signál, tak sa tieto dve napätia musia niekde prekrížiť.

AVR a PWM

Možno ste niekedy rozmýšľali ako je možné ,že tie malé hračky dokážu hovoriť alebo vydávať rozličné zvuky. Vždy som skúšal vyrábať zvuky pomocou nejakých jednoduchých oscilátorov ,ale nikdy sa to nepodobalo zvukom ,ktoré bežne počuť. Teraz vám stačí tento signál nahrať, získať jeho tvar(waveform), a potom už iba použiť mikrokontrolér, aby tieto priebehy napätí zopakoval. Potom tento signál priviesť na nejaký zosilňovač a rovno do reproduktora a máte ten zvuk čo ste nahrali.

Teraz vám ukážem ako vytvoriť analógový signál pomocou AVR mikrokontroléra Atmega8. Ak budete chcieť, aby váš mikrokontrolér vydával nejaké zvuky ,tak vám stačí naprogramovať mikrokontrolér, aby bežal v slučke a stále striedal nejaké hodnoty napätia veľmi rýchlo. Asi tak 44100-krát za sekundu. Znie to veľmi rýchlo, ale pre mikrokontrolér je to hračka. Na konci vám ukážem ako generovať sínusovou pomocou Atmegy8.

Mikrokontrolér robí niečo podobné ako analógový komparátor ,ale neporovnáva nejaké napätie k nejakému signálu ,ale porovnáva čísla.

Dúfam ,že viete ,že mikrokontrolér dokáže počítať. Na takéto počítanie použijeme TIMER(časovač) ,ktorý počíta impulzy. Použijeme na to 16bitový TIMER1. 16bitový znamená, že dokáže napočítať až 65536 impulzov (65536=2^16). Zakaždým čo detekuje impulz priráta k tomu počtu pulzov 1.

A okrem toho, že počíta tie pulzy ,tak dokáže tento počet impulzov porovnať k nejakému inému číslu a podľa toho ,či je menši alebo väčší riadiť svoj pin.



Takto to vyzerá, keď mikrokontrolér počíta od 0-65535 a potom pretečie a vynuluje sa a počíta odznova a tak to ide stále pokiaľ má mikrokontrolér napájacie napätie a zdroj impulzov. Osa X je čas a osa Y je počet pulzov ,ktoré uC napočítal.
Potom už stačí povedať mikrokontroléru, aby porovnával túto stále stupajúcu hodnotu k nejakému statickému číslu a podľa toho riadiť svoj pin a máme PWM.

Takže teraz začnem už s konkrétnym kódom (dúfam ,že už máte aspoň minimálne skúsenosti s jazykom C):

Kód: https://pastebin.com/MJTmgeYT

Rozobratie tejto funkcie:
Riadky PWMDDR |= 1<
TCCR1A |= 1<
Tým ,že sme nastavili bity COM1A1 a COM1B1 ako 1 umožnili sme Timer1 používať tieto piny PB1 a PB2 ako výstup neinvertujúceho PWM signálu, to znamená ,že tento pin bude mať 5V až pokiaľ sa počet pulzov a porovnávacie číslo nezhodnú
.
Bity WGM11, WGM12, WGM13 sme nastavili ako jednotky, aby sme nastavili funkciu Timer1 ako Fast PWM. Pozor lebo bit WGM11 je v registri TCCR1A ,ale ostatné sú už v registri TCCR1B.

Taktiež sme v registri TCCR1B dali bitu CS10 hodnotu 1 ,aby bežal na takej istej frekvencii ako CPU čiže 1MHz. Rôzné kombinácie bitov CS10, CS11, CS12 umožňujú ,aby Timer1 bežal napriklad 8, 64, 256 alebo 1024-krát pomalšie(všetky kombinácie nájdete v datasheete na strane 99).

Riadok ICR1 = 65535; iba nastavuje maximálnu hodnotu Timera 1. Číslo nemôže byť väčšie ako 65535!

Riadky OutputCompareRegister1 = 0; OutputCompareRegister2 = 0; nastavujú počiatočné PWM signály na D=0%.



Teraz si spravíme ďalšiu funkciu ,ktorá nám umožní meniť striedu PWM signálu. Pred tým si ale musíme uvedomiť ,že Timer1 má dva kanály, kanál A a kanál B. To znamená ,že máme aj dve porovnávacie čísla. Jedno je uchované v registri OCR1A a druhé je v registri OCR1B. Keď zmeníme OCR1A ,tak sa toto číslo bude porovnávať s počtom impulzov, ktoré narátal Timer1 a keď je počet pulzov väčší ako OCR1A ,tak pin PB1(OC1A(A-lebo ide o kanál A)) sa uzemní, ak nie, tak ma logickú hodnotu 1(5V). Tak isto to funguje aj pre register OCR1B akurát, že to mení striedu na pine PB2 označenú OC1B(B-ako kanál B):





Kód: https://pastebin.com/v0CsXvEK

Je to jednoduchá funkcia, ktorá vyžaduje dva parametre. Prvý parameter je hodnota 16bitového registra s porovnávacim číslom a druhý parameter je kanál ,ak zadáte kanál 1 ,tak sa tá hodnota uloží do registra OCR1A, čiže sa zmenístrieda kanála A. Ale ak zadáte ako druhý parameter číslo 2 ,tak sa zmení strieda kanála B lebo sa to číslo uloží do registra OCR1B.



A to je všetko ,čo sa týka práce s PWM. Teraz vám dám príklad ako môžete použiť tieto funkcie na to,aby ste regulovali jas LED diódy.

Kód: https://pastebin.com/6aHQSf0D

Naprogramujte mikrokontrolér a pripojte LED diódu na pin PB1 čiže pin 15 cez !vhodný rezistor! do zeme A .Nezabudnite nastaviť fuses ,aby váš mikrokontrolér mal nejaký zdroj signálu .Ja používam fuses 0xD9E1, zabezpečujú vnútorný RC oscilátor na frekvencii 1MHz. Malo by to potom vyzerať nejako takto (ta LED dióda bliká ,ale na kamere to moc nie je vidno):

Teraz vám vysvetlím prečo to bliká a nereguluje to jas ako sme pôvodne chceli.
Odpoveď znie vo frekvencii nášho uC. Beží iba na 1MHz čo znamená ,že mu posielame 1 000 000 pulzov za sekundu. Keďže jedna perióda PWM pulzu je taká dlhá ako rýchlo dokáže Timer narátať až do svojho maxima čo je v našom prípade 655535.
Môžeme vypočítať ako dlho mu to bude trvať:

Takto sa vypočíta frekvencia PWM signálu:

f_PWM=f_CPU/N_max = (〖10〗^6 Hz)/2^16 =15.26 Hz

Preto nám LED dióda ,tak rýchlo blikala. Blikala na frekvencii 15.26Hz a to je viditeľné. My teraz musíme zvýšiť túto frekvenciu na takú hodnotu kedy ľudské oko nebude stíhať a bude to vyzerať ako keby svietila stále. To sa dá dosiahnúťdvoma hlavnými spôsobmi. Buď zvýšime frekvenciu CPU alebo znížime rozlíšenie PWM signálu. Keby sme namiesto 16bitového maxima použili 8bitov, tak by naša obnovovacia frekvencia bola:

f_PWM=(〖10〗^6 Hz)/2^8 =3906.25 Hz


Čo je už frekvencia dosť veľká na to, aby si oko nevšimlo blikanie

V tom prípade by to vyzeralo asi takto(v kóde som zmenil iba for loop ,aby rátal iba do 256, a ICR1 na 255):


Alebo by som mohol použit vyššiu frekvenciu CPU a vtedy by to vyzeralo asi takto (kód je taký istý ako v tej prvej ukážke akurát, že teraz beží na frekvencii 18MHz namiesto 1MHz a zmenil som aj delay ,aby to išlo rýchlejšie):





Frekvencia obnovovania je v tomto prípade:

f_PWM=(〖18*10〗^6 Hz)/2^16 =274.66 Hz

A síce to nie je až taká vysoká frekvencia ako v 8 bitovom prípade ,stále je to dosť rýchle, aby to ľudské oko nespozorovalo.



Sínus
Teraz vám ukážem ako vytvoriť jednoduchú sínusovku.

Vytvorím ešte jednu novú funkciu, ktorej úlohou je generovať čísla od 0-255 tak, aby generovali sínusový priebeh. Potom ich už iba nechám vytvoriť pomocou PWM a je to. Takáto sínusovka sa môže použiťako zdroj zvuku ako vám aj v ukážke predvediem.

Kód: https://pastebin.com/eCmLBtBY

Sínus a LED dioda

Sínus a reproduktor




Záver
Takto sa generujú zvuky, stmievajú sa žiarovky, reguluje sa napätie, riadia sa motory, generujú sa signály pre transformátory, meniče a mnoho iných vecí. Kód si samozrejme môže každý upraviť podľa svojich predstáv, môžete napríklad meniť delay alebo môžete skúsiť vytvoriť nejaké zvuky, pokiaľ sú správne nastavené registre ,tak by to malo ísť na každom mikrokontroléri od Atmelu. Toto všetko boli ukážky použitia len jedného kanálu ,ale môžete použiť dva kanály súčasne (tri ak použijete aj Timer2) Ak používate iný uPC pozrite sa do datasheetu ako nastaviť registre pre váš konkrétny mikrokontrolér. Prajem veľa úspechov s PWM 🙂

Zdroje:
Simulácia el. obvodu bola vytvorená v LTSpice
Videá a kód som vytvoril ja :);

Ako sa vám páčil tento článok?
  • Páči sa mi (1)
  • Súhlasím (0)
  • Zábavné (0)
  • Informatívne (0)

Komentáre (5)

  1. buddy píše:

    Zdravim, velmi sa mi to paci a nieco take podobne by som potreboval urobit.
    Avsak s malymi zmenami.

    Potreboval by som automaticky stmievac ako aj rozsiecovac, co je vlastne tvoje riesenie.
    Avsak ja by som potreboval, aby to zhasilo velmi pomaly, asi tak pol hodinu a rozviecovalo sa tiez tak dlho, alebo este dlhsie.
    Je mozne to preprogramovat na dlhsiu dobu?

Pridaj komentár