Step 7 SCL auf Strukturelemente eines zur Laufzeit bekannten DBs zugreifen

MFreiberger

Level-3
Beiträge
2.853
Reaktionspunkte
758
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Zusammen,

ich habe da mal wieder eine Frage:
Gibt es eine Möglichkeit innerhalb einer SCL-Funktion auf Strukturvariablen eines DBs zuzugreifen, der erst zur Laufzeit bekannt ist (INPUT Block_DB)?
GGf. Struktur (UDT) an FC übergeben?

Konkretes Problem:
Um in einem Hochregallager die Sollposition zu bestimmen, stehen mir die Fachkoordinaten zur verfügung. In einem DB habe ich die entsprechenden Positionsdaten hinterlegt.
Dabei habe ich eine UDT100 "Fachdaten" mit folgenden Elementen angelegt:
BIT Struct
gesperrt BOOL
belegt BOOL
bitxy
.
.
.
X Struct
Position DINT
Offset DINT
Y Struct
Position DINT
Offset DINT

Jetzt möchte ich in einem SCL-Baustein wie folgt auf die Datenbausteinvariablen zugreifen:
FUNCTION FC100 : INT


VAR_INPUT
Ii_XFach : INT;
Ii_YFach : INT;
END_VAR


VAR_OUTPUT
Odi_XPosition : DINT;
Odi_YPosition : DINT;
END_VAR


VAR_IN_OUT
IOdi_XOffset : DINT;
IOdi_YOffset : DINT;
IOw_Bits : WORD;
END_VAR




// Anweisungsteil
Odi_XPosition := Idb_Regal.Fach[Ii_XFach,Ii_YFach].X.Position;
Odi_YPosition := Idb_Regal.Fach[Ii_XFach,Ii_YFach].Y.Position;


FC100 := 100;
END_FUNCTION

Dass das so nicht geht ist mir bewusst. Im Anweisungsteil kennt das Programm ja den DB und damit die Datenstruktur nicht. Trotzdem soll der DB variabel bleiben und ich will halt direkt auf die Positionwerte anhand der Fachkoordinaten zugreifen. Das muss doch gehen. Hat da jemand eine Idee?

vielen Dank im Voraus.

Gruß

MFreiberger
 
die wahrscheinlich einfachste und schnellste Variante ist das errechnen der ersten Byteadresse anhand der gegebenen Datenstruktur und das Erstellen eines dementsprechenden ANY-Pointers.
Damit ist es dann möglich den Datenblock in eine temporäre Struktur zu kopieren, zu bearbeiten und zurück zu kopieren.

Stichworte: ANY, AT, SFC20
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin vierlagig,

also doch mit Adressberechnung arbeiten. Ich hatte halt gedacht, ich könnte SCL entsprechend nutzen um über die Angabe mit der Fachnummer als Index auf die entsprechenden Variablen zuzugreifen.
Wenn es nur mit Adressberechnung und Pointer zerlegen geht, gehe ich doch wieder zurück zu AWL ;)

Gruß

MFreiberger
 
Hallo,
du könntest dem FC via IN_OUT den UDT100 auf der Schnittstelle übergeben. Dann "kennt" das System den Partner und du müßtest auch so programmieren können, wie du es vorhast.

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Kompilieren

Moin Larry Laffer,

das habe ich nicht ganz verstanden. Wie weise ich meinem DB den UDT zu? Oder muss ich die den UDT auch vor dem Aufruf in SCL programmieren?

Es gibt nämlich das Problem, dass die "Kompostierung" des Programms nicht ohne Fehler durchläuft. U.a. "Ungültige Variable".


Gruß

MFreiberger
 
Zuletzt bearbeitet:
Hast Du in Deinem Datenbaustein ein Array[0..x] of UDT 100 kannst du diese per Index an einen Funktionsbaustein übergeben.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin vierlagig,

mein DB sieht so aus:

Code:
Fach	ARRAY[1..100,1..20]			
	"Fachdaten"

und meine UDT so:

Code:
BIT	STRUCT			
gesperrt	BOOL	FALSE	Das Fach ist gesperrt	
belegt	BOOL	FALSE	Das Fach ist belegt	
SetOffsetX	BOOL	FALSE	Die neuen Offsetwerte für die X-Position übernehmen	
SetOffsetY	BOOL	FALSE	Die neuen Offsetwerte für die X-Position übernehmen	
bit12	BOOL	FALSE		
bit13	BOOL	FALSE		
bit14	BOOL	FALSE		
bit15	BOOL	FALSE		
bit0	BOOL	FALSE		
bit1	BOOL	FALSE		
bit2	BOOL	FALSE		
bit3	BOOL	FALSE		
bit4	BOOL	FALSE		
bit5	BOOL	FALSE		
bit6	BOOL	FALSE		
bit7	BOOL	FALSE		
	END_STRUCT			
X	STRUCT			
Position	DINT	L#0		
Offset	DINT	L#0		
	END_STRUCT			
Y	STRUCT			
Position	DINT	L#0		
Offset	DINT	L#0		
	END_STRUCT


Dann müsste ich ja innerhalb der FC immer die Feldgröße anpassen, wenn es unterschiedlich große Regale gibt, oder?

Gruß

MFreiberger
 
Moin vierlagig,

jetzt bin ich mir nicht sicher, was Du meinst.
Der Zugriff auf die Arrayelemente funktioniert ja...

Code:
FUNCTION FC100 : INT


VAR_INPUT
    Ii_XFach : INT;
    Ii_YFach : INT;
    Idb_Regal : BLOCK_DB;
