HEX, FLOAT Umrechnung bei Modbus

Hallo, es geht um eine Umsetzung von HEX nach Float.

Kann mir bitte jemand behilflich sein?

Das Beispiel

Macht aus float speed = 100.0 zwei HEX Werte HIGH(0x42C8) LOW(0x0000) oder float speed = 82.6 High(0x42A5) Low (0x3333).

Wie geht das? Ich komme einfach nicht dahinter.

Hat jemand eine Idee wie ich es bewerkstelligen kann, den umgekehrten Weg?

Also Ich benötige den float Wert.

Ich bekomme z.B. die Werte 0x42CF + 0x0333 und möchte als Ergebnis den passenden float 103.6 bekommen.

Wenn der eine Weg geht, muss es ja auch eine Möglichkeit für den Weg rückwärtigen geben.

Für Hilfestellung wäre ich Dankbar.

Mit HEX meinst du die Darstellung eines Bitmusters.
Wenn du weißt, wie eine float-Zahl in deiner Hardware gespeichert wird, insbesondere die Reihenfolge und Anzahl der Bytes, kannst du C++ überlisten.

Gerne kann man da das (formal) undefinierte Verhalten einer union missbrauchen, oder einen Zeiger auf ein float als einen Zeiger auf ein uint32_t oder ein Array von zwei uint16 uminterpretieren.

Und umgekehrt.

float f = 103.6;
uint16_t * ip = (uint16_t*) & f;
Serial.print( ip[0], HEX);
Serial.println( ip[1], HEX);

float* fp = (float*) ip;

Serial.println(*fp);

Floats werden nach IEEE-754 im Speicher abgelegt.

Schau dir mal IEEE-754 Floating Point Converter an.

Danke,

der rückwärts Weg im Beispiel funktioniert aber nur weil float f = 103.6 schon angegeben wurde.

Und das nur mit angegebenen f Werten.

Habe ich z.B. meine uint16_t Wert in result

uint16_t result = node.readHoldingRegisters(0x3001, 2); //Register Daten Lesen

float* fp = (float*) result;

funktioniert es Rückwärts nicht.

Irgendetwas fehlt, wegen dem fehlenden f Parameter.

uint16_t * result = (uint16_t*) & f; ????

Nur wenn wie in deinem Beispiel f angegeben wurde funktioniert es.
Ich möchte aber aus result welches sich immer ändert f bekommen.

Mein Rat: Lerne die Sprache die du verwendest!

Du brauchst aber 32 Bit um ein float zu bauen

result ist kein Ergebnis der ausgelesenen Register sondern nur ein OK oder Fehlercode aus dem Modbus Zugriff.
Du musst getResponseBuffer verwenden.
Schau dir mal die Beispiele der Library an.

1 Like

Sehe kein Lib.

Ja!
Sehe aber bisher noch nicht mal den einen Weg.
Wie soll ich da den Weg zurück finden?

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
float u2fA(uint16_t a, uint16_t b)
{
  float result = NAN;
  *(((uint16_t*)&result)+0) = a;
  *(((uint16_t*)&result)+1) = b;
  return result;
}
#pragma GCC diagnostic pop

float u2fB(uint16_t a,uint16_t b)
{
  union{float f;uint16_t u[2];} konverter;
  konverter.u[0] = a;
  konverter.u[1] = b;
  return konverter.f;
}

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

  Serial.println(u2fA(0x0333,0x42CF));
  Serial.println(u2fB(0x0333,0x42CF));
}

void loop() {}
node.readHoldingRegisters(0x3001, 2); 

Kann doch bestimmt auch 4 Byte in einem Schlag. Oder?

Irgendwo muss ja die Methode readHoldingRegisters definiert sein. Und die Klasse, die diese Methode enthält.
Oder was anderes, das ein Bitmuster erzeugt von dem man annimmt, es sei eine float Zahl.

Ja!

Wir sehen hier ein Problem, welches (mir) gruselig erscheint.
Vermutlich würde es sich leichter lösen lassen, wenn der Kontext offen liegen würde.

Quelle, Ziel und verwendete Komponenten.
Für mich ist es wieder Zeit:
"Ein dreifach Hoch auf die Salami!"

ups, falscher Thread

Danke für eure Antworten.

Ja, so ähnlich meinte ich das.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.