Kurs Arduino II – #7 – termometry analogowe i cyfrowe

Kurs Arduino II – #7 – termometry analogowe i cyfrowe

Podczas tej części kursu Arduino porównamy dwa podejścia do czujników. Sprawdzimy w praktyce termometry w wersji analogowej i cyfrowej!

W tym celu skorzystamy z bardzo popularnych czujników LM35 oraz DS18B20. Połączenie tych układów z poznanymi diodami programowalnymi pozwoli zbudować ciekawy termometr domowy!

W tej części kursu Arduino zajmiemy się czujnikami temperatury, które mogą się przydać podczas realizacji wielu projektów. Tym razem część elektroniczna będzie bardzo łatwa. Najważniejsze, aby po tej lekcji zapamiętać różnicę między czujnikami analogowymi i cyfrowymi.

Czujnik analogowy vs. czujnik cyfrowy

Tak jak było już omawiane w kursie podstaw elektroniki (poziom 2) na rynku dostępna jest ogromna ilość czujników. Sensory koloru, dźwięku, odległości, położenia - jest tego naprawdę dużo! Można jednak zdecydowanie wyróżnić dwie grupy czujników:

  • czujniki cyfrowe,
  • czujniki analogowe.

Czujniki analogowe zamieniają mierzoną wielkość (np. temperaturę) na wielkość elektryczną, która jest proporcjonalna do odczytanej wartości. Przykładowo wraz ze wzrostem temperatury na wyjściu czujnika będzie coraz wyższe napięcie lub pojawi się większa rezystancja.

Czujniki cyfrowe wysyłają informację w postaci ciągu bitów. Do jej odczytania potrzebne są układy cyfrowe, najczęściej mikrokontrolery - czyli np. nasze Arduino.

Termometr analogowy (1) - na wyjściu napięcie (3).Termometr cyfrowy (2) - na wyjściu sygnał binarny (4).

Termometr analogowy (1) - na wyjściu napięcie (3).
Termometr cyfrowy (2) - na wyjściu sygnał binarny (4).

W obecnych czasach czujniki cyfrowe zyskują na popularności. Mogą realizować coraz bardziej skomplikowane pomiary, a odczytanie i poprawne zinterpretowanie wyników z takich sensorów bywa łatwiejsze od podobnych układów analogowych.

Wiele osób decyduje się nadal na korzystanie z czujników analogowych, ponieważ są one tańsze. Co więcej, w przypadku prostych pomiarów typu termometr, sensor z wyjściem analogowym może być zwyczajnie wygodniejszy (wystarczy podłączyć go do wejścia analogowego).

Przejdźmy więc do praktyki!

Zestaw elementów do kursu

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

Części do wykonania ćwiczeć z kursu Arduino (poziom 2) dostępne są w formie gotowych zestawów! W komplecie m.in. diody programowalne, termometry analogowe i cyfrowe, wyświetlacze 7-segmentowe oraz czujnik ruchu (PIR).

Zamów w Botland.com.pl »

Termometr analogowy:  LM35

Na początku zajmiemy się popularnym termometrem LM35. Czujnik zamknięty jest w obudowie typu TO-92, którą najczęściej kojarzymy z tranzystorami. Oczywiście jej wyprowadzenia mają tutaj zupełnie inne zadanie. W przypadku LM35 skrajne nóżki doprowadzają zasilanie, a ze środkowej będziemy odczytywać temperaturę (mierząc napięcie).

Najważniejsze informacje na temat termometru analogowego LM35:

  • skalibrowany dla skali Celsjusza (10 mV/°C),
  • pomiar w zakresie od 0 do 100°C,
  • napięcie zasilania od 4 do 30V,
  • po szczegóły odsyłam do noty katalogowej.

Jak widać, dopuszczalny zakres zasilania jest wręcz ogromny. My oczywiście zasilimy czujniki ze standardowych 5V dostępnych na płytce Arduino. Sensor LM35 jest liniowy, oznacza to, że za każdym razem wzrost napięcia wyjściowego o 10 mV będzie oznaczał dodatkowy 1°C.

Podłączenie LM35 do Arduino

Zacznijmy od podłączenia jednego czujnika. Podłączamy zasilanie, tak jak było to zaznaczone na powyższym rysunku. Następnie środkowe wyprowadzenie łączymy bezpośrednio z analogowym pinem Arduino (np. A5).

Przykładowe podłączenie czujnika LM35 do Arduino.

Przykładowe podłączenie czujnika LM35 do Arduino.

To zdecydowanie jedno z najprostszych podłączeń wymaganych podczas kursu, oby zawsze było już tak łatwo! Teraz można przejść do programu...

