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).
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!
Gotowe zestawy do kursów Forbota
Komplet elementów 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).
Masz już zestaw? Zarejestruj go wykorzystując dołączony do niego kod. Szczegóły »
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).
Czujnik temperatury LM35.
Opis wyprowadzeń LM35.
Najważniejsze informacje na temat termometru analogowego LM35:
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.
Więcej informacji na temat LM35 znaleźć można w jego dokumentacji.
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.
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:
Arduino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define LM35 A5
voidsetup(){
Serial.begin(9600);
}
voidloop(){
//Przeliczenie odczytu ADC na temperaturę zgodnie z opisem z kursu
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.
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!
Uwaga dla bezpieczeństwa!
Jeśli ktoś wpadnie na pomysł schładzania czujników sprężonym powietrzem
i ogrzewania ich zapalniczką, to przypominam, że większość
puszek ze sprężony powietrzem zawiera łatwopalny gaz!
Bezpieczniej testować czujnik przykładając do niego coś zimnego
(np. kostkę lodu w worku foliowym, aby woda nie uszkodziła elektroniki).
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.:
Arduino
1
floattempMAX=0;//Aktualna temperatura maksymalna
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:
Arduino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#define LM35 A5
floattempMAX=0;//Aktualna temperatura maksymalna
voidsetup(){
Serial.begin(9600);
}
voidloop(){
//Przeliczenie odczytu ADC na temperaturę zgodnie z opisem z kursu
if(temperatura>tempMAX){//Jesli aktualna temperatura jest wyzsza od maksymalnej
tempMAX=temperatura;//to ustaw aktualną, jako maksymalną.
}
//Wyslanie przez UART temperatury maksymalnej
Serial.print("Max: ");
Serial.print(tempMAX);
Serial.println("*C");
delay(200);
}
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).
Teraz analogicznie spróbujmy zapamiętać wartość minimalną. Tworzymy nową zmienną:
Arduino
1
floattempMIN=0;//Aktualna temperatura minimalna
Następnie sprawdzamy, czy aktualna wartość jest mniejsza od poprzednio zapisanej, czyli:
Arduino
1
2
3
if(temperatura<tempMIN){//Jesli aktualna temperatura jest niższa od minimalnej
tempMIN=temperatura;//to ustaw aktualną, jako minimalną.
}
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).
Ten błąd popełnia wielu początkujących programistów!
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.
To jedna z metod rozwiązania tego problemu.
Drugą sprawdzimy podczas testów drugiego termometru.
Po wprowadzeniu zmiany cały program będzie wyglądał tak:
Arduino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#define LM35 A5
floattempMAX=0;//Aktualna temperatura maksymalna
floattempMIN=150;//Aktualna temperatura minimalna
voidsetup(){
Serial.begin(9600);
}
voidloop(){
//Przeliczenie odczytu ADC na temperaturę zgodnie z opisem z kursu
if(temperatura>tempMAX){//Jesli aktualna temperatura jest wyzsza od maksymalnej
tempMAX=temperatura;//to ustaw aktualną, jako maksymalną.
}
if(temperatura<tempMIN){//Jesli aktualna temperatura jest niższa od minimalnej
tempMIN=temperatura;//to ustaw aktualną, jako minimalną.
}
//Wyslanie przez UART temperatury maksymalnej
Serial.print("Max: ");
Serial.print(tempMAX);
Serial.println("*C");
//Wyslanie przez UART temperatury minimalnej
Serial.print("Min: ");
Serial.print(tempMIN);
Serial.println("*C");
delay(200);
}
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:
Arduino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#define LM35 A5
floattempMAX=0;//Aktualna temperatura maksymalna
floattempMIN=150;//Aktualna temperatura minimalna
voidsetup(){
Serial.begin(9600);
}
voidloop(){
//Przeliczenie odczytu ADC na temperaturę zgodnie z opisem z kursu
if(temperatura>tempMAX){//Jesli aktualna temperatura jest wyzsza od maksymalnej
tempMAX=temperatura;//to ustaw aktualną, jako maksymalną.
//Wyslanie przez UART temperatury maksymalnej
Serial.print("Nowa wartosc max: ");
Serial.print(tempMAX);
Serial.println("*C");
}
if(temperatura<tempMIN){//Jesli aktualna temperatura jest niższa od minimalnej
tempMIN=temperatura;//to ustaw aktualną, jako minimalną.
//Wyslanie przez UART temperatury minimalnej
Serial.print("Nowa wartosc min: ");
Serial.print(tempMIN);
Serial.println("*C");
}
delay(200);
}
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.
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.
Gdybyśmy chcieli mierzyć temperaturę w 6 pomieszczeniach,
to brakowałoby już nam wolnych pinów 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:
Opis wyprowadzeń DS18B20.
Czujnik temperatury DS18B20.
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,
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.
Dodanie tego rezystora jest konieczne!
Przykładowe podłączenie:
Podłączenie cyfrowego czujnika temperatury.
Koniecznie trzeba pamiętać o rezystorze 4,7k!
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ł.
Pamiętaj, aby zainstalować powyższe biblioteki zanim pójdziesz dalej!
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:
Arduino
1
2
#include <OneWire.h>
#include <DallasTemperature.h>
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:
Arduino
1
2
OneWireoneWire(A5);//Podłączenie do A5
DallasTemperaturesensors(&oneWire);//Przekazania informacji do biblioteki
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:
Arduino
1
2
3
4
voidsetup(void){
Serial.begin(9600);
sensors.begin();//Inicjalizacja czujnikow
}
W pętli loop() "pytamy czujnik" o aktualną temperaturę, a następnie ją wyświetlamy:
Arduino
1
2
3
4
5
6
voidloop(void){
sensors.requestTemperatures();//Pobranie temperatury czujnika
Serial.print("Aktualna temperatura: ");
Serial.println(sensors.getTempCByIndex(0));//Wyswietlenie informacji
delay(500);
}
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.
Wywołanie sensors.getTempFByIndex(0) zwróci wartość w skali Fahrenheita.
Reasumując, obecnie cały program wygląda tak:
Arduino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <OneWire.h>
#include <DallasTemperature.h>
OneWireoneWire(A5);//Podłączenie do A5
DallasTemperaturesensors(&oneWire);//Przekazania informacji do biblioteki
voidsetup(void){
Serial.begin(9600);
sensors.begin();//Inicjalizacja czujnikow
}
voidloop(void){
sensors.requestTemperatures();//Pobranie temperatury czujnika
Serial.print("Aktualna temperatura: ");
Serial.println(sensors.getTempCByIndex(0));//Wyswietlenie informacji
delay(500);
}
Efekt działania w monitorze protu szeregowego:
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!
Zamrożony termometr.
Odczytana temperatura.
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.
Tym razem ich wartość nie jest ważna!
Arduino
1
2
floattempMAX=0;//Aktualna temperatura maksymalna
floattempMIN=0;//Aktualna temperatura minimalna
Nie musimy się przejmować ich wartością, ponieważ trochę niżej w funkcji setup() przypiszemy im jednorazowo wartość pierwszego wykonanego odczytu:
Arduino
1
2
3
4
5
6
7
8
9
voidsetup(void){
Serial.begin(9600);
sensors.begin();//Inicjalizacja czujnikow
//ustawiamy pierwszy odczyt jako MAX i MIN
sensors.requestTemperatures();
tempMAX=sensors.getTempCByIndex(0);
tempMIN=sensors.getTempCByIndex(0);
}
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:
Arduino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <OneWire.h>
#include <DallasTemperature.h>
OneWireoneWire(A5);//Podłączenie do A5
DallasTemperaturesensors(&oneWire);//Przekazania informacji do biblioteki
floattempMAX=0;//Aktualna temperatura maksymalna
floattempMIN=0;//Aktualna temperatura minimalna
voidsetup(void){
Serial.begin(9600);
sensors.begin();//Inicjalizacja czujnikow
//ustawiamy pierwszy odczyt jako MAX i MIN
sensors.requestTemperatures();
tempMAX=sensors.getTempCByIndex(0);
tempMIN=sensors.getTempCByIndex(0);
}
voidloop(void){
sensors.requestTemperatures();//Pobranie temperatury czujnika
floattemperatura=sensors.getTempCByIndex(0);//zapis temperatury do zmiennej
if(temperatura>tempMAX){//Jesli aktualna temperatura jest wyzsza od maksymalnej
tempMAX=temperatura;//to ustaw aktualną, jako maksymalną.
//Wyslanie przez UART temperatury maksymalnej
Serial.print("Nowa wartosc max: ");
Serial.print(tempMAX);
Serial.println("*C");
}
if(temperatura<tempMIN){//Jesli aktualna temperatura jest niższa od minimalnej
tempMIN=temperatura;//to ustaw aktualną, jako minimalną.
//Wyslanie przez UART temperatury minimalnej
Serial.print("Nowa wartosc min: ");
Serial.print(tempMIN);
Serial.println("*C");
}
delay(500);
}
Efekt jego działania jest identyczny jak w poprzednim przypadku:
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.
Podczas tego testu omawiam tylko jedną z kilku możliwości
wykorzystania czujnika DS18B20!
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.
Przy podłączeniu kolejnego czujnika nie trzeba dodawać następnego rezystora!
Wystarczy jeden na całą linię danych!
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:
Arduino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <OneWire.h>
#include <DallasTemperature.h>
OneWireoneWire(A5);//Podłączenie do A5
DallasTemperaturesensors(&oneWire);//Przekazania informacji do biblioteki
voidsetup(void){
Serial.begin(9600);
sensors.begin();//Inicjalizacja czujnikow
}
voidloop(void){
sensors.requestTemperatures();//Pobranie temperatury czujnika
Serial.print("Pierwszy: ");
Serial.println(sensors.getTempCByIndex(0));//Wyswietlenie informacji
Serial.print("Drugi: ");
Serial.println(sensors.getTempCByIndex(1));//Wyswietlenie informacji
delay(500);
}
Działanie kodu w praktyce wygląda następująco:
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.
Oczywiście adresu nie znajdziemy na obudowie - należy go odczytać programowo.
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:
Arduino
1
OneWireds(10);
Zamieniamy na:
Arduino
1
OneWireds(A5);
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.
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:
Uwaga! Każdy musi podać tutaj unikalny adres swojego 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:
Arduino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <OneWire.h>
#include <DallasTemperature.h>
OneWireoneWire(A5);//Podłączenie do A5
DallasTemperaturesensors(&oneWire);//Przekazania informacji do biblioteki
sensors.requestTemperatures();//Pobranie temperatury czujnika
Serial.print("Aktualna temperatura: ");
Serial.println(sensors.getTempC(termometrZewnetrzny));//Wyswietlenie informacji
delay(500);
}
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.
Program będzie wtedy również odporny
na zmiany kolejności podłączenia czujników!
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
Natomiast, gdy świecą się od góry, na niebiesko, to oznaczają wartości ujemne:
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.
Podłączenie linijki – od przodu.
Podłączenie linijki – od tyłu.
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:
Arduino
1
2
3
4
5
voidsetup(void){
Serial.begin(9600);
sensors.begin();//Inicjalizacja czujnikow
linijka.begin();//Inicjalizacja
}
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:
Arduino
1
2
3
4
5
6
7
8
9
10
voidloop(void){
sensors.requestTemperatures();//Pobranie temperatury czujnika
Serial.print("Aktualna temperatura: ");
Serial.println(sensors.getTempC(termometrZewnetrzny));//Wyswietlenie informacji
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ść:
Arduino
1
2
3
4
5
6
7
8
9
10
11
voidtermometrRGB(inttemperatura){
//Sprawdzamy, czy temperatura jest w odpowiednim zakresie
if(temperatura>40){
temperatura=40;
}elseif(temperatura<-40){
temperatura=-40;
}
[...]
}
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):
Arduino
1
2
3
4
5
6
7
8
9
10
11
12
//Wyczysc linijkę
linijka.clear();
if(temperatura>=0){
//Dla wartosci dodatnich
temperatura=map(temperatura,0,40,1,8);
}else{
//Dla wartosci ujemnych
temperatura=map(temperatura,-40,0,1,8);
}
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().
//Sprawdzamy, czy temperatura jest w odpowiednim zakresie
if(temperatura>40){
temperatura=40;
}elseif(temperatura<-40){
temperatura=-40;
}
//Wyczysc linijkę
linijka.clear();
if(temperatura>=0){
//Dla wartosci dodatnich
temperatura=map(temperatura,0,40,1,8);
inti=0;
for(i=0;i<temperatura;i++){
linijka.setPixelColor(i,linijka.Color(255,0,0));//Dioda nr i świeci na czerwono
}
}else{
//Dla wartosci ujemnych
temperatura=map(temperatura,-40,0,1,8);
inti=0;
for(i=8;i>temperatura;i--){
linijka.setPixelColor(i,linijka.Color(0,0,255));//Dioda nr i świeci na niebiesko
}
}
linijka.show();
}
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.
Zainteresowanych odsyłam do dokumentacji czujnika oraz pozostałych przykładów
dołączonych do używanych tutaj bibliotek.
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.
Operacja odczytu temperatury generuje minimalne podgrzanie struktury czujnika,
więc częste pobieranie wyników może prowadzić do zakłamywania pomiarów!
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.
Wraz ze wzrostem ilości czujników nie musimy zwiększać ilości przewodów.
Co więcej, unikalne adresy pozwalają łatwo identyfikować termometry.
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 wpis był pomocny? Oceń go:
Średnia ocena 4.7 / 5. Głosów łącznie: 155
Nikt jeszcze nie głosował, bądź pierwszy!
Artykuł nie był pomocny? Jak możemy go poprawić? Wpisz swoje sugestie poniżej. Jeśli masz pytanie to zadaj je w komentarzu - ten formularz jest anonimowy, nie będziemy mogli Ci odpowiedzieć!
Dołącz do 20 tysięcy osób, które otrzymują powiadomienia o nowych artykułach! Zapisz się, a otrzymasz PDF-y ze ściągami (m.in. na temat mocy, tranzystorów, diod i schematów) oraz listę inspirujących DIY na bazie Arduino i Raspberry Pi.
Dołącz do 20 tysięcy osób, które otrzymują powiadomienia o nowych artykułach! Zapisz się, a otrzymasz PDF-y ze ściągami (m.in. na temat mocy, tranzystorów, diod i schematów) oraz listę inspirujących DIY z Arduino i RPi.
Trwa ładowanie komentarzy...