Przejdź do głównej zawartości

Programowanie AVR cz.8: Przetwornik analogowo-cyfrowy oraz modulacja szerokości impulsu.

Dziś kolejny wgląd w wyposażenie mikrokontrolera ATmega48P - tym razem przyglądamy się wbudowanemu w układ przetwornikowi analogowo-cyfrowemu oraz - dostępnej również w modelach ATtiny - modulacji szerokości impulsu realizowanej przez timery.

Artykuł ten jest w pewnym sensie wstępem do następnego, który pojawi się już wkrótce, a którego tematykę zdradziłem na końcu.

Przetwornik A-C (skrót spotykany w anglojęzycznej literaturze to ADC od Analog to Digital Converter) to układ pozwalający na zamianę wartości napięcia (elektrycznego sygnału analogowego ;-)) na liczbę. W przypadku mojej ATmegi przetwornik ma rozdzielczość 10-bitową, co oznacza, że wartość napięcia podawanego na wejście przetwornika może być po konwersji zapisana jako liczba z przedziału od 0 do 1023 (musimy użyć zmiennej word do zapamiętania tej liczby). Jeśli jesteśmy w posiadaniu mikrokontrolera w obudowie PDIP 28-wyprowadzeniowej, to mamy do dyspozycji sześć kanałów (niezależnych wejść) przetwornika A-C, przyporządkowanych wyprowadzeniom od 23 do 28. W sumie wszystkich kanałów jest osiem plus jeden dodatkowy, o którego przeznaczeniu napiszę w następnym artykule. Kwestie zasilania układu podczas korzystania z ADC przedstawiłem krótko na końcu posta.

Obsługa przetwornika analogowo-cyfrowego w BASCOMie wymaga wstępnej konfiguracji, podczas której ustawiamy m. in. tryb działania przetwornika (ciągły lub "na żądanie") oraz wartość napięcia odniesienia (najczęściej wartość doprowadzona do wyprowadzenia AVCC układu lub wewnętrzna wartość domyślna 1,1V). Szczegóły znajdziecie na stronie pomocy BASCOMa. Przykład konfiguracji (patrz: listing):

' Konfiguracja przetwornika analogowo-cyfrowego; napięcie odniesienia ustalone na 5V 
' (patrz: wyprowadzenie AVCC mikrokontrolera), czyli przedział od 0 do około 5V będzie 
' "rzutowany" na 10-bitową liczbę (od 0 do 1023). 
Config Adc = Single , Prescaler = Auto , Reference = Avcc 

Pojedyncze odczyty wykonywane są (w trybie "single") za pomocą funkcji getadc, która jako parametr przyjmuje numer kanału (w przypadku kanałów dostępnych fizycznie jest to liczba z przedziału od 0 do 5). Musimy pamiętać, że konwersja sygnału analogowego na cyfrowy wymaga czasu, dlatego też żeby otrzymać wiarygodne odczyty, należy unikać "lawinowego" wywoływania funkcji getadc. Wywołanie funkcji getadc w znakomitej większości przypadków sprowadza się do podania jako parametru numeru kanału przetwornika i zapamiętania wyniku w zmiennej typu word:

Dim Odczyt_0 As Word 
... 
Odczyt_0 = Getadc(0) 

Zawartość zmiennej Odczyt_0 możemy teraz swobodnie interpretować.

Kolejny opisywany dziś element wyposażenia ATmegi to generator PWM (ang. Pulse Width Modulation). Modulacja szerokości impulsu realizowana jest przez każdy z trzech timerów, jednak trzeba pamiętać, że tylko jeden z nich (timer1) jest 16-bitowy - pozostałe dwa to liczniki/timery 8-bitowe.
Jeśli chodzi o istotę zjawiska, modulacja szerokości impulsu to nic innego jak zmiana współczynnika wypełnienia dla fali prostokątnej o określonej częstotliwości.

Konfigurując timer jako generator PWM musimy ustalić, z jaką częstotliwością mają być generowane impulsy, jaki ma być zakres licznika (8, 9 czy 10 bitów; dotyczy tylko timera 16-bitowego - w przypadku liczników 8-bitowych nie ma możliwości zmiany zakresu) i czy rejestr porównania (przedstawiony w dalszym ciągu artykułu) ma decydować o szerokości (czasie trwania) logicznego zera bądź jedynki logicznej.

