TIA Verschieden große Array's an FB "Array[*] of UDT" dynamisch übergeben

soso

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

wir haben sehr viele MB_Client Aufrufe, welche verschiedene Geräte auslesen. Nun haben wir z.B. 32 Messgeräte die man im HMI parametrieren und auch den Hersteller auswählen kann. Bei 3 Herstellern sind das schon 96 Bausteine, die parametriert werden müssen. Diese werden dann über EN bei entsprechender Auswahl von der SPS bearbeitet. Das System wird ständig erweitert und bei jedem neuen Hersteller muss ein neuer Baustein erstellt und 32 mal parametriert werden.

Meine Idee war einen Baustein zu schreiben, welcher die auszulesenden Register in einem Array [*] of UDT einliest und ausführt. Somit gäbe es immer nur 32 Bausteinaufrufe und nur einen Standard-Baustein, welcher mit den Parametern am Array[*] of UDT arbeitet. Die UDT beinhaltet den Mode, Startadresse, Länge und Zieladresse. Aus den Grenzen wird eine Schrittkette gebildet und die Register ausgelesen. Das funktioniert als Einzelaufruf auch sehr gut. Mein Problem besteht jetzt in der Auswahl des Parameter Array's. Jeder Hersteller hat andere Register und Längen auszulesen, daher unterscheiden sich die längen der Array's.

Die Parameter liegen in einem DB:
Parameter Hersteller 1 = Array[0..3] of UDT
Parameter Hersteller 2 = Array[0..8] of UDT

Wie kann ich diese indiziert an meinen FB übergeben? Wenn ich im HMI Hersteller 1 auswähle möchte ich die entsprechenden Array's an den FB übergeben.

Viele Grüße
Benny
 
Konstanten..?

array[0..herstellerX] of udtX
array[0..herstellerY] of udtY

Und dann noch lower bound und upper bound Grenzen in der Funktion abfangen.. damit sich dein Baustein nicht verläuft
 
Was vom folgenden ist für Dich jetzt eigentlich Dein Problem?

1. Du legst im FB den Schnittstellenparameter ARRAY[*] of MyUDT an.
2. Im FB fragst Du die tatsächlichen Arraygrenzen mit LBOUND und UBOUND ab.
3. Dem FB übergibst Du variable Arrays [x..y] oder [i..j] oder ..., aber immer "of MyUDT"
 
Zuviel Werbung?
-> Hier kostenlos registrieren
3. Dem FB übergibst Du variable Arrays [x..y] oder [i..j] oder ..., aber immer "of MyUDT"
Wenn du "Variant" und "REF_to" auspackst, bist du nicht mal mehr auf den Datentyp festgelegt.
Damit lassen sich wirklich wilde Sachen bauen, wie z.B. "Array [*] of Technologieobjekt" und so Scherze.
Ein Beispiel:
https://support.industry.siemens.co...db_any-mit-technologieobjekten?dti=0&lc=de-DE
 
Sorry, bin schlecht im erklären...
Der FB funktioniert, es hapert an der dynamischen Beschaltung.
1. InOut "Par" ist ein "Array[*] of UDT_MB_Client_RW"
2. "Par" ist im FB mit lower_bound und upper_bound abgefragt, daraus errechne ich mir die Anzahl der Schritte
3. "Par" ist immer ein "Array[*] of UDT_MB_Client_RW", aber von unterschiedlicher Länge

Die Doku zu "REF_TO" habe ich gestern gelesen, habe das ehrlicherweise noch nicht ganz verstanden...

Wenn ich den FB wie auf dem Bild beschalte muss ich für jedes weitere Gerät einen neuen Aufruf vom Baustein machen.
Ein Aufruf mit Hersteller_1, einen mit Hersteller_2. Ich möchte den Baustein nur einmal aufrufen und den InOut "Par" über einen Index aus dem HMI umschalten können. Die "Parameter" befinden sich in einem globalen Datenbaustein.

