Forum: Mikrocontroller und Digitale Elektronik LM 75 negative Temperature


von D. R. (misterdimi1992)


Lesenswert?

Guten Tag zusammen,

ich benutze den LM75A und versuche mit Hilfe des Atmega 32 einen 
negativen Temperaturwert auszugeben auf einem LCD Display. Doch leider 
befindet sich in der negativen Berechnung ein Fehler, welchen ich nicht 
finde.

Die positive Temperaturmessung funktioniert.

Hat jemand eine Idee warum es nicht klappt? Lauf dem Datenblatt muss ich 
für negative Werte das Zweierkomplement anwenden und dieses Wert mit 
0,125 multiplizieren. Doch bei -1 Grad Celsius wird mir sofort -7937.000 
Grad auf dem LCD Display angezeigt.

Vielen Dank im Vorraus!






1
#include  <avr/io.h>
2
#define    F_CPU  8000000
3
#include  <util/delay.h>
4
#include  "lcd-routines.h"
5
#include  "i2cmaster.h"
6
7
8
9
10
uint8_t    MSByte_LM75, LSByte_LM75;
11
uint16_t  data_16bit, high_byte, low_byte, tempdata, tempdata_neg;
12
float    fMesswert_LM75, fMesswert_LM75_neg;
13
char    cBuffer_LM75[16], cBuffer_LM75_neg[8];
14
char    temp_min[16], temp_max[16];
15
16
17
18
int main(void)
19
{
20
    
21
    while (1) 
22
 /****Reading in values of temp register LM75  I²C ***/
23
  
24
25
lcd_init();
26
lcd_clear();
27
i2c_init();
28
i2c_start(0x92);      
29
i2c_write(0x00);        
30
i2c_rep_start(0x93);   
31
MSByte_LM75=i2c_readAck();  // Save MSB
32
LSByte_LM75=i2c_readNak();  // Save LSB
33
i2c_stop();    
34
  
35
data_16bit = (MSByte_LM75<< 8) | LSByte_LM75;  
36
tempdata = data_16bit;
37
tempdata = data_16bit >>5;            
38
39
          
40
41
          
42
43
/****negative temperature******/
44
45
if ( MSByte_LM75 & 0x80)  
46
    {  
47
      tempdata_neg = ~ tempdata + 1;      
48
49
      fMesswert_LM75_neg = tempdata_neg;            
50
51
      fMesswert_LM75_neg = fMesswert_LM75_neg *0.125;      
52
              
53
      dtostrf(fMesswert_LM75_neg,5,3,cBuffer_LM75);      
54
55
      lcd_setcursor(0,1);
56
      lcd_string("-");
57
              
58
      lcd_string(cBuffer_LM75);
59
      lcd_string(" ßC IST_Temp");
60
61
} // endif
62
63
else 
64
65
{
66
      fMesswert_LM75 =tempdata;
67
      fMesswert_LM75 = fMesswert_LM75 *0.125;      
68
              
69
      dtostrf(fMesswert_LM75,5,3,cBuffer_LM75);    
70
71
      lcd_setcursor(0,1);
72
              
73
      lcd_string(cBuffer_LM75);
74
      lcd_string(" ßC IST_Temp");
75
76
77
78
}
79
80
     _delay_ms(1000);
81
82
83
    }// end while(1)
84
}// end main

von A. B. (Gast)


Lesenswert?

Der LM75 liefert ein 9-Bit Ergebnis im 2er-Komplement. Nur bezieht sich 
das "2er-Komplement" auf dieses 9-Bit Ergebnis, nicht auf eine 
16-Bit-Zahl. Man muss also nach dem Bilden des 2er-Komplements die nicht 
vorhandenen 7 oberen Bits ausmaskieren.

Aber warum überhaupt so kompliziert? Wenn man das 9-Bit Ergebnis 
*LINKS*bündig als signed int interpretiert und dann nach float 
umwandelt, geht das doch alles automatisch ...
Die ganze Fallunterscheidung ist höchst überflüssig.

von Pete K. (pete77)


Lesenswert?

Das #define    F_CPU  8000000 gehört in das Makefile.

