Ta strona używa ciasteczek (plików cookies), dzięki którym może działać lepiej. Dowiedz się więcejRozumiem i akceptuję

Wszystko, co musisz wiedzieć, aby uruchomić PWM

Programowanie 26.05.2015 Grabki

DS1Z_QuickPrint5W artykule chciałbym wytłumaczyć inicjalizację i wykorzystanie sprzętowego PWM-u w robotach, np. do sterowania prędkością silników.

Pamiętam, że jako początkujący miałem z tym duży problem. Znałem zasadę działania PWM, ale nie wiedziałem jak to połączyć z resztą programu.

Gdy zaczynałem przygodę z programowaniem, w Internecie, można było znaleźć dużo przykładów w Bascomie oraz całkowitą pustkę jeśli chodzi o język C. Dodatkowo, sytuacji nie ułatwiał mi brak znajomości języka angielskiego. Próby szukania czegokolwiek w dokumentacji były porażkami.

Dlatego pamiętając o takich niby błahych – choć myślę, że częstych i utrudniających szybkie „wejście” w robotykę – problemach początkujących, chciałbym wytłumaczyć, jak sobie z nimi radzić. W tym artykule wskażę jakich rozdziałów i tabel szukać w dokumentacji, aby odpowiednio ustawić timery oraz jak to później wykorzystać w przykładowym kodzie robota.

Inicjalizacja PWM

W przykładzie posłużę się wykorzystaniem licznika (timera) 16-bitowego ustawionego w tryb Fast PWM. Posiada on dwa kanały, więc może służyć np.: do sterowania dwóch silników.

Tryb Fast PWM 8-bit oznacza, że wypełnienie sygnału będziemy mogli regulować w zakresie od 0 do 255, gdzie 0 będzie oznaczało ciągły stan niski, a 255 ciągły stan wysoki. Oto czynności, które należy wykonać w celu inicjalizacji PWM:

Szukamy w nocie katalogowej (datasheet) rozdziału dotyczącego np.: Timera 1 (jest to Timer 16-bitowy). W nim odszukujemy tabelkę Waveform Generation Mode Bit Description. Przykładowo dla mikrokontrolera ATMEGA8A (nota w załączniku) jest to tabela 16-5, która znajduje się na str. 101:

tabela_1

Widzimy z niej, że musimy ustawić na 1 bity WGM12 i WGM10, aby Timer pracował w wybranym przez nas trybie. W naszym przypadku (ATMEGA8A, 16-bitowy Timer1) bity te znajdują się w dwóch różnych rejestrach (TCCR1A oraz TCCR1B).

Widać to w dokumentacji (rejestry są rozpisane na poszczególne bity, w naszym przypadku TCCR1A znajduje się na str. 99, TCCR1B na str. 101). W przypadku liczników 8 bitowych mamy tylko jeden rejestr TCCRx (gdzie x jest numerem licznika), a do wyboru mamy zazwyczaj tylko cztery tryby pracy.

Kolejnym krokiem jest podłączenie Timera do odpowiedniego pinu mikrokontrolera oraz określenie sposobu sterowania tymże wyjściem. W tym celu szukamy tabelki Compare Output Mode, Fast PWM. W naszym przypadku jest to tabelka 16-3 na str. 100:

tabela_2

Interesują nas w zasadzie tylko dwie ostatnie opcje. Wybieramy: Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at BOTTOM, (non-inverting mode) – oznacza to, że na starcie mamy stan wysoki, a podczas przerwania (gdy wartość licznika będzie taka sama, jak wpisana przez nas do OCRx) wyjście jest ustawiane w stan niski.

„Na chłopski rozum” mówiąc – im większą wartość wpiszemy do OCRx, tym dłużej na wyjściu będzie panował stan wysoki (wyższe „średnie” napięcie). Po wpisaniu maksymalnej wartości (w naszym przypadku 255, ponieważ wybraliśmy tryb 8-bit) na wyjściu będzie ciągle ustawiony stan wysoki, a po wpisaniu 0, na wyjściu będzie ciągle panował stan niski. Kolejne ustawienie działa w odwrotny sposób. Musimy więc ustawić w TCCR1A bity COM1A1 i COM1B1.

Uwaga!
Jeśli chcemy mieć dwa kanały (A oraz B), to musimy ustawić bit COM1A1 oraz COM1B1!

Wybór prescalera

Ostatnią czynnością jest wybranie prescalera. Od niego będzie zależała częstotliwość, z jaką będzie pracował nasz PWM. Generalnie, co do odpowiedniej częstotliwości zdania są mocno podzielone, tutaj możemy przeczytać dyskusję która była prowadzona na naszym forum na ten temat, ale ostrzegam, jest bardzo długa!