Odczytanie temperatury: czujnik analogowy

Zadaniem programu będzie odczytanie napięcia na pinie A5 i jego odpowiednie przeliczenie. Tak, jak napisano w dokumentacji 1°C, to 10 mV. W związku z tym najpierw wartość ADC należy przeliczyć na napięcie. Dla przypomnienia robimy to mnożąc odczyt razy 5, a następnie wynik ten dzielimy przez 1024 (zakres pracy przetwornika to 0...1023). Aby uzyskać stopnie Celcjusza na koniec otrzymaną wartość mnożymy razy 100 (bo każde 10 mV, to 1 stopień).

W programie można to zapisać w jednej linii:

Po uruchomieniu powyższego programu w monitorze portu szeregowego będziemy otrzymywać odczyty aktualnej temperatury. Poniższa animacja przedstawia działanie czujnika po jego ogrzaniu.

Zmiana odczytów temperatury.

Zmiana odczytów temperatury.

Gdy spróbujemy ochłodzić czujnik (np. za pomocą kostki lodu), to na ekranie pokaże się "tylko" 0°C. Niestety, aby LM35 mógł mierzyć temperatury ujemne należy zmienić jego podłączenie. Dokładne informacje na ten temat znaleźć można w nocie katalogowej!

Zadanie dodatkowe 7.1

Rozbuduj program tak, aby mógł obsługiwać 2 czujniki temperatury i wyświetlać ich wyniki obok siebie. Trzecią wyświetlaną wartością (w nowej linii) powinna być różnica między 2 odczytami.

Termometr z funkcją MAX/MIN

Załóżmy jednak, że pomiar temperatury w zakresie 0-100°C nam wystarczy. Zbudujmy termometr pokojowy z funkcją zapamiętywania minimalnej i maksymalnej temperatury.

Zacznijmy od zapamiętywania najwyższej wartości w tym celu wystarczy utworzyć zmienną np.:

Oczywiście zmienna ta musi zostać zadeklarowana na samym początku (przed setup()/loop()), bo nie chcemy, aby każdy obieg pętli loop() ją zerował. Teraz musimy sprawdzić, czy aktualnie panuje najwyższa temperatura. Jak tego dokonać?

Wystarczy w każdym obiegu pętli sprawdzić, czy aktualna temperatura jest większa od zapisanej wartości maksymalnej, a następnie:

  • jeśli warunek będzie spełniony,
    to aktualna wartość powinna zostać zapisana jako maksymalna,
  • jeśli warunek nie będzie spełniony,
    to nie robimy nic!

W praktyce, cały program będzie wyglądał następująco:

Tym razem w monitorze portu szeregowego zobaczymy tylko informacje o najwyższej wartości. Nie ma takiej możliwości, aby kolejna pojawiająca się wartość była mniejsza od poprzedniej:

Zapamiętywanie wartości maksymalnej (animacja zapętlona).

Zapamiętywanie wartości maksymalnej (animacja zapętlona).

Teraz analogicznie spróbujmy zapamiętać wartość minimalną. Tworzymy nową zmienną:

Następnie sprawdzamy, czy aktualna wartość jest mniejsza od poprzednio zapisanej, czyli:

No i świetnie, tylko powyższe szukanie najniższej możliwej temperatury nie zadziała! Podczas tworzenia nowej zmiennej przypisaliśmy jej wartość "0", nie jest więc możliwe, aby kiedykolwiek odczytać jeszcze niższą temperaturę (nasz czujnik nie potrafi mierzyć wartości ujemnych).

Podczas inicjalizacji zmiennej trzymającej informację o temperaturze minimalnej powinniśmy jej przypisać dopuszczalną temperaturę maksymalną, czyli 150. Wtedy mamy szansę, że zmierzona wartość będzie od niej niższa.

Po wprowadzeniu zmiany cały program będzie wyglądał tak:

Jednak dla lepszej czytelności proponuję przenieść fragmenty kodu odpowiedzialne za przesyłanie tekstu do komputera. Nie ma sensu ciągle wysyłać wartości maksymalnych i minimalnych. Lepiej robić to wyłącznie, gdy ulegną one zmianie:

Teraz po uruchomieniu monitora protu szeregowego otrzymamy tylko informacje o zmianach. Na poniższej animacji widać efekt delikatnego ogrzania czujnika, a następnie szybkiego ochłodzenia:

Zapamiętywanie wartości maksymalnej i minimalnej.

Zapamiętywanie wartości maksymalnej i minimalnej.

Wady i zalety LM35

