Forum: Mikrocontroller und Digitale Elektronik Probleme mit Temperatursensor DS18B20


von Michael N. (lwl2012)


Lesenswert?

Hey Leute,

ich habe folgendes Problem, ich habe an mein ATMega8 (16MHz Tackt über 
Quarz) auf dem Pollinboard ein LC Display und einen Temperatursensor 
DS18B20.

Wichtig es ist DS18B20 also nicht DS18S20 oder DS1820.

Den Sensor habe ich VDD und GND gegen GND und DQ auf Portc.0 und mit 
einem 2,2k gegen Vcc. Hatte vorher ein 4,7k gegen Vcc gehabt, da war die 
Anzeige aber um 2,5 Grad höher.

Das Problem ist, auf dem LCD werden mir Temperaturen zwischen 45 und 50 
angezeigt (was im Raum eher unmöglich ist. Ein Fertigthermometer zeigt 
gerade mal rund 20 Grad an.).

Hier der Code:
1
$regfile = "m8def.dat"
2
$crystal = 1000000
3
4
5
Dim Rom1 As Byte
6
Dim Temp As Single
7
8
Config 1wire = Portc.0
9
10
11
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
12
Config Lcd = 16 * 2
13
14
Cursor Off
15
Cls
16
17
18
Locate 1 , 1
19
Lcd "AK Modul Bus"
20
21
Locate 2 , 1
22
Lcd "ES-M32"
23
24
Waitms 1500
25
26
Cls
27
28
Locate 1 , 1
29
Lcd "Temperatur: "
30
31
32
Do
33
34
   1wreset
35
   1wwrite &HCC
36
   1wwrite &H44
37
38
   Waitms 800
39
40
   1wreset
41
   1wwrite &HCC
42
   1wwrite &HBE
43
   Rom1 = 1wread(1)
44
45
   Temp = Rom1 / 2
46
47
   Locate 2 , 5
48
   Lcd Temp
49
50
Loop


Vielleicht sieht jemand ein Fehler im ganzen.

Danke schon mal im vorraus.


Michael

von holger (Gast)


Lesenswert?

>16MHz Tackt über Quarz

>$crystal = 1000000

Hmm.

von Mitesser (Gast)


Lesenswert?

Wenn
1
Rom1 = 1wread(1)
ein Byte einliest, liest Du nur das untere Byte ein, dass die 
Wertigkeiten
8 4 2 1 1/2 1/4 1/8 1/16
enthält.

Das obere Byte mit den Wertigkeiten
<5 gleiche Sign Bits> 64 32 16
lässt Du dann entfallen.

20° -16 = 4 => LSB = 64 (1/16°)
64 / 2 = 32
Da meine DS18B20 gerne 1 bis 2°C mehr anzeigen, haut 40 - 50 hin.

von Karl (Gast)


Lesenswert?

Wundert mich, dass überhaupt etwas angezeigt wird. Nach
1
1wwrite &HBE

liefert der IC 9 Bytes, die in ein Array eingelesen werden sollten.
1
Dim Rom1(9) As Byte
2
...
3
1wwrite &HBE
4
Rom1(1) = 1wread(9)
5
....

In den ersten beiden Bytes steckt die Temperatur:
1
Dim Temperatur As Word
2
....
3
Temperatur = Makeint(Rom1(1),Rom1(2)) 'T
4
...

So, dieser Wert muss noch mit 0.0625 multipliziert werden, und Du hast 
die Raumtemperatur.

von Michael N. (lwl2012)


Lesenswert?

Beim Code hatte ich das beim Compiler schon vorher geändert. Also habe 
das erst noch nicht gemacht und das war Code Version 1.0 wenn mans so 
nennen möchte.

Also in der Fertigen Version die auf dem µC (ATMega8) ist steht:

$crystal = 16000000



Und Sry Mitesser, kannst deins vielleicht auch mal ein wenig einfacher 
Formiulieren. Das war mein erster Versuch mit einem 1 Wire Komponente.

Weil 100 Pro komme ich mit deiner Erklärung nicht ganz mit. Vielleicht 
kannst mir helfen dies zu verstehen, bzw. beim anpassen helfen.