Screenshot 2025-03-21 072043.pngScreenshot 2025-03-21 072057.png
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Dann nimm doch die im drop down vorhanden variable als zeiger für dein array?
Das möchte ich ja, die Frage ist wie kann ich das umsetzen?
Ich kann den Zeiger nicht für das "Array of UDT_MB_Client_RW" benutzen, da sind die Parameter für die Abfrage drin.
Bei Hersteller 1 müssen zwei Register ausgelesen werden, bei Hersteller 2 müssen 90 Register ausgelesen werden.
Wenn ich den Hersteller jeweils in ein Array [1..1] bzw. [2..2] funktioniert das auch nicht, da die Namen anders sind und die CPU dann wegen Bereichslängenfehler in STOP gehen wird. Wenn ich die Hersteller in ein Array [1..2] packe kann ich sie auswählen, habe dann aber immer die gleichen Parameter.
 
Wenn ich den FB wie auf dem Bild beschalte muss ich für jedes weitere Gerät einen neuen Aufruf vom Baustein machen.
Ein Aufruf mit Hersteller_1, einen mit Hersteller_2. Ich möchte den Baustein nur einmal aufrufen und den InOut "Par" über einen Index aus dem HMI umschalten können. Die "Parameter" befinden sich in einem globalen Datenbaustein.
Ok, jetzt kommen wir der Sache näher^^
Besteht die Möglichkeit die Arrays aus "MG_Parameter" in eigene DBs zu verschieben?

Dann könntest du die Array-DBs (Array-DB! keine normalen/globalen DBs) in ein "Array[0..MaxCntHersteller] of DB_Any" mappen und dieses "Liste" der Schnittstellen dann an deinen "MB_Client_SK" übergeben.
Die prinzipielle vorgehensweise wird in Kapitel 5 des oben von mir verlinkten Beitrags beschrieben.
Dort sind es zwar Technologieobjekte, die sind aber im Prinzip auch nur DBs, die sich für was besseres halten ¯\_(ツ)_/¯

Die Doku zu "REF_TO" habe ich gestern gelesen, habe das ehrlicherweise noch nicht ganz verstanden...
"REF_TO" sind Referenzen auf Datentypen & keine eigentliche Variable.
Du kannst damit quasi eine "Maske" über z.B. einen Variant legen & darüber dann auf die Elemente des Variants lesend und schreibend zugreifen.
Das eignet sich speziell für große Strukturen, die du nicht per "MOVE_BLK_Variant" in eine Lokalvariable kopieren möchtest, oder für die Übergabe von Instanzen/Technologieobjekte an unterlagerte Bausteine.
Im Prinzip eine flexibel zuweisbare AT-Sicht.
 
Jetzt verstehe ich worauf du hinaus willst.

Mir ist nicht direkt bekannt, dass es möglich ist ein Array mit [*] im DB anzulegen.. vllt gehts ja in der Schnittstelle.. falls das geht:

> Am Hmi Hersteller anwählbar machen über einzelne Buttons
> In der Plc gibts ein kleines Scl Netzwerk was dafür sorgt dass wenn eins gesetzt ist, alle anderen false sind
> Im Hmi gibts dann dazu noch einen "Auswahl übernehmen" Button

> Deine verschiedenen Arrays sind alle im gleichen Datenbaustein, die Längen werden über verschiedene Konstanten übergeben
> Mit "Auswahl übernehmen" stößt du an, dass aus dem Array, auf welches gezeigt wird ins "Arbeits" Array geladen wird

So? @Botimperator
 
Zuviel Werbung?
-> Hier kostenlos registrieren
So? @Botimperator
Nicht direkt.
Er will ja per Auswahl über einen Index (Int oder sowas) einen Hersteller auswählen.
HMI HMI könnte das z.B. ein smybloisches E/A-Feld sein.

Über den Index zieht sich "MB_Client_SK" über seinen Formalparameter "Array[*] of DB_Any" dann den passenden DB_Any aus dem übergebenen "Array[0..MaxCntHersteller] of DB_Any".
Dieser DB_Any verweist dann nach "draußen" auf den zu dem gewählten Hersteller gehörenden "Array-DB of UDT_MB_Client_RW", welcher die Liste der zu lesenden Register enthält.
Den DB_Any machst du dann per "DB_ANY_TO_VARIANT" zu einem Variant.
Per CountOfElements bekommst du die Anzahl der enthaltenen Array-Elemente des Variants, der sich auf den DB_Any bezieht, welcher sich wieder auf den globalen Array-DB bezieht.
NUR die Gesamt-Anzahl => deswegen Start des Arrays bei 0 wichtig bzw. Array-DBs fangen ja sowieso immer bei 0 an.
Per "MOVE_BLK_VARIANT" kommst du an die einzelnen Elemente des Arrays.
Der Rest ist ne Schlefe & ab damit^^