Z jednej strony mamy stosunkowo tani i prosty w użyciu czujnik. Jednak z drugiej strony ma on swoje wady. Po pierwsze, odczytywanie przez ADC może być kłopotliwe, szczególnie przy długich przewodach pomiarowych, które mogą "łapać zakłócenia z powietrza". Co więcej, każdy czujnik wymaga kolejnego kanału ADC.

Po drugie, zakres pomiarowy jest dość ograniczony i w takiej podstawowej wersji czujnik LM35 nie nadaje się np. do pomiarów temperatury, która może panować w Polsce za oknem. Pora więc zająć się czujnikiem cyfrowym, który rozwiązuje powyższe problemy!

Zadanie dodatkowe 7.2

Termometr powinien wysyłać do komputera informacje o aktualnej temperaturze co 2 sekundy. Dwa przyciski powinny powodować wyświetlenie aktualnie zapisanych temperatur skrajnych.

Termometr cyfrowy: DS18B20

Teraz zajmiemy się bardzo, bardzo popularnym czujnikiem cyfrowym DS18B20, który komunikuje się z Arduino za pomocą interfejsu 1-wire, o którym więcej można przeczytać na Wikipedii.

Również ten czujnik produkowany jest w obudowie typu TO-92. Tak jak poprzednio dane będziemy odczytywać ze środkowej nóżki. Jednak uwaga na zasilanie! w przypadku tego czujnika należy doprowadzić je odwrotnie (względem LM35)! Poprawny opis wyprowadzeń wygląda tak:

Najważniejsze informacje na temat termometru cyfrowego DS18B20:

  • pomiar w zakresie od -50 do 125°C,
  • napięcie zasilania od 3 do 5,5V,
  • dokładność: +/- 0,5 °C w zakresie od -10 °C do 85 °C,
  • po szczegóły odsyłam do noty katalogowej.

Podłączenie termometru cyfrowego do Arduino

Podłączenie tego czujnika wygląda podobnie. Dwa skrajne wyprowadzenia łączymy z zasilaniem (zgodnie z powyższym rysunkiem), a środkową nóżką łączymy z Arduino (u mnie A5). Ważne jest, jednak, aby dodać rezystor 4,7 kΩ między wyjście (nóżka środkowa), a dodatnią szynę zasilania.

Przykładowe podłączenie:

Odczytanie temperatury: czujnik cyfrowy

Z czujnikiem należy się komunikować przez interfejs 1-wire. Wymaga to jednak przestudiowania noty katalogowej, aby wiedzieć jakie informacje należy wysyłać do sensora i jak interpretować to, co do nas wraca. Do takich eksperymentów zachęcam osoby, które nie boją się długich programów.

W kursie skupimy się jednak na bibliotece: Arduino-Temperature-Control-Library. Do jej poprawnej pracy potrzebna jest jeszcze biblioteka OneWire. Proces instalacji nowych pakietów pojawiał się już w kursie kilka razy (chociażby w 2 części), więc nie będę go powtarzał.

Zaczniemy, tak jak w przypadku czujnika analogowego od odczytywania w pętli aktualnej wartości temperatury otoczenia. Na początku dodajemy dwie linie informujące kompilator o bibliotekach:

Pierwsza odpowiada za komunikację przez 1-wire, a druga to właśnie zainstalowana biblioteka od czujników temperatury. Następnie musimy zadeklarować podłączenie czujnika:

Pierwsza linia odpowiada za uruchomienie komunikacji 1-wire na pinie nr A5, a druga przekazuje tę informację do zainstalowanej biblioteki, która obsługuje nasze czujniki.

W funkcji setup() uruchamiamy transmisję przez UART oraz inicjalizujemy czujniki:

W pętli loop() "pytamy czujnik" o aktualną temperaturę, a następnie ją wyświetlamy:

Tajemniczy zapis sensors.getTempCByIndex(0) oznacza pobranie temperatury z pierwszego czujnika (numerowane są od 0) w stopniach Celsjusza. Odczytanie informacji z drugiego sensora wyglądałoby więc następująco: sensors.getTempCByIndex(1). Podłączaniem kilku czujników zajmiemy się jednak trochę później.

Reasumując, obecnie cały program wygląda tak:

Efekt działania w monitorze protu szeregowego:

Temperatura zmierzona przez DS18B20.

Temperatura zmierzona przez DS18B20.

Przy okazji można sprawdzić, to co nie było możliwe podczas korzystania z sensora analogowego, czyli pomiar temperatury ujemnej. W tym celu wykorzystałem "możliwości chłodzące" odwróconej puszki ze sprężonym powietrzem. Jak widać, udało się osiągnąć temperaturę -27ºC!

