Forum: Compiler & IDEs DS18S20 Temperaturwerte in signed integer wandeln


von Rene Z. (renezimmermann)


Angehängte Dateien:

Lesenswert?

Hallo,

ich wollte den Temperaturwert eines DS18S20, zur weiteren 
Datenübertragung,in einen signed integer (int16_t) umwandeln. Dafür habe 
ich mir folgenden Code geschrieben:
1
void rechne(uint8_t msb, uint8_t lsb, uint8_t count_remain){
2
  ausgabe_u(msb);
3
  ausgabe_u(lsb);
4
  ausgabe_u(count_remain);
5
  //integer
6
  int16_t tempi = msb * 0x100 + lsb;
7
  ausgabe_i(tempi);
8
  tempi /= 2;
9
  ausgabe_i(tempi);
10
  tempi *= 100;
11
  ausgabe_i(tempi);
12
  tempi -= 25;
13
  ausgabe_i(tempi);
14
  ausgabe_i((count_per_c * 100 - count_remain * 100) / count_per_c);
15
  tempi += (count_per_c * 100 - count_remain * 100) / count_per_c;
16
  ausgabe_i(tempi);
17
  uart_puts("\r\n");
18
}

Zur Kontrolle habe ich mir die Werte über die USART ausgegeben lassen.
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <avr/pgmspace.h>
6
7
#define BAUD     38400
8
#include <util/setbaud.h> 
9
#include "uart.c"
10
11
#define count_per_c    0x10
12
13
void ausgabe_i(int16_t wert){
14
  char buf[7];
15
  itoa(wert, &buf[0], 10);
16
  uart_puts(&buf[0]);
17
  uart_putc(';');
18
}
19
20
void ausgabe_u(uint8_t wert){
21
  char buf[4];
22
  utoa(wert, &buf[0], 10);
23
  uart_puts(&buf[0]);
24
  uart_putc(';');
25
}
26
27
int main(void){
28
  uart_init();
29
  uart_puts("Start\r\n");
30
  for(int16_t temp = 0xFF92; temp < 0x00AB; temp++){
31
    for(uint8_t count_remain = 0x00; count_remain < 0x10; count_remain++){ 
32
      rechne((uint8_t) (temp >> 8), (uint8_t) temp, 0x0F - count_remain);
33
    }
34
  }
35
    
36
  while(1){                              // leere Endlosschleife
37
  }
38
}
Anbei das Logfile. Dort sieht man das sehr viele Werte stimmen aber 
ebend nicht alle.
Nach jetzt schon langem Grübeln, wo ich den Bock geschossen habe komme 
ich zu keinem Ergebniss. Vieleicht fällt euch ja dazu was ein.

Gruß Rene

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Rene Zimmermann schrieb:
> Anbei das Logfile.

In dieser Datenwurst findet sich doch keiner zurecht.  Welches soll
denn die Stelle sein, wo es nicht stimmt?

Hier ist eine DS18B20-Funktion, die ich mal benutzt habe:
1
double
2
Read_Temperature(void)
3
{
4
  uint8_t get[9];
5
  uint8_t temp_lsb,temp_msb;
6
  uint8_t k;
7
8
  ow_reset();
9
10
  ow_write_byte(0xCC); //Skip ROM
11
  ow_write_byte(0x44); // Start Conversion
12
13
  _delay_ms(750);
14
15
  ow_reset();
16
17
  ow_write_byte(0xCC); // Skip ROM
18
  ow_write_byte(0xBE); // Read Scratch Pad
19
20
#ifdef DEBUG
21
  PRINT("1wire: ScratchPAD DATA = ");
22
#endif
23
  for (k = 0; k < 9; k++){
24
    get[k] = ow_read_byte();
25
#ifdef DEBUG
26
    PRINTF("%02X ", get[k]);
27
#endif
28
  }
29
  k = ow_checkcrc(get, 9);
30
#ifdef DEBUG
31
  PRINTF(" (CRC %s)\r\n", k == 0? "OK": "FAIL");
32
#endif
33
  if (k != 0)
34
    return 0;
35
36
  temp_msb = get[1]; // Sign byte + lsbit
37
  temp_lsb = get[0]; // Temp data plus lsb
38
  int i = (temp_msb << 8) | temp_lsb;
39
40
  return i / 16.0;
41
}

