# Umwandlungsfehler  (DWORD -> REAL)



## try_and_error (1 April 2019)

Hallo zusammen,

ich habe ein ifm Durchflusssensor der einen Wert von 0.895 über IO-Link an meine SPS gibt. 

Ich habe versucht den Wert einzulesen, habe aber irgentwie ein Problem in der Umwandlung. 

Danke schonmal im Vorraus.


----------



## Heinileini (1 April 2019)

temp_dword := IL_SwapDWord(Input := rawDurchflussmengeges)
oDurchflussmengeges := DWORD_TO_REAL(temp_dword)


----------



## try_and_error (1 April 2019)

Hallo Heinileini,
klappt leider auch nicht.

MfG


----------



## Heinileini (1 April 2019)

try_and_error schrieb:


> klappt leider auch nicht.


Ist das Tauschen der ByteReihenfolge denn überhaupt nötig?
Was siehst Du denn, wenn Du "das Pferd von hinten aufzäumst"?

oDurchflussmengeges := 0.895
temp_dword := REAL_TO_DWORD(oDurchflussmengeges)

PS: 
wenn die Tauscherei nicht nötig ist, sollte
oDurchflussmengeges := DWORD_TO_REAL(rawDurchflussmengeges)
genügen.


----------



## Thruser (1 April 2019)

Hallo,

Du mußt mit Pointern arbeiten.

DWORD_TO_REAL(1234) -> 1234.0

s.a. Beckhoff und KSB Modbus-RTU-Modul PumpDrive 2

Gruß


----------



## try_and_error (1 April 2019)

Hat geklappt! Vielen Dank!


----------



## Heinileini (1 April 2019)

try_and_error schrieb:


> Hat geklappt! Vielen Dank!


D.h. DWORD_TO_REAL tut nicht das, was sein Name verspricht, sondern macht die NachKommaStellen platt?!?
Auf diesen "Luxus" könnte man aber gut verzichten!


----------



## StructuredTrash (1 April 2019)

Die Typumwandlungen in der IEC61131 sind ein buntes Sammelsurium. Zum Teil entsprechen sie dem, was man von Hochsprachen als "Type casting" kennt, also Zugriff auf eine Speicherstelle mit einem anderen Datentyp als eigentlich für sie deklariert, andere sind eher "Wertübertragungsfunktionen" zwischen zwei Datentypen. Eine saubere Trennung wäre da schon wünschenswert. Wenn es z. B. nicht nur DWORD_TO_REAL gäbe, sondern auch DWORD_AS_REAL, würde das Ganze schon klarer.


----------



## oliver.tonn (1 April 2019)

Hallo Heinileini,


Heinileini schrieb:


> D.h. DWORD_TO_REAL tut nicht das, was sein Name verspricht, sondern macht die NachKommaStellen platt?!?
> Auf diesen "Luxus" könnte man aber gut verzichten!


wie kommst Du auf das schmale Brett, dass DWORD_TO_REAL nicht macht was es soll, es macht genau das was es soll. Es wandelt eine Ganzzahl in eine Real-Zahl um, wobei, wenn man es ganz genau nimmt, ein WORD genauso wie ein BYTE eigentlich keine (Ganz-) Zahl ist sondern eine bestimmte Anzahl von Bits ist, die zusammen abgelegt werden. (Ganz-) Zahlen sind eigentlich Integer-Werte nur wird das heutzutage nicht mehr unterschieden. Da es Ganzzahlen (Integer) sind, bzw. als solche auch benutzt/betrachtet (WORD) werden, haben Sie keine Nachkommastellen, somit macht WORD_TO_REAL auch nichts falsch, wenn es etwas in XXX.0 wandelt. Dafür, dass jemand eine Zahl mit Nachkommastellen mit einem von der Konvertierungsfunktion nicht erkennbaren Faktor multipliziert hat um eine Ganzzahl zur Übertragung zu verwenden kann die Konvertierungsfunktion ja nichts.


----------



## Heinileini (1 April 2019)

oliver.tonn schrieb:


> wie kommst Du auf das schmale Brett, dass DWORD_TO_REAL nicht macht was es soll, es macht genau das was es soll.


Ja, wenn DWORD_TO_REAL das tut, was auch DINT_TO_REAL bzw. UDINT_TO_REAL tun tut bzw. täte, dann ist diese Funktion tatsächlich Luxus = "overfluid".
StructeredTrash hat schon Recht, dass die Praxis, Konvertierungen und TypeCastings in einen Topf zu werfen, ein buntes Sammelsurium darstellt.
Kein Wunder, wenn dies immer wieder zu Verwirrung, Missverständnissen und unerwarteten Ergebnissen führt.