Zdecydowanie odradzam Wam jednak zabawę sprężonym, łatwopalnym gazem. Bezpieczniej testować czujnik przykładając do niego coś zimnego (np. kostkę lodu w worku foliowym, aby woda nie uszkodziła elektroniki).

Termometr z funkcją MAX/MIN - wersja 2

Zgodnie z obietnicą wracamy teraz do tematu pomiaru minimalnej i maksymalnej temperatury. Tym razem "problem" wstępnego przypisania wartości zmiennych rozwiążemy inaczej. Na początku również deklarujemy dwie nowe zmienne.

Nie musimy się przejmować ich wartością, ponieważ trochę niżej w funkcji setup() przypiszemy im jednorazowo wartość pierwszego wykonanego odczytu:

Dzięki temu nie musimy się przejmować zakresem pracy czujnika. Zawsze zaczniemy od wartości, którą czujnik zarejestrował, więc wychwycimy zarówno mniejszą, jak i większą temperaturę.

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

Efekt jego działania jest identyczny jak w poprzednim przypadku:

Wykrywanie minimalne i maksymalnej temperatury - wersja 2.

Wykrywanie minimalne i maksymalnej temperatury - wersja 2.

Odczyt informacji z kilku czujników

Dużą zaletą czujników cyfrowych jest to, że komunikują się za pomocą bardziej rozbudowanych mechanizmów, które przynoszą wiele zalet. Przykładowo w tym przypadku do tego samego pinu można podłączyć wiele czujników. 

Dla testu można więc po prostu wsadzić drugi czujnik w te same wiersze na płytce stykowej lub przenieść połączenia przewodami. Dla większej czytelności wybrałem tę drugą wersję:

Podłączenie drugiego czujnika.

Podłączenie drugiego czujnika.

Zgodnie z tym, co było mówione wcześniej, aby odczytać temperaturę z kolejnego czujnika trzeba odwołać się do sensors.getTempCByIndex(1). Cały program testowy wygląda więc następująco:

Działanie kodu w praktyce wygląda następująco:

Odczytywanie informacji z dwóch czujników.

Odczytywanie informacji z dwóch czujników.

Każdy czujnik ma swój adres!

Podłączanie czujników do jednej linii danych jest możliwe, ponieważ producent przypisał każdemu wyprodukowanemu czujnikowi unikalny adres. Przy bardziej rozbudowanych projektach warto posługiwać się właśnie tymi adresami. Wtedy możemy jednoznacznie identyfikować nasze czujniki.

Tutaj możemy się posłużyć programem demo Plik → Przykłady → OneWire → DS18x20, trzeba jednak pamiętać, aby na samym początku zmienić informacje o podłączeniu czujników, czyli:

Zamieniamy na:

Po uruchomieniu programu w monitorze portu szeregowego zobaczymy poniższe informacje. Na kolorowo zaznaczyłem właśnie unikalne adresy czujników zapisane w systemie szesnastkowym:

Odczytanie adresów czujnika.

Odczytanie adresów czujnika.

Korzystanie z adresów czujnika DS18B20

Teraz w programie można będzie odwoływać się do konkretnych czujników. W tym celu przed funkcją setup() tworzymy obiekt typu DeviceAddress o nazwie termometrZewnetrzny i wpisujemy adres naszego czujnika:

W dalszej części programu informację na temat temperatury odnotowanej przez ten czujnik można będzie otrzymać wywołując polecenie sensors.getTempC(termometrZewnetrzny).

Cały program będzie wyglądał więc następująco:

Rozwiązanie to jest bardzo wygodne przy większej ilości sensorów. Gdybyśmy założyli te czujniki np. w całym mieszkaniu, to zdecydowanie łatwiej będzie się nam posługiwać w programie nazwami typu "termometrZewnetrzny", "termometrKuchnia" itd.

Wizualizacja temperatury na diodach RGB

Na zakończenie warto byłoby rozbudować nasz termometr o inny wskaźnik temperatury. Idealnie sprawdzi się tutaj linijka diod RGB, którą poznaliśmy już na początku kursu. Załóżmy, że każda z 8 diod symbolizuje 5ºC.

Gdy świecą się kolejno od dołu, na czerwono, to oznaczają wartości dodatnie:

Kolejno: 5ºC, 10ºC, 15ºC, 20ºC

Kolejno: 5ºC, 10ºC, 15ºC, 20ºC

Natomiast, gdy świecą się od góry, na niebiesko, to oznaczają wartości ujemne:

Kolejno: -5ºC, -10ºC, -15ºC, -20ºC