Und hier fehlt eine Klammer auf "{" nach while:
int main(void)
{

    while (1)
 /****Reading in values of temp register LM75  I²C ***/


lcd_init();

von D. R. (misterdimi1992)


Lesenswert?

A. B. schrieb:
> Der LM75 liefert ein 9-Bit Ergebnis im 2er-Komplement. Nur bezieht sich
> das "2er-Komplement" auf dieses 9-Bit Ergebnis, nicht auf eine
> 16-Bit-Zahl. Man muss also nach dem Bilden des 2er-Komplements die nicht
> vorhandenen 7 oberen Bits ausmaskieren.
>
ich benötige die 11-Bit-Zahl, da ich die negativen Werte auch mit der 
Nachkommazahl angeben möchte. Wie genau kann ich denn die oberen Bits 
ausmaskieren, dass diese nicht mit in die "Berechnung" fallen?

von D. R. (misterdimi1992)


Lesenswert?

Pete K. schrieb:
> Das #define    F_CPU  8000000 gehört in das Makefile.
>
> Und hier fehlt eine Klammer auf "{" nach while:
> int main(void)
> {
>
>     while (1)
>  /****Reading in values of temp register LM75  I²C ***/
>
>
> lcd_init();

Habe beim Einfügen des Textes die Kommentare gelöscht. Habe wohl die von 
dir erwähnte Klammer beim löschen erwischt!

Aber danke!

von Falk B. (falk)


Lesenswert?

@ D. R. (misterdimi1992)

>> Der LM75 liefert ein 9-Bit Ergebnis im 2er-Komplement. Nur bezieht sich
>> das "2er-Komplement" auf dieses 9-Bit Ergebnis, nicht auf eine
>> 16-Bit-Zahl. Man muss also nach dem Bilden des 2er-Komplements die nicht
>> vorhandenen 7 oberen Bits ausmaskieren.

Jain, er muss vorzeichenrichtig erweitern, bzw. schieben.

>ich benötige die 11-Bit-Zahl, da ich die negativen Werte auch mit der
>Nachkommazahl angeben möchte. Wie genau kann ich denn die oberen Bits
>ausmaskieren, dass diese nicht mit in die "Berechnung" fallen?

Du musst eine vorzeichenbehaftete Zahl zur Speicherung nutzen. Dann kann 
man auch ohne Hackertricks und kryptische Auswertung damit arbeiten. Und 
mit etwa Know How kann man auch Fließkommazahlen verzichten und mit 
einfacher Festkommaarithmetik arbeiten.
1
#include  <avr/io.h>
2
#define    F_CPU  8000000
3
#include  <util/delay.h>
4
#include  "lcd-routines.h"
5
#include  "i2cmaster.h"
6
7
uint8_t   MSByte_LM75, LSByte_LM75;
8
int16_t   tempdata;
9
char      cBuffer_LM75[16];
10
char      temp_min[16], temp_max[16];
11
12
int main(void) {
13
14
    i2c_init();
15
    lcd_init();
16
17
    while (1) {
18
        /****Reading in values of temp register LM75  I²C ***/
19
20
        i2c_start(0x92);      
21
        i2c_write(0x00);        
22
        i2c_rep_start(0x93);   
23
        MSByte_LM75=i2c_readAck();  // read MSB
24
        LSByte_LM75=i2c_readNak();  // read LSB
25
        i2c_stop();    
26
          
27
        tempdata = MSByte_LM75<< 8) | LSByte_LM75;  
28
        tempdata >>= 7;             // Temperatur mit 0.5 °C Auflösung
29
30
        lcd_clear();        
31
        lcd_setcursor(0,1);      
32
        if ( tempdata < 0) {  
33
            lcd_string("-");
34
            tempdata = -tempdata;             
35
        } else {
36
            lcd_string("+");
37
        }
38
        
39
        // Vorkommastellen      
40
        itoa(tempdata/2,cBuffer_LM75, 10);            
41
        lcd_string(cBuffer_LM75);
42
43
        // Nachkommastelle
44
        if (tempdata & 0x01) {
45
            lcd_string(".5");
46
        } else {
47
            lcd_string(".0");
48
        }
49
50
        _delay_ms(1000);
51
    }
52
}

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.