Za wartość prescalera odpowiadają bity CSxy. Aby dowiedzieć się, jakie mamy możliwości wyboru szukamy tabelki Clock Select Bit Description. W naszym przypadku jest to tabelka 16-6 na str. 102. W naszym przykładzie wybierzemy prescaler o wartości 64. Jak widać w tabelce, musimy w tym celu ustawić bity CS11 oraz CS10 w TCCR1B.

tabela_3

Jak więc obliczyć częstotliwość (f) naszego PWM? Załóżmy, że taktujemy nasz mikrokontroler częstotliwością 16MHz. Musimy więc podzielić ją przez prescaler oraz przez pojemność naszego licznika. Częstotliwość naszego PWM będzie wynosiła więc około 976Hz (16 000 000Hz / 64 / 256).

Inicjalizacja PWM powinna więc wyglądać tak:

Implementacja w programie robota

Teraz możemy przejść do wykorzystania PWM w programie (np.: robota). Po pierwsze musimy odpowiednie piny ustawić jako wyjścia. W przypadku omawianego mikrokontrolera (ATmega8A) są to PB1 oraz PB2. Nie można również pominąć pozostałych pinów, którymi sterowany będzie mostek H. Jednak to zależy już od konkretnej konstrukcji.

Następnie, w programie, musi nastąpić odpowiednie ustawienie PWM, czyli dokładnie, to czym zajmowaliśmy się poprzednio. Dalej można już pisać właściwy program. W celu zmiany wypełnienia sygnału PWM wystarczy wpisywać odpowiednie wartości do rejestrów OCR1A oraz OCR1B.

Przykładowy szkielet widoczny jest poniżej:

Podsumowanie

Mam nadzieje, że ten krótki artykuł udowodnił, że korzystanie z dokumentacji nie jest takie trudne. Wystarczy wiedzieć czego szukać, a najważniejsze informacje znaleźć można bez problemu w stosunkowo prostych tabelach. W razie problemów zachęcam do pytania w komentarzach.

Pierwsza publikacja: Grabki, 04-07-2012
Edycja i przeniesienie na blog: Treker, 26-05-2015, grafika tytułowa: Hudyvolt

Powiadomienia o nowych, darmowych artykułach!

Załączniki

Komentarze

marek1707

9:36, 05.07.2012

#1

"po ustawieniu pinów jako wyjścia, nie możemy ich podciągać do VCC, bo PWM nie będzie działał"

Mógłbyś to wyjaśnić?

Grabki
Autor wpisu

11:38, 05.07.2012

#2

marek1707 napisał/a:

"po ustawieniu pinów jako wyjścia, nie możemy ich podciągać do VCC, bo PWM nie będzie działał"

Mógłbyś to wyjaśnić?

Nie sprecyzowałem - chodziło mi o piny będące wyjściem PWM. Już poprawiam.

ps19

12:11, 05.07.2012

#3

Mógłbyś jeszcze napisać jaki tryb PWM ustawić do wybranej czynności np. PWM z Korekcją Fazy - Sterowanie silnikiem DC itd..

Grabki
Autor wpisu

13:37, 05.07.2012

#4

ps19 napisał/a:

Mógłbyś jeszcze napisać jaki tryb PWM ustawić do wybranej czynności np. PWM z Korekcją Fazy - Sterowanie silnikiem DC itd..

Moim celem w tym artykule było przedstawić [u:f5710defef]najprostszy[/u:f5710defef] sposób uruchomienia PWM bez zbędnych szczegółów, aby można było jak najłatwiej sterować silnikami, bądź wykorzystać to do innych celów.

marek1707

14:22, 05.07.2012

#5

"po ustawieniu pinów będących wyjściem PWM jako wyjścia, nie możemy ich podciągać do VCC, bo PWM nie będzie działał"

Nadal Cię nie rozumiem. Spróbuj się nad tym zdaniem pochylić i nie zbywać odpowiedzi jednym zdaniem. W jakim sensie podciągać? Co przez to rozumiesz?

OldSkull

14:44, 05.07.2012

#6

Grabki napisał/a:

aby można było jak najłatwiej sterować silnikami, bądź wykorzystać to do innych celów.

Ale warto pomyśleć jeszcze nad możliwie dobrym i prostym sposobem. Osobiście bardzo polecam krozystanie z negacji wyjść i przesuwania w fazie poprzez wpisywanie wartości początkowej :) Można starać się zminimalizować zakłócenia na linii zasilania generowanie podczas załączania tranzystorów PWMem.

danioto

17:01, 05.07.2012

#7

Moim zdaniem ciężko to nazwać artykułem. Wszystko można byłoby zwinąć do czterech linijek kodu, nazwać "Porada, jak ustawić tryb PWM w ATMega" i na tym zakończyć, a nie nazywać tego artykułem.

