| 

.NET C# Java Javascript Exception

5
Je nach Aufgabenstellung kann es erforderlich sein, dass Funktionsblöcke Parameter benötigen, die nur einmalig für Initialisierungsaufgaben verwendet werden. Ein möglicher Weg, diese elegant zu übergeben, bietet die Methode FB_init(). Vor TwinCAT 3 wurden Initialisierungs-Parameter sehr häufig über Eingangsvariablen übergeben. Dieses hatte den Nachteil, dass in den graphischen Darstellungsarten die Funktionsblöcke unnötig groß wurden. Auch war […]

Je nach Aufgabenstellung kann es erforderlich sein, dass Funktionsblöcke Parameter benötigen, die nur einmalig für Initialisierungsaufgaben verwendet werden. Ein möglicher Weg, diese elegant zu übergeben, bietet die Methode FB_init().

Vor TwinCAT 3 wurden Initialisierungs-Parameter sehr häufig über Eingangsvariablen übergeben.

(* TwinCAT 2 *)
FUNCTION_BLOCK FB_SerialCommunication
VAR_INPUT
 nDatabits : BYTE(7..8);
 eParity : E_Parity;
 nStopbits : BYTE(1..2);	
END_VAR

Dieses hatte den Nachteil, dass in den graphischen Darstellungsarten die Funktionsblöcke unnötig groß wurden. Auch war es nicht möglich, ein Ändern der Parameter zur Laufzeit zu verhindern.

Sehr hilfreich ist hierbei die Methode FB_init(). Diese Methode wird vor dem Start der SPS-Task einmal implizit ausgeführt und kann dazu dienen, Initialisierungsaufgaben durchzuführen.

Der Dialog zum Hinzufügen von Methoden bietet hierzu eine fertige Vorlage an.

In der Methode sind zwei Eingangsvariablen enthalten, welche Auskunft darüber geben, unter welchen Bedingungen die Methode ausgeführt wird. Die Variablen dürfen weder gelöscht noch verändert werden. Allerdings kann FB_init() um weitere Eingangsvariablen ergänzt werden.

Beispiel

Als Beispiel soll ein Baustein zur Kommunikation über eine serielle Schnittstelle dienen (FB_SerialCommunication). Dieser Baustein soll ebenfalls die serielle Schnittstelle mit den notwendigen Parametern initialisieren. Aus diesem Grund werden zu FB_init() drei Variablen hinzugefügt:

METHOD FB_init : BOOL
VAR_INPUT
 bInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)
 bInCopyCode : BOOL; // if TRUE, the instance afterwards gets moved into the copy code (online change)
 nDatabits : BYTE(7..8);
 eParity : E_Parity;
 nStopbits : BYTE(1..2);		
END_VAR

Das Initialisieren der seriellen Schnittstelle erfolgt nicht direkt in FB_init(). Deshalb müssen die Parameter in Variablen kopiert werden, die sich im Funktionsblock befinden.

FUNCTION_BLOCK PUBLIC FB_SerialCommunication
VAR
 nInternalDatabits : BYTE(7..8);
 eInternalParity : E_Parity;
 nInternalStopbits : BYTE(1..2);
END_VAR

In diesen drei Variablen werden die Werte aus FB_init() während der Initialisierung kopiert.

METHOD FB_init : BOOL
VAR_INPUT
 bInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)
 bInCopyCode : BOOL; // if TRUE, the instance afterwards gets moved into the copy code (online change)
 nDatabits : BYTE(7..8);
 eParity : E_Parity;
 nStopbits : BYTE(1..2);
END_VAR

THIS^.nInternalDatabits := nDatabits;
THIS^.eInternalParity := eParity;
THIS^.nInternalStopbits := nStopbits;

Wird eine Instanz von FB_SerialCommunication angelegt, so sind diese drei zusätzlichen Parameter mit anzugeben. Die Werte werden direkt nach dem Namen des Funktionsblocks in runden Klammern angegeben:

fbSerialCommunication : FB_SerialCommunication(nDatabits := 8,
 eParity := E_Parity.None,
 nStopbits := 1);

Noch bevor die SPS-Task startet, wird die Methode FB_init() implizit aufgerufen, so dass die internen Variablen des Funktionsblocks die gewünschten Werte erhalten.

 

Mit dem Start der SPS-Task und dem Aufruf der Instanz von FB_SerialCommunication kann jetzt die Initialisierung der seriellen Schnittstelle erfolgen.

Es ist immer notwendig alle Parameter anzugeben. Eine Deklaration ohne eine vollständige Auflistung der Parameter ist nicht erlaubt und erzeugt beim Compilieren eine Fehlermeldung:

 

Arrays

Wird FB_init() bei Arrays verwendet, so sind für jedes Element die vollständigen Parameter anzugeben (mit eckige Klammern):

aSerialCommunication : ARRAY[1..2] OF FB_SerialCommunication[
 (nDatabits := 8, eParity := E_Parity.None, nStopbits := 1),
 (nDatabits := 7, eParity := E_Parity.Even, nStopbits := 1)];

