Wertübergabe eines UDT an einer Funktion in SCL

Hotsch

Level-1
Beiträge
149
Reaktionspunkte
13
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Morgen,

ich habe folgende Problemstellung. An einem Funktionsbaustein wird ein DatenbausteinUDT mit mehreren Bool-Werten übergeben. Nun wollte ich diesen UDT an einer Funktion übergeben die in dem Baustein aufgerufen wird. Dies funktioniert nicht da beim kompilieren folgende Fehlermeldung erscheint:
Code:
[COLOR=black][FONT=Verdana]Hilfe zur Meldung 15:4664[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]Beschreibung:[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]Es liegt ein Aufruf eines (S)FC oder (S)FB vor, bei dem eine Parameterversorgung nicht im Anwenderprogramm abgebildet werden kann, obwohl der Parameter mit einem Objekt zulässigen Datentyps versorgt wird.[/FONT][/COLOR]
[FONT=Verdana][COLOR=black]In STEP 7 gibt es bestimmte Kombinationen von Parametern (Formalparameter) und Objekten (hier Aktualparameter genannt), die nicht abgebildet werden können und daher nicht erlaubt sind. Eine genauere Beschreibung dieser Kombinationen sollte der STEP 7-Dokumentation bzw. dem S7-SCL-Handbuch entnommen werden.[/COLOR][/FONT]
[COLOR=black][FONT=Verdana]Behebung:[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]Wählen Sie für den betreffenden Aktualparameter, falls möglich, eine andere Objektklasse (z.B. lokale Variable statt globaler Datenbereich, lokale Variable statt FC-Eingangsparameter, Bausteinbezeichner statt Variable, ...) und übersetzen Sie erneut. Wenn Sie mit dieser Methode nicht nach wenigen Versuchen eine erlaubte Kombination finden, empfiehlt sich das Nachschlagen in der STEP 7-Dokumentation.[/FONT][/COLOR]

Gibt es eine elegante Methode in SCL um dies zu beheben? Zur Not muss ich jeden einzelnen Bool Wert separat an die Funktion übermitteln, dies wäre allerdings unschön.
 
Hallo,
ein UDT ist nur eine Beschreibung. Also sowas wie ein type in C. Willst Du da Daten reinschreiben, musst du erst ein DB vom Typ deines UDT anlegen. Diesen kannst Du dann auch in Funktionen hinein/ausgeben.

Grüsse
Jens
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich hab mich vielleicht etwas blöd ausgedrückt, also probiere ich es noch mal.
Ich hab in einem Globalen DB ein UDT angelegt. Diesen Übergebe ich an einem FB. Soweit klappt es auch noch ohne Probleme. Nun wollte ich aber in diesem FB die Daten weiter an einem FC übergeben und da versagt dann SCL und die obige Fehlermeldung erscheint.
 
Hallo
Hast du den DB als "DB vom Typ" UDT xy angelegt oder hast du in einem DB eine Variable varX vom Typ UDT xy angelegt?

Gruss Hansruedi
 
Du kannst eine UDT nicht an weitere FB durchreichen. Was du evtl. probieren könntest, ist etwas aufwendig. Im FB die selbe UDT als STAT deklarieren. Dann die IN-UDT per Block-Move in die Stat-UDT und diese an den internen FB übergeben. Für den Blockmove mußt du ja eine Any zusammenbauen, schau dazu mal hier in der FAQ. Aber du könntest auch gleich auf die UDT verzichten, statt dessen einen Any-Pointer auf den gewünschten Bereich als IN-Parameter anlegen und diesen dann jeweils in dem FB, in welchem er gebraucht wird per Blockmove auf Temp oder Stat-Variablen kopieren, die dann deine einzelnen Bits enthalten.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke, für die Antwort. Ich hab befürchtet, dass das nicht geht. Ich werd meine Bemühungen jetzt wohl einstellen, da mir der Aufwand etwas zu groß ist nur um eine Handvoll BOOL Variablen zu übergeben.
 
Hallo,
es reicht, wenn du in dem FB den UDT anlegst - es geht sogar im TEMP-Bereich. Die Übertragung der Werte geht dann ganz einfach in dem du schreibst :
Code:
interne_UDT := IN_UDT ;
 
call FC100 (IN_UDT := interne_UDT) :
um das hin- und herkopieren der UDT-Inhalte mußt du dich innerhalb von SCL nicht kümmern. Das übernimmt SCL automatisch für dich.
Wichtig ist hier lediglich, dass SCL den Aufbau der UDT kennt und das IN_UDT und interne_UDT vom gleichen Typ sind ...

Gruß
LL
 
Ah ja, da hat Larry natürlich recht, wie immer hab ich die AWL-Variante hingeschrieben. In SCl ist das weniger aufwändig, das Prinzip aber das Selbe.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Wertübergabe funktioniert jetzt soweit einwandfrei, aber nun bin ich auf ein neues Problem gestoßen.
Also ich rufe eine Funktion mehrfach in einem FB auf. Der Funktion wird jeweils der oben genannte UDT übergeben, sowie einzelne BOOL Werte eines Arrays (z.B. MyArray[3]) als INOUT Variable. Nun werden die Rückgabewerte der Funktionen in einer if Anweisung abgefragt. Das Setzen der Array Variablen funktioniert nur unzuverlässig. Also bei einigen Arrays funktioniert es, bei anderen nicht. Ich denke mir dies ist so weil Step 7 wohl ein Problem damit hat, dass man Funktionen vom gleichen Typ mehrfach aufruft. Gibt es hierfür irgendeine einfache Möglichkeit um diese Geschichte zu realisieren. Als Beispiel hänge ich noch mal den prinzipiellen Code an, wie ich mir das gedacht habe.
Code:
[COLOR=black][FONT=Verdana]FUNCTION_BLOCK MYFUNCTIONBLOCK[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]VAR INPUT[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]  UDT1    :GLOBALUDT;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]END_VAR[/FONT][/COLOR]
VAR
   MYARRAY:ARRAY[1..50] OF BOOL;
END_VAR
[COLOR=black][FONT=Verdana]VAR_TEMP[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]  UDT2    :GLOBALUDT;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]END_VAR[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]BEGIN[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]UDT2:=UDT1;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]...[/FONT][/COLOR]
 
[COLOR=black][FONT=Verdana]IF (    [/FONT][/COLOR]
[COLOR=black][FONT=Verdana]  (MYFUNCTION(MYUDT:=UDT2, Array1:=MYArray[2],Array2:=MYARRAY[4])) OR[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]   (MYFUNCTION(MYUDT:=UDT2, Array1:=MYArray[30],Array2:=MYARRAY[32])) OR[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]   (MYFUNCTION(MYUDT:=UDT2, Array1:=MYArray[34],Array2:=MYARRAY[36]))[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]) then[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]WERT:=TRUE;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]END_IF;[/FONT][/COLOR]
 
[COLOR=black][FONT=Verdana]END_FUNCTION_BLOCK[/FONT][/COLOR]
 
Hallo,
ein Mehrfach-Aufruf, wie du ihn beschrieben hast, funktioniert grundsätzlich. Was mich ein hier stört ist, dass du UDT2 im Temp-Bereich des FB's erstellt hast. Das könnte zu den beschriebenen Zufalls-Ergebnissen führen.
Es würde mich aber auch interessieren, was MyFunction intern so macht ... Das wäre dann die nächste Möglichkeit ...

Gruß
LL
 
Hm, aber er füllt ja die Temp-UDT am Anfang bit den Daten der UDT aus dem Input. Mehrfachaufruf gerade von Funktionen sollte gehen, aber ich habe schon Probleme gehabt, wenn Inputs an den Funktionen gemischt aus unterschiedlichen Quellen (z.Bsp. unterschiedliche DB und Temp) angelegt wurden. Hatte dann den Eindruck, daß die DB wild durcheinander beschrieben wurden. Kann man denn mal versuchsweise UDT2 als Stat anlegen?

PS: Wird in der Funktion evtl. mit dem AR2 gearbeitet? Auf jeden Fall ist es sinnvoll am Anfang der Funktion AR1 und AR2 zu sichern und am Ende diese wieder zu restaurieren.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hm, aber er füllt ja die Temp-UDT am Anfang bit den Daten der UDT aus dem Input.

Das ist (denke ich) das Problem ...
Wir wissen ja gar nicht, was MyFunction nun wirklich tut ... Vielleicht ergänzt es auch nur den UDT2 mit den neuen Werten ... oder ... oder ... oder ... :ROFLMAO:
 
ich hätte da mal sone einfache, strukturelle anmerkung:

- ich würde myfunction nicht als bedingung sondern als funktion vor der if-abfrage aufrufen, dass darf dann auch mehrfach sein.

- dadurch gehst du sicher, dass alle werte verarbeitet werden und brauchst am ende nur noch die elemente deines arrays in einer einfachen logischen verknüpfung verdaddeln, kannst dir also das IF sparen