(Lizenbedingungen für Weiternutzung: "Beer-Ware License")

von Karlheinz (Gast)


Lesenswert?

Rene Zimmermann schrieb:
>   tempi /= 2;
>   ausgabe_i(tempi);
>   tempi *= 100;
>   ausgabe_i(tempi);


vertausche die beiden Operationen, multipliziere zuerst mit 100 und 
teile dann durch 2 !!! dann gehen keine (wichtigen) Stellen verloren

von Karl H. (kbuchegg)


Lesenswert?

Rene Zimmermann schrieb:

> Anbei das Logfile. Dort sieht man das sehr viele Werte stimmen aber
> ebend nicht alle.

Ich denke deine Umrechnung stimmt schon.

Lass dich nicht verwirren, das da manche Werte doppelt vorkommen, bzw. 
scheinbar die Reihenfolge nicht stimmt.
Wenn du vom DS die Daten bekommst, dann kommt das schon richtig raus.

von Karl H. (kbuchegg)


Lesenswert?

Karlheinz schrieb:
> Rene Zimmermann schrieb:
>>   tempi /= 2;
>>   ausgabe_i(tempi);
>>   tempi *= 100;
>>   ausgabe_i(tempi);
>
>
> vertausche die beiden Operationen, multipliziere zuerst mit 100 und
> teile dann durch 2 !!! dann gehen keine (wichtigen) Stellen verloren

Auch das ist ok.
Er muss zuerst das LSB loswerden (laut Maxim Doku). Die *100 sind nur 
der Festkommaarithmetik geschuldet, mit der dann die Nachkommastellen 
aus COUNT_REMAIN einrechnen will.

von Rene Z. (renezimmermann)


Lesenswert?

>In dieser Datenwurst findet sich doch keiner zurecht.

Ja war vieleicht etwas viel. ;-)

Das Auslesen der Sensoren ist nicht mein Problem. Ich will den Wert des 
MSB, LSB und count_remain Registers zu einem signed Integer verrechnen. 
Um zu prüfen ob es geht habe ich einfach alle Werte für die 3 Register 
durchrechnen lassen und mitgeschnitten. Deshalb auch so eine grosse 
Datei.

Wenn man das für z.B. MSB=0x00, LSB=0x01 und count_remain=0x05 rechnet 
kommt 0.94 Grad Celsius heraus. Nur leider nicht bei meiner Routine.

Gruß Rene

von Karl H. (kbuchegg)


Lesenswert?

Rene Zimmermann schrieb:

> Wenn man das für z.B. MSB=0x00, LSB=0x01 und count_remain=0x05 rechnet
> kommt 0.94 Grad Celsius heraus.

Nö.
Da hast du dich mit dem Taschenrechner verhaut (hast du auch nicht 
vergessen, dass du das LSB wegwerfen musst?). Da kommt 0.4375 raus. Und 
deine Routine erreichnet 43. Passt also.

von Rene Z. (renezimmermann)


Lesenswert?

Oh man,

so was blödes, ich suche einen Fehler wo es keinen gibt. Na super.

Hat noch einer eine Idee zu dem Rundungsfehler? Nicht das es mich stört 
aber korrekt ist es ja nicht.

Dann schreibe ich jetzt mal den Code für die Ausgabe in Grad Celsius mit 
zwei Nachkommastellen. Damit ich auch wieder was zum Fehler suchen habe. 
;-)

Vielen Dank
Rene

von Karl H. (kbuchegg)


Lesenswert?

Rene Zimmermann schrieb:
> Oh man,
>
> so was blödes, ich suche einen Fehler wo es keinen gibt. Na super.
>
> Hat noch einer eine Idee zu dem Rundungsfehler? Nicht das es mich stört
> aber korrekt ist es ja nicht.

vergiss ihn.
Die Temperatur stimmt sowieso nicht auf 1/100 Grad genau.

