Książki o elektronice i programowaniu w promocji 2 za 1 (tańsza za 0 zł)! Sprawdź listę tytułów »

Kurs STM32 – #6 – Pomiar napięcia, przetwornik ADC

Kurs STM32 – #6 – Pomiar napięcia, przetwornik ADC

Tym razem poznamy bliżej działanie przetwornika analogowo-cyfrowego. Za jego pomocą będziemy mogli zmierzyć napięcie na wejściu układu.

Podstawowa wiedza o ADC konieczna jest nie tylko przy budowie robotów. Peryferia te używane są w większości systemów, które mają czujniki.

ADC w naszym STM32

Mikrokontroler STM32F103RB jest wyposażony w dwa, 12-bitowe przetworniki analogowo-cyfrowe. Każdy z przetworników posiada na wejściu multiplekser, dzięki któremu odczytywać dane nawet z 16 różnych linii wejściowych.

Efekt działania jednego z programu, ADC na STM32.

Działanie programu, ADC na STM32.

Dodatkowo nasz układ posiada wbudowany czujnik temperatury oraz źródło napięcia referencyjnego 1.2V. O ile czujnik temperatury jest mało dokładny i można nim mierzyć tylko zmiany temperatury, o tyle napięcie referencyjne możemy wykorzystać do przetestowania naszego sposobu odczytu napięcia za pomocą ADC.

Jak interpretować wynik?

Najpierw odrobina matematyki. Pomiar wykonywany jest względem napięcia zasilania, czyli 3.3V. Czujnik jest 12-bitowy, więc wynik jest liczbą z zakresu 0 - 4095 (212 = 4096 wartości). Jeśli na wejściu przetwornika pojawi się napięcie Vadc, powinniśmy odczytać wartość, którą możemy obliczyć według wzoru:

ADC = Vadc  / 3.3V * 4096

Przykład: wiemy, że napięcie referencyjne to 1.2V, jaki powinniśmy otrzymać odczyt?

ADC = 1.2V / 3.3V * 4096 = 1489

Spróbujmy teraz napisać program, który odczyta wartość napięcia referencyjnego, a wynik wyśle przez złącze szeregowe do komputera PC - nauczyliśmy się, jak to zrobić w poprzedniej części kursu. Dzięki temu sprawdzimy, czy uzyskamy wynik zgodny z naszymi oczekiwaniami. 

Zestaw elementów do kursu

 999+ pozytywnych opinii  Gwarancja pomocy  Wysyłka w 24h

Zestaw ponad 120 elementów do przeprowadzenia wszystkich ćwiczeń z kursu można nabyć u naszych dystrybutorów! Dostępne są wersje z płytką Nucleo lub bez niej!

Zamów w Botland.com.pl »

STM32 - pomiar napięcia referencyjnego

Jak wiemy, STM32F103 posiada dwa przetworniki A/C. Napięcie referencyjne jest podłączone tylko do pierwszego z nich, oznaczonego jako ADC1. Pierwszy krok, to jak zwykle podłączenie zegara:

Ponieważ zegar systemowy ma częstotliwość 64MHz, konieczne jest zmniejszenie częstotliwości za pomocą preskalera, czyli dzielnika częstotliwości. Podzielimy 64MHz przez 6, dzięki temu uzyskamy nieco ponad 10MHz, a więc wartość w dopuszczalnym zakresie.

Następnie musimy zadeklarować zmienną konfiguracyjną przetwornika i ustawić parametry pracy:

Wybieramy tryb ciągły, nasz przetwornik będzie wykonywał jeden pomiar po drugim. Ustawiamy liczbę kanałów na 1 oraz wyzwalanie na brak – uruchomimy przetwornik programowo.

Następnie musimy ustawić parametry multipleksera. Przetwornik może odczytywać dane z maksymalnie 16 wejść zewnętrznych (numerowanych od 0 do 15), termistora (kanał 16) lub napięcia referencyjnego (kanał 17). Właśnie kanał 17 jest tym który nas interesuje:

Ostatni parametr to liczba cykli przeznaczonych na próbkowanie wartości wejściowej. Ponieważ nie potrzebujemy wyników bardzo szybko wybieramy wartość 71.5 cyklu na pomiar (możliwe są wartości od 1.5 cyklu do 239.5).

Włączenie przetwornika ADC i kalibracja

Nasz przetwornik jest już skonfigurowany. Pozostaje go włączyć:

Aby poprawić dokładność pomiarów powinniśmy wykonać autokalibrację przetwornika. Jest to czynność zalecana, chociaż niewymagana. Należy ją wykonać po uruchomieniu przetwornika, czyli dokładnie teraz. Kod wygląda następująco:

Nasz przetwornik jest już gotowy do pracy, włączmy więc napięcie referencyjne (1.2V) i możemy zaczynać pomiar:

Przetwornik działa w trybie ciągłym, nie musimy więc ponownie startować pomiaru, ani czekać na jego zakończenie. Wystarczy odczytać wartość za pomocą funkcji: ADC_GetConversionValue.

Ponieważ chcemy sprawdzić, jakie otrzymujemy rezultaty, to nasz wynik wyślemy przez UART. W poprzednich częściach kursu omówiliśmy jak przekierować wyjście funkcji printf. Dzięki temu kod jest bardzo prosty:

Cały program wygląda jak poniżej:

Natomiast wyniki działania programu przedstawia poniższy zrzut ekranu:

ADC_01

Wartość odczytana z przetwornika ADC na STM32.

Jak widać otrzymaliśmy, prawie, to co wychodziło z naszych obliczeń. Spodziewaliśmy się wyniku 1489, a otrzymaliśmy 1490-1491. Widzimy więc, że nasz program działa poprawnie. Warto zwrócić uwagę, że wynik jest nieco inny niż idealny, a ostatnia cyfra jak widać zmienia się w kolejnych pomiarach.

Zadanie domowe 6.1

Oblicz częstotliwość próbkowania, którą ustawiliśmy w pierwszym przykładzie (czyli częstotliwość z jaką są wykonywane pomiary). Niezbędne informacje są w dokumentacji (Reference Manual) mikrokontrolera.

STM32 - pomiar napięcia zewnętrznego

Pierwszy przykład dał nam możliwość upewnienia się, że umiemy obsługiwać przetwornik A/C. Jednak pomiar znanego napięcia referencyjnego nie jest zbyt pasjonujący. Spróbujmy więc zmierzyć napięcie podłączone z zewnątrz.

Elementy, wykorzystane w dalszej części artykułu:

STM32_6_6

Bez specjalnych zabezpieczeń możemy do wejścia przetwornika podłączyć tylko napięcia z zakresu Vss do Vdd, czyli od 0V do 3.3V. Każde napięcie spoza tego zakresu może uszkodzić mikrokontroler.

Aby temu zapobiec podłączymy potencjometr między masę, a zasilanie 3.3V – w takim układzie, kręcąc potencjometrem będziemy mogli regulować napięcie w pełnym, bezpiecznym zakresie.

Używając multimetru będziemy mogli również zweryfikować nasze wyniki. Podłączmy napięcie z potencjometru do pinu PA0. Jest to jednocześnie wejście kanału 0 przetwornika ADC1.

adc-pot_bb

Zdjęcie złożonego układu:

STM32_6_2

Program będzie bardzo podobny do poprzedniego, omówmy więc tylko różnice. Pierwsza zmiana, to konieczność skonfigurowania pinu PA0 jako wejścia analogowego. W tym celu piszemy:

Jak widać poznaliśmy nowy tryb pracy pinu – wejście analogowe (Analog In). Poprzednio odczytywaliśmy dane z kanału 17, teraz interesuje nas kanał 0. Wybieramy go instrukcją:

W tym przykładzie nie używamy już napięcia referencyjnego, nie musimy więc go podłączać (programowo). Jeśli jednak podłączymy, nic złego się nie stanie, ale zawsze możemy zaoszczędzić odrobinę prądu rezygnując z nieużywanego elementu.

Pozostały kod wygląda dokładnie tak samo jak w poprzednim przykładzie. Czas uruchomić program i obserwować odbierane dane zmieniając nastawy potencjometru. Warto również porównać wyniki ze zmierzonymi za pomocą multimetru.

Cały kod wygląda więc następująco:

Uruchomiony program prezentował następujące dane:

ADC_03

STM32 - pomiar napięcia zewnętrznego.

Pomiar uzyskany multimetrem w moim przypadku wynosił: 1.460 V, więc jak widać wskazania przesyłane z STM32 do komputera były zbliżone.

Czujnik oświetlenia

Czas na bardziej robotyczny przykład. Odłączmy potencjometr, a w jego miejsce podłączmy fotorezystor oraz rezystor tworząc dzielnik napięcia. Schemat montażowy widoczny jest poniżej:

adc-phres_bb

Układ złożony w praktyce:

STM32_6_4

Teraz możemy zobaczyć jak zmieniają się odczyty naszego układu, w zależności od poziomu oświetlenia. Dokładnie w ten sposób możemy zbudować światłoluba, czyli prostego robota szukającego silniejszego źródła światła. Podobnie działają również czujniki odbiciowe, używane w robotach typu linefollower, czy micromouse.

Niestety jeden czujnik nie wystarczy do sterowania robota, potrzebujemy więc odczytu napięcia z większej ilości kanałów ADC.

Zadanie domowe 6.2

Napisz program do automatycznej lampki, która będzie zapalała diody święcące w zależności od poziomu zewnętrznego oświetlenia.

Zadanie domowe 6.3

Za pomocą funkcji ADC_RegularChannelConfig ustalamy czas pobierania próbek przez przetwornik. Spróbuj zmieniać ten czas, porównaj stabilność i wynik odczytów. Przeprowadź testy dla wartości z zakresu  od ADC_SampleTime_1Cycles5 do ADC_SampleTime_239Cycles5.

