Aufruf einer FUNCTION abhängig von einer Eingangsvariablen

SolidPro

Level-1
Beiträge
5
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi.

Bin ein absoluter Neuling zum Thema TwinCat und Codesys.

Habe bis dato immer Siemens eingesetzt und möchte mich jetzt mal an Beckhoff herantrauen.

Nun mein Problem:

"Ich möchte abhängig von einer Eingangsvariablen eine Function aufrufen."

Beim Aufruf des Function_Block soll der Name der auszuführenden Function übergeben werden.

TwinCat 3

Beispiel:
____________________________________________________________
Function_Block XXX
____________________________________________________________
Var_In
Baustein : Function;
End_Var
____________________________________________________________

Baustein();
____________________________________________________________



Ist diese Aufgabe zu lösen ?

Und wenn "JA", wie ?

VIELEN DANK IM VORRAUS
 
Zuletzt bearbeitet:
Also wenn ich Dich richtig verstehe möchtest Du einen Baustein aufrufen, aber dessen Verhalten durch eine Variable steuern, nicht durch die Variable steuern OB der Baustein ausgeführt wird.
Dann ist Dein Ansatz schon ganz in Ordnung. Über die Deklaration einer VAR_INPUT erhälst Du einen Eingang den Du beschalten kannst. Hier könntest Du z.B. eine INT übergeben. Innerhalb Deiner Funktion wird dann je nach übergebener Zahl etwas anderes ausgeführt.

Wie genau das zu lösen ist hängt von der verwendeten Programmversion sowie der gewünschten Programmiersprache ab.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi.

Ich möchte über die Eingangsvariable entscheiden, welcher Baustein ausgeführt wird.
Die Eingangsvariable soll den Namen der auszuführenden Funktion beinhalten.

Der Function_block führt also die Function aus, welche ihm über die Eingangsvariable mitgeteilt wird.
 
Hmm, gibt es tatsächlich echten Bedarf für eine solche Art zu programmieren (außer unverständlichen und unrobusten Code zu schreiben)? :confused:

Man könnte einen codierten Modus-Wert übergeben und die verschiedenen Funktionsaufrufe in eine CASE-Anweisung einfügen.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Leider nicht zufriedenstellend.

Der Function_block sollte später für andere zur Verfügung stehen, ohne ihn ändern zu müssen.
Lediglich die Beschaltung der Var_Input sollte geändert werden.
Deshalb keine festen Zuweisungen im Function_block. Alles über Variablen.
 
Das macht sogar richtig SINN !!!

Wenn ich den Bedarf nicht hätte, würde ich es wohl kaum programmieren.

Da steckt später einiges dahinter, was diese Programmierweise auf jeden Fall rechtfertigt.

Gruß

Dann passt es ja! Es ist eben nur so, dass GENAU bei solchen Beiträgen meist herauskommt, dass der Themenstarter eine abenteuerliche Programmierung umsetzen will und wenn man dann genau fragt was er eigentlich will das Problem einfacher, schneller und besser mittels anderem Weg lösbar ist.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich denke, das geht nicht, auch wenn ich kein Codesys-Crack bin. Denkbar wäre eine Referenz zu übergeben auf ene Funktion, die dann aufgerufen wird, aber was sollte so etwas bringen? Aber ob Codesys das so kann??? Case-Anweisung, ja das ginge sicher, aber dann stehen die Funktionen fest im Programm. Macht ja aber nichts, denn auch in der vom TE gewünschten Variante, müßten die Funktionen zumindest schon im Programm stehen, also existent sein.

Ich denke auch wie PN/DP ud borromeus, das Ganze wäre abenteuerlich und in einer SPS eher fehl am Platze, aber bitte, jedem sein Königreich :)
 
In IEC nicht vorgesehen

Ich kann mir schon vorstellen, was der Sinn sein soll aber in dieser Umgebung nicht vorgesehen.

In manchen Sprachen aus der PC und Rechner Welt ist das möglich, in Oracle ist es sogar möglich, ein Array Element mit einem String zu adressieren. Aber diese "elegante späte Bindung" verbirgt einen gewaltigen Overhead mir Hashtabels und Dictionaries etc.

Die SPS aber hat in jedem Zustand deterministisch zu reagieren!

Wenn ich über einen Übergabestring entscheide, welche Funktion ich aufrufe, dann muss deshalb die Funktion bekannt sein schon zum Zeitpunkt des Compilierens und Bindens.

Ein bedingtes Nachladen mit später Bindung (wie z.B. einer Resource oder einer DLL) gibt es in der SPS Welt absichtlich nicht, denn dann könnte das Nachladen fehlschlagen und eine NULL Referenz entstehen und dann steht die SPS.

