IO-Link Prozessdaten aufbereiten

try_and_error

Level-1
Beiträge
9
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich bin momentan an meiner Abschlussarbeit dran und bräuchte mal eure Hilfe.


Ich hab einen Drucksensor mit folgender IODD:

IO-Link Prozessdatenstruktur laut IODD
Druck 14 Bit
Schaltausgänge 2 Bit
---------------------------------
Gesamtlänge 16 Bit (2 Bytes)



Zur Druckberechnung hab ich folgendes zusammengebastelt:

(lowerByteDruck = %IB10 , higherByteDruck =%IB11)


wDruck := (lowerByteDruck*255) + higherByteDruck;
wShiftedDruck := SHR(wDruck,2);
rDruck := WORD_TO_REAL(wShiftedDruck);
oDruck := (RDruck/100);

Funktioniert auch, aber gibt es da eventuell eine elegantere Lösung?
Wenn ich versuche direkt aufs Wort zuzugreifen, zeigt er mit falsche Druckwerte an.


Prozessdatenstruktur.png

Programmiert wird auf einer Rexroth SPS. :roll:


Danke euch schonmal.


Grüße
 
Ob es eleganter geht kann ich nicht sagen, aber Du hast einen Fehler in Deinem Programm. Um lowerByteDruck um 8 Bit nach links zu verschieben musst Du den Wert mit 256 und nicht mit 255 multiplizieren, denn 2^8 ergibt 256 und nicht 255.
Was für einen Typ hat die Variable lowerByteDruck eigentlich? Falls Byte solltest Du sie mit BYTE_TO_WORD erst in ein WORD umwandeln und dann multiplizieren.
Gibst Du bitte auch noch den Typ des Sensors preis, dann kann mal einen Blick in das Handbuch werfen und vielleicht noch ein paar weitere Tipps geben.
 
Zuletzt bearbeitet:
Wenn ich richtig sehe, dann sind High- und Lowbyte vertauscht.
Das Tauschen müsste in Codesys eigentlich mit ROL(Eingangsword, 8) funktionieren.
Danach dann SHR,2

Gruß
Blockmove
 
Zuletzt bearbeitet:
Mich irritieren bei der Sache gleich mehrere Dinge. Zum einen wenn ich das Handbuch richtig deute wird erst das High Byte (Höherwertige) und dann das Low Byte übertragen. Deine Variablennamen müssten also vertauscht werden. Dann kann Dein ganzes Programm so nicht funktionieren, denn laut Handbuch wird ein Integer übertragen und bei negativen Zahlen würdest Du ganz abenteuerliche Werte bekommen. Beim Lower Byte müsstest Du den Wert mit 16#FC UND-Verknüpfen umd die Steuerbits auszublenden, dann das Ganze per MEMCPY in eine INT-Variable kopieren, aber dabei bitte auf die Byte-Order Deiner CPU achten. Dann kannst Du den Wert entweder erst durch 4 teilen, anschließend in ein Real umwandeln und dann nochmals durch 100 teilen oder aber gleich in ein Real wandeln und anschließend durch 400 teilen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Blockmove,
da warst Du etwas schneller.
Wenn ich richtig sehe, dann sind High- und Lowbyte vertauscht.
Das Tauschen müsste in Codesys eigentlich mit ROL(Eingangsword,8) funktionieren.
Danach dann SHR,2
Das siehst Du meiner Meinung richtig, dass Low- und Highbyte vertauscht sind, aber bitte auf keinen Fall SHR nutzen, der Sensor überträgt nämlich einen Integer-Wert.
 
IO-Link wurde für Siemens designed
Das ist halt so und aller anderen müssen damit leben, dass sie die Bytes in einem Integer erst mal drehen müssen, damit sie einen vernünftigen Wert bekommen.

Die ifm electronic bietet auch kostenlos Funktionsbausteine an, die Dir den Rohwert aufbereiten und die Signale zur Verfügung stellen.
Kontaktier doch einfach mal die Hotline
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Blockmove,
da warst Du etwas schneller.

Das siehst Du meiner Meinung richtig, dass Low- und Highbyte vertauscht sind, aber bitte auf keinen Fall SHR nutzen, der Sensor überträgt nämlich einen Integer-Wert.

Da hast du natürlich 100% Recht.
Vorallem ist das bei IFM-Sensoren wichtig.
Auch wenn der Messbereich z.B. 0-10bar ist, kann da mal ein negativer Wert kommen.

Gruß
Blockmove
 
Da hast du natürlich 100% Recht.
Vorallem ist das bei IFM-Sensoren wichtig.
Auch wenn der Messbereich z.B. 0-10bar ist, kann da mal ein negativer Wert kommen.

Gruß
Blockmove

Auch Du hast Recht
Nur trifft das nicht nur Sensoren von ifm electronic, sondern alle IO-Link Devices
Wenn man einfach nach rechts schiebt, werden die Stellen mit 0 aufgefüllt.
So wird evtl. aus einem negativen, ein sehr großer positiver Wert.
Ein Drucksensor der z.B. -1/1 bar messen kann, zeigt auf einmal 16000 bar an.

Siemens macht bei KOP und FUB dies automatisch richtig.
Bei Text-Sprachen sollte man statt SRWx SSIx verwenden.
 
Siemens macht bei KOP und FUB dies automatisch richtig.
Bei Text-Sprachen sollte man statt SRWx SSIx verwenden.
Oder den INT einfach durch 4 dividieren, das wäre die richtige Anweisung. :cool: (Das hat mit KOP/FUP nichts zu tun, wenn man die falsche Anweisung verwendet - und auch KOP/FUP kommt dann "automatisch" zum falschen Ergebnis)

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
(lowerByteDruck = %IB10 , higherByteDruck =%IB11)
wDruck := (lowerByteDruck*255) + higherByteDruck;
Sorry, was ich noch nicht verstanden habe:
Worauf beziehen sich die Bezeichnungen "lowerByte" und "higherByte"?
Auf die Wertigkeit der Bytes im Word oder auf die Adressen der Bytes im Speicher bzw. an einer Schnittstelle?
Wenn ersteres der Fall ist, müsste es doch egal sein, ob wir in einem little oder big Endian System arbeiten UND wenn
wDruck := higherByteDruck * 256 + lowerByteDruck gerechnet wird!?

Gruss, Heinileini
 
Das Problem ist, dass es kein WORD ist, sondern ein INT, weswegen Du auch mit der Multiplikation nichts erreichst, da das nur bei einer vorzeichenlosen Zahl (WORD, UINT) funktionieren würde. Entweder Du machst es so wie ich geschrieben habe oder Du empfängst die Daten in ein Word machst dann eine UND-Verknüpfung mit 16#FFFC und kopierst mit MEMCPY das Ganze in eine Variable vom Typ INT, aber dann muss die Byte-Order von Sensor und SPS passen. Dann teilst Du entweder das INT durch 4, wandelst es in ein REAL und weißt es gleichzeitig einer REAL-Variable zu und teilst dann den Wert durch 100 oder du wandelst den Integer Wert gleich in Real um (inklusive Zuweisung zu einer Real Variable) und teilst die Real-Variable dann durch 400.
 
Oder den INT einfach durch 4 dividieren, das wäre die richtige Anweisung. :cool: (Das hat mit KOP/FUP nichts zu tun, wenn man die falsche Anweisung verwendet - und auch KOP/FUP kommt dann "automatisch" zum falschen Ergebnis)

Harald

Danke für den Hinweis.
Das ist aber schon allgemein bekannt.
Schieben sieht aber eleganter aus
Wenn man das Programm nicht selber geschrieben hat, muss man erst mal nachvollziehen können, warum hier geteilt wird.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Schieben sieht aber eleganter aus
Wenn man das Programm nicht selber geschrieben hat, muss man erst mal nachvollziehen können, warum hier geteilt wird.
Mag eleganter aussehen führt aber zu fatalen Fehlern, bei Codesys basierten Steuerungen werden nämlich alle Bits verschoben, auch das Vorzeichen Bit, darum nochmals "Bitte keinen Schiebebefehl bei Integer Werten benutzen!!!".
Übrigens ist Siemens mittlerweile auch nicht viel besser. Laut Doku füllt der Schiebebefehl beim Rechtsschieben die freiwerdenden Stellen mit dem Wert des Vorzeichens, was soll das bitte?
SHR_Siemens.PNG

Nachtrag: Ich muss Abbitte leisten. Bei Codesys hat sich anscheinend von mir unbemerkt etwas getan. Das Schieben funktioniert mittlerweile (Zumindest bei TwinCAT 3) auch vernünftig bei INT Werten. Bei einer Zahl von -64 und einem SHR von 2 kommt -16 raus.
 
Zuletzt bearbeitet:
Da LowerByte und HighterByte tatsächlich vertauscht werden, hab ich es heute nochmal mit der ROL-Funktion gelöst:
So scheint es zu klappen und negative Drücke werden auch richtig angezeigt. Vielen Dank euch!

VAR
rawDruck AT %IW10 :INT;
iDruck :INT;
iShiftedDruck :INT;
rDruck :REAL;
oDruck :REAL;
END_VAR

iDruck := ROL(rawDruck,8);
iShiftedDruck := SHR(wDruck2);
rDruck := INT_TO_REAL(iShiftedDruck);
oDruck := (rDruck/100);
 
Mag eleganter aussehen führt aber zu fatalen Fehlern, bei Codesys basierten Steuerungen werden nämlich alle Bits verschoben, auch das Vorzeichen Bit, darum nochmals "Bitte keinen Schiebebefehl bei Integer Werten benutzen!!!".
Dass "alle Bits verschoben" werden "auch das VorzeichenBit", ist doch irrelevant und selbstverständlich.
Der zu beachtende Unterschied ist doch, ob beim RechtsSchieben links mit Nullen aufgefüllt (SRW) wird oder mit dem höchstwertigen Bit (= "VorzeichenBit") (SVW alias SSI).
Wenn ein IntegerWert auch nach dem RechtsSchieben immer noch ein IntegerWert sein soll, muss natürlich links mit dem "VorzeichenBit aufgefüllt werden.
Steht kein SchiebeBefehl zur Verfügung, der mit VorzeichenBit nach rechts schiebt, so behilft man sich mit der Division durch die entsprechende ZweierPotenz.
Ich kann leider immer noch nicht nachvollziehen, worin das Problem besteht.
Ist die Zahl an der Schnittstelle nun fälschlicherweise als INT deklariert und in Wirklichkeit als UINT zu interpretieren?
Dann könnte man nach dem RechtsSchieben um 2 BitPositionen bzw. hach der Division durch 4 doch einfach die beiden höchstwertigen Bits löschen (mit 3FFF verunden).
Ist die Deklaration als INT korrekt, dann muss man nichts weiter beachten.
Es bleibt auch dabei, dass wDruck := higherByteDruck * 256 + lowerByteDruck, egal, ob dies Bytes aus einem INT oder UINT bzw. WORD sind.
Das Schieben des higherBytes um 8 BitPositionen nach links (sogar in der Form Multiplikation mit 256) läuft korrekt und die Addition des lowerBytes macht auch keinerlei Probleme.
Haben wir denn jetzt Lösungen gefunden, für die es (noch) keine Probleme gibt?
Gruss, Heinileini
PS:
Da LowerByte und HighterByte tatsächlich vertauscht werden, hab ich es heute nochmal mit der ROL-Funktion gelöst:
Anscheinend hast Du das HigherByte als LowerByte bezeichnet und umgekehrt. Die Bezeichnungen in #1 sind vertauscht bzw. beziehen sich irreführenderweise nicht auf die Wertigkeit. Man kann natürlich durch Rotieren den Tausch wieder rückgängig machen.
 
Übrigens ist Siemens mittlerweile auch nicht viel besser. Laut Doku füllt der Schiebebefehl beim Rechtsschieben die freiwerdenden Stellen mit dem Wert des Vorzeichens, was soll das bitte?
Anhang anzeigen 44999
Hast Du nur sinnentstellend verkürzt zitiert? Ich meine, die Funktion ist so genau richtig (wenn man denn SHR mit signed Datentypen überhaupt zuläßt). Hast Du die ganze Beschreibung des SHR gelesen?
Könntest Du beim nächsten Mal bitte eine genaue Quelle angeben wo Du das gefunden hast? Und wie die Beschreibung des Bildes bzw. die Erklärung von SHR lautet?
Und hast Du mal nachgeprüft ob die Erklärung stimmt? In den TIA-Dokumentationen sind sooo vieeele Fehler drin, da kann man nur glauben, was man selber nachgeprüft hat.

z.B. TIA V13 SP1 Hilfe
SHR: Rechts schieben (S7-1200, S7-1500) KOP und FUP
Bei Werten ohne Vorzeichen werden die beim Schieben frei werdenden Bitstellen im linken Bereich des Operanden mit Nullen aufgefüllt. Wenn der angegebene Wert ein Vorzeichen aufweist, werden die freien Bitstellen mit dem Signalzustand des Vorzeichenbits belegt.

Das folgende Bild zeigt, wie der Inhalt eines Operanden vom Datentyp Integer um vier Bitstellen nach rechts verschoben wird:
( Bild: 1010|1111|0000|1010 ---> 1111|1010|1111|0000 )
Die freigewordenen Bitpositionen
werden mit dem Signalzustand
des Vorzeichenbits aufgefüllt.
Das ist so korrekt beschrieben und imho auch korrekt implementiert.

SHR: Rechts schieben (S7-1200, S7-1500) SCL
Die beim Schieben frei werdenden Bitstellen im linken Bereich des Operanden werden mit Nullen aufgefüllt.

Das folgende Bild zeigt, wie der Inhalt eines Operanden vom Datentyp Integer um vier Bitstellen nach rechts verschoben wird:
( Bild: 1010|1111|0000|1010 ---> 0000|1010|1111|0000 )
Die freigewordenen Bitpositionen
werden mit Nullen aufgefüllt.
(rote Markierungen von mir)
Das ist FALSCH beschrieben! SHR funktioniert in SCL genauso Datentyp-abhängig wie in KOP/FUP.

Harald
 
Zurück
Oben