----------



## oliver.tonn (1 April 2019)

Heinileini schrieb:


> Ja, wenn DWORD_TO_REAL das tut, was auch DINT_TO_REAL bzw. UDINT_TO_REAL tun tut bzw. täte, dann ist diese Funktion tatsächlich Luxus = "overfluid".


Ja, tut sie, aber ich verstehe auch nicht so ganz welche Erwartungen Du an diese Funktionen stellst. Woher sollen die Funktionen denn ahnen, dass der Wert den sie konvertieren sollen in Wahrheit eigentlich eine Zahl mit Nachkommastellen ist und woher sollen sie wissen, um wie viele Nachkommastellen es sich handelt.
Überflüssig, bzw. Luxus sind sie übrigens, wenn man nicht so leichtsinnig ist sich darauf zu verlassen, dass eine automatische Typkonvertierung schon alles abfängt, mitnichten. Angenommen der übertragene Wert wurde mit 10 multipliziert, dann sollte man ihn vor einer Division durch 10 zunächst erst in eine REAL-Zahl oder LREAL-Zahl wandeln und zwar genau mit dieser Funktion. OK, UDINT_TO_REAL könnte das mit übernehmen, aber dann passt die Bezeichnung ja nicht ganz.


----------



## Heinileini (1 April 2019)

oliver.tonn schrieb:


> . . . aber ich verstehe auch nicht so ganz welche Erwartungen Du an diese Funktionen stellst . . .


DINT_TO_REAL: Konvertierung einer Ganzzahl (+2147483647 … 0 … -2147483648 ) in REAL bzw.
UDINT_TO_REAL: Konvertierung einer positiven Ganzzahl (0 … +4294967295) in REAL.
Niederwertige VorKommaStellen gehen dabei zwangsläufig verloren, wenn die Mantisse der RealZahl diese nicht (sondern nur "zufällig") darstellen kann. NachKommaStellen werden nicht hinzugedichtet. 
Wenn die Dint- bzw. UdintZahl "heimliche" NachKommaStellen enthält, so muss die in REAL gewandelte Zahl noch durch 10-hoch-AnzahlNachKommaStellen dividiert werden - dies ist aber NICHT Bestandteil der DINT_TO_REAL- bzw. UDINT_TO_REAL-Konvertierung. 
Der Programmierer muss also wissen, dass z.B. die Ganzzahl die Einheit MilliEuro hat, er aber die RealZahl in der Einheit Euro verstanden wissen will und muss dementsprechend handeln.

DWORD_TO_REAL (besser DWORD_AS_REAL): keine Konvertierung, nur TypeCast. D.h. das BitMuster, das bereits dem der RealZahl entspricht bzw. entsprechen muss, wird nicht verändert.

PS:
Letzteres entspricht dem Beispiel des TE, wobei zusätzlich die ByteReihenfolge "umendianifiziert" wird.


----------



## PN/DP (2 April 2019)

oliver.tonn schrieb:


> wie kommst Du auf das schmale Brett, dass DWORD_TO_REAL nicht macht was es soll, es macht genau das was es soll. Es wandelt eine Ganzzahl in eine Real-Zahl um


Und genau diese Wandlung sollte es eigentlich nicht machen. DWORD ist ein Bitstring-Datentyp, kein numerischer Datentyp (keine Ganzzahl) - mit DWORD dürfte man gar nicht rechnen dürfen. Und folglich auch nicht von einem numerischen Datentyp (Ganzzahl) in einen anderen numerischen Datentyp (REAL) umwandeln.

Das Problem kommt daher, weil in allen Codesys-Dialekten DWORD = UDINT gleichgesetzt wird und deshalb bei DWORD_TO_REAL immer eine numerische Konvertierung stattfindet anstatt den Bitstring des DWORD als REAL zu interpretieren (wie bei Siemens SCL). Diesen Designfehler kann man nur umgehen, indem man per Pointer so tut als ob man eine REAL-Variable lesen würde (eigentlich auch unsauber), oder indem man ab Codesys 3 per UNION eine DWORD-Variable und eine REAL-Variable auf den selben Speicherplatz legt ("AT" bei Siemens SCL), und da das DWORD hineinspeichert und als REAL wieder herausliest.

Harald


----------