"REF_TO" bzw. ein Arbeits-Arry würde hier nur eingeschränk funktionieren, da dafür die Länge der Arrays vorher bekannt sein oder eine Maximalgröße innerhalb von "MB_Client_SK" definiert werden müsste.
 
Über den Index zieht sich "MB_Client_SK" über seinen Formalparameter "Array[*] of DB_Any" dann den passenden DB_Any aus dem übergebenen "Array[0..MaxCntHersteller] of DB_Any".
Dieser DB_Any verweist dann nach "draußen" auf den zu dem gewählten Hersteller gehörenden "Array-DB of UDT_MB_Client_RW", welcher die Liste der zu lesenden Register enthält.
Den DB_Any machst du dann per "DB_ANY_TO_VARIANT" zu einem Variant.
Per CountOfElements bekommst du die Anzahl der enthaltenen Array-Elemente des Variants, der sich auf den DB_Any bezieht, welcher sich wieder auf den globalen Array-DB bezieht.
NUR die Gesamt-Anzahl => deswegen Start des Arrays bei 0 wichtig bzw. Array-DBs fangen ja sowieso immer bei 0 an.
Per "MOVE_BLK_VARIANT" kommst du an die einzelnen Elemente des Arrays.
Der Rest ist ne Schlefe & ab damit^^
Ich bin mir nicht sicher, ob ich das jetzt alles richtig verstanden habe, aber ich werf mal meine Lösung in den Ring:

1742555249515.png
1742555651211.png
An der Stelle auch nochmal Shoutout an Siemens, dass ich für Array[0..x] of Int und Array[0..x] of UDT nicht die selbe Anweisung nutzen kann (ist allerdings auch noch V16)

Im FB ist dann #_data ein Zwischenspeicher mit der maximalen Arraylänge die ich irgendwo hab, damit ich auch alle sicher Platz habe. MOVE_BLK_VARIANT überschreibt dann die von außen übergebene Anzahl der Arrayeinträge (bitte bedenken, die restlichen bleiben im Fall von static bestehen, diese beim Wechsel ggf. selbst initialisieren)
Zum Zurückschreiben einen weiteren Aufruf von MOVE_BLK_VARIANT mit SRC und DEST vertauscht genommen und fertig ist der Lack.
 
Ich bin mir nicht sicher, ob ich das jetzt alles richtig verstanden habe, aber ich werf mal meine Lösung in den Ring:
Die Referenz auf die Arrays Baustein-extern zu mappen ist auch eine Möglichkeit ¯\_(ツ)_/¯
Wobei ich bei mehr Einträgen eher eine Case-Anweisung nehmen würde.
Es hätte auf jeden Fall den Vorteil alle Arrays weiterhin in einem DB ablegen zu können.
An der Stelle auch nochmal Shoutout an Siemens, dass ich für Array[0..x] of Int und Array[0..x] of UDT nicht die selbe Anweisung nutzen kann (ist allerdings auch noch V16)
Du meinst "VariantGet" und "MOVE_BLK_VARIANT"?
Das eine ist ein primitiver Datentyp, das andere eine Struktur aus Strukturen und/oder primitiven Datentypen.
Macht halt aus sicht des Betriebssystems doch irgendwo einen Unterschied...
Im FB ist dann #_data ein Zwischenspeicher mit der maximalen Arraylänge die ich irgendwo hab, damit ich auch alle sicher Platz habe.
Auch möglich das komplette Array in eine Arbeitsvariable zu lesen, was aber bei Überschreitung dieser projektierten Grenze blöd werden kann.
Ich würde diesem möglichen Problem ganz aus dem Weg gehen indem "MOVE_BLK_VARIANT" die einzelnen Array-Elemente während der Verarbeitung jeweils separat in eine Arbeitsvariable kopiert.
 
Zurück
Oben