Forum: Mikrocontroller und Digitale Elektronik Temperaturberechnung für DS18S20


von Patrick (Gast)


Lesenswert?

Hallo Leute,

ich weis, DS18S20-Themen gibt es mehr als genug, ich hab auch schon fast 
alle gelesen, aber ich komme trotzdem nicht weiter, vielleicht kann mir 
ja jemand helfen.

Ich möchte mit meinem tiny2313 einen DS18S20 betreiben (ohne 
Parasite-Power).
Nach langem hin und her kann ich ihn jetzt endlich ansprechen und die 
Temperatur auf einem LCD-Display anzeigen lassen.

Probleme macht mir allerdings die Temperaturberechnung für Auflösungen 
mit mehr als 9bit.
Ich bin mir nicht sicher an was es liegt, hab ich mich verrechnet, 
liegts an den Variablen-Typen… ?
Wahrscheinlich ists ganz simpel, aber ich werd noch wahnsinnig, ich kann 
den Fehler nicht finden!

Hier mein C-Code (Auszug):
1
void TH_SendCommand (unsigned char command)
2
{  TH_InitBus();
3
  TH_WriteByte(SKIP_ROM);
4
  TH_WriteByte(command);    
5
// hier entweder CONVERT_TEMPERATURE oder READ_SCRATCH_PAD
6
}
7
8
int TH_GetTemp( void )
9
{  int i, iTempResult;
10
  unsigned char ucByteRead[9] = {0,0,0,0,0,0,0,0,0};
11
  signed char Temp_Read;
12
13
  TH_SendCommand(CONVERT_TEMPERATURE);
14
  _delay_us(100);
15
  TH_SendCommand(READ_SCRATCH_PAD);
16
                    
17
  for (i=0; i<2; i++)  { ucByteRead[i] = TH_ReadByte();  }
18
  
19
//  BERECHNUNG DER TEMPERATUR
20
21
  if (ucByteRead[1] >= 1){ Temp_Read = (-1)*(((~ucByteRead[0])+1)/2);  }
22
  // Temperatur kleiner Null: 
23
  // Zweierkomplement -> um 1 rechtsschieben -> Vorzeichen setzen
24
  if (ucByteRead[1] < 1) { Temp_Read = ucByteRead[0]/2;  }  
25
  // Temperatur größer Null:
26
  // um 1 rechtsschieben
27
  
28
  iTempResult = (100*Temp_Read + 75  - (100*ucByteRead[6])/16);  
29
  // *100 um keine Kommazahl auszugeben (<-> Datentyp int)
30
  // 16, da Count_Per_C „hard-wired to 16“
31
  // 25,25°C wird also zu 2525°C
32
  
33
  return iTempResult;  
34
}

Abgesehen davon, dass die Temperatur ca. 1°C zu hoch ausgegeben wird, 
habe ich als Nachkommastellen immer ,75.
Ich habe bereits ein paar Temperaturberechnungen im Forum gesehen, aber 
aus denen werde ich nicht schlau.

Weis jemand Rat?

Grüße,

Patrick

von Jan M. (mueschel)


Lesenswert?

>Wahrscheinlich ists ganz simpel
>...
>for (i=0; i<2; i++)  { ucByteRead[i] = TH_ReadByte();  }
>...
>ucByteRead[6]


Bytes einlesen vor dem Benutzen ;-)

von Patrick (Gast)


Lesenswert?

>>Wahrscheinlich ists ganz simpel
>>...
>>for (i=0; i<2; i++)  { ucByteRead[i] = TH_ReadByte();  }
>>...
>>ucByteRead[6]


>Bytes einlesen vor dem Benutzen ;-)

ups, da steht ja ne 2, das muss doch nicht sein!
so kanns nicht klappen!

Danke Dir!

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Diskussionsgrundlage sei das Datenblatt
http://pdfserv.maxim-ic.com/en/ds/DS18S20.pdf

