Błędny odczyt temperatury z DS18B20

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Błędny odczyt temperatury z DS18B20

Post autor: M@ciej » 19 kwie 2009, 8:57

Witam.

Mam taki problem:
Zmontowałem prosty 2-czujnikowy termometr na DS18B20, sterowany prockiem Atmega8 z wyświetlaczem. Program przepisałem z książki M. Wiązani "Programowanie mikrokokntrolerów w języku Bascom". Niestety odczytana temperatura z obu układów jest błędna, i pokazuje -70°C w temperaturze pokojowej.

Nie wiem,gdzie tkwi błąd. W książce program jest opisany na podstawie DS1820, tymczasem ja mam DS18B20, czy w tym tkwi różnica?

Pozdrawiam :)

kaliska5
Użytkownik
Posty: 348
Rejestracja: 01 maja 2008, 8:24
Lokalizacja: z nienacka
Kontakt:

Post autor: kaliska5 » 19 kwie 2009, 9:39

A masz rezystor podciągający linie do + ?U mnie tez działy się takie rzeczy bez rezystora dałem rezystor i spokój

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 19 kwie 2009, 10:13

Mam rezystor SMD 4,7kΩ wpięty pomiędzy +5V a linię.

kaliska5
Użytkownik
Posty: 348
Rejestracja: 01 maja 2008, 8:24
Lokalizacja: z nienacka
Kontakt:

Post autor: kaliska5 » 19 kwie 2009, 10:28

Wiec problemu bym szukał w programie możesz pokazać kod . Nie jestem specjalista ale ostatnio zrobiłem sobie taki termometr i tez miałem podobne problemy

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 19 kwie 2009, 11:24

Mogłem pokopać adresy.W sumie wzięte z wspomnianej książki.
Oto kod:

Kod: Zaznacz cały

Declare Sub Odcz_temp(czujnik As Byte)                      'procedura odczytu temp. z czujnika
Declare Sub Zapisz_id                                       'procedura zapisu ID do DS1820

Dim Temperatura(2) As Byte                                  'tablica na zmierzoną temperature
Dim Id(8) As Byte                                           '8-elementowa tablica na numer ID

Dim I As Byte                                               'zmienne licznikowe
Dim J As Byte
Dim K As Byte

Dim Nukl As Byte                                            'liczba układów

Set _lcd
Cls
Nukl = 1wirecount()                                         'odczytujemy liczbe ukladow
If S1 = 0 Then
 Lcd "Liczba ukladow:" ; Nukl
 If Nukl > 0 Then
  Id(1) = 1wsearchfirst()                                   'odczytanie numeru seryjnego ID
  For I = 1 To 8
   Writeeeprom Id(i) , I                                    'zapis ID pierwszego ukladu do eepromu
  Next I
 End If
 If Nukl > 1 Then
  Id(1) = 1wsearchnext()                                    'odczyt drugiego ukladu
  J = 0
  For I = 9 To 16
   Incr J
   Writeeeprom Id(j) , I
  Next I
 End If
 Lowerline
 Lcd "Prog OK. Zresetuj!"
 Do
 Loop
End If

Do
 Home
 For K = 1 To Nukl
  Call Odcz_temp(k)
  If Temperatura(2) = 0 Then                                'temp. dodatnia
   Lcd "Temp" ; K ; ": " ; Temperatura(1) ; Chr(0) ; "C"
  Else
   Lcd "Temp" ; K ; ": -" ; Temperatura(1) ; Chr(0) ; "C"
  End If
  Lowerline
 Next K
Loop
End

Sub Odcz_temp(czujnik As Byte)

 If Czujnik = 1 Then
  For I = 1 To 8
   Readeeprom Id(i) , I                                     'odczyt ID 1. czujnika z pamięci EEPROM  (komórki 1-8)
  Next I
 End If
 If Czujnik = 2 Then
  J = 0
  For I = 9 To 16
   Incr J
   Readeeprom Id(j) , I                                     'odczyt ID 2. czujnika z pamięci eeprom (komórki 9-16)
  Next I
 End If

 1wreset                                                    'reset/inicjalizacja magistrali 1-wire
 Call Zapisz_id
 1wwrite &H44                                               'komenda startu pomiaru temp.
 Waitms 750                                                 'czas na konwersje temp. w ukladzie DS
 1wreset                                                    'reinicjalizacja 1-wire
 Call Zapisz_id                                             'wybranie czujnika przez zapis do niego ID aktualnie obsługiwanego układu
 1wwrite &HBE                                               'komenda odczytu układu
 Temperatura(1) = 1wread(2)                                 'odczyt zmierzonej temperatury
 1wreset                                                    'reinicjalizacja
 If Err = 1 Then                                            'jeśli brak układu (zmienna ERR=1) to
  Cls
  Lcd "Brak układow!"
  Lowerline
  Lcd "Zrestartuj"
  Do
  Loop
 End If

 If Temperatura(2) > 0 Then                                 'jeśli wieksza od 0, to temp. ujemna
  Temperatura(1) = 256 - Temperatura(1)                     'przeliczenie temp. ujemnej
 End If

 Temperatura(1) = Temperatura(1) / 2                        'przeliczenie temp. bo czujnik zwraca 2x za wysoką
