TIA Float aus Modbus Sensor

alfred0905

Level-1
Beiträge
50
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi!

Ich verzweifle gerade etwas mit einem Gerät, aus dem ich einen Float Wert per Modbus auslesen möchte. Das Gerät gibt mir einen 32bit Float aus, egal welchen Datentyp ich im Empfangsarray verwende kommt dabei aber nicht die richtige Zahl raus. Ich vermute mal es hat etwas mit der Bytereihenfolge zutun, das Manual des Geräts sagt dazu nur folgendes:

The Float or Real values are transferred in
accordance with the IEEE754 Standard Format
for 32-bit values. Example using the figure
1.25:
Hexadecimal: 3F A0 00 00 (0: + ; 1: -)
Signed (S): 0
Exponent (E): 0111 1111
Mantissa (M): 010 0000 0000 0000 0000

Kann mir jemand dabei helfen, wie ich den Wert auslesen kann?
Der Sensor schickt z.B. den Wert 869,3504, auf der S7 bekomme ich dafür 0100_0000_0000_0000_0100_0100_0101_1001

Egal wie ich versuche das in ein Real umzuwandeln, kommt dabei leider nicht mein Ergebnis raus - mit einem anderen Modbustool klappt es jedenfalls richtig, wenn ich auf 32bit float big endian stelle. Hat jemand vielleicht eine Idee wie ich das lösen könnte? Vielen Dank im Voraus!
 
Du brauchst nichts 'umzuwandeln'. Die Zahl wird richtig als Float interpretiert, wenn du in der SPS die 2 Worte (Register) auch auf Big-Endian 'umstellst'. Das geht aber nicht einfach so, sondern du muss die 2 Worte tauschen, so dass das 2. Wort an erster Stelle steht und das erste an zweiter. Wie du das machst hängt von deiner SPS und deiner bevorzugten Sprache ab. Bei einer S7-300 in AWL könnte man 'TAD' verwenden, bei einer S7-1500 ist wahrscheinlich der Slice-Zugriff (Variable.%W0) auf die 2 Wörter am einfachsten oder der SWAP-Befehl.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke schonmal für die ersten Antworten! In meinem Fall ist es eine S7-1200. Eigentlich wollte ich den Slicezugriff vermeiden, hätte gehofft dass es etwas einfacher geht - aber zumindest habe ich schon in die richtige Richtung gedacht :)
 
Der Sensor schickt z.B. den Wert 869,3504, auf der S7 bekomme ich dafür 0100_0000_0000_0000_0100_0100_0101_1001
von Sensor 869.3504 = 0x4459566d
S7 erhält 0100_0000_0000_0000_0100_0100_0101_1001 = 16#40004459

SWAP, READ_LITTLE, READ_BIG werden nicht helfen, weil diese Anweisungen die Byte-Reihenfolge ändern. Wie man aber an den 16#4459 sieht, darf keine Byte-Reihenfolge geändert werden.

Ich würde mal vermuten, Dein Modbus-Read liest die falschen 2 Register. Erhöhe mal die Registernummer um 1.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn ich das Empfangswort zB. in einen Integer verschiebe erhalte ich 17495 als Wert. Denselben zeigt mir auch mein Modbus Tool an, wenn ich die Darstellung auf Signed Int stelle statt auf 32bit float big endian. Mir ist leider immer noch schleierhaft, wie ich von 17945 auf 869.3504 kommen kann.

Swap ist offenbar tatsächlich der falsche Ansatz, dann stimmt auch die 17495 nicht mehr überein.

Das mit der Registeradresse habe ich natürlich schon probiert und deswegen auch extra mit einem Modbustool nochmals getestet und die Werte verglichen.
 
Wenn ich das Empfangswort zB. in einen Integer verschiebe erhalte ich 17495 als Wert.
Du empfängst nicht ein Word sondern 2 Words. Du brauchst ja einen 32-Bit-Wert.
Per Modbus müssen 2 aufeinanderfolgende 16-Bit-Register gelesen werden, um einen 32-Bit-Wert (z.B. REAL/Float) zu übertragen.

Das mit der Registeradresse habe ich natürlich schon probiert und deswegen auch extra mit einem Modbustool nochmals getestet und die Werte verglichen.
Zeigt Dein Modbus-Tool denn den korrekten REAL/Float-Wert an?
Dann vergleiche Dein Modbus-Tool mit dem was das S7-Programm macht. Dafür vergleiche am besten die 4 Empfangs-Bytes in hexadezimal-Ansicht. Da sieht man am besten, ob die richtigen Daten kommen, und ob und wie die Bytes eventuell vertauscht sind.

