Forum: Mikrocontroller und Digitale Elektronik Verständnisfrage Wandlung nach Float sowie Verständnis von Q8.4 bei NXP Pressure Sensor


von cab_leer (Gast)


Lesenswert?

Hallo zusammen,

ich habe einen NXP MPL3115A2 mit einem AVR 328 p. Laut Datenblatt wird 
der Temperaturmesswert in 2 Registern mit der Adresse 0x4h und 0x5h 
gespeichert.

 http://www.nxp.com/assets/documents/data/en/data-sheets/MPL3115A2.pdf

The temperature data is stored as a signed 12-bit integer with a 
fractional part. The OUT_T_MSB (04h) register contains the integer part 
in °C and the OUT_T_LSB (05h) register contains the fractional part. 
This value is representative as a Q8.4 fixed point format where there 
are eight integer bits (including the signed bit) and four fractional 
bits.

Heisst also, in Register 4 steht der Teil vor dem Komma, inclusive 
Vorzeichen. Wie darf ich mir das dann vorstellen? ist das dann ein in 
Bit 7 ein Vorzeichenbit und in bit 6...0 ein Wert von 0..127?

Im Zweiten Byte 0x05 stehen dann die Nachkommastellen mit 4Bit left 
adjusted. Die 4 LSB sind leer.

Mein Problem ist dass ich nicht ganz verstehe wie der Datentyp float bei 
Arduino funktioniert und ich generell auch nicht genau verstehe wie die 
Konversion funktioniert. Im Beispielcode wird das ganze erst in einen 16 
bit integer kopiert:

  int16_t t;
  t = Wire.read(); // receive DATA
  t <<= 8;
  t |= Wire.read(); // receive DATA
  t >>= 4;

Jetzt steht ja das ja quasi als signed integer da drin, die ersten 4 MSB 
sind leer, oder?


  float temp = t;
  temp /= 16.0;

Jetzt wird durch 16 geteilt, durch den Punkt ist eine Floating point 
operation forciert. Und ich teile durch 16, weil durch 16 teilen das 
gleiche ist wie 4 bit nach links schieben und ich damit die 4 
nachkommastellen-bits in den nachkommabreich verschiebe? aber genau da 
hört mein Verständnis auf weil ich nicht genau weiss wie die 32Bit der 
float auf arudino funktioniert.

wenn mir das einer erklären könnte wäre super..

grüße und danke.

von eProfi (Gast)


Lesenswert?

> aber genau da hört mein Verständnis auf weil ich nicht genau weiss
> wie die 32Bit der float auf arudino funktioniert.
Brauchst Du auch gar nicht. Der Compiler macht das bei der impliziten 
Umwandlung von int nach float automatisch.

> Und ich teile durch 16, weil durch 16 teilen das gleiche ist
> wie 4 bit nach links schieben und ich damit die 4
> nachkommastellen-bits in den nachkommabreich verschiebe?

Nein, durch 16 teilen ist das selbe wie um 4 Bit nach rechts schieben.

  int16_t t;
  t = Wire.read(); // receive DATA
  t <<= 8;
  t |= Wire.read(); // receive DATA
  //jetzt stehen die 12 Bits linksbündig drin
  t >>= 4;
  //und jetzt rechsbündig. Dieser Integer ist die Temperatur in 1/16°C.

> Jetzt steht ja das ja quasi als signed integer da drin,
> die ersten 4 MSB sind leer, oder?
Nein, beim Rechtsschieben von int wird das Vorzeichenbit kopiert 
(bleibt erhalten).
0x80 (-128) >>1  ist  0xc0 (-64).


  float temp = t; // integer in float wandeln
  temp /= 16.0;   // 1/16°C in Grad umrechnen

Float würde ich aber gar nicht verwenden.
Vergleiche etc. funktionieren viel einfacher in int (1/16°C).
Beispielcode für die Ausgabe findest Du zur Genüge, z.B. hier:

(zweiter Teil des Postings) ab Zeile "f=t12&15; //fractionals "
Beitrag "Re: DS18S20 - extended resolution bei Temperaturen um 0°C"

von eProfi (Gast)


Lesenswert?

Es wird also 2 mal durch 16 dividiert. Zuerst das int16 mit dem >>4, und 
dann nochmal das float mit /16.

Das hätte man auch einfacher haben können:
 float f= ((Wire.read()<<8) + Wire.read()) / 256.0;

Beachte das 256.0: dadurch wird erreicht, dass die Division nicht in 
Integer, sondern in float geschieht. Sonst gingen die Nachkommastellen 
verloren.

von Joe F. (easylife)


Lesenswert?

wenn es dir darum geht die Temperatur auf einem Display anzuzeigen, 
kannst du vollständig bei integer bleiben.
Vorkommawert steht in Register 4. Dann "," aufs Display schreiben und 
dann Registerwert 5 geteilt durch 26 (als integer). Gibt genau 1 
Nachkommastelle, aber mehr macht bei 1/16 Grad C Auflösung eh keinen 
Sinn.

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.