Forum: Mikrocontroller und Digitale Elektronik DS1624


von Nico M. (hannover)


Lesenswert?

Hallo,
ich lese mit folgender Funktion die Temperatur eines DS1624 aus.
Allerdings bekomme ich so die Nachkommastelle nur als 0.5 ich möchte
die Nachkommastelle aber genau bekommen. Im Datenblatt steht das
+25.0625 Grad = 00011001 00010000 Bin = 1910 Hex sind. Aber ich werde
daraus irgendwie nicht schlau. Ich brauche von euch auch kein Code
bespiel oder so was. Ich möchte nur gerne wissen die sich diese
Temperatur zusammen setzt. Eine Fukntion kann ich mir dann daraus
bestimmt selber zusammenbasteln.
u08 get_temp_a_temp1, get_temp_a_temp2;    // Temperatur LSB/MSB
u16 get_temp_a_temp3;            // Umgerechnete Temperatur
char get_temp_ac[7];            // Konvertierte Temperatur INT->ASCII
char* get_temp_a(unsigned char i2c_address){
    i2c_init();                      // I2C initialisieren
    i2c_start(i2c_address);                // I2C starten
    i2c_write(0xEE);                  // Start Convert T
    i2c_stop();                      // I2C STOP
    i2c_rep_start(i2c_address);              // I2C Schreiben an DS16xx
    i2c_write(0xAA);                  // Befehl zum Temperatur lesen an 
DS16xx
    i2c_stop();                      // STOP
    i2c_rep_start(i2c_address+1);            // I2C Lesen an DS16xx
    get_temp_a_temp1 = i2c_readAck();          // MSB der Temperatur 
lesen
    get_temp_a_temp2 = i2c_readAck();          // LSB der Temperatur 
lesen
    i2c_write(0x22);                  // Stop Convert T
    i2c_stop();                      // I2C Stop
    get_temp_a_temp3 = get_temp_a_temp1*0x0A;            // temp1 mit 10
multiplizieren, damit keine Kommazahlen enstehen
    if(get_temp_a_temp2 > 0x80) { get_temp_a_temp3 +=0x05; }  // Wenn
temp2 groesser als 128 dann 5 addrieren
    itoa(get_temp_a_temp3, get_temp_ac, 10 );          // Temperatur von 
INT
nach ASCII
    return get_temp_ac;
}

Gruß & Danke
Nico

von Thorsten L. (tlauf79)


Lesenswert?

abo ( Problem habe ich auch )

von A. W. (wiwil)


Lesenswert?

Hallo,

habe deinen Code jetzt nicht durchforstet, aber das Format ist
eigentlich relativ einfach.

Wenn du die zwei ausgelesenen Bytes betrachtest, hast du ja automatisch
16 bit. Die Auflösung des DS1624 beträgt jedoch 13 bit. Die drei letzten
bit, also die drei kleinsten bit des ausgelesenen LSB kannst du also
verwerfen.
Übrig bleiben 13bit, deren Wert multipliziert mit 0,03125°C genau
deinen Temperaturwert ergibt.

Angeordnet sind die bits wahrscheinlich so, weil du für ganze Grad dann
nur das MSB auswerten musst und direkt die Temperatur hast.
Die 5 höherwertigen bits des LSB geben also genau den Nachkommawert an,
wenn du ihn mit 0,03125 multiplizierst.

Zusammengefasst:
16bit-Wert auslesen, durch 8 teilen, mit 0,03125°C malnehmen =
Temperatur in voller Auflösung.

Ich hoffe, ich konnte helfen.

Gruß
WiWil

von GRmusik (Gast)


Lesenswert?

Hi Nico,

das erste Byte ist die Mantisse und berechnet sich so wie man es vom
dualen Zahlensystem her kennt:

25 = 00011001

das zweite Byte ist der Exponent und dessen Aufbau sieht so aus:

      binär     dezimal

2e-1  00000001  0,5
2e-2  00000010  0,25
2e-3  00000100  0,125
2e-4  00001000  0,0625
2e-5  00010000  0,03125
2e-6  00100000  0,015625
2e-7  01000000  0,0078125
2e-8  10000000  0,00390625

ein kleines Rechenbeispiel findest Du hier:

http://board.gulli.com/thread/447189-gleitkommaoperation-binaer-ausfuehren-mantisse-und-exponent-gegeben-bitte-um-hilfe/

von A. W. (wiwil)


Lesenswert?

Hallo GRMusik,

Das passt aber dann nicht mit der Wertetabelle aus dem Datenblatt
zusammen.
Nach deiner Berechung kommt man mit 1910h, seinem Beispielwert auch
nicht auf 25,0625 °C, oder?

von Christoph Kessler (db1uq) (Gast)


Lesenswert?

Die Tabelle "binär" ist falsch herum, außerdem ist es kein Exponent,
sondern normale Nachkommastellen, nach dem Komma beginnend mit der 0,5

von Nico (Gast)


Lesenswert?

Hallo,
ich habe jetzt eine Lösung:

u08   get_temp_a1, get_temp_a2;
char   get_temp_rv[8];
float  temp;
char* get_temp_a(unsigned char I2C_ADDRESS){
  i2c_init();
  i2c_start(I2C_ADDRESS);
  i2c_write(0xEE);
  i2c_stop();
  i2c_rep_start(I2C_ADDRESS);
  i2c_write(0xAA);
  i2c_stop();
  i2c_rep_start(I2C_ADDRESS+1);
  get_temp_a1 = i2c_readAck();
  get_temp_a2 = i2c_readAck();
  temp = get_temp_a1 + (get_temp_a2/8)*0.03125;
  dtostrf(temp, 6, 3, get_temp_rv);
        return get_temp_rv;
}
Ich hoffe ihr könnt damit was Anfangen. Wenn doch noch ein Fehler
drinne sein sollte, bitte ich um verbesserung.

MfG
Nico

von A. W. (wiwil)


Lesenswert?

Ja, so gehts auch, erspart bei einem 8-bitter etwas Rechenpower, weil er
nur mit einem Byte Multiplizieren muss.

von Profi (Gast)


Lesenswert?

So, jetzt kommt der Fixed-Point-Fan und rechnet ganz einfach:
Vorkomma geht 1:1  0x19 ist 25
Nachkomma: 0x10 multipliziere ich mit 0x27 (39 dez) und erhalte
16*39=624. Das zeige ich 4 stellig an (mit führender 0) und erhalte:
25,0624 (statt 25,0625). Eine einzige 8x8-bit-Multiplikation, ohne
Float

25,500 wird als 25,4992 angezeigt (0x80*0x27=0x1380=4992).

Noch genauer wird es, wenn man vorher /8 rechnet (man verliert keine
gültigen Bits) und dafür mit 10000/32=312(,5) multipliziert - denkste,
ist auch nicht genauer. Aber man kann 313 verwenden, dann kommt statt
0x1908: 25,03125 25,0313
0x1910: 25,0625  25,0626
0x1980: 25,5000  25,5008
0x19f8: 25,96875 25,9703

Braucht allerdings eine 6x9-bit-Multiplikation, also 8x16->16.


Wer es wirklich genau will, nimmt eine 8x16->24 Mult ohne Schieben:
0x80*0x2710=0x138800    128 * 10000=1280000  (8x16->24bit)
            0x1388      1280000/256=   5000  (unterstes Byte weglassen
->4 Nachkommastellen)

0xf8*0x2710=0x25D780    248 * 10000=2480000
            0x25d7      2480000/256=   9687  ->25,9687

Noch Fragen?

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.