Sollen alle Elemente die gleichen Initialisierungswerte erhalten, so ist es ausreichend, wenn die Parameter einmal vorhanden sind (ohne eckige Klammern):

aSerialCommunication : ARRAY[1..2] OF FB_SerialCommunication(nDatabits := 8,
 eParity := E_Parity.None,
 nStopbits := 1);

Mehrdimensionale Arrays sind ebenfalls möglich. Auch hier müssen alle Initialisierungswerte angegeben werden:

aSerialCommunication : ARRAY[1..2, 5..6] OF FB_SerialCommunication[
 (nDatabits := 8, eParity := E_Parity.None, nStopbits := 1),
 (nDatabits := 7, eParity := E_Parity.Even, nStopbits := 1),
 (nDatabits := 8, eParity := E_Parity.Odd, nStopbits := 2),
 (nDatabits := 7, eParity := E_Parity.Even, nStopbits := 2)];

Vererbung

Kommt Vererbung zum Einsatz, so wird die Methode FB_init() immer mit vererbt. Als Beispiel soll hier FB_SerialCommunicationRS232 dienen:

FUNCTION_BLOCK PUBLIC FB_SerialCommunicationRS232 EXTENDS FB_SerialCommunication

Wird eine Instanz von FB_SerialCommunicationRS232 angelegt, so müssen auch die Parameter von FB_init() angegeben werden, welche von FB_SerialCommunication geerbt wurden:

fbSerialCommunicationRS232 : FB_SerialCommunicationRS232(nDatabits := 8,
 eParity := E_Parity.Odd,
 nStopbits := 1);

Es besteht außerdem die Möglichkeit FB_init() zu überschreiben. In diesem Fall müssen die gleichen Eingangsvariablen in der gleichen Reihenfolge und vom gleichen Datentyp vorhanden sein, wie bei dem Basis-FB (FB_SerialCommunication). Es können aber weitere Eingangsvariablen hinzugefügt werden, so dass der abgeleitete Funktionsblock (FB_SerialCommunicationRS232) zusätzliche Parameter erhält:

METHOD FB_init : BOOL
VAR_INPUT
 bInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)
 bInCopyCode : BOOL; // if TRUE, the instance afterwards gets moved into the copy code (online change)
 nDatabits : BYTE(7..8);
 eParity : E_Parity;
 nStopbits : BYTE(1..2);
 nBoudrate : UDINT;	
END_VAR

THIS^.nInternalBoudrate := nBoudrate;

Wird eine Instanz von FB_SerialCommunicationRS232 angelegt, so sind alle Parameter, auch die von FB_SerialCommunication, anzugeben:

fbSerialCommunicationRS232 : FB_SerialCommunicationRS232(nDatabits := 8,
 eParity := E_Parity.Odd,
 nStopbits := 1,
 nBoudRate := 19200);

In der Methode FB_init() von FB_SerialCommunicationRS232 ist nur das Kopieren des neuen Parameters (nBoudrate) notwendig. Dadurch, dass FB_SerialCommunicationRS232 von FB_SerialCommunication erbt, wird vor dem Start der SPS-Task auch FB_init() von FB_SerialCommunication implizit ausgeführt. Es werden immer beide FB_init() Methoden implizit aufgerufen, sowohl die von FB_SerialCommunication, als auch die von FB_SerialCommunicationRS232. Der Aufruf von FB_init() erfolgt bei Vererbung immer von ‚unten‘ nach ‚oben‘. Also erst von FB_SerialCommunication und anschließend von FB_SerialCommunicationRS232.

Parameter weiterleiten

Als Beispiel soll der Funktionsblock (FB_SerialCommunicationCluster) dienen, in dem mehrere Instanzen von FB_SerialCommunication deklariert werden:

FUNCTION_BLOCK PUBLIC FB_SerialCommunicationCluster
VAR
 fbSerialCommunication01 : FB_SerialCommunication(nDatabits := nInternalDatabits, eParity := eInternalParity, nStopbits := nInternalStopbits);
 fbSerialCommunication02 : FB_SerialCommunication(nDatabits := nInternalDatabits, eParity := eInternalParity, nStopbits := nInternalStopbits);
 nInternalDatabits : BYTE(7..8);
 eInternalParity : E_Parity;
 nInternalStopbits : BYTE(1..2);	
END_VAR

Damit die Parameter der Instanzen von außen einstellbar sind, erhält auch FB_SerialCommunicationCluster die Methode FB_init() mit den notwendigen Eingangsvariablen.

METHOD FB_init : BOOL
VAR_INPUT
 bInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)
 bInCopyCode : BOOL; // if TRUE, the instance afterwards gets moved into the copy code (online change)
 nDatabits : BYTE(7..8);
 eParity : E_Parity;
 nStopbits : BYTE(1..2);
END_VAR

THIS^.nInternalDatabits := nDatabits;
THIS^.eInternalParity := eParity;
THIS^.nInternalStopbits := nStopbits;

Hierbei gibt es allerdings einiges zu beachten. Die Aufrufreihenfolge von FB_init() ist in diesem Fall nicht eindeutig definiert. In meiner Testumgebung erfolgen die Aufrufe von ‚innen‘ nach ‚außen‘. Erst wird fbSerialCommunication01.FB_init() und fbSerialCommunication02.FB_init() aufgerufen, danach erst fbSerialCommunicationCluster.FB_init(). Es ist nicht möglich, die Parameter von ‚außen‘ nach ‚innen‘ durchzureichen. Die Parameter stehen in den beiden inneren Instanzen von FB_SerialCommunication somit nicht zur Verfügung.

Die Reihenfolge der Aufrufe ändert sich, sobald FB_SerialCommunication und FB_SerialCommunicationRS232 vom gleichen Basis-FB abgeleitet werden. In diesem Fall wird FB_init() von ‚außen‘ nach ‚innen‘ aufgerufen. Dieser Ansatz ist aus zwei Gründen nicht immer umzusetzen:

  1. Liegt FB_SerialCommunication in einer Bibliothek, so kann die Vererbung nicht ohne weiteres geändert werden. Die Aufrufreihenfolge von FB_init() ist bei Verschachtelung nicht weiter definiert. Es ist also nicht auszuschließen, dass sich dieses in zukünftigen Versionen ändern kann.

Eine Variante das Problem zu lösen, ist der explizite Aufruf von FB_SerialCommunication.FB_init() aus FB_SerialCommunicationCluster.FB_init().

fbSerialCommunication01.FB_init(bInitRetains := bInitRetains, bInCopyCode := bInCopyCode, nDatabits := 7, eParity := E_Parity.Even, nStopbits := nStopbits);
fbSerialCommunication02.FB_init(bInitRetains := bInitRetains, bInCopyCode := bInCopyCode, nDatabits := 8, eParity := E_Parity.Even, nStopbits := nStopbits);

Alle Parameter, auch bInitRetains und bInCopyCode, werden direkt weitergegeben.

Achtung: Der Aufruf von FB_init() hat immer zur Folge das alle lokalen Variablen der Instanz initialisiert werden. Das muss beachtet werden, sobald FB_init() aus der SPS-Task explizit aufgerufen wird, statt implizit vor der SPS-Task.

Zugriff über Eigenschaften

Durch die Übergabe der Parameter per FB_init(), können diese zur Laufzeit weder von Außen gelesen noch verändert werden. Die einzige Ausnahme wäre der explizite Aufruf von FB_init() aus der SPS-Task. Dieses sollte aber grundsätzlich vermieden werden, da dadurch alle lokalen Variablen der Instanz werden neu initialisiert.

Soll der Zugriff aber dennoch möglich sein, so können für die Parameter entsprechende Eigenschaften angelegt werden:

Die Setter und Getter der jeweiligen Eigenschaften greifen auf die entsprechenden lokalen Variablen in dem Funktionsblock zu (nInternalDatabits, eInternalParity und nInternalStopbits). Somit lassen sich die Parameter bei der Deklaration, als auch zur Laufzeit vorgeben.

Durch das Entfernen der Setter kann ein Ändern der Parameter zur Laufzeit verhindert werden. Sind die Setter vorhanden kann allerdings auch auf FB_init() verzichtet werden. Eigenschaften können ebenfalls direkt bei der Deklaration einer Instanz initialisiert werden.

fbSerialCommunication : FB_SerialCommunication := (Databits := 8,
 Parity := E_Parity.Odd,
 Stopbits := 1);

Es können die Parameter von FB_init() und die Eigenschaften auch gleichzeitig angegeben werden:

fbSerialCommunication : FB_SerialCommunication(nDatabits := 8, eParity := E_Parity.Odd, nStopbits := 1) :=
 (Databits := 8, Parity := E_Parity.Odd, Stopbits := 1);

Vorrang haben in diesem Fall die Initialisierungswerte der Eigenschaften. Die Übergabe per Eigenschaft und FB_init() hat hier den Nachteil, das die Deklaration des Funktionsblocks unnötig lang wird. Beides zu implementieren erscheint mir auch nicht notwendig. Sind alle Parameter auch über Eigenschaften schreibbar, so kann auf die Initialisierung per FB_init() verzichtet werden. Als Fazit gilt: Dürfen Parameter zur Laufzeit nicht änderbar sein, so ist der Einsatz von FB_init() in Betracht zu ziehen. Soll der Schreibzugriff möglich sein, so bieten sich Eigenschaften an.

Beispiel 1 (TwinCAT 3.1.4022) auf GitHub

iec-61131-3 oop codesys-v3 twincat vererbung sps methoden schnittstellen
Weitere News:
Schreibe einen Kommentar:
Themen:
schnittstellen methoden sps vererbung twincat codesys-v3 oop iec-61131-3
Entweder einloggen... ...oder ohne Wartezeit registrieren
Benutzername
Passwort
Passwort wiederholen
E-Mail