Mikrokontrolery AVR XMEGA w praktyce, część 13. PWM
PWM to skrót od Pulse Width Modulation czyli modulacja szerokości impulsu. Generowany jest sygnał o stałej amplitudzie i częstotliwości, a zmieniać może się jedynie współczynnik wypełnienia. Dzięki takiemu zabiegowi można bardzo łatwo sterować różnymi urządzeniami: prędkością silnika, jasnością żarówki lub diody LED.
Mikrokontrolery XMEGA mają możliwość wygenerowania jednocześnie bardzo wielu sygnałów PWM. Timer typu 0 może generować cztery takie sygnały, a typ 1 może tylko dwa. Jednak mając do dyspozycji cztery timery typu 0 oraz trzy timery typu 1, możemy uzyskać aż 22 kanały PWM. W nowszych XMEGA (takich jak np. ATxmega128A3U) timery 16-bitowe można podzielić na 8-bitowe timery typu 2, a każdy z nich ma 4 kanały. W końcowym rozrachunku można mieć nawet 32 kanały PWM!
Jeśli wiesz jak działa PWM – przeskocz kilka akapitów i zacznij czytać opis kodu programu.
Timer generujący PWM może pracować w trybie single slope, czyli licząc zawsze w tym samym kierunku albo może pracować w trybie dual slope, czyli liczyć naprzemiennie w górę i w dół.
W trybie single slope timer zaczyna liczyć od zera do wartości określonej w rejestrze PER. Kiedy rejestr licznika CNT i PER zrównają się, wówczas CNT zostaje wyzerowany i timer zaczyna liczyć od początku. Sygnał PWM dostępny jest na nóżce OCxx. Na początku cyklu, na pinie OCxx jest stan logiczny wysoki. W chwili, kiedy rejestr CNT zrówna się z liczbą wpisaną do rejestru CCX, wówczas pin OCxx ustawia się w stan niski i pozostaje tak do końca cyklu. Wykresy czasowe takiej sytuacji zostały przedstawione na rysunku 1.
Rys. 1. PWM single slope
W trybie dual slope, timer liczy od zera do wartości PER, a potem zmienia kierunek liczenia i wraca do zera. Zmiana stanu pinu OCxx dokonuje się w chwili zrównania się rejestrów CNT i CCx, jednak zależy jeszcze od kierunku liczenia timera. Gdy timer liczy w górę, przy zrównaniu się, stan pinu OCxx zmienia się z wysokiego na niski, a w przypadku liczenia w dół jest odwrotnie. Aby opis był bardziej zrozumiały zamieściłem rysunek 2.
Rys. 2. PWM dual slope
Należy mieć na uwadze, że częstotliwość sygnału będzie dwukrotnie mniejsza niż przy identycznie ustawionym trybie single slope, ponieważ cykl pracy jest dwukrotnie dłuższy.
Tryb dual slope czasami nazywany jest określeniem PWM z korekcją fazy . Czym on się różni od single slope? Niektórzy twierdzą, że jest lepszy i wynika to z teorii sygnałów… Otóż, jeśli wykorzystujemy tylko jeden kanał timera, to w obu trybach możemy uzyskać całkowicie identyczny sygnał. Różnica jest wtedy, gdy jeden timer kontroluje kilka kanałów PWM, a tym samym kilka odbiorników. W przypadku single slope, na początku cyklu wszystkie odbiorniki, którymi sterujemy, włączają się jednocześnie. Bardzo często PWM wykorzystywany jest do sterowania urządzeniami dużej mocy. Jednoczesne załączenie kilku takich urządzeń może powodować spadki napięć na szynach zasilających. Nie bez powodu mówi się, że PWM sieje zakłoceniami . Rozwiązaniem problemu jest zastosowanie PWM dual slope. Spójrz jeszcze raz na rysunek 2 – w tym przypadku w danej chwili otwierany lub zamykany jest tylko jeden z trzech kanałów PWM. Z pewnością ograniczy to zakłócenia generowane przez PWM.
Przejdźmy wreszcie do pisania programu. Po włączeniu zasilania, uruchomione zostaną cztery kanały PWM do których podłączymy diody LED. Aby zaobserwować jak działa PWM, po starcie programu będzie on skonfigurowany z bardzo dużym preskalerem. Dopiero po wciśnięciu przycisku FLIP zostanie uruchomiona normalna prędkość pracy, a poszczególne diody LED będą świecić się z różną jasnością. W tym przykładzie wykorzystamy timer E0, który jest identyczny jak opisywany w poprzedniej części C0. Schemat przedstawia rysunek 3, a przykład wykonania jest na rysunku 4.
Rys. 3. Schemat układu demontującego działanie PWM
Rys. 4. Fotografia zbudowanego układu
Program zaczynamy standardowo od konfiguracji układów wejścia i wyjścia, dokładnie tak jak to opisałem w odcinku na temat portów w XMEGA.
int main(void) { // przycisk PORTE.DIRCLR = PIN5_bm; // pin E5 jako wejście (przycisk FLIP) PORTE.PIN5CTRL = PORT_OPC_PULLUP_gc; // podciągnięcie do zasilania // diody od PWM PORTE.DIRSET = 0b00001111; // piny 3..0 jako wyjście // wyświetlacz LcdInit();
Aby móc skorzystać z dobrodziejstw PWM, musimy nieco inaczej skonfigurować timer, a w szczególności jego rejestr CTRLB – spójrzmy na fragment dokumentacji przedstawiony na rysunku 5.
Grupa konfiguracyjna WGMODE odpowiada za tryb pracy timera. W odcinku opisującym podstawy pracy timerów w mikrokontrolerach ATxmega wykorzystaliśmy tryb TC_WGMODE_NORMAL_gc. PWM możemy generować przy pomocy czterech trybów – jednego single-slope, w którym timer cały czas zlicza w tym samym kierunku oraz trzech trybów dual-slope. Tryby dual-slope różnią się jedynie chwilami, w których zostanie zgłoszone przerwanie przepełnienia licznika. Ponieważ przerwań w niniejszych przykładzie nie wykorzystujemy, to możemy wybrać dowolny tryb dual-slope.
Oprócz tego, w rejestrze CTRLB musimy wybrać, które kanały CCx zamierzamy wykorzystać, wpisując do rejestru odpowiednie stałe TC0_CCxEN_bm, gdzie x oznacza wybór kanału A, B, C oraz D.
Rys. 5. Opis rejestru CTRLB