DWORD_TO_REAL( REAL_TO_DWORD( REAL ) ) unterschiedlich?!

Jörn

Level-1
Beiträge
58
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin,

ich bekomme via Schnittstelle von einem Roboter REAL-Werte und muss auch REAL-Werte an den Roboter schicken. Die Schnittstelle ist als ARRAY OF DWORD (1) deklariert. Wenn ich nun ein REAL in ein DWORD konvertiere, dann schneidet er die Nachkommazahlen ab. Das wäre u.U. zu vertreten. Aber bei der Rückumwandlung wirds richtig ungemütlich:

REAL_TO_DWORD_TO_REAL.jpg

Ich probiere schon den ganzen Tag herum, komme aber auf keinen grünen Zweig. Vielleicht hat jemand eine Idee? Oder muss ich mir eine Funktion schreiben, die mir das DWORD in ein IEEE REAL umrechnet (2)?

Gruß
Jörn



(1) https://www.sps-forum.de/codesys-un...ka-krc4-und-ipc-via-bridge-el6695-1001-a.html

(2) https://de.wikipedia.org/wiki/Gleitkommazahl #Berechnung_einer_IEEE_single_precision_Gleitkommazahl_(32-Bit-Gleitkommazahl)
 
DWORD ist vorzeichenlos. Du musst DINT nehmen.
Aber warum ist die Schnittstelle als Array of DWORD deklariert, wenn doch REALs übertragen werden sollen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was du brauchst ist ein umkopieren des dwords auf Real ohne Umwandlung. Das geht nur mit einem Pointer.

Oder vielleicht auch eine Union mit einem DWORD und einem Real drin, das ist vielleicht noch eleganter.
 
DWORD ist vorzeichenlos. Du musst DINT nehmen.
Aber warum ist die Schnittstelle als Array of DWORD deklariert, wenn doch REALs übertragen werden sollen?
Achtung, Klugscheißerei!!! Die Vorzeichenfrage kann sich genaugenommen bei Variablen der Typen BYTE, WORD, DWORD, usw. nicht stellen, da dies genaugenommen keine Variablentypen für Zahlen sind und sie demzufolge auch keine Zahlen enthalten. Es sind vielmehr Containertypen zur Aufnahme einer bestimmten Anzahl von Bits, im Falle des DWORDS 32. Ich vermute mal der Roboter hat das Bitmuster des Real-Wertes einfach übertragen und bei Dir kommt es jetzt in einem DWORD an. Hier hilft Dir kein Konvertierungsbefehl weiter, außer Du steigst auf Siemens um, denn da gibt es Befehle mit denen die Bitmuster 1:1 in ein REAL übertragen werden können. Du müsstest entweder eine UNION mit einem DWORD und einem REAL anlegen und das DWORD dann mit der EL6695 verknüpfen, oder mit MEMCPY das Ganze von einer DWORD-Variable in eine REAL-Variable kopieren. Das klappt aber nur, wenn das wieder mit den Indianern passt, wie ich schon in dem von Dir verlinkten Thread schrieb. Ansonsten müsstest Du ein Array of BYTE erstellen und das dann mit dem Eingang verknüpfen, dann die einzelnen Bytes sortieren und das Ergebnis mit MEMCPY in eine REAL-Variable kopieren.
Umgekehrt halt genauso Daten mit MEMCPY von Real in DWORD kopieren.

Argh, zulange getippt, ms_gp war schneller.
 
Zuletzt bearbeitet:
Aber warum ist die Schnittstelle als Array of DWORD deklariert, wenn doch REALs übertragen werden sollen?
Weil Kuka die Prozessdaten die via EtherCAT übertragen werden so definiert hat, da kann der TE nichts für, natürlich hätte Kuka das auch anders machen können und ein Real in der Beschreibungsdatei definieren können, wenn das überhaupt geht, aber wenn sich die Indianer dann mal wieder nicht grün sind kommt da ein heilloses Chaos bei raus und da ist es so noch am Besten.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
@oliver.tonn:
Ich weiss, konnte aber nicht der Versuchung widerstehen, mich provokativ etwas dumm zu stellen. Warum führt der TE seinen ursprünglichen Thread nicht fort, es geht doch wohl immer noch um das selbe Problem? Und was ist mit unseren beiden Lösungsvorschlägen, haben die nicht funktioniert? Dann wäre der nächste Schritt doch zu prüfen, warum nicht. Die möglichen Stolpersteine hast Du doch genannt.
 