- Genau welche Modbus-Register liest Dein Modbus-Tool? Wie sehen die 4 empfangenen Bytes in hex-Ansicht aus? (Welches Modbus-Tool verwendest Du?)
- Genau welche Modbus-Register liest Dein S7-Programm? Wie sehen die 4 empfangenen Bytes in hex-Ansicht aus? Werden auch tatsächlich 4 Bytes = 2 Words = 2 Register abgefordert und empfangen? Wie sehen die 4 empfangenen Bytes in hex-Ansicht aus, wenn Du die Modbus-Register-Nummer/Adresse um 1 höher angibst? (interessehalber auch mal mit Adresse um 1 niedriger ausprobieren).
- Wie sieht der Aufruf des Modbus-Lesebausteins in der online-Beobachtung aus? Ist das MB_CLIENT?

Harald
 
Ich hatte auch schon mal so ein "Problem" und habe dann so getauscht:

Empfangene Bytes (by0, by1, by2, by3) gedreht in ein Real (Float schreiben) also eben (by3, by2, by1, by0), dann sollte das wieder passen.

Beispiel für Real-Wert (4 Byte) also bei dir ja Float:
Code:
  Neu[0] := Gelesen[3]; 
  Neu[1] := Gelesen[2];
  Neu[2] := Gelesen[1];
  Neu[3] := Gelesen[0];
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Empfangene Bytes (by0, by1, by2, by3) gedreht in ein Real (Float schreiben) also eben (by3, by2, by1, by0), dann sollte das wieder passen.
Das ist genau das, was SWAP und READ_LITTLE tun. Hier im Thread wurde aber bereits festgestellt, daß keine Bytes vertauscht werden müssen/dürfen. Es ist nur noch nicht klar, ob evtl. die beiden Words getauscht werden müssen (unwahrscheinlich, weil da würde das Modbus-Gerät der S7 eine andere Antwort senden als dem Modbus-Testtool ;) ), oder ob lediglich die Anfangs-Registeradresse um 1 versetzt falsch angegeben wurde.

mit einem anderen Modbustool klappt es jedenfalls richtig, wenn ich auf 32bit float big endian stelle.
Das ist genau die Byte-Order, die auch die S7 nativ verwendet. Es sollte also "schon so" passen. Es sei denn, der Empfangspuffer (Byte-Array) wird noch zwischen "optimiertem" Speicher und Speicher mit Standard-Zugriff kopiert - das wäre aber ein anderes Problem und würde auch nicht zu den zwei falschen Bytes 16#40 16#00 passen.

Harald
 
Ich stehe leider immer noch etwas auf der Leitung - ich habe 2 Wörter in einem Array, die ich zu einem Real zusammenfassen möchte, und leider momentan keine Idee wie ich das auf der S7 1200 in KOP umsetzen kann.. Mein ursprünglicher Fehler war es zu glauben, dass die Daten in einem Wort enthalten sind.

Sorry, mir fehlen da offensichtlich wirklich so manche Grundlagen..

Die Daten die ich bekomme jedenfalls richtig ins array geschrieben, sieht genauso aus wie im Modbustool (Modbus Poll von Modbustools.com). Was mich dort wiederrum verwundert, ist dass beim Umschalten auf Binär nur 16bit zu sehen sind). Habe mal Screenshots beigefügt
 

Anhänge

  • Modbus tool float.PNG
    Modbus tool float.PNG
    8,9 KB · Aufrufe: 18
  • Modbus tool.PNG
    Modbus tool.PNG
    8,3 KB · Aufrufe: 17
  • Modbus tool hex.PNG
    Modbus tool hex.PNG
    9,8 KB · Aufrufe: 16
  • TIA Empfangsarray.PNG
    TIA Empfangsarray.PNG
    12,8 KB · Aufrufe: 19
Die einfachste Lösung ist in der Tat so, daß man den Empfangspuffer einfach so mit Datentypen strukturiert, wie man die Werte zu empfangen gedenkt. Da kann man dann die Werte einfach so im richtigen Datentyp herauskopieren. :cool: Da braucht man keine umständlichen Zykluszeit-Bomben wie Deserialize.

PS: das passt auch zu Deinem TIA-Bild in #13:
Receive[1] = 16#444D + Receive[2] = 16#566D = DWORD#16#444D566D = REAL#821.3504
also: Receive nicht als Array[1..2] of Word deklarieren, sondern als REAL Und schon passt es.

PPS: Wenn Dein Modbus-Empfangspuffer ein Array of Word bleiben muß/soll, dann kannst Du die zwei Words so in eine REAL-Variable kopieren:
Code:
#tempDWord.%W1 := "MyDB".Receive[1];
#tempDWord.%W0 := "MyDB".Receive[2];
#MyReal := DWORD_TO_REAL(#tempDWord);

Harald
 
Zuletzt bearbeitet:
Zurück
Oben