Deshalb wie oben schon erwähnt, einen INT oder eine Enumeration (endliche Menge von Möglichkeiten) als Übergabe und eine CASE Liste mit ggf. einem ebenfalls definierten ELSE Verhalten.
 
Ja RobiHerb hat Recht, in Hochsprache z.B. C# geht das. Nennt sich "Delegate". Nutzt man z.B. wenn man eine Funktion schreibt die immer das gleiche machen soll mit unterschiedlichen Datentypen. Entweder kann man da die Funktion überladen und mehrmals mit dem gleichen Namen implementieren jedoch mit unterschiedlichen Signaturen oder man nutzt delegates. Dann erübrigt es sich Funktionen mit dem selben Inhalt jedoch unterschiedlichen Datentypen zu implementieren.

Beispiel:

FunktionA(int a, int b)
{
return a*b;
}

FunktionA(real a, real b)
{
return a*b;
}

Beide Funktionen haben den selben Inhalt jedoch für unterschiedliche Datentypen. Hier müsste man diese Fkt. nun überladen oder halt eine Delegate anlegen dann funktioniert das für alle Datentypen die definiert sind. Ist natürlich ein Pippifaxbeispiel. Aber soweit ich mich erinnere trifft das den Gedanken ganz gut.

Kurzum: In Codesys geht das so nicht. Das einzige was du tun kannst ist (Achtung: würde ich nicht empfehlen):
Eine Funktion anlegen mit einer Signatur mit einem Pointer to Byte dann brauchst du noch einen Eingang der jeweils definiert auf welchen Datentyp gezeigt wird damit du das intern per Pointer to Byte in ein Real oder Dint oder was auch immer kopieren kannst. Du musst dann die Maxanzahl der möglichen Singaturparameter anlegen und in der Funktion jeweils den beschreibenden Parameter prüfen ob dieser > 0 ist was bedeutet, dass der Typ verwendet wird. Dann siehst du ob der Pointer auch valide Daten zugreift. Du musst natürlich trotzdem jeden Parameter immer beim Fktaufruf anlegen da das sonst syntaktisch nicht korrekt wäre.

Beispiel:
Funktion(
pValue1 : Pointer to Byte,
TypeValue1 : INT,
pValue2 : Pointer to Byte,
TypeValue2 : INT,
pValue3 : Pointer to Byte,
TypeValue3 : INT,
)

Wobei TypeValue jeweils intern z.b. so interpretiert wird:
0 = Pointerwert nicht valide
1 = DINT
2 = REAL
3 =...
==> Kannst natürlich auch als Enum anlegen dann wird es übersichtlicher

Wie gesagt: Nicht zu empfehlende Lösung...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi.
Also ich habe das so verstanden, dass du in deinem FunctionBlock an einem bestimmten Punkt die Funktion ausführen möchtest, welche an dem Eingang liegt.
Also was Du vorhast geht sehrwohl und dies auch noch relativ simple. Stichwort Interface.
Du deklarierst dir ein Interface vom Typ "Irgendwas", welches eine Methode "genericFunction" enthält.
als Eingang deklarierst Du:

Code:
VAR_INPUT
Baustein : Irgendwas;
END_VAR

Jetzt kannst du einen FunktionsBlock erstellen, welcher das Interface "Irgendwas" implementiert.
in diesem kannst du jetzt die Methode "genericFunction" erstellen und eine "Funktion" deiner Wahl hinterlegen, bzw. ausprogrammieren.

als letzte Aktion übergibst du nun den Baustein an dein Eingang.

Code:
Instanz(Baustein:=DeinNeuerBaustein);

Und in deinem Baustein kannst du die externe "Funktion" jetzt so aufrufen:

Code:
Baustein.genericFunction();


Zugegeben, diese Version macht dann Sinn, wenn du der Methode werte übergeben möchtest,
diese nicht als Ausgang Preis geben magst, oder einfach elegant programmieren willst :p.
Andernfalls kannst au auch einfach eine INOUT Variable ungleich 0 setzen und dann darauf reagieren.
bspw. in einer Case Struktur.

Ich persönlich finde jedoch die Variante des Inteface eleganter.
Man kann so in dem FB die externe Methode aufrufen und es kann natürlich auch so ein Wert von außen an den FB über den Methodenrückgabewert zurückgegeben werden.


ich hoffe ich konnte dir helfen.
 
Zuletzt bearbeitet:
Früher hieß es "Nobel geht die Welt zugrunde".
Heutzutage ist niemand mehr nobel, heute geht die Welt durch "elegante" Programmierung zugrunde. :ROFLMAO:

Harald
 
Früher hieß es "Nobel geht die Welt zugrunde".
Heutzutage ist niemand mehr nobel, heute geht die Welt durch "elegante" Programmierung zugrunde. :ROFLMAO:

Harald
Ein Kunde von uns hat es mal so in einer Ausschreibung spezifiziert, das der Originallaut: "...... Es ist ausreichend Speicherplatz vorhanden. Auf trickreiche Programmierung wird kein Wert gelegt".
;)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wir benutzen so etwas als "Callback" Funktion.
Beispiel:
In einem FB soll aufgrund äußerer Einflüsse eine Aktion ausgeführt werden.
Bevor dies passiert, wird eine Callbackmethode aufgerufen (externe Methode).
In dieser Methode, welche einige Werte übergeben bekommen hat, können nun Rückgabewerte manipuliert werden.
Nachdem die Callbackmethode aufgerufen wurde, wird die Aktion im FB mit den manipulierten
oder den ursprüglichen Werten ausgeführt.
 
Wir benutzen so etwas als "Callback" Funktion.
Beispiel:
In einem FB soll aufgrund äußerer Einflüsse eine Aktion ausgeführt werden.
Bevor dies passiert, wird eine Callbackmethode aufgerufen (externe Methode).
In dieser Methode, welche einige Werte übergeben bekommen hat, können nun Rückgabewerte manipuliert werden.
Nachdem die Callbackmethode aufgerufen wurde, wird die Aktion im FB mit den manipulierten
oder den ursprüglichen Werten ausgeführt.
Interessant, kannst Du beschreiben welche Prozessfunktion sich da konkret dahinter verbirgt, also was macht das "Teil" genau?
 
@SY50
Ja, aber ich habe den TE eher so verstanden, dass er einen String "My_Function" mit dem Inhalt "Funktion_1" übergeben will und im FB dann diese Funktion (Funktion_1) aufrufen und ausführen lassen will.
Übergibt er den String "Funktion_2", dann eben diese Funktion aufrufen und ausführen.

Wäre das mit deinem Konstrukt möglich?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@Ralle
Indirekt. Er kann ja der Interfacemethode dann einfach den String als Input Variable übergeben und darin dann auf den String reagieren.

@borromeus
Ich könnte mir da so einiges vorstellen. Von einfacher Hardware angefangen... Bspw. wenn man auf mehrere externe einflüsse warten möchte oder so....
Wir benutzen es knkret in folgenden Anwendungen:
Wir haben in der Steuerung Verschiedene Parameter angelegt, die für diverse Schnittstellen nach außen "sichtbar" sind.
Diese Parameter können bspw. beschrieben werden. => Wenn ein Schreibbefehl von außen in die Steuerung gelangt, wird eben ein solcher Callback aufgerufen.
Wird dort nichts gemacht, so wird der Parameter einfach geschrieben.
Andernfalls kann in dem Callback eine Kundenspezifische Auflösung / Normierung vorgenommen werden, oder schlicht und ergreifend aufgrund des Maschinenzustands das Schreiben des Parameters verweigert werden.

Ich hoffe das war irgendwie verständlich...

Also im Großen und Ganzen kann man sagen, wir setzen es da ein, wo man Entscheidungen / Veränderungen in einem Abstrakten FB treffen muss, die man innerhalb des FBs garnicht entscheiden kann... dann wird dies eben nach außen gelegt.

"Vergleichbar" mit einem Event das in C# von einer Klasse geschmissen wird.
Gruß
 
@Ralle
Indirekt. Er kann ja der Interfacemethode dann einfach den String als Input Variable übergeben und darin dann auf den String reagieren.

Da ist er aber mit der Case-Variante von PN/DP wesentlich effizienter, nachvollziehbarr und einfacher dran. Mehr wäre es ja bei deiner Methode zum Schluß auch nicht.
 
Da ist er aber mit der Case-Variante von PN/DP wesentlich effizienter, nachvollziehbarr und einfacher dran. Mehr wäre es ja bei deiner Methode zum Schluß auch nicht.

Oh... Weit gefehlt. Würde er eine case in dem FB machen, dann müsste er ja beim erzeugen des FBs schon wissen was passieren soll und wenn der Parameter für die case Struktur ein ausgabeparameter des FB wäre, dann würde diese ja erst abgearbeitet werden, wenn der Code durchlaufen würde... Das wäre eben bei der interfacevariante nicht so, da direkt die Methode aufgerufen wird.
und ja, das wird in manchen Anwendungen manchmal benötigt, auch wenn. Sich nicht jeder das vorstellen kann ;-)
 
Zurück
Oben