@ StructuredTrash:
Ich hab deswegen einen neuen Thread aufgemacht, weil dieses Problem nur bedingt mit dem ursprünglichen Problem zu tun hat. In dem genannten Thread ging es grundsätzlich darum, 128 Byte gemischte Datentypen auf ein ARRAY OF DWORD zu mappen, hier ist das speziellere Problem ein REAL korrekt aus einem DWORD zu bekommen. Wer nach DWORD_TO_REAL sucht, wird kaum in einem Thread namens Variablenverknüpfung zwischen KUKA und IPC schauen. Wobei ich sagen muss, daß die Suchfunktion hier einiges besser als in so manch anderem Forum ist, in dem ich bisher unterwegs war. ;)

Ich danke auf jeden Fall für die Tipps. Ich schau es mir morgen mal an. :)

Gruß
Jörn
 
Zuviel Werbung?
-> Hier kostenlos registrieren
In TwinCAT3 ist es prinzipiell auch möglich Variablen ungleichen Typs zu verknüpfen.
Hierzu muss bei der Verknüpfung der Variablen zwischen den Prozessabbildern im Auswahldialog das Häkchen bei "passender Typ" entfernt werden. Dann kannst Du Deine DWORD Variable aus EtherCAT mit einer REAL Variable aus der SPS verknüpfen und sparst die Verwendung von Memcpy.
 
Moin,

nach ein bissl Rumprobieren hab ich mich jetzt für die UNION entschieden. Sieht nicht schön aus, geht aber:

Code:
TYPE U_REALDWORD:
  UNION
    uReal:   REAL;
    uDword:  DWORD;
  END_UNION
END_TYPE


REAL_TO_DWORD_TO_REAL_2.jpg




In TwinCAT3 ist es prinzipiell auch möglich Variablen ungleichen Typs zu verknüpfen. Hierzu muss bei der Verknüpfung der Variablen zwischen den Prozessabbildern im Auswahldialog das Häkchen bei "passender Typ" entfernt werden. Dann kannst Du Deine DWORD Variable aus EtherCAT mit einer REAL Variable aus der SPS verknüpfen und sparst die Verwendung von Memcpy.
Auch eine nette Sache, werde ich mir fürs nächste Mal merken. An dieser Stelle ist sie leider nicht anwendbar, weil die Jungs, die für die Schnittstelle zuständig sind, gepennt haben. Das ist aber eine lange Geschichte. :(

Gruß
Jörn
 
Zuletzt bearbeitet:
Ok, dann entschuldige bitte meine Kritik.
Aber warum musst Du, nachdem Du die Daten irgendwie über die DWORD-Schnittstelle der EtherCat-Bridge bekommen hast, nochmal so eine Konvertierung machen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Weil die beiden Leute, die sich eigentlich um die Schnittstelle hätten kümmern sollen, dies nicht taten und ich jetzt die real überlappend in den dword stehen habe, d.h. das high-Word eines real steht im low-Word eines dword und das low-Word des gleichen real steht im high-Word des darauffolgenden dword. Etwa so:

Code:
REAL:      [fedcba9876543210  fedcba9876543210]
DWORD:  ... fedcba9876543210][fedcba9876543210 ...

Deshalb sieht mein Programm zum Mapping entsprechend gruselig aus. Zum einen eine union mit einem real und einem dword als Hilfskonstruktion (weil real_to_dword bzw. dword_to_real nicht sauber bzw. gar nicht funktionieren) und zum anderen haufenweise shl( ... and 2#00000000000000001111111111111111, 16) bzw. shr(...) wegen der Überlappung.

Und um Deinem nächsten Einwand zuvorzukommen:
Ich hätte einfach real_to_dint(trunc(real*1000.0)) geschickt, dann hätte auf Roboterseite ein REAL = SIGNAL/1000.0 gereicht. Fertig. Dazu hätte man "nur" die Überlappung rausnehmen müssen, aber das war den Herren zu aufwändig. So hab ich jetzt halt 3 Tage damit verdaddelt. :roll:

Immerhin weiß ich jetzt über IEEE-konforme Fließkommazahlen bescheid und wie man sie berechnet. ;)

Vielen Dank an alle für die vielen Tips. :)

Gruß
Jörn
 
Ja ja, die Schnittstellen. Ich habe manchmal das Gefühl das 50% meiner Arbeit dem Definieren, Absprechen und Programmieren von Schnittstellen zwischen Geräten besteht.

Aber das was du beschreibst hatte ich noch nicht. Wenn du auf deiner Seite solche Klimmzüge machen musst, dann muss die Gegenseite das doch auch? Wie kommt das zustande?
 
