4 Bytes in Float konvertieren

Hallo,

beim Auslesen eines EEPROMS bin ich auf ein Problem gestoßen: in einem Array von 4 bytes steckt eine Gleitkommazahl. Beispielsweise kodieren die Hexadezimalzahlen "BC 34 39 58"die Zahl "-0,011" nach dem IEEE-754 Standard. Verfügt Arduino über eine einfache Möglichkeit, ein solches 4-Byte Array in eine Float-Zahl umzuwandeln?

Danke für die Hilfe.

Tiesl

http://de.wikipedia.org/w/index.php?title=Datei:IEEE-754-single.svg&filetimestamp=20080215164135

Ganz simple, solange das Format stimmt:

char text[4] = ReadBytesVonWoAuchImmer ();
float resultat = *((float *)text);

Oder, wenn es nur ums Lesen aus dem EEPROM geht, dann dir Funktionen aus der AVR-Library statt der Arduinofunktionen verwenden.

include <avr/eeprom.h>
...
float resultat = eeprom_read_float (byteAdresseImEeprom / 4);

Korman

http://sps-forum.de/showthread.php?p=11186

Unglaublich, wie schnell hier die Antwort kommen.

Ich habe folgendes ausprobiert, weil mir dies am geeignetsten erschien:

#include <OneWire.h>
OneWire ds(8);
byte addr[8];
char dataread[4];
float resultat;
[…]
for (i=0; i < 3; i++)
dataread = ds.read();
_ float resultat = *((float *) dataread);_

  • Serial.print(resultat);*
    Das Array “dataread” wird mit den ausgelesenen Werten bestückt - das funktioniert. Aber das Zusammenfügen des Arrays zu einem float-Wert scheint nicht so richtig zu funktionieren. Das ausgegebene “resultat” beträgt 0.00. Was läuft hier schief? Ich blicke leider nicht so recht durch.
    Tiesl

Ich denke mal das Du der Variablen Resulatat 3 mal hintereinander einen neuen Wert zuweist.

Wenn Du den float Wert byteweise zusammensetzen willst. Dann benötigst Du erst einmal die Startadresse der Variablen Resultat im Speicher. Danach müsstest Du die einzelnen Bytes ab dieser Speicherstelle in den Speicher schreiben und den Offset der Speicheradresse dazu jedesmal um ein Byte erweitern.

Du brauchst also als erstes einen Pointer auf die Startadresse der Variable Resultat.

http://de.wikipedia.org/wiki/Zeiger_(Informatik)

Demonstrate the Unary '&' and '*' operators: http://home.fhtw-berlin.de/~junghans/cref/EXAMPLES/address.c

Die Vorgehensweise sollte schon passen.
Aber mit
for (i=0; i < 3; i++)liest Du nur 3 Bytes ein.

Richtig wäre:

for (i=0; i <= 3; i++)

@ MaFu: Danke für den Hinweis, das habe ich geändert, leider hat es trotzdem nicht funktioniert.

zum Testen habe ich nun folgendes eingegeben:

byte dataread[4];
float resultat;

void setup(void)
{
  Serial.begin(9600);
}

void loop(void)
{
    dataread[0] = 0xBD;
    dataread[1] = 0x99;
    dataread[2] = 0x99;
    dataread[3] = 0x9A; 

    Serial.print(dataread[0], HEX);
    Serial.print(dataread[1], HEX);
    Serial.print(dataread[2], HEX);
    Serial.print(dataread[3], HEX);
    Serial.println();
    float resultat = *((float *) (dataread, BIN));
    Serial.print(resultat);    
    delay(10000);  
}

Ich habe bewusst auf Schleifen verzichtet um Fehlerquellen auszuschließen. Laut http://babbage.cs.qc.edu/IEEE-754/32bit.html müsste das Float-Ergebnis von "BD 99 99 9A" rund -0.075 sein, der Arduino spuckt mir jedoch die Zahl 865545.75 aus. Hat jemand eine Idee, woran das liegen könnte? Ich habe schon sämtliche Datentypen für "dataread[4]" durchprobiert.

Tiesl

Zwei Sachen:

float resultat = *((float *) (dataread[glow], BIN[/glow]));

Das ,BIN sorgt bestimmt für Verwirrung. Probiere:

float resultat = *((float *) dataread);

Korman

Korman: Das "BIN" habe ich entfernt, leider blieb der Erfolg aus. Falls jemand einen Arduino frei hat, wäre es super, wenn ihr den zuletzt geposteten Sketch mit Kormans Korrektur mal ausprobieren und vielleicht sogar korrigieren könntet. Bei BD 99 99 9A sollte -0.75 rauskommen. Ich habe das Gefühl, als wären wir kurz vorm Ziel :)

Wenn sich bis dahin keine Lösung ergeben sollte, teste ich es Heute Abend.

Ich komme auch erst am Abend zu meiner Bastelkiste.

Noch eine Idee zum Probieren:

*((float *) dataread) = -0.75;
for (int i = 0; i < 4; i++) {
   Serial.println (dataread[i], HEX);
}

Und dann schauen, was du bekommst.

Ach ja, noch ein kleines Detail am Rande: Die Reihenfolge der Bytes ist wahrscheinlich verkehrt. -0.075 solltest du damit bekommen:

    dataread[0] = 0x9A;
    dataread[1] = 0x99;
    dataread[2] = 0x99;
    dataread[3] = 0xBD;

Korman

Bei der Konvertierung von -0.075

9A
99
99
BD

=> die Bytes müssen von hinten nach vorn gelesen werden. Das ist der Durchbruch, danke!
Aber eine Sache bleibt: Es werden nur zwei Dezimalstellen angezeigt. Ist es auch möglich, den Floatwert mit 3 Dezimalstellen auszugeben?

Tiesl

Aber eine Sache bleibt: Es werden nur zwei Dezimalstellen angezeigt. Ist es auch möglich, den Floatwert mit 3 Dezimalstellen auszugeben?

Als zweiten Parameter bei Serial.print die Anzahl der Stellen angeben.

Serial.print(resultat, 3);

Das ist unter Serial.print dokumentiert.

Korman

Jetzt klappt auch noch das mit den Nachkommastellen. Perfekt. Man muss nur wissen, wo alles steht. Vielen Dank für die tolle Hilfe.

Floating Point Co-Processor uM-FPU v3.1 Sparkfun COM-08129: http://www.lipoly.de/index.php?main_page=product_info&cPath=880_883_923_1762&products_id=103768

Conversion Functions: ?Convert floating point to ASCII ?Convert ASCII to floating point