Obsługa DS18x20


Zawarte fragmenty programów dotyczą czujników DS18S20 i DS18B20. Procedury obsługi tych układów nie różnia się od siebie w prostych zastosowaniach, poza sposobem obliczania temperatury na podstawie odczytanych wartości z rejestrów czujników.

Język Bascom AVR


Odczyt 8 bajtów numeru seryjnego DS18S20 lub DS18B20 gdy na magistrali jest tylko jeden układ. Numer seryjny zostanie zapisany do zmiennej tablicowej Ds:
Config 1wire = Pind.7
Dim Ds(8) As Byte
 
1wreset
1wwrite &H33
Ds(1) = 1wread(8):

Uruchomienie konwersji temperatury przez wszystkie czujniki podłączone do magistrali 1-wire. Po wydaniu rozkazu konwersji należy odczekać pewien czas (max 750ms) przed przystąpieniem do odczytu temperatury:

Config 1wire = Pind.7
 
1wreset
1wwrite &HCC
1wwrite &H44

Odczyt zawartości dwóch pierwszych rejestrów układu DS18x20, zawierających informację o wartości temperatury w przypadku gdy na magistrali jest tylko jeden czujnik.

...
1wreset
1wwrite &HCC
1wwrite &HBE
 
Lsb = 1wread():
Msb = 1wread():
1wreset

Dla większej ilości czujników podłączonych do jednej magistrali odczytujemy dane z jednego układu wykorzystując jego numer seryjny odczytany wcześniej i zapisany do zmiennej tablicowej Ds(8 bajtów).

...
1wreset
1wwrite &H55
1wwrite Ds(1) , 8
1wwrite &HBE
 
Lsb = 1wread():
Msb = 1wread():
1wreset

Po odczytaniu bajtów Msb i Lsb wykonujemy oblicznia temperatury.
Układ DS18S20:

Dim Temp As Single
...
If Msb = 0 Then
  Temp = Lsb / 2
Else
  Lsb = Not Lsb
  Lsb = Lsb +1
  Temp = Lsb/2
  Temp = Temp * (-1)
End If

Układ DS18B20:

Dim Temp As Single
Dim Tempa As Integer
...
 
Tempa = Msb * 256
Tempa = Tempa + Lsb
 
If Msb.7 = 0 Then
   Temp = Tempa / 16
Else
  Tempa = Not Tempa
  Tempa = Tempa +1
  Temp = Tempa / 16
  Temp = Temp * (-1)
End If

Poniżej przedstawiony jest cały prosty program testowy do obsługi dwóch czujników (DS18S20 i DS18B20) podłączonych na jednej magistrali. Całość została uruchomiona na Płytce Testowej opisanej w dziale projekty. Wskazania temperatury wyświetlane są na wyświetlaczu LCD

'***********************************************
'Konfiguracja AVR
'***********************************************
$regfile = "m162def.dat"
$crystal = 16000000
 
$baud = 2400
 
Config Porta = 255
Porta = 255
Config Portb = 255
Portb = 255
Config Portc = 255
Portc = 255
Config Portd = 255
Portd = 255
Config Porte = 255
Porte = 255
 
'Config Scl = Portd.6
'Config Sda = Portd.7
'I2cinit
 
Config 1wire = Pind.7
 
Config Lcdpin = Pin , Db4 = Porta.5 , Db5 = Porta.4 , Db6 = Porta.3 , Db7 = Porta.2 , E = Porta.0 , Rs = Porta.1
Config Lcd = 20 * 2
Cls
Cursor Off Noblink
 
'Config Int0 = Falling
'Enable Int0 : On Int0 Przerw_zewn
 
'Config Timer0 = Timer , Prescale = 64
'Enable Timer0 : On Timer0 Przerwanie1
 
'Config Timer1 = Timer , Prescale = 8
'Enable Timer1 : On Timer1 Przerwanie2
 
Enable Interrupts
'///////////////////////////////////////////////
 
'***********************************************
'Zmienne
'***********************************************
Dim Lsb As Byte
Dim Msb As Byte
Dim Tempa As Single
Dim Ds1(8) As Byte , Ds2(8) As Byte
Dim Tekst1 As String * 10
Dim Tekst2 As String * 10
'///////////////////////////////////////////////
 
Lcd "test DS18B20"
Wait 1
 
'Numery wpisane na sztywno
Ds2(1) = 40
Ds2(2) = 55
Ds2(3) = 181
Ds2(4) = 1
Ds2(5) = 1
Ds2(6) = 0
Ds2(7) = 0
Ds2(8) = 207
 
Ds1(1) = 16
Ds1(2) = 171
Ds1(3) = 224
Ds1(4) = 167
Ds1(5) = 0
Ds1(6) = 8
Ds1(7) = 0
Ds1(8) = 220
 
Do
  1wreset
 
  1wwrite &HCC
  1wwrite &H44
  Waitms 250
  Waitms 250
 
  1wreset
 
  1wwrite &H55
  1wwrite Ds2(1) , 8
  1wwrite &HBE
 
  Lsb = 1wread():
  Msb = 1wread():
 
  Tempa = Msb * 256
  Tempa = Tempa + Lsb
  Tempa = Tempa / 16
  Tekst1 = Fusing(tempa , "#.##")
 
 
  1wreset
 
  1wwrite &H55
  1wwrite Ds1(1) , 8
  1wwrite &HBE
 
  Lsb = 1wread():
  Msb = 1wread():
 
  Tempa = Lsb / 2
  Tekst2 = Fusing(tempa , "#.#")
 
  Cls
  Lcd "DS18B20= " ; Tekst1
  Lowerline
  Lcd "DS18S20= " ; Tekst2
Loop
End




mordacz222's picture

Witam Siedzę nad tym dobrą

Witam

Siedzę nad tym dobrą godzinę i nie rozumiem po co są te obliczenia dla np.: DS18B20

Polecenie

tempa=not tempa
tempa=tempa/16
tempa=tempa*(-1)
rozumiem i się zgadzam ale w takim razie po co całą reszta, siedzę przy windowsowym kalkulatorze i nigdy nie wychodzi to co by miało, no chyba że się pomyliłeś.

Możesz mi napisać po co to robisz?

mirley's picture

Re; DS18B20

Nie ma tu pomyłki, poniższy fragment wykonuje się gdy temperatura jest ujemna (odpowiednia wartość w starszym bajcie)

  Tempa = Not Tempa
  Tempa = Tempa +1
  Temp = Tempa / 16
  Temp = Temp * (-1)

Pierwsze dwie linijki to klasyczna zamiana z kodu U2(Uzupełnień do dwóch) na kod binarny, kolejna linijka dzieli przez 16 aby uzyskac zapis w stopniach, potem zmiana znaku na ujemna wartość bo wiemy ze jest ujemna z wcześniejszych przesłanek a odczytujemy wartość bezwzględną

mordacz222's picture

Przepraszam jeśli się mylę

Przepraszam jeśli się mylę ale np temp. +25 to przy 9 bitach naprawdę jakby +50 dlatego dzielone przez 2 czyli binarnie 00110010 a polecenie not da wynik 11001101 czyli 205/2 czyli 102,5 stopnia czyli gdzie popełniam błąd, i jeszcze pytanie jak przełączyć 18B20 na 9bit.

mirley's picture

Re: DS18B20

Niestety nie wiem jak przełaczyć DS'a w tryb 9 bitów bo nigdy nie było mi to potrzebne.... raczej napewno trzeba wpisać do rejestru odpowiednia wartość na podstawie karty katalogowej

Jeśli chodzi o te obliczenia to tak zaplątałeś że nie mogę zrozumieć o to Ci chodzi. Wartość policzyłem na podstawie karty katalogowej

gosc's picture

DS1820

Mam taki zabytek, który wciąż nieźle działa ale wymaga peceta. Jak zrobić odczyt temperatury 0-99 C i przy użyciu at89c2051 wyświetlać wynik na dwóch wyświetlaczach LED (bez części dziesiętnych)?

Ewentualnie jakiś alarm przy spadku temperatury poniżej np. 40 C (piec CO).

Pozdrawiam

mirley's picture

Re: Termometr

Program masz wyżej a w projektach mam gotowe dwa termometry z wyświetlaczem LED

mordacz222's picture

Chodziło mi o to że 00110010

Chodziło mi o to że 00110010 oznacza 50/2 czyli 25 stopni a polecenie not zamieni każdy bit w bajcie czyli da wartość 11001101 czyli 205/2 czyli 102,5 stopnia więc gdzie popełniam błąd???

mirley's picture

Re: DS18S20

Nie zrozumiałem wcześniej co ci chodzi ale teraz już wiem..... Błąd jest tu że negujesz wartości temperatury gdy jest ona dodatnia. To przeliczenie z negacją działa jak liczba jest ujemna zapisana w kodzie U2, robiąc z liczby U2 liczbę dodatnią binarną.

If Msb = 0 Then     'jesli temperatura większa od zera to:
  Temp = Lsb / 2    
Else                'jeśli mniejsza od zera to:
  Lsb = Not Lsb      
  Lsb = Lsb +1
  Temp = Lsb/2
  Temp = Temp * (-1)
End If

Dla przykładu jeśli temperatura jest -25 stopni to ds18B20 ma wartości w dwóch bajtach 1111 1111 1100 1110, pierwszy bajt niesie informacje o znaku a drugi po negacji dodaniu 1 i podzieleniu przez 2 daje liczbę 25, a że jest to -25 to wiemy z pierwszego bajtu który zawiera same 1. Dla DS18B20 nie wszystkie bity starszego bajtu są 1 i sprawdzam tylko pierwszy bit bo inne kombinacje sa niedopuszczalne z punktu widzenia samego DS'a.

popatrz na tabelkę w karcie katalogowej

mordacz222's picture

Dziękuję bardzo teraz

Dziękuję bardzo teraz popatrzyłem do datasheet i już to zrozumiałem, ale jeszcze pytanko po co dodawać 1?

mirley's picture

Re: U2

gosc's picture

DS18(S)20 - temperatura ujemna

Else
  Lsb = Not Lsb
  Lsb = Lsb +1
  Temp = Lsb/2
  Temp = Temp * (-1)
End If

A nie prościej byłoby:

Else
  Lsb = 256 - Lsb
  Temp = Lsb/2
End If

Poza tym nawiązuję do mojego wcześniejszego postu: czy obsługa DS1820 (taki mam) i DS18S20 jest taka sama ?

mirley's picture

Re: DS18S20

Ds18S20 to chyba to samo co DS1820.... do pdf-a popatrz na tabelkę z przeliczeniem temperatury.

Co do fragmentu przeliczającego temperatury to jest wiele sposobów żeby to zrobić....Raz wieki temu napisałem te linijki i teraz zawsze wklejam do swoich programów, nawet za bardzo nie zastanawiam się nad tym. Z tego co patrze to twój kod tez poprawnie konwertuje ujemne temperatury... tylko było by lepiej gdyby dać Lsb-256, wtedy wyjdzie z minusem (jak zmienna będzie integer)

Ps. kody źródłowe należy umieszczać w odpowiednim znaczniku, czasami poprawiam wpisy a czasami kasuje więc dostosuj się do regulaminu

gosc's picture

zamiana ds1820 na 18b20

Witam Cię Mirley
Wiem że terminaż masz napięty, ale może mógłbyś pomóc??
mam gotowy soft do sterownika akwariowego w którym odczyt temp. jest z czujnika 1820 czy mogłbyś zerknąć jak zamienić go na 18b20 ponieważ takie czujniki mi przysłano. Czytałem trochę ale nic z tego nie rozumię coś się przelicza inaczej.
pozdrawiam

oto fragment kodu:

Sub Read1820
   Waitms 250
   Waitms 100
   1wreset
   1wwrite &HCC
   1wwrite &HBE
   Bd(1) = 1wread(9)
   1wreset
   Tmp = Bd(1) And 1
   If Tmp = 1 Then Decr Bd(1)
   T = Makeint(bd(1) , Bd(2))
   T = T * 50 : T = T - 25 : T1 = Bd(8) - Bd(7) : T1 = T1 * 100
   T1 = T1 / Bd(8) : T = T + T1 : T = T / 10
   X = T / 10
End Sub

rafliczek22's picture

1wreset 1wwrite &hcc 1wwrite

1wreset
1wwrite &hcc
1wwrite &h44 
wait 1
1wwrite &hcc
1wwrite &hbe
Lsb = 1wread():
Msb = 1wread():
1wreset
 
temperatura=makeint(lsb,msb)
temperatura=temperatura/16

To co podałem to bez liczb po przecinku, chyba że będzie to zmienna single, inaczej jesli nie chcesz miejsc po przecinku to word.
Ten kod co podałeś jest jakiś "niedziałający", nie ma prawa działać.

Post new comment

The content of this field is kept private and will not be shown publicly. If you have a Gravatar account, used to display your avatar.
  • You can use BBCode tags in the text. URLs will automatically be converted to links.
  • Use the special tag [adsense:format:slot] or [adsense:format:[group]:[channel][:slot]] or [adsense:block:location] to display Google AdSense ads.
  • You can enable syntax highlighting of source code with the following tags: [code], [blockcode], [c], [cpp], [java], [javascript], [php], [python], [qb].
  • Image links with 'rel="lightbox"' in the <a> tag will appear in a Lightbox when clicked on.

More information about formatting options