TIA Array - Bytes zusammen fügen

Automatonator

Level-1
Beiträge
19
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Mahlzeit,

ich hoffe ich hab hier das richtige Unterforum erwischt :???:

ich benutze eine S1200 und versuche IO-Link parameter über ein HMI zugänglich zu machen.
Die Programmierung ist in KOP.

Ein Wert (von einem IO-Link Device) wird in einem Array als Hex-zahl gespeichert.
Wenn der Wert mehr als ein Byte benötigt wird dieser aufgeteilt - und zwar würde zb ein Hexadezimal wert 0154 wie folgt aufgeteilt werden :

Index 1 enthält : 01 // Index 2 enthält 54 ( Siehe Bild - was ich als startwert eingetragen habe wäre ggf. beobachtungswert)

Zunächst mal müsste ich um den wert auf einem HMI darstellen zu können die Zahlen wieder zusammen fügen, in eine Dezimalzahl umwandeln und in ein MD speichern. (?)

Zum Schreiben eines Parameter müsste ich eine Dezimalzahl (niemand würde eine hex zahl eintragen wollen) in eine Hex verwandeln, entsprechend aufteilen und in die jeweiligen Bytes des Arrays schreiben.

Hat jemand eine Idee oder einen Denkanstoß wie sich das umsetzen liesse?
 

Anhänge

  • Bild 1.jpg
    Bild 1.jpg
    56,4 KB · Aufrufe: 60
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Als kleiner Tipp, ein Word hat 2 Byte ...
Du hast ein Array of Byte und daher hast Du da das Low und High Byte des Word somit ist 0154h --> 01 und 54

Entweder die beiden Bytes als Word verarbeiten oder einen passende Structur anlegen wo dies halt passen declariert ist.


(Allerdings bin ich noch Classic Programmierer :ROFLMAO:)
 
... Ein Wert (von einem IO-Link Device) wird in einem Array als Hex-zahl gespeichert.
Wenn der Wert mehr als ein Byte benötigt wird dieser aufgeteilt ...
... niemand würde eine hex zahl eintragen wollen ...
Und woher weiss man dann, welche Bytes zusammen gehören und wo der wievielte Eintrag beginnt und wie lang er ist?
Machst Du Dir (und anderen) das Leben nicht unnötig schwer?

Wer wäre denn derjenige, der eine HexZahl eintragen müsste? Könnte er sich damit ersparen, eine als HexZahl vorliegende Vorgabe zunächst in eine DezimalZahl umzuwandeln, um sie dezimal einzutragen?

Gruss, Heinileini
 
Danke erstmal für die Antworten ich werde mich gleich mal mit der slice funktion auseinander setzen und mich melden ob und wie es geklappt hat.

Ich hoffe mal alle aufgekommenen Nachfragen auf einmal beantworten zu können :

Es geht hier darum die Parameter von IO-Link devices auszulesen und beschreiben zu können- dafür verwende ich einen fertigen Funktionsbaustein der als Lese / Schreibeort einen Array mit 232 Byte verlangt.
Da immer nur auf einen Parameter gleichzeitig (azyklische Daten) zugegriffen werden kann, muss ich mir keine Gedanken machen wo welcher Eintrag beginnt. Interessant sind immer nur die ersten beiden Byte - über Merker wird gesteuert welcher Parameter grad "verwendet" werden soll.

Also am Ende Soll es möglich sein über ein HMI die Sensoren zu parametrieren.
Wäre dann natürlich schön wenn man in das E/A-Feld einfach die zahlen wie gewohnt einschreiben könnte.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn der Wert mehr als ein Byte benötigt wird dieser aufgeteilt - und zwar würde zb ein Hexadezimal wert 0154 wie folgt aufgeteilt werden :

Index 1 enthält : 01 // Index 2 enthält 54
Kann das nicht eher sein, daß der Wert original ein Word ist, was generell 2 Byte belegt?
z.B.
* 340 dezimal = 16#0154 ---> 01 54
* 200 dezimal = 16#00C8 ---> 00 C8

Harald
 
Moin Automatonator,

Es geht hier darum die Parameter von IO-Link devices auszulesen und beschreiben zu können- dafür verwende ich einen fertigen Funktionsbaustein der als Lese / Schreibeort einen Array mit 232 Byte verlangt.

wieso benötigt der Baustein 232 Byte, wenn nur die ersten beiden Byte benötigt werden?

Wie ist denn die Strukur der Parameter des IO-Link-Device?
Wenn doch mehr als die ersten beiden Byte interessant sind, würde ich eine Struktur der Daten anlegen und dann den Array[0..n] of Byte mit serialize/deserialize der Struktur übergeben...

oder sind die 232 Byte für x IO-Link-Devices vorgesehen? Dann könnte auch eine Struktur helfen, die Daten zuzuordnen...


Ansonsten wie schon geschrieben:

tag1 (array[0..231] of byte)
tag2 (Word)

tag2.B0 := tag1[0];
tag2.B1 := tag1[1];

VG

MFreiberger
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Als kleiner Tipp, ein Word hat 2 Byte ...
Du hast ein Array of Byte und daher hast Du da das Low und High Byte des Word somit ist 0154h --> 01 und 54

Entweder die beiden Bytes als Word verarbeiten oder einen passende Structur anlegen wo dies halt passen declariert ist.


(Allerdings bin ich noch Classic Programmierer :ROFLMAO:)

Das hatte ich schon verstanden , unklar ist mir nur wie ich diese beiden Byte in ein Merkerwort speichere / wieder zusammenfüge in KOP:confused:

Vielen Dank für die Infos und Antworten :)

PS: ich hatte nicht die Absicht mit mangelnden Infos die Aufgabenstellung interessanter klingen zu lassen.
 
Moin Automatonator,



wieso benötigt der Baustein 232 Byte, wenn nur die ersten beiden Byte benötigt werden?

Wie ist denn die Strukur der Parameter des IO-Link-Device?
Wenn doch mehr als die ersten beiden Byte interessant sind, würde ich eine Struktur der Daten anlegen und dann den Array[0..n] of Byte mit serialize/deserialize der Struktur übergeben...

oder sind die 232 Byte für x IO-Link-Devices vorgesehen? Dann könnte auch eine Struktur helfen, die Daten zuzuordnen...


MFreiberger

Der Baustein ist so vorgegeben, dass als Quell/Zielort für Lese / schreibprozesse 232 Byte benötigt werden.
Es gibt auch azyklische Daten, die wesentlich mehr als 2 Bytes benötigen (zb Produkt ID).

Die in meinem Fall relevanten Werte benötigen aber alle nur entweder 1 oder 2 Byte.

Das Array zeigt immer nur den aktuell ausgelesenen / eingeschriebenen Wert an, fungiert also quasi nur als Zwischenspeicher und kann somit auch für x Devices verwendet werden.#
 
Wenn es immer nur die ersten beiden Bytes sind (oder die relevanten Bytes immer an der gleichen Stelle im Array stehen) dann könntest du dir auf dein Array auch eine AT-Sicht anlegen, die dieses in einem anderen Datenformat (also z.B. Array of INT oder Array of Word) interpretiert. Dann greifst du alternativ einfach auf dieses Array zu und brauch gar nicht mehr zu rechnen ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn es immer nur die ersten beiden Bytes sind (oder die relevanten Bytes immer an der gleichen Stelle im Array stehen) dann könntest du dir auf dein Array auch eine AT-Sicht anlegen, die dieses in einem anderen Datenformat (also z.B. Array of INT oder Array of Word) interpretiert.

Moooment, Larry!
Wir pendeln uns jetzt erst noch langsam ein. Z.Z. sind wir auf dem Stand ...

... Die in meinem Fall relevanten Werte benötigen aber alle nur entweder 1 oder 2 Byte. ...
... und wissen noch nicht, woran wir erkennen, ob gerade komplette zwei Byte oder nur ein Bisschen von zwei Byte angesagt sind!

Gruss, Heinileini
 
Ich hol jetzt mal etwas weiter aus ( Dazu ein Bild des FB im Anhang).

-Req Merker löst Anfrage aus
-an Port / ID wird festgelegt welches am Master angeschlossene Device angesprochen wird
-Index und Subindex geben an auf welchen Parameter zugegriffen wird.

Ein Beispiel :

im HMI gibt es die Auswahl auf Schaltpunkt von Sensory X zugreifen zu wollen.
Wenn diese getätigt wird werden die zugehörigen Werte in die jeweiligen Eingänge des IO-Link FB geschrieben. (auf das programm dahinter geh ich jetzt mal nicht genauer ein)

Ich weiss aus dem Datenblatt (bzw. IODD) , dass der Schaltpunkt 2 Byte benötigt.

jetzt möchte ich diese 2 byte in ein Merkerwort speichern und den Inhalt auf dem HMI angezeigt haben.

Diesen Vorgang muss ich jetzt für alle erwünschten Parameter festlegen und als Startpunkt des ganzen gibt es eine zugehörige schaltfläche - aber wie gesagt weiss ich beim programmieren ja auf welche und wie viele bits und bytes ich zugreifen muss.
 

Anhänge

  • IO_Baustein.jpg
    IO_Baustein.jpg
    60,8 KB · Aufrufe: 48
Und die eingebbaren WerteBereiche sind
- im Falle 1-Byte: 0 ... 255 oder -128 ... 127 ?
- im Falle 2-Byte: 0 ... 65.535 oder -32.768 ... 32.767 ?
Kenne mich mit dem HMI so gar nicht aus.
Müsstest Du, abhängig davon, welche Varianten benötigt werden, verschiedene Bilder/Masken anlegen?
Oder könntest Du in einem Bild/Maske mehrere Varianten projektieren und Fall-abhängig eines der Eingabe-Felder freigeben und die anderen sperren?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin Automatonator,

noch ne Idee:
Du kannst ja auch einfach ein SCL-Netzwerk einfügen. Da kannst Du wunderbar den Datentyp von BYTE in INT convertieren.
Dann einfach das höherwertige Byte mit 256 multiplizieren und beide Werte addieren:

Code:
#Tb_val[0] := 16#01;
#Tb_val[1] := 16#54;

#Ti_val := BYTE_TO_INT(IN := #Tb_val[0]) * 256 + BYTE_TO_INT(IN := #Tb_val[1]);


BYTE_TO_INT(IN := #Tb_val[0]) ==> 1
BYTE_TO_INT(IN := #Tb_val[1]) ==> 84

1*256+84 = 340


Liefern die IOLink-Devices denn immer nur 2 Byte (oder halt nur eines, wenn der Wert entsprechend klein ist)?


VG

MFreiberger
 
... aber wie gesagt weiss ich beim programmieren ja auf welche und wie viele bits und bytes ich zugreifen muss.

Dann teste doch mal meinen Vorschlag ... denn dieser ändert ja nicht dein Array sondert ermöglicht dir lediglich eine andere Sicht darauf - vielleicht lösst das ja schon dein Problem ...

Gruß
Larry
 
Es geht hierbei generell nur um die azyklischen Daten der Devices, also die Parameter.
Das hat nichts mit dem Einbinden von variablen Prozesswerten zu tun.

1 Byte wird für die Fälle benötigt wo es festgelegte Eingabemöglichkeiten gibt ( zb. 1 bedeutet Öffner, 2 Schliesser, etc..)
2 Byte für Dinge wie Schaltpunkt, Rückschaltpunkt etc.
Die Wertebereiche sind jeweils vorgegeben
(Im Anhang ausschnitt der IODD)

Auf dem HMI stell ich mir das so vor :
Jeder Parameter bekommt ein E/A-Feld und eine "übernehmen" schaltfläche.
Das E/A-Feld ist an ein MW / MB gekoppelt.

Wenn jetzt zum Beispiel eine 1 in einen parameter geschrieben werden soll, muss diese 1 im MB gespeichert werden, der wert in den array geschrieben und alle relevanten merker aktiviert werden um die übertragung zu starten.

Ich kann die EA-Fläche nicht direkt an den Array binden, da dieser für alle parameter benutzt wird.

mein problem liegt ja in folgendem :

wenn jetzt jemand zum beispiel als Wert für den Schaltpunkt 300 (hier entpsrechend 30cm) eintragen würde müsste ich irgendwie 16#12c in den array geschrieben bekommen , aufgeteilt auf low und hi byte.

bzw.:
wenn ich den selben wert auslesen wollen würde ( worum es ja erstmal ging die ganze zeit) wäre das spiel natürlich anders rum - high und low byte zusammenfügen - in MW - MW ans ea feld

Das große Ziel ist es alle Sensoren über ein HMI an der Anlage (Nach-)parametrieren zu können .
 

Anhänge

  • IODD.jpg
    IODD.jpg
    131,7 KB · Aufrufe: 24
Dann einfach das höherwertige Byte mit 256 multiplizieren und beide Werte addieren:

Code:
#Tb_val[0] := 16#01;
#Tb_val[1] := 16#54;

#Ti_val := BYTE_TO_INT(IN := #Tb_val[0]) * 256 + BYTE_TO_INT(IN := #Tb_val[1]);
Sooo einfach sollte man es besser nicht machen, weil das "BYTE_TO_INT(IN := #Tb_val[0]) * 256" ergibt einen Überlauffehler wenn der Wert des Bytes 128..255 (16#80..16#FF) ist, weil Ergebnisse >= 32768 nicht in INT passen.
Wenn man mit Speicherinhalten (Bytes und Words ...) bastelt, dann sollte man die zum Basteln vorgesehenen Funktionen verwenden und nicht einfach als Ganzzahl rechnen. Also z.B. so:
Code:
#iVal := WORD_TO_INT( SHL(IN := BYTE_TO_WORD(#Byte1), N := 8) OR #Byte2 );

//in TIA kann man auch schreiben:
#iVal := WORD_TO_INT( SHL_WORD(IN := #Byte1, N := 8) OR #Byte2 );

Wenn es denn unbedingt mit Ganzzahl-Rechenfunktionen sein soll dann funktioniert es fehlerfrei z.B. so:
Code:
#iVal := WORD_TO_INT(UINT_TO_WORD( BYTE_TO_UINT(#Byte1) * 256 + BYTE_TO_UINT(#Byte2) ));

Noch besser ist es, wenn man über die beiden direkt hintereinanderliegenden Bytes per "AT" ein WORD oder INT legen kann, dann braucht man nicht basteln (wenn die Endianness passt). Oder man bastelt die Bytes per "Slice" in ein WORD, was man danach in INT konvertieren kann.

Harald
 
Zurück
Oben