1) Nie podoba mi się brak wstępu teoretycznego. To znaczy ten odnośnik.

2) Opisałeś tylko jeden tryb PWM, a sama ATMega ma ich kilka.

3) Linijki Twojego kodu można znaleźć w dokumentacji uC.

4) Dużo błędów merytorycznych (np. PID to nie algorytm tylko regulator).

Grzesieq94

17:41, 05.07.2012

#8

Przydatnym plikiem przy PWM jest http://www.societyofrobots.com/member_tutorials/files/ATMega8.pdf - ładnie rozpisane rejestry dot. PWM (tutaj dla Atmegi8)

Grabki
Autor wpisu

20:17, 05.07.2012

#9

marek1707 napisał/a:

Nadal Cię nie rozumiem. Spróbuj się nad tym zdaniem pochylić i nie zbywać odpowiedzi jednym zdaniem. W jakim sensie podciągać? Co przez to rozumiesz?

Podciąganie wewnętrznym rezystorem do napięcia zasilania.

Cytat:

1) Nie podoba mi się brak wstępu teoretycznego. To znaczy ten odnośnik.

Stwierdziłem, że skoro jest to już pisan na forum w dwóch miejscach, to bezsensu jest o tym pisać po raz trzeci.

danioto napisał/a:

3) Linijki Twojego kodu można znaleźć w dokumentacji uC.

Tyle że moim celem było napisanie tego dla osób, które jeszcze nie potrafią odnajdywać potrzebnych informacji w dokumentacji.

BlackJack

20:37, 05.07.2012

#10

Szczerze nie mam przekonania do tego artykułu, takie wszystko i nic w jednym. przy czym więcej jest tego NIC. Dla mnie wrzucenie dwóch fragmentów kodu nie czyni z tego artykułu, brak tutaj wytłumaczenia wykresu z noty ATMegi 8, wzmianki o innych trybach PWM. ja odnoszę wrażenie że pisane takie bardzo na szybko. gdyby była szkolna ocena, od 1 do 6, to dałbym dwa.

Słaby art, nie podnoszący w żaden sposób jakości forum, a pewnie będący generatorem pytań od początkujących.

Taka uwaga dla kolegów startujących w konkursie.

Nie śpieszcie się, to nie sprint, ani akord. Ja uważam że lepiej mniej artykułów, a lepszych, niż masa szybciorów, które właściwie nic nie wnoszą do tematyki forum.

marek1707

13:36, 06.07.2012

#11

Jakim rezystorem? Ustawiając kierunek portu na wyjście (odpowiednim bitem w rejestrze DDRx) nie możesz już włączyć rezystora podciągajacego - takiej opcji nie przewiduje producent, bo byłoby to dość głupie, nie sądzisz? Wyjściowy kierunek portu jest jedynym warunkiem, który musisz spełnić by móc sterować wyjściem ze sprzętowego generatora przebiegów (Waveform Generator) dołączonym do timera. O tym co się będzie z daną linią portu działo decydujesz właśnie za pomocą bitów COMxxx. Jeśli oba będą na zero, możesz spokojnie wystawiać zera i jedynki ręcznie (rejestr PORTx). Jeżeli inna kombinacja - sterowanie wyjścia przejmuje timer i wtedy to już od reszty jego ustawień zależy, co na linii portu zobaczysz. Wracając do ustawienia bitów COMxxx=00 z powrotem na wyjściu zobaczysz to, co jest wpisane do rejestru PORTx - to wydaje się dość proste i nie ma tu miejsca na żadne rezystory podciągające.

fero

0:23, 05.01.2014

#12

Świetnie wytłumaczony(w przystępnym angielskim) temat PWM, jego trybów i konfiguracji dla AVR jest tutaj: http://www.societyofrobots.com/member_tutorials/book/export/html/228

Treker
Administrator

9:46, 26.05.2015

#13

Artykuł został trochę przeredagowany i przeniesiony na bloga :)

Wszystko, co musisz wiedzieć, aby uruchomić PWM

konradem

12:24, 28.05.2015

#14

Fajna szybka ściąga jak uruchomić PWMy na Atmedze.

pelson

23:19, 23.04.2017

#15

genialne :) w internetach jest cała masa materiałów a temat PWM ale nie ma nigdzie opisane tak ładnie krok po kroku jak uruchomić od A do Z

po wielu dniach prób głupiego sterowania jasnością diody nareszcie są jakieś postępy

dziękuję za ten artykuł

Zobacz powyższe komentarze na forum

FORBOT Damian Szymański © 2006 - 2018 Zakaz kopiowania treści oraz grafik bez zgody autora. vPRsLH.