Deshalb sieht mein Programm zum Mapping entsprechend gruselig aus. Zum einen eine union mit einem real und einem dword als Hilfskonstruktion (weil real_to_dword bzw. dword_to_real nicht sauber bzw. gar nicht funktionieren) und zum anderen haufenweise shl( ... and 2#00000000000000001111111111111111, 16) bzw. shr(...) wegen der Überlappung.
Das sieht so gruselig aus, weil Du (noch) keine Ahnung hast, wie man das ganz einfach macht. Aber Hallo, das Zusammenbasteln von Variablen verschiedenster Datentypen aus Word-Stücken ist doch unser täglich Brot :cool: Schau Dir mal Modbus an, da geht das nur so und da kannst Du keinen anderen Jungs die Schuld geben...

Ich kenne Twincat 3 nicht und weiß nicht genau ob die Syntax ganz richtig ist, doch das Basteln sollte ungefähr so einfach aussehen:
Code:
TYPE U_REALWORDS:
  UNION
    uReal:   REAL;
    uaWord:  ARRAY[0..1] OF WORD;   //(könnte auch eine Struktur mit 2 Word sein)
  END_UNION
END_TYPE

tempU : U_REALWORDS;


tempU.uaWord[0] := dasEineWord;
tempU.uaWord[1] := dasAndereWord;
rMyReal := tempU.uReal;


Und um Deinem nächsten Einwand zuvorzukommen:
Ich hätte einfach real_to_dint(trunc(real*1000.0)) geschickt, dann hätte auf Roboterseite ein REAL = SIGNAL/1000.0 gereicht. Fertig. Dazu hätte man "nur" die Überlappung rausnehmen müssen, aber das war den Herren zu aufwändig. So hab ich jetzt halt 3 Tage damit verdaddelt. :roll:
So was würde Dein Problem nur verkomplizieren anstatt vereinfachen. Ob man einen REAL direkt verschickt oder vorher durch 1000.0 dividiert, macht keinen Unterschied, nur mehr Verwirrung und mehr Aufwand.


Immerhin weiß ich jetzt über IEEE-konforme Fließkommazahlen bescheid und wie man sie berechnet. ;)
Aha - Dein Problem hatte aber doch gar nichts mit irgendeiner Berechnung von Fließkommazahlen zu tun... :confused: ;)

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
PS: Wenn das REAL über 2 DWORDs überlappend liegt (und wenn Du Glück mit den Indianern hast) dann kannst Du den REAL so zusammensetzen:
Code:
TYPE U_REALDWORDS :
  UNION
    STRUCT
      uTrash1 : WORD;
      uReal   : REAL;
      uTrash2 : WORD;
    END_STRUCT
    uaDword : ARRAY[0..1] OF DWORD;
  END_UNION
END_TYPE

tempU : U_REALDWORDS;


tempU.uaDword[0] := dasEineDWord;
tempU.uaDword[1] := dasAndereDWord;
rMyReal := tempU.uReal;
//xresult := F_SwapRealEx(rMyReal); //falls die Words noch getauscht werden müssen

PPS: gibt es in TC3 nicht schon was fertiges, um die zwei WORDs in einem DWORD zu tauschen (swap-en), anstatt mit Shiften und Ver-ORen zu hantieren?

Harald
 
Im Systemmanager kann man einstellen man hibyte und lobyte und oder loword und hiword tauschen will. Geht aber nur für das ganze Modul.

Aber nochmal meine Frage:Wie sieht das auf der anderen Seite aus? Vielleicht ist da nur was um 2 Byte verschoben und die müsstest nur einen Teil der ganzen Daten um 2 Byte shiften und dann passt alles. Es muss ja eine Definition der einzelnen datenelemente geben und wie groß sie sind.
 
So was würde Dein Problem nur verkomplizieren anstatt vereinfachen. Ob man einen REAL direkt verschickt oder vorher durch 1000.0 dividiert, macht keinen Unterschied, nur mehr Verwirrung und mehr Aufwand.
Das Problem ist des jeweiligen Herstellers interne Darstellung von REAL und die Tatsache, daß da einige nicht am gleichen Süppchen mitkochen. Viele Hersteller arbeiten inzwischen mit REAL, die der IEEE entsprechen, aber eben nicht alle. Wo ich bisher so gut wie keine Probleme hatte, war, mit real_to_dint(trunc(real*1000.0)) einfach ein INT zu schicken, das auf der Gegenseite mit int_to_real() bzw. int/1000.0 wieder in ein REAL umgewandelt wird.


... Wie sieht das auf der anderen Seite aus? Vielleicht ist da nur was um 2 Byte verschoben und die müsstest nur einen Teil der ganzen Daten um 2 Byte shiften und dann passt alles. Es muss ja eine Definition der einzelnen datenelemente geben und wie groß sie sind.
Die high- und low-Bytes zu tauschen hab ich schon probiert, das ist es nicht. Die Gegenseite ist ein KUKA und obwohl dort die entsprechende Variable, in die der Werte dann geschrieben wird, als REAL deklariert ist, kommt dort immer ein verdammt großes INT an. KUKA hat nur die Datentypen INT, REAL, BOOL und CHAR. Ein int_to_real() gibt es bei KUKA nicht! Eine Umwandlung von int nach real macht man mit int/1000.0! Das .0 ist hier wichtig, Stichwort implizite Typkonvertierung. Wenn man die .0 weglässt kommt wieder ein int raus. Da hab ich in meinem letzten KUKA-Programm auch schon mal einen Tag lang nach gesucht. :ROFLMAO:

Hier ein Auszug aus der KUKA-Doku. Mehr als das erfährt man nicht:
datentypen_kuka.JPG
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Das Problem ist des jeweiligen Herstellers interne Darstellung von REAL und die Tatsache, daß da einige nicht am gleichen Süppchen mitkochen. Viele Hersteller arbeiten inzwischen mit REAL, die der IEEE entsprechen, aber eben nicht alle.
Klingt unglaublich. Hättest Du mal ein Beispiel wer sich nicht an die IEEE hält? ;)

Wo ich bisher so gut wie keine Probleme hatte, war, mit real_to_dint(trunc(real*1000.0)) einfach ein INT zu schicken, das auf der Gegenseite mit int_to_real() bzw. int/1000.0 wieder in ein REAL umgewandelt wird.
Solche Krücken sollte man nur brauchen, wenn man die Länge der verschickten Daten verringern muß. Normalerweise ist das absichtliche Umgehen/Vermeiden des REAL-Datentypes nicht nötig.

obwohl dort die entsprechende Variable (...) als REAL deklariert ist, kommt dort immer ein verdammt großes INT an.
Da kommt ziemlich sicher nicht ein "verdammt großes INT" an, sondern 32 Bits in 4 Bytes, die sich irgendjemand fälschlicherweise als Ganzzahl anschaut. Dabei muß man sich das Bitmuster der 4 Bytes einfach nur als REAL anschauen, dann sieht man, daß das tatsächlich ein REAL ist.


Betreffen die "Überlappungenen" bzw. der 2 Byte Versatz viele/alle Daten in dem ganzen empfangenen Datenblock? Wie ms_gp schon schrieb, wäre es in dem Fall einfacher, den betreffenden Datenblock-Teil um 2 Byte zu verschieben und dann passt die vereinbarte Struktur wieder über die Daten? Vielleicht hast Du auch nur irgendwo in Deinem Programm beim Kopieren/Übergeben des Empfangstelegramms eine falsche um 2 Byte versetzte Anfangsadresse angegeben? Oder entspricht der von den Anderen gesendete Datenblock gar nicht Euren Vereinbarungen, vielleicht sind da nur unerwartet/unbemerkt zu viele oder zu wenig Füll-Bytes drin?

Ich will Dir nicht zu nahe treten, aber sorry: Was hast Du eigentlich für einen Job, daß Du für die Lösung simpler Standard-Probleme mehrere Tage verdaddeln kannst? Vielleicht sollte Dein AG Dich mal zu einem guten Programmier-Lehrgang schicken? :cool: Wenn andere Leute etwas für Dich unverständliches tun, dann heißt das nicht automatisch, daß "die Anderen" etwas falsch machen...

Harald
 
Klingt unglaublich. Hättest Du mal ein Beispiel wer sich nicht an die IEEE hält? ;)
Siemens bei der S5 zum Beispiel.
Ja klar. Da kann ich so ziemlich jede Steuerung und Computer nehmen, die älter als der Standard IEEE 754 ist, und ihr vorwerfen, daß sie den damals noch gar nicht existierenden Standard nicht verwendet ... ;)

Siemens nennt das Gleitpunktformat der S5 auch nicht REAL oder FLOAT. Und Siemens liefert Konvertierbausteine zur Anpassung S5 Gleitpunkt <-> IEEE

Harald
 
Zurück
Oben