Es ist eine Sache einen Wert auf 4 Nachkommastellen auszugeben. Es ist 
aber eine ganz andere Sache, welche von den 4 Nachkommastellen reine 
Phantasie sind und welche nicht. Nur weil in einer Rechnung 4 
Nachkommastellen rauskommen, heißt das ja nicht, dass das physikalische 
System deswegen exakt diese Wert hat. Den WOhnraum zeigst du mir mal, 
bei dem die komplette Luftmasse im Raum auf 1/100 Grad genau diesen 
einen Wert hat.

von Rene Z. (renezimmermann)


Lesenswert?

>vergiss ihn.
>Die Temperatur stimmt sowieso nicht auf 1/100 Grad genau.

Ja, da hast du wohl so recht, nochmals Danke.

Gruß Rene

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wenn du zwei Nachkommastellen haben willst, dann nimm einen SHT-21
bzw. seinen nicht-feuchtemessenden kleinen Bruder STS-21.  Die
können auch keinen 10 mK absolut genau messen, aber bei denen passt
die 10-mK-Stelle dann zumindest noch in der Tendenz.  (Hier wurde
neulich noch ein anderer Sensor genannt, der noch einen Tick genauer
ist, aber den Typ habe ich vergessen.)

Bei den billigeren Sensoren ist oft schon die 100-mK-Stelle nur noch
Rauschen.

von Rene Z. (renezimmermann)


Lesenswert?

>Wenn du zwei Nachkommastellen haben willst, dann nimm einen SHT-21
>bzw. seinen nicht-feuchtemessenden kleinen Bruder STS-21.

Nee, das ist nicht notwendig. Wir reden hier über die Wassertemperatur 
in meinem Pool und der Poolheizung sowie der Umgebungsluft. Das sind 
Daten die ich per Funk zu meinem Server schicke. Somit weiss ich immer 
was los ist und die Steuerung wenn sie die Pumpe zu schalten hat. Mir 
ging es hier hauptsächlich darum nur 2 Bytes zu übertragen. Vorher habe 
ich einfach 3 x 9 Bytes SCRATCHPAD + 2 Bytes Checksumme gesendet. Jetzt 
reichen 3 x 2 Bytes + 2 Bytes Checksumme.

Gruß Rene

von Karl H. (kbuchegg)


Lesenswert?

Rene Zimmermann schrieb:

> Nee, das ist nicht notwendig. Wir reden hier über die Wassertemperatur
> in meinem Pool und der Poolheizung sowie der Umgebungsluft.

In dem Fall würde ich mir noch nicht mal Gedanken um die Zehntelgrad 
machen. Die 0.5°, die du standardmässig kriegst sind nämlich schon 
falsch.

Also jetzt nicht 'falsch' im Sinne von 'der Sensor liefert falsche 
Werte'. Sondern falsch im Sinne von 'das Wasser' im Pool hat 23.5°C. 
Denn das hat es ganz sicher nicht überall.

von Rene Z. (renezimmermann)


Lesenswert?

>In dem Fall würde ich mir noch nicht mal Gedanken um die Zehntelgrad
>machen. Die 0.5°, die du standardmässig kriegst sind nämlich schon
>falsch.

Grundsätzlich muß ich dir da recht geben. Nur ist das bei uns in der 
Firma schon so eine Art Kult. Jeder darf im Sommer mal schauen was die 
Wassertemperatur macht. Ihr glaubt gar nicht was da los ist. Da ich mir 
aber keine Daten aus den Fingern saugen will nehme ich mal 1/10 Grad. 
Für die Technik kann ich ja nichts. ;-)

Gruß Rene

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> Sondern falsch im Sinne von 'das Wasser' im Pool hat 23.5°C.
> Denn das hat es ganz sicher nicht überall.

Man kann den Temperatursensor ja in einem U-Boot montieren, das die
Daten quer durch den Pool hinweg einsammelt und dann nach dem
Auftauchen funkt. :)

von Rene Z. (renezimmermann)


Lesenswert?

>Man kann den Temperatursensor ja in einem U-Boot montieren, das die
>Daten quer durch den Pool hinweg einsammelt und dann nach dem
>Auftauchen funkt. :)

Geil, das ist das richtige Projekt für meinen Junjor. 8-)

Gruß

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.