Termometr cyfrowy z wykorzystaniem Arduino Uno i Bascom AVR

W ostatnim artykule krok po kroku opisałem moduł Arduino UNO oraz w jaki sposób  można go programować za pomocą środowiska Bascom AVR. We wpisie obiecałem również, że przedstawię to w praktyce. Zdecydowałem się wykonać termometr cyfrowy z dwoma czujnikami DS18B20 do pomiaru temperatury na zewnątrz oraz w budynku.

Główne założenia projektu 

Program będzie dokonywał pomiaru z czujnika numer 1 (temperatura wewnętrzna pomieszczenia) po ustawieniu Flagi w stan 1, a następnie dokonując w nim wszystkich potrzebnych konfiguracji. Uzyskany z obliczeń wynik będzie zapisany w zmiennej String i i następnie wydrukowany na wyświetlaczu. Po tych czynnościach Flaga zostanie wyzerowana po to aby umożliwić pomiar temperatury zewnętrznej z wodoszczelnego czujnika DS18b20. Analogicznie jak poprzednio zostanie odczytana wartość, odpowiednio sformatowana i wyświetlona na ekranie wyświetlacza 2*16 w dolnej jego linii. Temperatura wewnątrz będzie pokazana w pierwszym wierszu .

Kilka informacji o magistrali 1-Wire i czujniku DS18B20

1-Wire to interfejs umożliwiający komunikację z dwoma lub kilkoma urządzeniami. Nazewnictwo wywodzi się z tego, że do komunikacji korzysta, tylko z jednej linii danych ponadto może ona służyć jako linia zasilająca układ. Moduł posiada kondensator o pojemności 800 pF ( w pewnym sensie bufor) co umożliwia po jego naładowaniu zasilanie, gdy na wyprowadzeniu następuje transmisja danych. Tak więc za pomocą przewodu dwużyłowego ( drugi GND) można zrealizować w pełni cyfrową komunikację pomiędzy dwoma urządzeniami.

Przed odbiorem każdego bitu danych master (np. mikrokontroler) wysyła niski impuls startu (od 1 μs do 15 μs) następnie wracając do stanu wysokiego na linii danych. Jeśli SLAVE wysyła logiczną jedynkę nie bierze udziału komunikacji i pozostawia magistralę w stanie wysokim. Gdy SLAVE wysyła zero, wówczas zwiera linię danych do masy na 60 μs. Po przesłaniu 8 bitów następuje wysłanie komendy/ rozkazu (również postaci ośmiobitowej). Konfiguracja magistrali umożliwia stosunkowo niewielką przepustowość w stosunku do innych interfejsów komunikacyjnych tj.16 kbps . Sposobem transmisji danych bardzo przypomina Magistralę I2C niemniej jednak posiada jedną linię danych co czyni ją wolniejszym oraz tańszym rozwiązaniem. Przykładowe układy pracujące jako 1-Wire  to termometry cyfrowe, zamki elektroniczne (ibutton), czujniki naładowania akumulatorów oraz wszelakie kontrolery meteorologiczne.

DS18B20 jest urządzeniem o danych właściwościach:

  • obsługa za pomocą interfejsu 1-Wire
  • w wewnętrznej pamięci ROM każdy czujnik posiada 64 bitowy kod
  • prosty odczyt temperatury
  • jest cyfrowym układem i nie potrzebuje innych elementów do poprawnej pracy
  • możliwość zasilania z linii danych
  • zakres napięcia zasilnia – 3V-5.5 V
  • rozdzielczość temperatury od 9 do 12 bitów
  • 12 bitowy odczyt potrzebuje ok. 750 ms

Pomiar temperatury na co najmniej dwóch czujnikach

Użycie co najmniej dwóch czujników zmusza nas do określenia numeru seryjnego układu. Operacja jest konieczna do poprawnego rozróżnienie czujników. Aby dokonać pomiaru należy krok po kroku wykonać takie czynności:

  • określenie liczby czujników na magistrali
  • odczyt numerów identyfikacyjnych oraz zapisanie ich w pamięci
  • pominięcie identyfikacji
  • rozkaz wykonania pomiaru i odczekanie ok. 750 ms na dokonanie konwersji
  • komunikacja z pierwszym czujnikiem ( pomiar temperatury w pokoju)
  • odczytanie wyniku
  • uruchomienie drugiego czujnika( pomiar temperatury zewnętrznej)
  • odczytanie wyniku