Przykład konfiguracji ośmiobitowego timera jako generatora PWM (szczegóły znajdziecie w dokumentacji BASCOMa - Timer0 i Timer1):

' Timer0 pracujący z największą szybkością w trybie PWM; porównywanie wartości timera 
' w systemie "clear up" spowoduje zwiększanie szerokości impulsu wraz ze wzrostem wartości zmiennych 
' PWM0A i PWM0B (patrz dalej). 
Config Timer0 = Pwm , Prescale = 1 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up 

W dalszej części artykułu skupimy się właśnie na 8-bitowym timerze 0.

Każdy timer pracujący w trybie PWM posiada dwa wyjścia (stąd wniosek, że mamy do dyspozycji 6 kanałów PWM) - dla timera 0 są to OC0A i OC0B, przypisane odpowiednio wyprowadzeniom 11 i 12 układu. Każde z tych wyjść może być osobno konfigurowane ze względu na współczynnik wypełnienia przebiegu, czyli na dobrą sprawę mogą one pracować niezależnie (przynajmniej z punktu widzenia programu).

Za zmianę szerokości impulsu odpowiadają tzw. rejestry porównania, które w BASCOMie dostępne są poprzez zmienne (a raczej identyfikatory, symbole) Pwm0a i Pwm0b (dla timera 0; w przypadku pozostałych timerów używamy identyfikatorów z odpowiednio podmienioną cyfrą, zresztą podobnie rzecz ma się ze wspomnianymi wcześniej wyjściami). Wartości tych zmiennych, których rozmiar jest uzależniony od konfiguracji timera (w przypadku timera 0 są to zmienne 8-bitowe), mogą być ustalane programowo. Są one cyklicznie porównywane ze stanem licznika i w oparciu o wynik tego porównania (i konfigurację generatora) ustalany jest - że użyję szalenie skompresowanego skrótu - czas trwania jedynki logicznej lub zera logicznego na wyjściu generatora PWM.

Wyczerpujący opis działania timerów jako generatorów PWM w mikrokontrolerach AVR przedstawił Piotr Górecki w swojej książce Mikrokontrolery dla początkujących (Wydawnictwo BTC, Warszawa 2006) - polecam.

Ilustracją do tego artykułu jest prosty układ, przedstawiony na poniższym schemacie:


Za pomocą potencjometrów, które pełnią tutaj rolę regulowanych dzielników napięcia, podajemy na kanały 0 i 1 przetwornika analogowo-cyfrowego napięcie o wartościach między 0 a 5V (uwaga: program zakłada, że pracujemy z napięciem zasilania równym 5V; można obniżyć napięcie, ale wyniki wyświetlane na LCD będą przekłamane, chyba, że zmienimy w programie przelicznik). Wartość odczytanego z ADC napięcia, przetworzona na postać liczbową, a następnie na wolty według zaszytego w programie przelicznika, jest wizualizowana na opcjonalnie dołączonym do układu wyświetlaczu LCD (opisywany przeze mnie moduł wyświetlacza sterowany przez port szeregowy UART), natomiast za jasność świecenia diod LED odpowiada właśnie współczynnik wypełnienia przebiegu prostokątnego pozyskanego z generatora PWM. Współczynnik ten zależy w sposób pośredni od wartości napięcia odczytanej przez ADC, więc za pomocą potencjometrów regulujemy jasność świecenia diod.

Program z przedstawionego niżej listingu nie powinien zawierać żadnego zaskakującego elementu - kod sam dla siebie stanowi komentarz, choć parę rzeczy dorzuciłem.

Na koniec uwaga dotycząca zasilania mikrokontrolera podczas korzystania z przetwornika analogowo-cyfrowego. Zapewne zauważyliście, że lewa strona schematu zawiera mnóstwo kondensatorów o wartości 100nF oraz cewkę 10μH. Jest to po prostu standardowe podłączenie zasilania, zgodne z kartą katalogową ATmegi, szalenie ważne ze względu na prawidłową filtrację napięcia, pozwalającą uniknąć niestabilnego działania układu, a w niektórych przypadkach nawet umożliwić w ogóle działania.

W następnym poście przedstawię schemat układu szalenie prądożernego termometru mikroprocesorowego - oczywiście wykorzystującego m. in. opisane tutaj ficzery.

Komentarze

Popularne posty z tego bloga

Niesamowicie prosty czujnik zmierzchowy.

Tym razem zero programowania, będzie natomiast nostalgiczno-wspomnieniowy układzik, lekko zmodyfikowany. Otóż kilka dni temu rozmawialiśmy w gronie znajomych o różnego rodzaju czujnikach zmierzchowych i czujnikach ruchu. Ponieważ należę do tych wariatów, co to hołdują jeszcze owej przestarzałej i kompletnie odrealnionej dziś zasadzie: "po co kupować, gdy można zrobić", stwierdziłem, że poskładam takie coś (czujnik zmierzchowy; sensor ruchu faktycznie lepiej nabyć, choćby ze względu na rozmiary ;)) i być może podłączę do jakiegoś mikrokontrolera. Przypomniało mi się też przy okazji, że znalazłem ostatnio w elektronicznych śmieciach stary fotorezystor (dla niewtajemniczonych: element zmieniający rezystancję, czyli opór elektryczny, pod wpływem działania strumienia światła) RPP130, jeden z kilku pozostałych po montowanych wieki temu układach tranzystorowych do zdalnego sterowania pracą urządzeń za pomocą latarki... No OK, nie było to specjalnie rozbudowane zdalne sterowanie ;)

Aktualizacja oprogramowania układowego w ESP-01 do najnowszej wersji NodeMCU

Oprogramowanie i projekt NodeMCU cieszą się niesłabnącym zainteresowaniem świata konstruktorów urządzeń IoT, zatem co jakiś czas warto odświeżyć sobie firmware w naszych płytkach ESP. Osobiście jestem przeciwnikiem zmienienia czegoś, co dobrze działa, tylko dla zasady czy z chęci cieszenia się świadomością posiadania najnowszej wersji, ale tym razem chodzi jednak o coś innego – zwiększenie funkcjonalności i zapewnienie poprawnego działania oraz kompatybilności z najnowszymi projektami i bibliotekami. W tytule tego artykułu jest mowa o najprostszych płytkach z układem ESP8266 – ESP-01 . To właśnie w oparciu o ten model opracowałem płytkę prototypową, o której pisałem w poprzednim rozdziale. Dotychczas wszystkie moje płytki ESP miały na pokładzie oprogramowanie NodeMCU w wersji 0.9.5 . Zorientowani choć trochę w temacie od razu zauważą (Google? Bing?), że wersja ta ma już co najmniej dwa lata... Najwyższy czas zatem na aktualizację.

Płytka prototypowa na bazie ESP8266 (ESP-01)

To nie jest kolejny artykuł traktujący od początku do... nieco dalej (bo na pewno nie do końca) o płytkach ESP8266 . Żeby się dowiedzieć, co to takiego, odwiedźcie proszę np. tę stronę (oraz wiele innych – poproście o pomoc Waszą ulubioną wyszukiwarkę): http://www.esp8266.com/wiki/doku.php?id=esp8266-module-family . No ale żeby nie było, ESP8266 to układ zawierający na pokładzie wydajny mikrokontroler z rdzeniem RISC-owym, taktowany zegarem 40MHz (wersja, o której jest ten wpis) lub 80MHz, 512KB pamięci flash i podsystem komunikacji przez sieć WiFi . Jest powszechnie wykorzystywany jako swego rodzaju karta sieciowa do połączeń bezprzewodowych naszych urządzeń IoT , które budujemy w zaciszu domowych laboratoriów (i nie tylko). Układ montowany jest na płytkach występujących w kilku wersjach, różniących się przede wszystkim liczbą wyprowadzeń uniwersalnych, czyli GPIO – im większa liczba, tym większe możliwości wykorzystania układu (więcej urządzeń peryferyjnych itp.). Są też pewne