End Sub

Sub Zapisz_id
 1wwrite &H55                                               'wysłanie komendy do zapisu ID układu
 For I = 1 To 8
  1wwrite Id(i)                                             'wysłanie do czujników ID z tablicy
 Next I
End Sub

Awatar użytkownika
c4r0
Moderator
Posty: 2152
Rejestracja: 13 kwie 2004, 19:56
Lokalizacja: z lasu
Kontakt:

Re: Błędny odczyt temperatury z DS18B20

Post autor: c4r0 » 19 kwie 2009, 12:12

M@ciej pisze:W książce program jest opisany na podstawie DS1820, tymczasem ja mam DS18B20, czy w tym tkwi różnica?
Tak, jest różnica i pewnie w tym tkwi problem. Coś tam się inaczej robiło na 1-wire.

Awatar użytkownika
gwozdex
Użytkownik
Posty: 879
Rejestracja: 24 lut 2006, 10:04
Lokalizacja: Czechowice-Dziedzice
Kontakt:

Post autor: gwozdex » 19 kwie 2009, 13:46

Nie wiem dokładnie gdzie ale należy przesunąć o jeden bit wynik pomiaru temp. przez DS1820 aby otrzymać poprawne wskazanie dla DS18B20. Jes to dosłownie jedna linijka kodu więcej. Szczegółów można szukać w książce "Mikroporocesorowa ośla łączka"

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 19 kwie 2009, 14:41

Mam cykl artykułów w EdW na temat M.O.Ł., zaraz tam poszukam.

Awatar użytkownika
RcTomek
Moderator
Posty: 243
Rejestracja: 27 wrz 2007, 21:15
Lokalizacja: Głogów / Wrocław

Post autor: RcTomek » 19 kwie 2009, 17:16

Różnica między DS1820 i DS18B20 jest taka, że ten drugi ma możliwość pomiaru temperatury z większą rozdzielczością. Część ułamkowa jest zapisana na czterech bitach LSB, natomiast w DS1820 tylko na jednym (dokładność +/-0.5oC). Wystarczy więc odczytaną wartość odpowiednio przesunąć.

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 19 kwie 2009, 17:44

Poświęcenie nieco czasu lekturze Mikroprocesorowej Oślej Łączki oraz nieco więcej na napisanie programu zaowocowało programikiem odczytującym poprawnie temperaturę z 1-4 czujników. Gdyby zastosować większy wyświetlacz, zmieściłoby się więcej niż 4 danych na ekranie. Ja miałem 2x20.

Chętnym udostępnię kod.

Dzięki wszystkim za pomoc :)

Arko
-
Posty: 16
Rejestracja: 02 gru 2006, 11:04
Lokalizacja: okolice Kielc
Kontakt:

Post autor: Arko » 20 kwie 2009, 17:29

tu masz opisane pozdro

Kod: Zaznacz cały

' C032d         Proste wykorzystanie DS18x20      - jumper J2 B-C
'przestawiona kolejność poleceń konwersji i odczytu powoduje, że widać,
' iż po podaniu zasilania T=85oC i że podczas konwersji można
' odczytać stan SCRETHPAD-a, ale ze "starym" wynikiem
Config 1wire = Portd.5 : Dim Odczyt(2) As Byte , A As Byte ,
Dim Licznik As Byte , T As Integer
 Cls : Lcd "Termometr" : Lowerline : Lcd Licznik : Wait 2
Do
   Incr Licznik                                             ' tylko po to, żeby pokazać, iż program "żyje"
   1wreset : 1wwrite &HCC : 1wwrite &HBE                    'polecenie odczytu DS18x20
   Odczyt(1) = 1wread(2)                                    'odczytaj dwa pierwsze bajty - temperaturę
   T = Odczyt(2)                                            '          starszy bajt temperatury
   Shift T , Left , 8                                       'przesuń w lewo o 8 miejsc
   T = T + Odczyt(1)                                        'w zmiennej Integer jest dziwna "ułamkowa" wartość
   Shift T , Right , 4                                      'zamiast dzielić przez 16 przesuń w prawo
 '   Shift T , Right , 1       'dla kostek DS18S20, DS1820 przesuń o 1 bit
   Cls : Lcd "Temp=" ; T ; "oC"                             'wyświetl wynik - liczbę całkowitą
   Lowerline : Lcd Licznik                                  'w dolnej linii wyświetl stan licznika
     1wreset                                                '   dopiero teraz daj polecenie konwersji:
     1wwrite &HCC                                           'polecenie SKIP ROM, bo pojedyncza kostka
     1wwrite &H44                                           '   dokonaj konwersji - zmierz temperaturę
  Wait 1                                                    'po cyklu pracy poczekaj
Loop

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 20 kwie 2009, 18:29

Wow, procedura krótsza od mojej, ale nie wiem, jak ją "podłączyć" do pozostałej części programu, bo odczyt temperatury to tylko jedna z funkcji, jaką ma pełnić projektowane urządzenie.

Niemniej dzięki i również pozdrawiam :)

tomson
-
Posty: 29
Rejestracja: 26 lut 2007, 18:02
Kontakt:

Post autor: tomson » 05 maja 2009, 16:57

@M@ciej
Nie chcę się madrzyć ale wydaje mi się że temperatura(1) powinna być podzielona przez 16 a nie jak u ciebie przez 2
znajdź tą linijkę w swoim kodzie i sprawdź moje przypuszczenie

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 05 maja 2009, 20:00

Z tego co wiem, to są dwa podejścia. Albo z dzieleniem przez 16, albo z przesuwaniem bitów. Ja zastosowałem ten drugi sposób i jak na razie dobrze działa. Poczytaj w EdW, bo stamtąd brałem tą metodę z przesuwaniem.
Pozdrawiam.

*zaba*
-
Posty: 3
Rejestracja: 15 gru 2008, 20:15
Lokalizacja: Pawłowice

Post autor: *zaba* » 28 maja 2009, 22:09

Witam to ja mogę udostępnić jeszcze krótszy kod z jakiejś tam książki i napewno działa testowałem

Kod: Zaznacz cały

        $crystal = 1000000                                  'deklaracja częstotliwo?ci pracy kwarcu

$regfile "m8def.dat"                                        'model procesora dla którego jest ten program
Deflcdchar 1 , 14 , 17 , 17 , 14 , 32 , 32 , 32 , 32        ' definicja znaki stopnia


Config 1wire = Portc.5                                      ' konfiguracja portu PD.5 jako wej?cia magistrali 1-wire

Dim Odczyt(2) As Byte , A As Byte , Licznik As Byte , T As Integer , T1 As Single , Napis As String * 5
'Deklaracja wszystkich zmiennych potrzebnych do pracy programu

Do
  1wreset                                                   'reset
  1wwrite &HCC                                              'jedna kostka, więc wykorzystujemy rozkaz SKIP ROM
  1wwrite &H44                                              'dokonaj konwersji
  Waitms 750                                                'przeczekaj czas konwersji
  1wreset                                                   'reset
  1wwrite &HCC                                              'rozkaz adresowy SKIP ROM
  1wwrite &HBE                                              'rozkaz funkcyjny - polecenie odczytu DS18x20
  Odczyt(1) = 1wread(2)                                     'odczytaj dwa pierwsze bajty
  T = Odczyt(2)                                             'przepisz starszy bajt do zmiennej typu Integer
  Shift T , Left , 8                                        'przesuń ten bajt w lewo na wyższe pozycje
  T = T + Odczyt(1)                                         'przepisz - dodaj młodszy bajt

  T1 = T * 0.0625                                           'wyra? w stopniach Celsjusza, wynik wpisz do zmiennej Single

Napis = Fusing(t1 , "#.#")
  Cls : Cursor Off : Lcd "* Temperatura *"
  Lowerline
  Lcd "Wynik: " ; Napis ; " " ; Chr(1) ; "C"                'wy?wietl wynik ze zmiennej Single
Loop : End

ODPOWIEDZ