- wenn du das nicht machen willst, so empfehle ich dir aber mindestens einen else-zweig in dem wert (der wahrscheinlich im stat, inout oder out liegt) auf false gesetzt wird.
 
Also MYFunction ist nur eine Abfolge von IF Anweisungen. Die Vergleichen die UDT Werte auf TRUE und schieben dann je nach Fall die Werte von MYArray[x] in MYArray[y] oder umgekehrt.
Code:
FUNCTION MYFUNCTION :BOOL
VAR INPUT
      UDTFUNCTION:GLOBALUDT
end_VAR
VAR INOUT
      ARRAY1:BOOL;
      ARRAY2:BOOL;
end_VAR
BEGIN
if UDTFUNCTION.TEACH then
  ARRAY1:=ARRAY2;
end_IF;
if MYARRAY1<>MyARRAY2 then
   MYFUNCTION:=TRUE;
else MYFUNCTION:=FALSE;
end_function
Wenn ich diese IF Anweisungen direkt in dem FB Aufrufe dann funktioniert das ganze Programm auch genau so wie es soll, aber sobald ich Funktionen einsetzte wird es für mich nicht mehr nachvollziehbar.

Ich hab den UDT2 jetzt auch in den statischen Speicher verlegt, aber leider ohne Erfolg.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Sorry,
ich reviediere mich. Der Fehler ist, dass das UDT2 in IN-Parameter ist. Es müßte ein IN_OUT-Parameter sein, da ja mit den veränderten Werten im nächsten Zyklus weitergearbeitet werden soll ...


Code:
[COLOR=black][FONT=Verdana]FUNCTION_BLOCK MYFUNCTIONBLOCK[/FONT][/COLOR]
[FONT=Verdana][COLOR=red][B]VAR INOUT[/B][/COLOR][/FONT]
   [COLOR=black][FONT=Verdana] UDT1    :GLOBALUDT;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]END_VAR[/FONT][/COLOR]
VAR
   MYARRAY:ARRAY[1..50] OF BOOL;
END_VAR
[COLOR=black][FONT=Verdana]VAR_TEMP[/FONT][/COLOR]
[COLOR=black][FONT=Verdana] UDT2    :GLOBALUDT;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]END_VAR[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]BEGIN[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]UDT2:=UDT1;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]...[/FONT][/COLOR]
 
[COLOR=black][FONT=Verdana]IF (    [/FONT][/COLOR]
[COLOR=black][FONT=Verdana] (MYFUNCTION(MYUDT:=UDT2, Array1:=MYArray[2],Array2:=MYARRAY[4])) OR[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]  (MYFUNCTION(MYUDT:=UDT2, Array1:=MYArray[30],Array2:=MYARRAY[32])) OR[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]  (MYFUNCTION(MYUDT:=UDT2, Array1:=MYArray[34],Array2:=MYARRAY[36]))[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]) then[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]WERT:=TRUE;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]END_IF;[/FONT][/COLOR]
 
[FONT=Verdana][COLOR=red][B]UDT1:=UDT2;[/B][/COLOR][/FONT]
[COLOR=black][FONT=Verdana]END_FUNCTION_BLOCK[/FONT][/COLOR]
Wie sieht es jetzt aus ?

Gruß
LL
 
Ich hab mich da vertippt, UDT1 ist als INOUT deklariert und die letzte Zeile UDT1:=UDT2 hab ich auch vergessen. Sorry
 
Zuletzt bearbeitet:
Dann hätte ich noch eine andere Frage, wäre es egal wenn ich statt Array vom Typ BOOL, Arrays vom Typ TIME,DINT oder INT verwende? Oder gibt es da Beschränkungen die man beachten muss? Also die Funktion würde dann so aussehen:
Code:
FUNCTION MYFUNCTION :BOOL
VAR INPUT
      UDTFUNCTION:GLOBALUDT
end_VAR
VAR INOUT
      ARRAY1:[B]TIME[/B];
      ARRAY2:[B]TIME[/B];
end_VAR
BEGIN
if UDTFUNCTION.TEACH then
  ARRAY1:=ARRAY2;
end_IF;
if MYARRAY1<>MyARRAY2 then
   MYFUNCTION:=TRUE;
else MYFUNCTION:=FALSE;
end_function
 
Du kannst erstmal grundsätzlich jeden Variablentyp übergeben.

Zu deinem Problem nochmal :
Bist du sicher, dass deine Function korrekt funktioniert ?
Was ist der Sinn derselben ? Das habe ich aus dem Code nicht nachvollziehen können ...
 
Zurück
Oben