Ich sehe nirgends die Stelle, wo du COUNT_REMAIN (bei dir ucByteRead[6]) 
ausliest. Für mich sieht es so aus, als ob du nur TEMP_READ (MSB und 
LSB) aus dem Scratchpad ausliest (for (i=0; i<2; i++)  { ucByt...).

Deine Formel sieht auch etwas anders aus, als die Formel im Datenblatt. 
Wahrscheinlich weil du nicht mit reellen Zahlen sondern mit Ganzzahlen 
arbeiten willst.

von Hans J. (hjm)


Lesenswert?

Hallo Patrick,

der DS1820 liefert in den ersten 3 Nibbels die Ganzzahl, dann im letzten 
Nibbel die Nachkommastelle welche bei max. Auflösung mit 0,0625°C 
multipliziert werden muß.

Daher stimmt Deine Berechnung nur für die Ganzzahl.

Sowas in der Art wie:

wert = ((value >> 4)*10) + ((value << 12) / 6553);

Sollte funktionieren, wobei value das Eingangsword ist.

Grüße
Hans-Josef

von Gerhard. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Patrick,

im Anhang habe ich hier ein Beispielsprogram von Dallas mit dem ich vor 
Jahren etwas experimentiert habe. Obwohl die automatische ROM Search bei 
mir nicht funktioniert hat, gab's keine Probleme mit dem Auslesen der 
Temepartur bei einem einzelnen DS1820. Vielleicht hilft Dir das. Die 
Berechnung des Resultats war ueberhaupt kein Problem.

Gruss,
Gerhard

von Patrick (Gast)


Lesenswert?

Hallo Leute,

erstmal vielen Dank für Eure Antworten!

@Stefan
Ich habe die 2 jetzt durch eine 9 ausgetauscht, lese jetzt also alle 
Byte ein
Ja, ich will mit Ganzzahlen arbeiten, weil mir die Einführung von longs 
und floats den Speicher flutet (aber liegt wohl genau der Hund 
begraben…?!)

@Hans-Josef
Deine Berechnung kann ich prinzipiell verstehen.
Aber soweit ich das Datenblatt vom ds18’S’20 verstanden habe, steht im 
Byte0 die Temperatur (wobei das LSB die 0,5°C ausdrückt) und im Byte1 
lediglich das Vorzeichen (die Temperatur im Byte0 ist dann im 
Zwierkomplement)
…oder habs ich falsch verstanden?

@Gerhard
Vielen Dank für den Code. Allerdings komme ich damit nicht ganz klar:
Ich sehe noch wie Du tmp_in[0] und tmp_in[1] belegst.
Gleich danach machst du den Vorzeichencheck:
1
// Check for sign bit.
2
          if(value.tmp_w > 32767){
3
              temp = (signed long) value.tmp_w - 65536;
4
          }else
5
              temp = (signed long) value.tmp_w;

Allerdings kann ich nicht erkennen, wo tmp_w belegt wird und was da drin 
steht.

Ist die Berechnung beim ds18’B’20 anders als beim ds18’S’20?
Für welchen Controller hast du das Programm denn geschrieben?

Ich werde jetzt erstmal versuchen alle Einträge der Bytes 0-8 auf mein 
LCD auszugeben um die Rechnung evtl. auf dem Papier nachvollziehen zu 
können (das kann erstmal dauern).

Vielen Dank derweil,
Grüße und schönes Wochenende,
Patrick

von Gerhard. (Gast)


Lesenswert?

Hallo Patrick,

das Program ist eine Adaptierung eines Dallas Programbeispiels fuer den 
8051. Das Programbeispiel wurde von mir adaptiert um auf einem 
PIC18F8722 zu laufen. Der Compiler ist von CCS. Ich habe mich nur damit 
etwas rumgespielt. Soweit ich mich errinnern kann, haben die ROM Search 
Funktion nicht richtig gearbeitet. Konnte aber ohne weiteres DS18?20 
lesen. Desahlb dachte ich das koennte Dir nuetzlich sein. Ich kann mich 
nicht mehr genau errinnern ob ich den 18B20 oder den 18S20 angeschlossen 
hatte.

"value.tmp_w" ist Teil der unten geschrieben Union. Da value.tmp_in[n] 
den selben Speicher Platz belegen wie value.tmp_w ist das ein bequemer 
Weg um den Bau eines 16-bit Wertes zu vereinfachen.

    union {
    int tmp_in[2];
    long tmp_w;
    } value;

Das ist der uebliche Weg:

    u_int16_temperature = (uint8_msb_wert << 8) + uint8_lsb_wert;

Der CCS compiler hat dafuer die Funktion:

    u_int16_temperature  = make16(msb, lsb);

Da die restlichen bits vom DS1820 bei Temperaturen unter Null gesetzt 
sind, brauchst Du nur zu prufen ob der Wert groesser als 32767 ist und 
in dem Fall einfach 65536 abziehen. Dann erhaeltst Du einen "Signed 
Integer" Wert mit der Temperatur.

Der DS18B20 gibt die Temperatur mit 12-bit Aufloesung aus.

Gruss,
Gerhard

von Marco M. (marco1987)


Lesenswert?

Hallo Patrick hast du zwischen einen Funktionierenden Code in C?

Könntest du den mal allen zur Verfügung stellen?

Danke

von Mikes (Gast)


Lesenswert?

@Marco M.
hab was da, dann gib mal deine email, dann schick ich es dir

Gruß

von Marco M. (marco1987)


Lesenswert?

Hier meine Addy danke fürs zuschicken,



rapid11@gmx.net

von Christian S. (picpgm)


Lesenswert?

Hallo Zusammen,

hab auch schon mit den DS1820, DS18S20 bzw. DS18B20 gearbeitet. Unter 
folgendem Link kann der Treiber heruntergeladen werden. Der Code kann 
auch alle Sensoren automatisch finden (Search ROM Algorithmus). Die 
Temperatur wird als float oder als Rohwert mit einer Aufkösung von 
1/256°C zurückgegeben:
http://members.aon.at/electronics/pic/projects/ds1820/ds1820.html

MfG

von Volker (Gast)


Lesenswert?

Patrick schrieb:
> //  BERECHNUNG DER TEMPERATUR
>
>   iTempResult = (100*Temp_Read + 75  - (100*ucByteRead[6])/16);

> Abgesehen davon, dass die Temperatur ca. 1°C zu hoch ausgegeben wird,
> habe ich als Nachkommastellen immer ,75.

Woher kommt denn auch diese seltsame Formel? Im Datenblatt zum Sensor 
steht für die Temperaturberechnung mit Nachkommastellen die Formel:

Temperatur = Gelesene_Temperatur - 0,25 + (16 - Remain) / 16

Also muss deine obige Zeile lauten:

iTempResult = (100*Temp_Read - 25 + (16 - ucByteRead[6]) / 16 * 100) ;

Dann kommt auch das Richtige raus!

Ansonsten ist für den Fall eines negativen Vorzeichens (MS-Byte != 0) 
die Methode der Komplementierung, Inkrementierung und Shift um ein Bit 
nach rechts (= Teilen durch 2) für das LS-Byte sehr klug, denn sie 
braucht deutlich weniger Arbeitsspeicher als andere Berechnungen.

Gruß, Volker

von eProfi (Gast)


Lesenswert?

So geht es beim DS18S20 und DS18B20 ohne Float:
Beitrag "Re: DS18S20 - extended resolution bei Temperaturen um 0°C"

Es sind ICs mit der Aufschrift DS1820 im Umlauf (z.B. Pollin 180014 
2,50), die in Wirklichkeit DS18S20 sind, da CountsPerDegree immer 16 
ist.

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.