Kurs STM32 F1 HAL – #6 – pomiar napięcia, przetwornik ADC

Kurs STM32 F1 HAL – #6 – pomiar napięcia, przetwornik ADC

Tym razem sprawdzimy działanie przetwornika analogowo-cyfrowego. Dzięki niemu będziemy mogli zmierzyć napięcie na wejściu układu.

Podstawowa wiedza o ADC przydaje się prawie zawsze podczas tworzenia nowych projektów. Peryferia te używane są w większości systemów, które np. mają czujniki analogowe.

Przetwornik ADC w STM32 F1

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 można 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 opisywany 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ć następującą wartość:

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 UART 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

Gwarancja pomocy na forum Błyskawiczna wysyłka

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!

Kup w Botland.com.pl

STM32 - pomiar napięcia referencyjnego

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

Nie konfigurowaliśmy jeszcze pętli PLL, więc nasz układ pracuje z domyślnym taktowaniem 8MHz. Oznacza to, że nawet bez dzielnika mieścimy się w zakresie pracy przetwornika analogowo-cyfrowego. Niestety najmniejsza wartość dzielnika to 2, czyli zegar naszego przetwornika będzie pracował z częstotliwością 4 MHz. Konfigurujemy go następującym kodem:

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.

Teraz możemy wykonać autokalibrację przetwornika. Powinniśmy wykonać ją raz na początku programu. Dzięki temu odczyty będą dokładniejsze:

Następnie ustawiamy parametry multipleksera. Przetwornik może odczytywać dane nawet z 16 wejść zewnętrznych (numerowanych od 0 do 15), termistora (kanał 16) lub napięcia referencyjnego (kanał 17). Właśnie ten kanał (17) nas interesuje:

Ostatni parametr to liczba cykli przeznaczonych na próbkowanie wartości wejściowej. Wybieramy wartość 13.5 cyklu na pomiar (możliwe są wartości od 1.5 cyklu do 239.5). 

Włączenie przetwornika ADC

Nasz przetwornik jest już skonfigurowany. Pozostaje uruchomić 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: HAL_ADC_GetValue.

Chcemy sprawdzić, jakie otrzymujemy rezultaty, nasz wynik wyślemy więc przez UART. W poprzednich częściach kursu omówiliśmy jak przekierować wyjście funkcji printf. Kod jest więc prosty:

Cały program wygląda następująco:

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 nie jest idealny, a ostatnia cyfra 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 Reference Manual mikrokontrolera.

STM32 - pomiar napięcia zewnętrznego

Pierwszy przykład dał nam możliwość upewnienia się, że umiemy obsługiwać przetwornik ADC. 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 od 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 (Mode Analog). Poprzednio odczytywaliśmy dane z kanału 17, teraz interesuje nas kanał 0. Wybieramy go następującym kodem:

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 kolejny 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.

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.

Pomiar napięcia z kilku kanałów ADC na STM32

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ą HAL_ADC_GetValue pobieraliśmy odczytaną wartość. Takie działanie było wystarczające w przypadku jednego wejścia. Jednak gdyby przetwornik sprawdzał dwa wejścia to nie moglibyśmy pobrać dwóch wartości. HAL_ADC_GetValue 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 HAL_ADC_GetValue 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. Wykorzystujemy 2 wejścia, więc musimy je odpowiednio skonfigurować:

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

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

Pierwsza część, to wybór kanału, następna, to uruchomienie konwersji i oczekiwanie na zakończenie konwersji wykorzystując funkcję HAL_ADC_PollForConversion. Gdy dane są gotowe, odczytujemy je za pomocą HAL_ADC_GetValue.

Mając tę funkcję możemy w pętli głównej programu odczytać 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 jak ś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

Autor kursu: Piotr Bugalski
Testy: Piotr Adamczyk
Redakcja: Damian Szymański

ADC, kursSTM32F1HAL, stm32, uart

Komentarze

Komentarze do tego wpisu są dostępne na forum: