TIA UDT an Position auslesen

JanB1

Level-2
Beiträge
384
Reaktionspunkte
56
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen

Ich habe mich ein wenig in weiner Funktion verrannt. Ich habe zwar einen funktionierenden Lösungsansatz, aber der ist irgendwie nicht zufriedenstellend. Ich hab so ein kribbeln im Hinterkopf nach dem Motto "Das muss doch besser gehen..." :ROFLMAO:

Folgende Ausgangslage: wir haben einen unoptimierten Datenbaustein welcher Datenblöcke mit einer Breite von 1'000 Bytes enthält. Die Datenblöcke haben einen Header aus 10 Bytes, gefolgt von einem Datenbereich in strukturierter Form von 990 Bytes (hier mal "myData" genannt).
Siemens.Automation.Portal_2020-02-25_14-04-18.jpg

Ich will nun mit einer Funktion während der Laufzeit einen Datenbereich in Abhängigkeit von der ID auslesen und bestimmte Daten innerhalb des UDTs "myData" herausnehmen und in eine andere Struktur packen, welche ich dann ausgebe.

Das ganze soll in SCL programmiert werden, da AWL ja inzwischen als "Legacy" definiert wurde und bereits jetzt in vielen neueren Funktionen im TIA Portal gar nicht mehr unterstützt wird.

Mein Ansatz bis jetzt ist folgender:
Ich gehe mit WHILE-Schlaufe durch den Baustein durch. In der Schlaufe habe ich eine Variable "byteZeiger" definiert. Mit "PEEK_WORD" mit einem ByteOffset von "byteZeiger" + 0 lese ich den Wert "ID_Daten" aus. Stimmt die ID an der aktuellen Stelle mit der gesuchten ID überein, so gehe ich in eine FOR-Schlaufe (FOR i := 0 TO 989 DO) mit welcher ich über "PEEK_BYTE" mit einem ByteOffset von ("byteZeiger" + 10) + i die 990 Bytes des UDTs auslese und in ein Array[0..989] of Byte schreibe. Über dieses Array habe ich über AT den UDT "myData" gelegt, wodurch ich nun auf die strukturierten Daten zugreifen kann.

So weit der Plan. Das ganze funktioniert nun auch relativ okay. Nur habe ich das Gefühl, dass ich das ganze falsch angehe und es einen einfacheren Weg gibt. Oder täuscht mich hier mein Gefühl und das Kribbeln im Hinterkopf sind nur Flöhe die ich mir selber in den Kopf gesetzt habe? :p

PS. Falls sich jemand wundert warum ich nicht "BLKMOV" verwende: BLKMOV wurde von Siemens ebenfalls als "Legacy" markiert, also bin ich hier nicht sicher wie lange diese Funktion noch zur Verfügung steht.
Und Ja, mir ist bewusst, dass das ganze mit einem Array deutlich einfacher wäre, nur ist die Vorgabe dass in diesem ersten Schritt in Richtung SCL nicht gleich alle Strukturen über den Haufen geworfen werden sollen die über die Jahre etablierrt wurden (da noch sehr viele Funktionen im Hintergrund sind die auch auf diese Daten zugreifen wollen und ich nicht all diese Funktionen auf einen Schlag von AWL mit indirekter Adressierung auf SCL mit Arrays umschreiben kann).
 
Warum sind die Daten nicht von Anfang ab in ein Array arrangiert ?
Dann kannst du es einfach und sauber in SCL programmieren, ohne lästigen PEEK, POOK, BLKMOV oder WHILE !.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Servus,

Soweit ich es verstanden habe, könntest du auch statt der FOR-Schleife eine einfache zuweisung machen.
Bsp. du hast die Daten gefunden,

IF DatenID_OK THEN
myData := gefundeneDaten;
END_IF;

Da sparst du dir die For-schleife und die AT überlagerung.

Mit freundlichen Grüßen
Piit


Gesendet von iPhone mit Tapatalk
 
Zuletzt bearbeitet:
Wenn die zu kopierende Daten denselbe Struktur über UDT haben, dann braucht man keine FOR Schleifen.

Wenn die Daten in ein Array arrangiert sind, dann einfach etwas in diesen Stil:

Dataset[targetindex].data := Dataset[sourceindex].data ;

Der SCL Compiler sorgt für wie die Daten tatsächlich kopiert werden.
 
Warum sind die Daten nicht von Anfang ab in ein Array arrangiert ?
Dann kannst du es einfach und sauber in SCL programmieren, ohne lästigen PEEK, POOK, BLKMOV oder WHILE !.

Bitte den Text unter "PS." lesen. ;)


Servus,

Soweit ich es verstanden habe, könntest du auch statt der FOR-Schleife eine einfache zuweisung machen.
Bsp. du hast die Daten gefunden,

IF DatenID_OK THEN
myData := gefundeneDaten;
END_IF;

Da sparst du dir die For-schleife und die AT überlagerung.

Mit freundlichen Grüßen
Piit

Wie erhalte ich denn "gefundene Daten"? Ich suche ja über das Offset im DB und über das Offset kenn ich den Anfangspunkt meiner Daten. Aber das "gefundene Daten" ist ja zur Zeit des programmierens noch nicht klar sondern erst, wenn der Suchdurchlauf gestartet wurde.
 
PS. Falls sich jemand wundert warum ich nicht "BLKMOV" verwende: BLKMOV wurde von Siemens ebenfalls als "Legacy" markiert, also bin ich hier nicht sicher wie lange diese Funktion noch zur Verfügung steht.
Und Ja, mir ist bewusst, dass das ganze mit einem Array deutlich einfacher wäre, nur ist die Vorgabe dass in diesem ersten Schritt in Richtung SCL nicht gleich alle Strukturen über den Haufen geworfen werden sollen die über die Jahre etablierrt wurden (da noch sehr viele Funktionen im Hintergrund sind die auch auf diese Daten zugreifen wollen und ich nicht all diese Funktionen auf einen Schlag von AWL mit indirekter Adressierung auf SCL mit Arrays umschreiben kann).

Ja, das hatte ich ursprünglich auch so gedacht, aber es ist einfach nicht sinnvoll. Irgendwann (eher zeitnah) kommt man dann ohenhin an den Punkt, wo man das umändern muß. Es macht auf einer 1500-er wirklich keinen Sinn, mit Peek, Poke, ind. Adressierung etc. alte Strukturen zu retten. Also mach dir die Arbeit gleich, später wirds noch schwieriger, da du dann auch noch die "neuen" Strukuren erneut anfassen mußt.
 
Ja, das hatte ich ursprünglich auch so gedacht, aber es ist einfach nicht sinnvoll. Irgendwann (eher zeitnah) kommt man dann ohenhin an den Punkt, wo man das umändern muß. Es macht auf einer 1500-er wirklich keinen Sinn, mit Peek, Poke, ind. Adressierung etc. alte Strukturen zu retten. Also mach dir die Arbeit gleich, später wirds noch schwieriger, da du dann auch noch die "neuen" Strukuren erneut anfassen mußt.

Hmm...Problem ist (was mir gerade einfällt), dass ich in diesem DB manchmal nicht nur 1 UDT "myData" sondern noch 2 weitere UDTs "myData_Spezial1" und "myData_Spezial2" drin habe, bei welchen zwar die Breite und das jeweilige Offset der darunterliegenden Daten gleich bleibt, aber gewisse Bereiche die in "myData" als Reserve definiert sind hier mir zusätzlichen Daten belegt sind. Das macht das ganze etwas unschön...

Ich werde da mal versuchen eine Vereinfachung der Strukturen durchzuboxen. 1 UDT und das ganze in einem Array und gut ist. SCL ist super mit Arrays, bei AWL haste das ganze halt mit indirekter Adressierung gemacht. Ich seh schon, da kommen einige Stunden an Arbeit auf mich zu...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Vorschlag, anstatt nur 1 Datentyp erstellst du 2 Datentypen:

Code:
TYPE typenutzdaten: STRUCT
  ??? 
  ???

TYPE typealledaten: 
data: ARRAY[1..20] OF STRUCT
  ID: INT
  Res_1: INT
  Res_2: INT
  Res_3: INT
  Res_4: INT
  Daten : UDT "typenutzdaten"

Wenn du in ein FC ein IO pin belegt:
InOut: meinedaten : typealledaten

Dann kannst du in den FC einfach addressieren, z.B:
Code:
IF #meinedaten.data[suchindex].ID := #Suchwert THEN
  #meinedaten.data[arbeitindex].Daten := #meinedaten.data[suchindex].Daten;
[COLOR=#333333]END_IF ;[/COLOR]
 
Zu das Thema unterschiedliche UDTs, dann wäre die beste Lösung einen UDT zu erstellen die alle Datentypen decken kann.
Wenn das nicht geht, dann wäre einen Umweg, den standardisierte UDT zu behalten, und die spezielle Daten in einen weitere DB zu auslagern.
 
Vorschlag, anstatt nur 1 Datentyp erstellst du 2 Datentypen:

Code:
TYPE typenutzdaten: STRUCT
  ??? 
  ???

TYPE typealledaten: 
data: ARRAY[1..20] OF STRUCT
  ID: INT
  Res_1: INT
  Res_2: INT
  Res_3: INT
  Res_4: INT
  Daten : UDT "typenutzdaten"

Wenn du in ein FC ein IO pin belegt:
InOut: meinedaten : typealledaten

Dann kannst du in den FC einfach addressieren, z.B:
Code:
IF #meinedaten.data[suchindex].ID := #Suchwert THEN
  #meinedaten.data[arbeitindex].Daten := #meinedaten.data[suchindex].Daten;
[COLOR=#333333]END_IF ;[/COLOR]

Ja, so hatte ich mir das in etwa gedacht. Dann kann ich sehr schlank wie du es hier auch geschrieben hast die Daten rausholen. Da würd ich halt gerne hin, aber leider hab ich da aktuell noch ein paar Steine im Weg.


Zu das Thema unterschiedliche UDTs, dann wäre die beste Lösung einen UDT zu erstellen die alle Datentypen decken kann.
Wenn das nicht geht, dann wäre einen Umweg, den standardisierte UDT zu behalten, und die spezielle Daten in einen weitere DB zu auslagern.

Ja, aber nein. Das würde dann wieder nicht mit den bestehenden Bausteinen funktionieren da somit die entsprechenden Daten am falschen Ort sind. Ausserdem würde ich dann eher einen Cleanup anstreben, da die Daten nicht so weit voneinander abweichen als dass ich sie nicht in einem einzigen UDT der auf alles passt zusammenfassen kann. Und die Breite von 1'000 Bytes bleibt, da werd ich ja nicht grösser.


Aktuell wird es darauf rauslaufen dass ich für das aktuelle Projekt eine Funktion schreibe die mit den bestehenden Strukturen arbeiten kann, und als Vorbereitung zum nächsten Projekt werde ich alles auf Arrays umschreiben.

Dann werde ich einfach ein Problem haben dass ich pro Datenbereich 64 Störungsbits habe die ich dann noch irgendwie nicht indirekt auslesen muss um zu wissen, ob irgend eines der Bits auf TRUE ist. Aber auch da werde ich wohl auf ein "Array[0..63] of Bool" umsatteln müssen.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Dann werde ich einfach ein Problem haben dass ich pro Datenbereich 64 Störungsbits habe die ich dann noch irgendwie nicht indirekt auslesen muss um zu wissen, ob irgend eines der Bits auf TRUE ist. Aber auch da werde ich wohl auf ein "Array[0..63] of Bool" umsatteln müssen.
Ein Tip:
Mach einen zusätslichen überlagerte AT Sicht von die 64 bits. Z.B. als 2 DINTs.
Um zu erkennen ob ein bit TRUE ist, dann einfach die 2 DINTs nach "nicht gleich L#0" testen.
 
J
Dann werde ich einfach ein Problem haben dass ich pro Datenbereich 64 Störungsbits habe die ich dann noch irgendwie nicht indirekt auslesen muss um zu wissen, ob irgend eines der Bits auf TRUE ist. Aber auch da werde ich wohl auf ein "Array[0..63] of Bool" umsatteln müssen.

Das ist bei mir der einzige Bereich, in welchem noch zwei Mal PEEK_DWORD in einer Schleife vorkommt.
Ich schau da direkt auf de HMI-Meldebit-DB und dieser ist bei mir als Einziger noch "nicht optimiert". Ich hab noch nicht ausprobiert, ob der überhaupt "optimiert" sein kann, m.E. nach nicht, da das HMI ja direkt die Bits nutzt und diese in optimierten DB als Byte abgelegt sind.

Vlt. hat da jemand eine bessere Lösung, wenn man das Bitmeldeverfahren nutzt.
 
Ein Tip:
Mach einen zusätslichen überlagerte AT Sicht von die 64 bits. Z.B. als 2 DINTs.
Um zu erkennen ob ein bit TRUE ist, dann einfach die 2 DINTs nach "nicht gleich L#0" testen.

Oh...daran hab ich noch nicht gedacht... :eek:

Würde ich dann im Static/Temp des Bausteins eine Temp-Variable vom Typ "UDT_Störungen" (der UDT welcher all diese Bits enthält) machen und diese in einer zweiten Variable "Array[0..1] of DWORD" über AT überlagern?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hier ist ein Beispiel von 2-Mal Sicht von dieselbe Daten in ein FB STAT Deklaration. Verwende ich sehr viel um Daten die nicht in Array Strukturiert sind, trotzdem als Array zu betrachten.
Die Baustein ist hier "nicht optimiert". Wenn die Daten mit "Remanenz in IDB setzen" eingestellt sind, sollte es möglich sein auch mit optimierte Daten. Verwende ich aber nicht.
Ich glaube das dasselbe ist möglich InOut Daten in ein FC.
AT_in_FB_declaration.png
 
...
Ich schau da direkt auf de HMI-Meldebit-DB und dieser ist bei mir als Einziger noch "nicht optimiert". Ich hab noch nicht ausprobiert, ob der überhaupt "optimiert" sein kann, m.E. nach nicht, da das HMI ja direkt die Bits nutzt und diese in optimierten DB als Byte abgelegt sind.

Vlt. hat da jemand eine bessere Lösung, wenn man das Bitmeldeverfahren nutzt.
Das geht auch alles optimiert. Meine Trigger in der SPS liegen in einem Word-Array. Das Array liegt wiederum symbolisch als Variable im HMI und beherbergt die Bitmeldungen 0 bis n.
 
Hier ist ein Beispiel von 2-Mal Sicht von dieselbe Daten in ein FB STAT Deklaration. Verwende ich sehr viel um Daten die nicht in Array Strukturiert sind, trotzdem als Array zu betrachten.
Die Baustein ist hier "nicht optimiert". Wenn die Daten mit "Remanenz in IDB setzen" eingestellt sind, sollte es möglich sein auch mit optimierte Daten. Verwende ich aber nicht.
Ich glaube das dasselbe ist möglich InOut Daten in ein FC.
Anhang anzeigen 48685

Ja, so in etwa hab ich deine vorherige Aussage intepretiert. Danke, das hilft! :ROFLMAO:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das geht auch alles optimiert. Meine Trigger in der SPS liegen in einem Word-Array. Das Array liegt wiederum symbolisch als Variable im HMI und beherbergt die Bitmeldungen 0 bis n.

Ok, verstehe ich.
Ich will aber unbedingt die die Einzelbits auch als Bit haben, also "MeinErrorDB".Error_001 usw. Daher hab ich den den mit 3 UDT zu je 2048 Bit organisiert und das geht nur "nicht optimiert", leider.
 
Moin Ralle,

das ist ein Thema, mit dem wir uns auch bei der Erstellung von Meldungen herumgeschlagen haben.

Man könnte den einzelnen Array-Elementen individuelle Kommentare mitgeben.

VG

MFreiberger
 
Zurück
Oben