Kolejno: -5ºC, -10ºC, -15ºC, -20ºC

Linijkę diod RGB podłączyłem standardowo, tak jak podczas drugiego odcinka tego kursu. Dlatego nie będę opisywał tutaj tego zagadnienia. Dla pewności umieszczam jedynie zdjęcia.

Na początku napisanego wcześniej programu musimy dodać informację o nowej bibliotece oraz zadeklarować linijkę RGB:

W funkcji setup() konieczne jest dodanie inicjalizacji zadeklarowanej wcześniej linijki:

W pętli loop(), oprócz wysyłania informacji o temperaturze do komputera, tworzymy nową zmienną typu int, do której przepisujemy odczytaną temperaturę. Zmienna jest zadeklarowana jako int, czyli liczby całkowite, ponieważ i tak nie wykorzystamy tutaj wartości ułamkowych.

Taka liczba przekazywana jest do funkcji termometrRGB(), która odpowiada za sterowanie linijki:

Funkcja termometrRGB()

Zakładamy, że minimalna pokazywana temperatura to -40ºC,a maksymalna to +40ºC. Dlatego na początku funkcji sprawdzamy warunkami, czy otrzymana wartość nie przekracza tego zakresu.

Jeśli tak się dzieje to uznajemy, że temperatura osiągnęła maksymalną wartość:

Teraz należy zająć się wyświetlaniem informacji na diodach. Na początku będziemy wyłączać wszystkie diody za pomocą komendy linijka.clear(). Następnie sprawdzimy, czy wartość, którą mamy pokazać jest większa lub równa zero, czy nie. Od razu przeliczamy też temperaturę na wartości, które może pokazać nasz termometr (od 1 do 8 diod):

Następnie za pomocą pętli for zapalamy odpowiednie diody. W przypadku wartości dodatnich zależy nam, aby włączać diody od dołu linijki, więc pętla musi działać od i=0 do wartości, która opisuje aktualną temperaturę.

W przypadku wartości ujemnej chcemy uruchamiać diody od góry do dołu, więc najwygodniej będzie, aby pętla for działała odwrotnie - od wartości maksymalnej i=8, do wartości wskazującej aktualną temperaturę. Na koniec wywołujemy również operację linijka.show().

Gotowy program wygląda więc następująco:

Po jego uruchomieniu linijka diod RGB będzie wskazywała aktualną temperaturę!

Czego nie napisałem o DS18B20?

Podczas tego artykułu omówiłem jedynie podstawową konfigurację wykorzystania tych czujników. W praktyce pozwalają one na znacznie więcej operacji. Możliwe jest przykładowo regulowanie rozdzielczości pomiaru temperatury.

Możliwe są również inne sposoby podłączania czujników np. z użyciem jedynie dwóch przewodów. Artykuł ten miał za zadanie jedynie przybliżyć podstawowe informacje o termometrach analogowych i cyfrowych, więc nie chciałem zagłębiać się w szczegóły.

Wady i zalety DS18B20

W porównaniu do wcześniej omawianego czujnika analogowego, termometr DS18B20 okazał się znacznie "trudniejszy" do obsłużenia. Należy poświęcić mu trochę więcej czasu. Niestety jest on również droższy od swojego poprzednika.

Z drugiej strony czujnik ten jest zdecydowanie bardziej uniwersalny. Transmisja cyfrowa, przez interfejs 1-Wire okazuje się niezastąpiona, gdy chcemy czujnikami pokryć większy obszar.

Podsumowanie

Wykorzystanie omówionych czujników nie ogranicza się jedynie do budowy zwykłego, domowego termometru. Pomiar warunków atmosferycznych przydaje się również do kontroli pracy bardziej rozbudowanych urządzeń. Przykładowo w robocie mobilnym można sprawdzać czy np. silniki lub akumulatory nie osiągnęły zbyt wysokiej temperatury. Taka diagnoza pozwoli uchronić urządzenie przed uszkodzeniem!

W kolejnym odcinku kursu Arduino nadal będzie o czujnikach atmosferycznych. Tym razem będzie jednak pora na popularny DHT11, czyli czujnik temperatury i wilgotności w jednej obudowie.

Czy artykuł był pomocny? Oceń go:

Średnia ocena 4.8 / 5. Głosów łącznie: 46

Nawigacja kursu

Autor kursu: Damian (Treker) Szymański

Załączniki

LM35 (pdf, 342 KB)

Dokumentacja LM35.

DS18B20 (pdf, 256 KB)

Dokumentacja DS18B20.

analogowy, arduino, cyfrowy, czujnik, kursArduino2, temperatury

Trwa ładowanie komentarzy...