STM32 - pomiar napięcia z kilku kanałów

Spróbujmy odczytać dane z więcej niż jednego czujnika. Na początek zmieniamy konfigurację naszego układu. Do pinów PA0 i PA1 podłączymy potencjometry, a w programie spróbujemy odczytywać wartości z obu wejść.

adc-pot2-b_bb

Układ złożony w praktyce:

STM32_6_3

Poprzednio uruchomiliśmy przetwornik w trybie ciągłym, a funkcją ADC_GetConversionValue pobieraliśmy odczytaną wartość. Takie działanie było wystarczające w przypadku jednego wejścia.

Jednak gdyby przetwornik ciągle odczytywał np. dwa wejścia, jak moglibyśmy pobrać dwie wartości? ADC_GetConversionValue zwraca wynik ostatniego pomiaru, jednak nie pozwala na wybór, które wejście chcemy odczytać.

Moglibyśmy wykorzystać tryb ciągły i np. w przerwaniach pobierać dane – jest to popularna metoda w przypadku mikrokontrolerów 8-bitowych, np. AVR. Wywołujemy ADC_GetConversionValue zaraz po zakończeniu konwersji i zapisujemy wynik w buforze. Ponieważ przerwanie jest zgłaszane zaraz po otrzymaniu kolejnego wyniku, możemy pobrać dane z obu czujników.

Takie rozwiązanie jest jednak bardzo nieefektywne - procesor "co chwilę" musi obsługiwać przerwania tylko po to, żeby buforować wyniki pomiarów.

Teraz wykorzystajmy jednak tryb pojedynczego odczytu - będziemy uruchamiać przetwornik i czekać na wynik. Ponieważ wykorzystujemy 2 wejścia, to musimy je odpowiednio skonfigurować:

Wyłączamy tryb ciągły, nie chcemy żeby przetwornik ciągle odczytywał dane:

Ponieważ będziemy odczytywać dwa kanały, napiszemy funkcję, która skonfiguruje multiplekser wejściowy przetwornika, uruchomi pomiar, poczeka na zakończynie i odczyta wyniki. Oto jej treść:

Pierwsza linia, to wybór kanału, a następna, to uruchomienie konwersji. W pętli while czekamy na koniec przetwarzania (EOC – End Of Conversion). Gdy dane są gotowe, odczytujemy je za pomocą ADC_GetConversionValue.

Mając tą funkcję możemy w pętli głównej programu odczytywać oba wejścia przetwornika:

Cały kod programu wygląda następująco:

Wynik działania programu widoczny jest na poniższym zrzucie ekranu. Przy okazji widać tutaj w praktyce, dlaczego programiści tak bardzo lubią printf:

ADC_04

Odczytywanie napięcia z dwóch kanałów - STM32.

Zadanie domowe 6.4

Podłącz więcej czujników i potencjometrów, np. dwa fotorezystory i dwa potencjometry. Napisz program, który wysyła wszystkie dane do komputera za pomocą UARTa.

Prawie światłolub

Czas zastąpić potencjometry fotorezystorami. Poprzednio wykorzystywaliśmy jeden, teraz możemy podłączyć dwa czujniki.

adc-phres2_bb

Układ złożony w praktyce:

STM32_6_5

Na początek wystarczy nam program który już mamy - za jego pomocą możemy sprawdzić jak nasz światłlub reaguje na zmiany oświetlenia. Jeśli odpowiednio ustawimy czujniki, będziemy mogli obserwować zmiany odczytów w zależności od kierunku, z którego oświetlimy nasz układ.

Napisanie programu, który na podstawie wartości odczytanych z czujników podejmie decyzję w którą stronę ma się poruszać robot jest już dosyć łatwe - i będzie to świetna praca domowa.

Zadanie domowe 6.5

Napisz program do sterowania światłolubem. Zamiast sterowania silnikami, wysyłaj na złącze szeregowe, co robot powinien robić, np. komendy "prosto", "w lewo", "w prawo".

Podsumowanie

Tym razem omówiliśmy podstawy wykorzystywania przetwornika ADC dostępnego w układach STM32. Na ten moment widoczne są dwie główne zalety (względem AVR) - duża liczba dostępnych kanałów oraz stosunkowo niski czas wykonania pomiaru. Jednak prawdziwa rewolucja dopiero przed nami, mowa oczywiście o DMA, które odmieni sposób korzystania z ADC!

Nawigacja kursu

W następnej części zajmiemy się jednym z trudniejszych tematów, czyli licznikami (timerami). Jeśli nie chcesz przeoczyć kolejnego odcinka, to skorzystaj z poniższego formularza i zapisz się na powiadomienia o nowych publikacjach!

Autor kursu: Piotr (Elvis) Bugalski
Redakcja: Damian (Treker) Szymański

ADC, kursSTM32, stm32, uart

Trwa ładowanie komentarzy...