Ponieważ do komunikacji z czujnikami korzysta się z dosyć skomplikowanych rozkazów przygotowałem sobie specjalną bibliotekę zastępując skomplikowane kody na przyjazne mi nazwy co przedstawiam na poniższym screenie:

Ponadto opiszę komendy Bascoma użyte  do obsługi dwóch czujników w programie:

  • 1wirecount- Zlicza liczbę urządzeń na magistrali 1-wire       =>          zmienna=1wirecount()
  • 1wsearchfirst- Funkcja zwraca nam pierwszy odczytany numer identyfikacyjny z magistrali 1Wire                      =>     zmienna= 1wsearchfirst()

gdzie zmienna  lub tablica musi mieć pojemność 8 bajtów numeru ID 

  • 1wsearchnext- Zwraca numer ID następnego znalezionego urządzenia podłączonego do magistrali 1Wire                     =>   zmienna= 1wsearchnext()

,gdzie zmienna  lub tablica musi mieć pojemność 8 bajtów numeru ID 

Na początku programu tradycyjnie znajdują się komendy konfiguracyjne mikrokontrolera], następnie także wyświetlacza 2*16 LCD oraz Portd.7 jako magistralę 1-Wire. Kilka zdeklarowanych zmiennych służy do przetwarzania i zobrazowania wyniku temperatury na wyświetlaczu LCD. Po wyświetleniu krótkiego napisu powitalnego program przechodzi do określenia liczby czujników na magistrali 1-Wire i po dwóch sekundach wyświetli ich numery identyfikacyjne, które z nich odczytał . Przed startem pętli głównej zostaje wyczyszczony ekran i przygotowany do zobrazowania danych zmierzonych z czujników. Odbywa się to poprzez cykliczny pomiar w pętli głównej temperatury tzn. jeśli zostanie zmierzona temperatura w pomieszczeniu to zostaje flaga tak skonfigurowana, żeby w następnym obiegu pętli została zmierzona wartość ciepła na zewnątrz. Dzięki temu pomiar na danym czujniku jest dokonywany co niecałe dwie sekundy. Po wywołaniu odczytu temperatury program zapisuje dwa bajty danych do zmiennych. Następnie dokonujemy ich konwersji na wynik typu Single. Program sprawdza również czy zmienił się bit znaku (1-liczba ujemna, 0-liczba nieujemna) i w odpowiednim przypadku dokonuje korekty wartości zmieniając na początku znak na minus lub plus. Ostatnią czynnością jest formatowanie danych do wyświetlenia z dokładnością do jednego miejsca po przecinku oraz ze znakiem „+” lub „-„. Kod programu jest rzeczywiście mało skomplikowany aczkolwiek w pełni realizuje założenia.

Poniżej przedstawiam pełny kod programu do termometru:


'********************** Arduino Uno - termometr pokojowy i zewnętrzny na DS18b20********************
$regfile = "m328pdef.dat"
$Crystal = 16000000
$include "BibliotekaDS18b20.bas" ' konfiguracje mikrokontrolera
' częstotliwość 16 Mhz
' Mikrokontrolera na pokładzie arduino uno
'___________________________________________________
Config Lcd = 16 * 2 'Konfiguracja podłączonego wyświetlacza do portu D mikroprocesora
Config Lcdpin = Pin , Db4 = Portd.2 , Db5 = Portd.3 , Db6 = Portd.4 , Db7 = Portd.5 , E = Portd.1 , Rs = Portd.0
Deflcdchar 1 , 6 , 9 , 9 , 6 , 32 , 32 , 32 , 32 'znak stopnia
Cls 'inicjalizacja LCD
Cursor Off Noblink 'wyłączenie kursora

Config 1wire = pind.7 ' konfiguracja magistrali 1wire