END_VAR


VAR_OUTPUT
    Odi_XPosition : DINT;
    Odi_YPosition : DINT;
END_VAR


VAR_IN_OUT
    IOdi_XOffset : DINT;
    IOdi_YOffset : DINT;
    IOw_Bits : WORD;
    IO_UDT : UDT100;
END_VAR




    // Anweisungsteil
    Odi_XPosition := Idb_Regal.Fach[Ii_XFach,Ii_YFach].X.Position; //funktioniert nicht
    Odi_YPosition := Idb_Regal.Fach[Ii_XFach,Ii_YFach].Y.Position; //funktioniert nicht
   
    Odi_YPosition :=DB101.Fach[Ii_XFach,Ii_YFach].Y.Position; //funktioniert
    ;
    FC100 := 100;
END_FUNCTION

wenn ich den DB fest reinschreibe, bekomme ich meine Fachpositionen, wie gewünscht.
Nur mit dem variablen Zugriff das funktioniert nicht.


Gruß

MFreiberger
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
was ich hier meinte war folgendes :
Du hast deinen DB (Regal). Hierin hast du dein Array of UDT 100 angelegt.
Nun machst du an deinen Baustein einen IN_OUT-Parameter vom Typ UDT100.
Diesem übergibst du dann den gewünschten Fach-Inhalt - also z.B.
Code:
call FC123
   Daten := "Regal".Fach[3,12]
... nun kannst du in dem FC123 den Parameter Daten wie gewünscht behandeln ...

Gruß
Larry
 
Hallo,
was ich hier meinte war folgendes :
Du hast deinen DB (Regal). Hierin hast du dein Array of UDT 100 angelegt.
Nun machst du an deinen Baustein einen IN_OUT-Parameter vom Typ UDT100.
Diesem übergibst du dann den gewünschten Fach-Inhalt - also z.B.
Code:
call FC123
   Daten := "Regal".Fach[3,12]
... nun kannst du in dem FC123 den Parameter Daten wie gewünscht behandeln ...

Gruß
Larry

und die 3,12 kann, wie in Beitrag #8 erwähnt variabel gestaltet werden - x,y vom Typ INT
 
... ich glaube, dass das nur funktioniert, wenn du dem Baustein gleich das ganze ARRAY of UDT übergibst und die jeweiligen Indexe als IN-Parameter ... (vielleicht mal testen ...)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin Zusammen,

ich habe jetzt Folgendes ausprobiert:

Code:
      CALL  FC   100
       Ii_XFach     :=MW200
       Ii_YFach     :=MW202
       RET_VAL      :=MW204
       Odi_XPosition:=MD206
       Odi_YPosition:=MD210
       IOdi_XOffset :=MD214
       IOdi_YOffset :=MD218
       IOw_Bits     :=MW222
       IO_Daten     :="Regal_1".Fach

Code:
FUNCTION FC100 : INT


VAR_INPUT
    Ii_XFach : INT;
    Ii_YFach : INT;
END_VAR


VAR_OUTPUT
    Odi_XPosition : DINT;
    Odi_YPosition : DINT;
END_VAR


VAR_IN_OUT
    IOdi_XOffset : DINT;
    IOdi_YOffset : DINT;
    IOw_Bits : WORD;
    IO_Daten : ARRAY [1..100,1..20] OF udt100;
    
END_VAR




    // Anweisungsteil
  
    Odi_YPosition :=IO_Daten[Ii_XFach,Ii_YFach].Y.Position; //funktioniert
    ;
    FC100 := 100;
END_FUNCTION

Das sieht, zumindest funktionell, nicht schlecht aus. Leider kann ich bei der Array-Deklaration von "IO_Daten" nur Konstanten angeben...
Aber immerhin.
@vierlagig: das Übergeben mit variablen ("Regal_1".Fach[X,Y]) Indexen funktionier, wie Larry Laffer schon vermutet hat, leider nicht.

Soweit ich das verstehe, bleibt mir entweder der immerwährende Eingriff in die FC (Indexe ändern) oder die Adressberechnung, wo ich wieder bei AWL wäre ;)

Vielen Dank für die Unterstützung

Gruß

MFreiberger
 
... hast du denn meinen Vorschlag auch mal in Erwägung gezogen ?

Oder ... andere Variante : du läßt deine Regal-Daten von einem FB als Bestandteile von dessen Instanz verwalten. Dann hast du in dem FB auch wieder vollen Zugriff auf die Einzeldaten - auch indexiert in SCL.

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin Larry Laffer,

... hast du denn meinen Vorschlag auch mal in Erwägung gezogen ?

ich dachte, das, was ich in #15 versucht habe, hättest Du gemeint.

Oder ... andere Variante : du läßt deine Regal-Daten von einem FB als Bestandteile von dessen Instanz verwalten. Dann hast du in dem FB auch wieder vollen Zugriff auf die Einzeldaten - auch indexiert in SCL.

aber wenn ich dann aus anderen Bausteinen auf diese Daten zugreifen will, muss ich auf den IDB dieses FBs zugreifen. Ich bin der Meinung, auf die IDB-Daten darf nur der jeweilige FB zugreifen.
Mann könnte allerdings auch den gleichen IDB für mehrere FBs verwenden (Hat SIEMENS ja auch in dem Beispiel bei TCON, et. gemacht). Dann müssen diese FBs immer mit der gleichen Struktur umgehen können ... Muss halt diszipliniert aufgebaut werden.

Gruß

MFreiberger
 
Zurück
Oben