Vorallem komme ich nich ganz mit, dass 40-50 okay sein soll wenn im Raum 
gerad mal 20 Grad ist.

Hoffe auf noch weitere Hilfe von euch. Danke schon mal im vorraus.


Michael

von Michael N. (lwl2012)


Lesenswert?

Karl schrieb:
> ...
>
1
> Dim Rom1(9) As Byte
2
> ...
3
> 1wwrite &HBE
4
> Rom1(1) = 1wread(9)
5
> ....
6
>
> ...


Schiebt diese Codezeile also Rom1(1) = 1wread(9) gleich die Werte in den 
Array Rom1()?


Michael

von Karl (Gast)


Lesenswert?

Was Mitesser und ich Dir versuchen zu sagen, ist, dass die Temperatur 
richtig gemessen wurde, Du das Ergebnis aber noch einmal mit 0.0625 bzw. 
0.625 multiplizieren solltest.

PS. Im Internet gibt es viele funktionierenden Beispiele, sind mit 
"DS18B20 BASCOM" zu finden.

von Karl (Gast)


Lesenswert?

Michael N. schrieb:
> Schiebt diese Codezeile also Rom1(1) = 1wread(9) gleich die Werte in den
> Array Rom1()?

Jepp. Und die ersten beiden brauchst Du jetzt, die anderen vielleicht 
noch später.

von Michael N. (lwl2012)


Lesenswert?

Karl schrieb:
> Was Mitesser und ich Dir versuchen zu sagen, ist, dass die Temperatur
> richtig gemessen wurde, Du das Ergebnis aber noch einmal mit 0.0625 bzw.
> 0.625 multiplizieren solltest.
>
> PS. Im Internet gibt es viele funktionierenden Beispiele, sind mit
> "DS18B20 BASCOM" zu finden.

Wenn ich aber z.B. die angezeigte 50 mit 0.625 Multipliziere erhalte ich 
eine Temp. über 30 Grad. Und das wäre ja immer noch 10 Grad über 
Realwert.

Michael

von Karl (Gast)


Lesenswert?

Ja, Du wertest auch nur ein einziges Byte aus. Du brauchst aber 2 Bytes. 
Hier mal ein Beispiel aus dem Datenblatt:

http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf


Messung Byte 1: &B0000_0001
Messung Byte 2: &B1001_0001

Macht als Word (in HEX) = &H0191, da (256*Byte_1)+Byte2

macht als Integer = 401. So, da Du das Modell DS18B20 hast, musst du den 
Wert mit 0.0625 multiplizieren oder durch 16 teilen. Dann kommt heraus: 
25.0625. Das sind 25.0625 °C.

von Karl (Gast)


Lesenswert?

Habe mal etwas geschrieben (hier das Wichtigste daraus, mit Format 
sollte man noch das Komma richtig setzen):
1
Declare Sub Init_ds18b20
2
Declare Sub Measure_ds18b20
3
Declare Sub Read_ds18b20
4
5
Dim Ds18b20r(9) As Byte
6
Dim Ds18b20temp As Word
7
Dim Ds18b20tempstr As String * 6
8
9
Call Init_ds18b20  
10
11
12
Do
13
14
  Call Measure_ds18b20
15
  Waitms 800
16
  Call Read_ds18b20
17
18
  Ds18b20temp = Makeint(ds18b20r(1) , Ds18b20r(2))
19
  Ds18b20temp = Ds18b20temp * &H64
20
  Ds18b20temp = Ds18b20temp / &H10
21
  Ds18b20tempstr = Str(ds18b20temp)
22
  Print Ds18b20tempstr
23
24
Loop
25
26
Init_ds18b20:
27
   1wreset
28
   1wwrite &HCC
29
   1wwrite &H4E
30
   1wwrite &H0
31
   1wwrite &H0
32
   1wwrite &H1F   '1F (0.5°C), 3F (0.25°C), 5F(0.125°C), 7F(0.0625°C)
33
Return
34
35
Measure_ds18b20:
36
   1wreset
37
   1wwrite &HCC
38
   1wwrite &H44
39
Return
40
41
Read_ds18b20:
42
   1wreset
43
   1wwrite &HCC
44
   1wwrite &HBE
45
   Ds18b20r(1) = 1wread(9)
46
Return

von Michael N. (lwl2012)


Lesenswert?

Danke werde den Code von Karl die Tage Testen. Aber jetzt hab ich an 
sich was gefunden was läuft. Ist zwar eine Messdifferenz von noch 1° 
aber das ist akzeptabel.

Karl geht den mit deiner möglichkeit auch mehrer Sensoren an zusprechen?

Und könntest die Zeilen bissel besser Komentieren? Also vorallem wofür 
die einzelnen vermutlich Hexzahlen stehen oder sind das festdefinierte 
Werte?



Michael

von Karl (Gast)


Lesenswert?

Hey Michael. Freut mich, dass Du etwas gefunden hast. So wirklich schwer 
ist es nämlich nicht, einen DS18B20 anzusprechen (und Infos aus dem Netz 
darüber zu bekommen).

Die Hexzahlen ergeben sich (fast) alle aus dem Datenblatt und sind fest. 
Man kann auch mehrere DS18B20 ansprechen, muss dafür aber die 
Seriennummer der einzelnen ICs kennen und den Code somit verändern.

Siehe dazu auch:

http://www.rn-wissen.de/index.php/Bascom_und_1-Wire

Und ich kann nur immer wieder das Datenblatt empfehlen. Da ist jede 
Hexzahl ausgezeichnet dokumentiert. Viel ausführlicher als man es mit 
einem Kommentar im Code machen könnte.

http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf

Der Rest ist hoffentlich logisch:
1
Call Init_ds18b20: IC initialisieren, sprich Messgenauigkeit einstellen. 
2
Call Measure_ds18b20: Messung anwerfen
3
Call Read_ds18b20: Daten lesen

Der Rest macht aus den 2 Bytes ein Word. Das Ergebnis wird durch 16 
geteilt und ausgegeben. Wie geschrieben, es fehlt noch die Position des 
Kommas.

von Michael N. (lwl2012)


Lesenswert?

Ja sagen wir so, die Adressen der chips (Temp. Sensoren) hab ich raus 
bekommen. Nur irgendwie hab ichs nicht richtig verstanden wie ich dann 
die Seriennummer (wenn ich mich nich vertue waren es 9 x 2Stellen Hoffe 
ich vertue mich da nicht) in den Array genau einfügen soll, damit es 
Funst.

Karl kannst mir vielleicht ein Beispiel mal zeigen wie das aussehen 
muss, bei einem x Beliebigen Temp. Sensor.?

Also Anhand des Beispielcodes 1-Wire erklärung aus Bestimmtes "Gerät 
ansprechen" von der Seite 
http://www.rn-wissen.de/index.php/Bascom_und_1-Wire

Das mit Alle Seriennummern hat geklappt und Putty gab mir die Adresse 
des Temp. Sensors aus. Habt ihr eure irgendwie makiert welche Seriennr. 
welcher Chip hat?

Also falls mal einer Kaputt geht im Bus oder sonst irgendwie ersetzt 
wird und man dann weiß welche Seriennummer ersetzt werden muss?

Ich hoffe es ist verständlich was ich meine.



Michael

von Karl (Gast)


Lesenswert?

Naja, in meinem Beispiel sende ich immer &HCC. Das Datenblatt sagt dazu, 
dass der nachfolgende Befehl von allen ICs im Bus ausgeführt werden 
soll.

Will man einen einzelnen IC ansprechen, so sagt das Datenblatt sende 
&H55 und danach die 64-Bit Adresse des ICs. In BASCOM würde das so 
aussehen:
1
Dim DS18B20-ID(8) As Byte 
2
3
1wreset
4
1wwrite &H55
5
1wwrite DS18B20-ID(1) , 8 'Sendet 64-Bit
6
....

Du kannst auch immer zum Programmstart oder im Programm die 
Seriennummern der ICs ermitteln. Wenn es wichtig ist, sollte man sich 
natürlich aufschreiben, wo welcher Sensor etwas misst.

von Michael N. (lwl2012)


Lesenswert?

Stimmt, so könnte ich mit dem Beispiel von der Website auch was machen.

Ich hätte die Seriennummern in Constanten bzw in den EEprom gepackt und 
beim Start abgerufen. Also, dass nicht bei jedem Start der Bus 
untersucht wird, welche Sensoren vorhanden sind.

Nur dann muss ich entweder alles nur DS18B20 Sensoren haben oder muss 
einfach die Adresse des Sensors abfragen und die ersten beiden Stellen 
seperat untersuchen, die bilden ja die Family Adresse.


Aber danke. Manchmal sieht man den Walt vor lauter Bäumen nicht grins

Werde es die Tage mal Testen. Also erst Bus durchsuchen lassen, welche 
SN vorhanden sind und dann in der Do loop Schleife die Temp. messen 
lassen und dann per Print ausgeben lassen. Evtl mit der Kombination von 
Text, der den Ort des Sensors vermittelt.

Den gebe ich wie folgt aus, wenn ichs richtig verstanden habe.

Print "Sensor 1"; Temp(1); "°C"

Stimmts?

Michael

von Karl (Gast)


Lesenswert?

Michael N. schrieb:
> Print "Sensor 1"; Temp(1); "°C"

Hängt davon ab, was in Temp(1) steht und "°" wird wahrscheinlich nicht 
richtig angezeigt werden.

Du solltest beim Auslesen unbedingt das Timing beachten. Bei höchster 
Genauigkeit dauert die Umrechnung um die 750ms.

von Michael N. (lwl2012)


Lesenswert?

kann ja einfach zwischen Auslesen und Ausgeben ein Waitms einbauen. Aber 
werde es einfach mal Testen.



Michael

von Michael N. (lwl2012)


Lesenswert?

So habe den Code von Karl getestet, nur leider ist in dem Fall die 
Ausgabe wieder nicht passend. Also er zeigt ein Wert über 1000 an.

Aber naja ich werde mir das alles noch mal näher zu gemüte führen 
müssen. Vorallem wenn alles ersma richtig läuft wie ich das bei meinem 
Funktionstüchtigem Code hin bekomme verschiedene Sensoren seperat ab zu 
fragen. Also müsste ich gucken wie ich den code modifiziert bekomme.


Hier ist der Code der Funktioniert mit etwa 2 Grad Messdifferenz.
1
Const Ds1920 = &H10
2
Const Skiprom = &HCC
3
Const Read_rom = &H33
4
Const Convertt = &H44
5
Const Read_ram = &HBE
6
Const Write_ram = &H4E
7
Const Copy_ram = &H48
8
Const Recall_ee = &HB8
9
Const Read_power = &HB4
10
11
Dim Family_code As Byte
12
Dim Serial_number(6) As Byte
13
Dim Crc As Byte
14
Dim Scratch(9) As Byte
15
16
Dim I As Byte
17
Dim Temp As Word
18
Dim Temp1 As Integer
19
Dim Stemp As Single
20
21
22
Do
23
  1wreset
24
  1wwrite Read_rom
25
  Family_code = 1wread()
26
  For I = 1 To 6
27
    Serial_number(i) = 1wread()
28
  Next
29
  Crc = 1wread()
30
  1wwrite Convertt
31
  Do
32
    Temp = 1wread()
33
  Loop Until Temp = &HFF
34
35
  1wreset
36
  1wwrite Skiprom
37
  1wwrite Read_ram
38
39
  For I = 1 To 9
40
    Scratch(i) = 1wread()
41
  Next
42
43
44
 Temp = Scratch(2)
45
  Shift Temp , Left , 8
46
  Temp = Temp + Scratch(1)
47
  Stemp = Temp
48
  Stemp = Stemp / 16
49
50
51
52
  Locate 1 , 1
53
  Lcd "Raumtemperatur"
54
  Locate 2 , 1
55
  Lcd "Temp: " ; Fusing(stemp , "#.##") ; " Grad C"
56
  Cursor Off
57
  Wait 1
58
59
Loop
60
61
End


Michael


PS: Ich hoffe ich habe den Code jetzt nicht vertauscht.

von Karl (Gast)


Lesenswert?

Natürlich zeigt er mehr als 1000 an, da Du noch das Komma bzw. den Punkt 
einfügen musst...mit Format...Format(Wert, "00.00").

von Michael N. (lwl2012)


Lesenswert?

Em joa stimmt. Bei dem Gedanken, wo es sagst hab ich dies vergessen.

Kannst mir vielleicht den mal den Punkt sagen wo genau die Seriennummer 
angegeben werden muss, wenn man mehere Sensoren nimmt? Dann müsste ich 
ja den Abfragebereich in eine For - Schleife packen und die Seriennummer 
als Array mit fortlaufenden I - Wert. Und dann am Ende den Array (mit 
den Messwerten) wieder aus zu gebene.

Oder gibts da ne andere Lösung für?


Michael

von Karl (Gast)


Angehängte Dateien:

Lesenswert?

Ok, Michael. Musste noch Geld verdienen, mich um die Familie kümmern....

Anbei der Code für bis zu 8 DS18B20. Viel Spaß damit.

Eine umfangreiche Fehlerbehandlung gibt es nicht. Ohne DS18B20 am Bus = 
keine Funktion. Ebenso fehlt noch die Prüfsumme und das Verhalten bei T 
< 0°C.

von Michael N. (lwl2012)


Lesenswert?

Tausend und 1 Dank Karl.

Das für < 0 Grad noch nicht enthalten ist, ist nicht schlimm. Soll 
Primär Raumtemperatur Messen und wenn die unter 0 Grad ist wäre, ich 
schon tief in Sibierien. Da wollte ich aber nicht hin. :-) also würde es 
für mein Zweck reichen.

Wie gesagt vielen Danke und daraus das mit minusgraden werde ich mir 
noch selber zu gemüt führen. Denke das kann ich hin bekommen mit 
probieren. üben und so weiter.

Und wenn ich doch mehr Sensoren haben möchte sollte ich, hin bekommen. 
Da müsste ich ja nur mehr ran packen, aber wenn es nicht funktionieren 
würde, wäre es nicht sonderlich schlimm. 8 Sind ja schon eine Menge.

Das hier Begrenzt doch die Anzahl auf 8 oder?
1
Ds18b20_id(8)


Michael

von Karl (Gast)


Lesenswert?

Michael N. schrieb:
> Das hier Begrenzt doch die Anzahl auf 8 oder?
> Ds18b20_id(8)

Ja. Ich weiß allerdings nicht, wie viele "Double" Variablen Dein AVR 
verkraftet.

Hoffe, Du lernst auch ein wenig dabei. Es ist nicht viel kommentiert, da 
alle 1wire Funktionen in der BASCOM-Hilfe erklärt sind und der Rest im 
mehrfach erwähnten Datenblatt steht.

von Michael N. (lwl2012)


Lesenswert?

Klar, ich bin eher weniger der viel liest grins eher Lernen beim üben 
und nachmachen und bastel aus dadraus dann meins was ich benötige.

Und an sich habe ich vor den ATMega8 zu nehmen, aber notfalls kann ich 
auch auf ein mega32 zurück greifen.

Und würde ich jeden verfügbaren Speicherplatz für Adressen nehmen, 
könnte ich 128 Sensoren nehmen. Aber denke ich fange mal mit bis zu 8 an 
und werde höchstens auf 16 erweitern. Ist bei einem 1Wire Bus nicht die 
Anzahl sowieso auf 16 begrenzt? Gut man könnte mehrere 1Wire Bus auf 
machen aber okay.

Und 1 Sensor werde ich im Kühlschrank nutzen (original Termostat is 
Kaputt werde mir da was nachbauen. Es ist nur ein Party Kühlschrank, da 
lohnt reperatur nicht, is schon älter und läuft nur wenige Tage im Jahr. 
Würde das normale Termostat überbrücken mit einem Relais, welches vom µC 
geschalten wird. Und ein Temp. Sensor überwacht die Temperatur. :-)

Danke nochmal.

Michael

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.