Dim Flaga as bit 'flaga do obsługi danego czujnika
Dim A as byte 'zmienna licznika przesuwania znaków
Dim LSB as byte 'Młodszy bajt danych z czujników
Dim MSB as byte 'Starszy bajt danych z czujników
Dim T as single 'zmienna danych podczas przeliczeń temperatury
Dim Wynik as String * 6 'zmienna do wyświetlania wyniku na LCD
Dim ID1(8)as byte 'zmienna na ID czujnika nr.1 temperatury
Dim ID2(8)as byte 'zmienna na ID czujnika nr.2 temperatury
Dim Ilosc as byte 'zmienna w której jest zapisana ilość czujników w układzie

lcd " Arduino Uno i programowanie modułu w Bascom AVR" ' tekst powitania na start układu
lowerline
lcd " Termometr z czujnikiem DS18b20"
For A = 1 to 15 step 1 'Zbyt długi więc zastosowano
Shiftlcd left ' przesuwanie w lewo 10 razy
waitms 500 'by wyświetlić cały napis
Next A

CLS

'______________________________________________________________________________________________________
Ilosc = 1wirecount()
Locate 1 , 1
Lcd "Czujnikow: " ; Ilosc
Locate 2 , 1
Lcd "ID czujnikow: "
Wait 2

'program zliczy liczbę urządzeń 1wire podpiętych do procesora

'______________________________________________________________________________________________________

Id1(1) = 1wsearchfirst()
Id2(1) = 1wsearchnext()
'odczytujemy numery identyfikacyjne układów
'każdy numer składa się z 8 bajtów, dlatego używamy odpowiednich tablic
Locate 1 , 1
For Ilosc = 1 To 8 Step 1
Lcd Hex(id1(Ilosc))
Next Ilosc
Locate 2 , 1
For Ilosc = 1 To 8 Step 1
Lcd Hex(id2(Ilosc))
Next Ilosc
Wait 2

'wyświetlamy na ekranie numery identyfikacyjne poszczególnych czujników
'____________________________________________________________________________________________________

cls
locate 1 , 1
LCD "IN :"
locate 1 , 11
LCD Chr(1) ; "C"
Locate 2 , 1
LCD "OUT:"
locate 2 , 11
LCD Chr(1) ; "C"

' Konfiguracja i wyświetlenie stałego tekstu na LCD

Do

1wreset
1wwrite Skip_rom
1wwrite Convert_t
Waitms 750
'wysyłamy do wszystkich termometrów polecenie dokonania pomiaru temperatury

If Flaga = 1 Then
Flaga = 0

1wreset
1wverify Id1(1)
'wywołujemy tylko pierwszy czujnik
'a potem doczytujemy z niego dane
1wwrite Read_scratchpad
Lsb = 1wread()
Msb = 1wread()
T = Msb * 256
T = T + Lsb
T = T / 16
If Msb.7 = 1 Then T = T - 4096
Locate 1 , 5
Wynik = Fusing(t , "##.#")
Wynik = Format(wynik , "+00000")
Lcd Wynik

Else
Flaga = 1

1wreset
1wverify Id2(1)
'powtarzamy sekwencję dla drugiego układu
1wwrite Read_scratchpad
Lsb = 1wread()
Msb = 1wread()
T = Msb * 256
T = T + Lsb
T = T / 16
If Msb.7 = 1 Then T = T - 4096
Locate 2 , 5
Wynik = Fusing(t , "##.#")
Wynik = Format(wynik , "+00000")
Lcd Wynik

End If

Loop
end  

Podsumowanie 

Wyżej opisana aplikacja jest prostym przykładem jak w banalny sposób można zbudować bardzo ciekawy i użyteczny projekt przy pomocy dowolnego modułu Arduino. Osobiście dla mnie stanowi ono idealną bazę do testowania swoich pomysłów. Polecam każdemu korzystanie z Arduino zwłaszcza na początku poznawania elektroniki, automatyki oraz informatyki.

Prezentacja wideo działania termometru Arduino Uno z czujnikami cyfrowymi DS18b20:

 

 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *