Mehrere GOOSE Publisher/Subscriber an einem Netzwerkadapter (ohne Client-Server-Kommunikation)

Dieses Beispiel zeigt die Implementierung von mehreren GOOSE Publishern und Subscribern in einem TwinCAT Projekt. Mehrere Publisher und Subscriber werden zu IED-Gruppen zusammengefasst und so konfiguriert, dass sie für den Austausch der GOOSE-Nachrichten nur einen TwinCAT Real-Time Ethernet Adapter benötigen.

Download TwinCAT XAE Project (*.zip): Sample29.zip

Allgemeine Information zu diesem Beispielprojekt

In einem GOOSE-Netzwerk befinden sich manchmal mehrere baugleiche IED-Geräte (Intelligent Electronic Devices). Diese baugleichen Geräte besitzen dann logischerweise das gleiche IEC 61850 Datenmodell (Logischen-Knoten, Datenobjekte, Datenattribute usw.). Wenn die TwinCAT Applikation mit mehreren baugleichen Geräten GOOSE-Nachrichten austauschen soll, dann ist es von Vorteil im TwinCAT Projekt ein Array von IED-Instanzen für diesen Zweck anzulegen und zu verwenden. Ein IED-Arrayelement entspricht dann einer GOOSE Publisher oder Subscriber-Geräteinstanz im Feld. Die Arrayelemente sollten am besten entweder alle vom Typ: GOOSE Publisher oder alle vom Typ: GOOSE Subscriber sein. Dies vereinfacht die Implementierung der einzelnen GOOSE-Funktionen in der SPS-Applikation. Die SPS-Applikation kann dann z. B. in einer FOR-Schleife alle Publisher aktivieren oder deaktivieren. Andere Konfigurationen (einige IED-Arrayelemente sind Subscriber und andere Publisher) sind auch möglich, werden aber in diesem Beispiel nicht vorgestellt, um das Beispiel einfach halten zu können. Die Geräte im Feld haben logischerweise unterschiedliche IED- und Logical-Device Namen. Alle IED-Arrayelemente haben aber zunächst die gleichen IED- und Logical-Device Namen. Dies stellt für die SPS-Applikation aber kein Problem dar. Die einzelnen IED-Arrayelemente können beim SPS-Programmstart entsprechend umkonfiguriert werden. Jedes IED-Arrayelement bekommt einen neuen, einzigartigen IED- und LD-Namen. Wegen dieser Umbenennung müssen einige Attributwerte, wie z. B. „GoID“ oder „DatSet“ ebenfalls angepasst werden.

Das IEC 61850 Datenmodell für diese baugleichen IED-Geräte ist dann im TwinCAT-Projekt nur einmal vorhanden und muss nicht für jede einzelne IED-Geräteinstanz dupliziert und umbenannt werden. Dies spart Ressourcen und steigert die Performance der Applikation.

Bei Projekten mit nur einem Subscriber oder Publisher wird der Link von dem „TwinCAT Real-Time Ethernet Adapter“ (RT-Ethernet Adapter) zur SPS über die Instanzen des Funktionsbausteins „FB_[IEDName]Gse“ hergestellt. Das zu kommunizierende IED-Datenmodell eines Subscribers oder Publishers wird dem Funktionsbaustein über die Eigenschaft „ipIED“ mitgeteilt. Weitere Informationen dazu finden Sie unter: RT – Ethernet Adapter Konfiguration und in den Beispielen: Client - GOOSE Subscriber und Server - GOOSE Publisher.
Es ist theoretisch möglich bis zu 20 Instanzen des Funktionsbausteins „FB_[IEDName]Gse“ auf diese Weise mit einem „TwinCAT RT-Ethernet Adapter“ zu verlinken. Dadurch können bis zu 20 Publisher oder Subscriber in einem Projekt implementiert werden. Ressourcenschonender ist es aber z. B. nur eine Instanz des Adapterfunktionsbausteins für eine Gruppe von Publishern und eine weitere Instanz für die Gruppe der Subscriber zu verwenden.

Befinden sich alle Geräte in einem gemeinsamen GOOSE-Netzwerk, dann können alle Publisher/Subscriber in der TwinCAT Applikation den gleichen „Real-Time Ethernet Adapter (Multiple Protocol Handler)“ verwenden. Wie ist es im Beispiel realisiert worden? Zuerst wurden mehrere Publisher einer IED-Gruppe zugeordnet. Alle Subscriber wurden einer zweiten IED-Gruppe zugeordnet. Jede IED-Gruppe bekam einen einzigartigen Gruppennamen. Bei den IED-Gruppen handelt es sich um Instanzen des Funktionsbausteins: „FB_GROUP_[GroupName]“. Die zu kommunizierende IED-Gruppe wird dem Adapterfunktionsbaustein „FB_[GroupName]Gse“ über die Eigenschaft „ipGroup“ mitgeteilt. Die zwei Instanzen des Adapterfunktionsbausteins „FB_[GroupName]Gse“ (eine gehört zur Publisher- und die andere zur Subscriber-Gruppe) werden dann mit dem „TwinCAT Real-Time Ethernet Adapter“ wie in der RT – Ethernet Adapter Konfiguration beschrieben, verlinkt.

Generierung des IED-Datenmodells

Das IEC 61850 Datenmodell der IEDs in diesem Beispiel wurde zuerst mit dem TwinCAT Telecontrol Configurator aus der SCL-Datei: Sample29.icd generiert. Die Datei befindet sich ebenfalls in dem TwinCAT-Projekt zip-Archiv. Diese ICD-Datei beschreibt das Datenmodell von 6 unterschiedlichen IED-Geräten. Im Bild unten sind die IEDs im TwinCAT Telecontrol Configurator zu sehen:

Mehrere GOOSE Publisher/Subscriber an einem Netzwerkadapter (ohne Client-Server-Kommunikation) 1:

Jedes IED besitzt einen DataSet und einen GOOSE-Steuerblock. Nach der automatischen SPS-Codegenerierung (z.B. als Client-Projekt) wurde das SPS-Projekt manuell modifiziert und die nicht benötigten Funktionsbausteine für die Client/Server-Kommunikation entfernt.

Definition der IED-Gruppen

Aus den 6 automatisch generierten IED-Datenmodellen sollen in diesem Beispielprojekt insgesamt 3 Publisher und 11 Subscriber implementiert werden. Alle Publisher wurden einer IED-Gruppe mit dem Namen „PubGroupName“ und die Subscriber einer IED-Gruppe mit dem Namen „SubGroupName“ zugeordnet.

Globale Variablenliste TcTelecontrol

In dieser GVL wird jeweils eine Publisher-Gruppe „fbPubGroupName“ und eine Subscriber-Gruppe „fbSubGroupName“ instanziiert. Außerdem befindet sich dort eine Instanz des Publisher-Adapterfunktionsbausteins „fbPubGroupNameGse“ und eine Instanz des Subscriber-Adapterfunktionsbausteins „fbSubGroupNameGse“.

Mit Hilfe der Eigenschaft „ipGroup“ wird dem „fbPubGroupNameGse“ die Publisher IED-Gruppe zugewiesen und dem „fbSubGroupNameGse“ die Subscriber IED-Gruppe zugewiesen.

VAR_GLOBAL
    ipCreator: I_AcsiCodeCreatorClass := GVL_AcsiVars.Creator.SetCodeRev(codeRev:=3).SetGuiVer(major:=3, minor:=1, build:=96, revision:=3);

    fbSubGroupName: FB_GROUP_SubGroupName:=(bLinkResult:=fbSubGroupName.Init());
    fbPubGroupName: FB_GROUP_PubGroupName:=(bLinkResult:=fbPubGroupName.Init());

    fbSubGroupNameGse: FB_SubGroupNameGse := (fbAdapter:=(ipGroup:=fbSubGroupName, settings:=(sMulticastAddr:='01-0C-CD-01-00-01', eDispatchMode:=E_GseDispatchMode.NonPromiscuous)));
    fbPubGroupNameGse: FB_PubGroupNameGse := (fbAdapter:=(ipGroup:=fbPubGroupName, settings:=(sMulticastAddr:='01-0C-CD-01-00-00', eDispatchMode:=E_GseDispatchMode.NonPromiscuous)));
END_VAR

Subscriber Gruppe

Die Subscriber-Gruppe „FB_GROUP_SubGroupName“ konfiguriert 11 Subscriber. „IED5Name“ wird als Array[1..8] in der Subscriber Gruppe instanziiert. Jedes Arrayelement soll ein Subscriber sein, der GOOSE-Nachrichten von einem anderen baugleichen Gerät im Feld empfängt. Die Subscriber-Gruppe kann nur GOOSE-Nachrichten von einem Publisher empfangen, wenn dieser die GOOSE-Nachricht an die Adresse: '01-0C-CD-01-00-01' oder Broadcastadresse oder an die MAC-Adresse des TwinCAT RT-Netzwerkadapters sendet. Die Subscriber-Quelladresse wird für alle Subscriber in einer Subscriber-Gruppe an der Instanz des „FB_[GroupName]Gse“ konfiguriert. Die Tabelle unten listet die wichtigsten Parameter der Subscriber in dieser IED-Gruppe auf.

IED

IED-Name/LD-Name

SrcAddress

APPID

GoID

DatSet

IED1Name

IED1Name/IED1NameLD1

01-0C-CD-01-00-01

16#0010

'IED1NameLD1/LLN0.gocb01'

'IED1NameLD1/LLN0.ds01'

IED2Name

IED2Name/IED2NameLD1

01-0C-CD-01-00-01

16#0020

'IED2NameLD1/LLN0.gocb01'

'IED2NameLD1/LLN0.ds01'

IED3Name

IED3Name/IED3NameLD1

01-0C-CD-01-00-01

16#0030

'IED3NameLD1/LLN0.gocb01'

'IED3NameLD1/LLN0.ds01'

IED5Name[1]

CH1/CH1LD1

01-0C-CD-01-00-01

16#0051

'CH1LD1/LLN0.GoID.gocb01'

'CH1LD1/LLN0.ds01'

IED5Name[2]

CH2/CH2LD1

01-0C-CD-01-00-01

16#0052

'CH2LD1/LLN0.GoID.gocb01'

'CH2LD1/LLN0.ds01'

IED5Name[3]

CH3/CH3LD1

01-0C-CD-01-00-01

16#0053

'CH3LD1/LLN0.GoID.gocb01'

'CH3LD1/LLN0.ds01'

IED5Name[4]

CH4/CH4LD1

01-0C-CD-01-00-01

16#0054

'CH4LD1/LLN0.GoID.gocb01'

'CH4LD1/LLN0.ds01'

IED5Name[5]

CH5/CH5LD1

01-0C-CD-01-00-01

16#0055

'CH5LD1/LLN0.GoID.gocb01'

'CH5LD1/LLN0.ds01'

IED5Name[6]

CH6/CH6LD1

01-0C-CD-01-00-01

16#0056

'CH6LD1/LLN0.GoID.gocb01'

'CH6LD1/LLN0.ds01'

IED5Name[7]

CH7/CH7LD1

01-0C-CD-01-00-01

16#0057

'CH7LD1/LLN0.GoID.gocb01'

'CH7LD1/LLN0.ds01'

IED5Name[8]

CH8/CH8LD1

01-0C-CD-01-00-01

16#0058

'CH8LD1/LLN0.GoID.gocb01'

'CH8LD1/LLN0.ds01'

Der Group-Funktionsbaustein „FB_GROUP_SubGroupName“ ist abgeleitet von dem Funktionsbaustein „FB_AcsiCommonIEDGroupClass“ und dient als Container für mehrere IEDs. Die Methode „AddIEDToContainer“ fügt die einzelnen IEDs der Subscriber-Gruppe hinzu. Bei den IED-Arrayelementen muss auf diese Weise jedes einzelne Arrayelement der Subscriber-Gruppe hinzugefügt werden.

Die Eigenschaft „Tag“ kann verwendet werden, um die einzelnen Arrayelemente von „IED5Name“ mit einer zusätzlichen Information zu versehen. Im Beispiel sind dort die Array-Elementnummern gesetzt. Diese Nummer kann in der „Init“-Methode oder später zur Laufzeit in den Methoden des IEDs abgefragt werden. Jedes Arrayelement kann auch abhängig von der Nummer, ein wenig anders konfiguriert werden.

FUNCTION_BLOCK FB_GROUP_SubGroupName EXTENDS FB_AcsiCommonIEDGroupClass
VAR CONSTANT
    Max_GROUP_IED5Name: DINT:=8; (* Max. number of IED5Name instances *)
END_VAR
VAR_INPUT
    IED1Name: FB_IED_IED1Name:=(bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED1Name));
    IED2Name: FB_IED_IED2Name:=(bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED2Name));
    IED3Name: FB_IED_IED3Name:=(bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED3Name));
    IED5Name: ARRAY[1..Max_GROUP_IED5Name] OF FB_IED_IED5Name:=
    [
        (Tag:=1, sObjectName:='CH1', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[1])),
        (Tag:=2, sObjectName:='CH2', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[2])),
        (Tag:=3, sObjectName:='CH3', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[3])),
        (Tag:=4, sObjectName:='CH4', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[4])),
        (Tag:=5, sObjectName:='CH5', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[5])),
        (Tag:=6, sObjectName:='CH6', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[6])),
        (Tag:=7, sObjectName:='CH7', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[7])),
        (Tag:=8, sObjectName:='CH8', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[8]))
    ];
END_VAR
VAR
    fbError     : FB_ServiceErrorClass;
    ipLastError : I_ServiceErrorClass;
    i           : DINT; (* Temp array index variable *)
END_VAR

Methoden der Subscriber-Gruppe

Der Funktionsbaustein „FB_GROUP_SubGroupName“ implementiert mehrere Methoden. „Enable“ aktiviert alle Subscriber. Disable“ deaktiviert alle Subscriber. „Execute“ muss zyklisch aufgerufen werden. „Init“ initialisiert alle IEDs, LDs, LNs usw. in der Gruppe. Die Methode „Init“ wird vom Initialisierungscode (bereits vor dem ersten SPS-Zyklus) einmalig ausgeführt.

Anpassung des IED-Names und LD-Namens beim IED5Name Array

Der Setter der Eigenschaft „sObjectName“ des Funktionsbausteins „FB_IED_IED5Name“ wurde überschrieben. Beim Setzen eines neuen IED-Namens wird die neue Setter-Implementierung aufgerufen und der neue IED-Name übernommen. Der Logical-Device-Name des Funktionsbausteins „FB_LD_IED5NameLD1“ wird ebenfalls korrigiert da dieser auch den IED-Namen enthält.

PROPERTY FINAL sObjectName : T_AcsiObjectName
VAR
END_VAR
(* Adopt the modified IED name *)
SUPER^.sObjectName:= sObjectName;

(* Adjust the logical-device names too *)
IED6NameLD1.sObjectName:= CONCAT(sObjectName, 'LD1');

Anpassung der APPID, GoID und DatSet beim IED5Name Array

Die Anpassung wird in der Methode „Init“ des logischen Knotens „LLN0“ vorgenommen.

METHOD FINAL Init : BOOL
VAR_INPUT
    IED: REFERENCE TO FB_IED_IED5Name;
    LogicalDevice: REFERENCE TO FB_LD_IED5NameLD1;
END_VAR
VAR
END_VAR
IF NOT __ISVALIDREF(IED) THEN RETURN; END_IF
IF NOT __ISVALIDREF(LogicalDevice) THEN RETURN; END_IF

(* Example: Adjust subscribers GoID string *)
gocb01.GoID.sValue:= CONCAT(CONCAT(LogicalDevice.sObjectName, '/'), CONCAT(CONCAT(THIS^.sObjectName, '.'), gocb01.sObjectName));

(* Example: Adjust subscribers data-set reference string *)
gocb01.DatSet.sValue:= CONCAT(CONCAT(LogicalDevice.sObjectName, '/'), CONCAT(CONCAT(THIS^.sObjectName, '.'), ds01.sObjectName));

(* Example: Adjust subscribers APPID by use of IED's Tag property value *)
gocb01.DstAddress.APPID.nValue:= WORD#16#0050 + TO_WORD(IED.Tag);

(* Forward IED reference to all data-sets *)
Init:= TRUE;
Init:= Init AND ds01.Init(IED:=IED);

Publisher Gruppe

Die Publisher-Gruppe „FB_GROUP_PubGroupName“ konfiguriert 3 Publisher. „IED6Name“ wird als Array[1..2] in der Publisher Gruppe instanziiert. Jedes Arrayelement soll ein Publisher sein, der die GOOSE-Nachrichten an eine andere Zieladresse und mit einer speziellen APPID sendet. Die Tabelle unten listet die wichtigsten Parameter der Publisher in dieser Gruppe auf.

IED

IED-Name/LD-Name

DstAddress

APPID

GoID

DatSet

IED4Name

IED4Name/IED4NameLD1

01-0C-CD-01-00-00

16#0040

'IED4NameLD1/LLN0.gocb01'

'IED4NameLD1/LLN0.ds01'

IED6Name[1]

CNT1/CNT1LD1

01-0C-CD-01-00-01

16#0061

'CNT1LD1/LLN0.gocb01'

'CNT1LD1/LLN0.ds01'

IED6Name[2]

CNT2/CNT2LD1

01-0C-CD-01-00-02

16#0062

'CNT2LD1/LLN0.gocb01'

'CNT2LD1/LLN0.ds01'

Der Group-Funktionsbaustein „FB_GROUP_PubGroupName“ ist abgeleitet von dem Funktionsbaustein „FB_AcsiCommonIEDGroupClass“ und dient als Container für mehrere IEDs. Die Methode „AddIEDToContainer“ fügt die einzelnen IEDs der Publisher-Gruppe hinzu. Bei den IED-Arrayelementen muss auf diese Weise jedes einzelne Arrayelement der Publisher-Gruppe hinzugefügt werden.

Die Eigenschaft „Tag“ kann verwendet werden, um die einzelnen Arrayelemente von „IED6Name“ mit einer zusätzlichen Information zu versehen. Im Beispiel sind dort die Array-Elementnummern gesetzt. Diese Nummer kann in der „Init“-Methode oder später zur Laufzeit in den Methoden des IEDs abgefragt werden. Jedes Arrayelement kann auch, abhängig von der Nummer, ein wenig anders konfiguriert werden.

FUNCTION_BLOCK FB_GROUP_PubGroupName EXTENDS FB_AcsiCommonIEDGroupClass
VAR CONSTANT
    Max_GROUP_IED6Name: DINT:=2; (* Max. number of IED6Name instances *)
END_VAR
VAR_INPUT
    IED4Name: FB_IED_IED4Name:=(bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED4Name));
    IED6Name: ARRAY[1..Max_GROUP_IED6Name] OF FB_IED_IED6Name:=
    [
        (Tag:=1, sObjectName:='CNT1', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED6Name[1])),
        (Tag:=2, sObjectName:='CNT2', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED6Name[2]))
    ];
END_VAR
VAR
    bUpdate_GROUP_IED4Name_IED4NameLD1_LLN0_gocb01: BOOL; (* If TRUE => Update 'IED4Name.IED4NameLD1.LLN0.gocb01' publisher *)
    aUpdate_GROUP_IED6Name_IED6NameLD1_LLN0_gocb01: ARRAY[1..Max_GROUP_IED6Name] OF BOOL; (* If array element n is TRUE => Update 'IED6Name[n].IED6NameLD1.LLN0.gocb01' publisher *)

    fbError          : FB_ServiceErrorClass;
    ipLastError      : I_ServiceErrorClass;
    i                : DINT; (* Temp array index variable *)
    iUpdateElement   : DINT; (* Array index of first array element that needs to be updated *)

    bSimulation      : BOOL := TRUE; (* Enables/disables simulation of cyclic GOOSE data update *)
    tSimulation      : TIME := T#5S; (* Cycle time of simulated GOOSE data update *)
    fbUpdateTimer    : TON;
    iLiveCounter     : LINT; (*Live counter (example) *)
    tT               : T_UtcTime; (* Temp time-stamp value *)
END_VAR

Methoden der Publisher-Gruppe

Der Funktionsbaustein „FB_GROUP_PubGroupName“ implementiert mehrere Methoden. „Start“ startet alle Publisher. „Stop” stoppt alle Publisher. „Execute” muss zyklisch aufgerufen werden. „Update“ führt ein Update der Publisher-Daten. „Init“ Initialisiert alle IEDs, LDs, LNs usw. in der Gruppe. Die Methode „Init“ wird vom Initialisierungscode (bereits vor dem ersten SPS-Zyklus) einmalig ausgeführt. In der Methode „MapSimuPubData“ werden Publisher-Daten simuliert/verändert.

Anpassung des IED-Names und LD-Namens beim IED6Name Array

Der Setter der Eigenschaft „sObjectName“ des Funktionsbausteins „FB_IED_IED6Name“ wurde überschrieben. Beim Setzen eines neuen IED-Namens wird die neue Setter-Implementierung aufgerufen und der neue IED-Name übernommen. Der Logical-Device-Name des Funktionsbausteins „FB_LD_IED6NameLD1“ wird ebenfalls korrigiert da dieser auch den IED-Namen enthält.

PROPERTY FINAL sObjectName : T_AcsiObjectName
VAR
END_VAR
(* Adopt the modified IED name *)
SUPER^.sObjectName:= sObjectName;

(* Adjust the logical-device names too *)
IED6NameLD1.sObjectName:= CONCAT(sObjectName, 'LD1');

Anpassung der APPID, GoID und DatSet beim IED6Name Array

Die Anpassung findet statt in der Methode „Init“ des logischen Knotens „LLN0“.

METHOD FINAL Init : BOOL
VAR_INPUT
    IED: REFERENCE TO FB_IED_IED6Name;
    LogicalDevice: REFERENCE TO FB_LD_IED6NameLD1;
END_VAR
VAR
    mac: ETHERNET_ADDRESS;
END_VAR
IF NOT __ISVALIDREF(IED) THEN RETURN; END_IF
IF NOT __ISVALIDREF(LogicalDevice) THEN RETURN; END_IF

(* Example: Adjust publishers GoID string *)
gocb01.GoID.sValue:= CONCAT(CONCAT(LogicalDevice.sObjectName, '/'), CONCAT(CONCAT(THIS^.sObjectName, '.'), gocb01.sObjectName));

(* Example: Adjust publishers data-set reference string *)
gocb01.DatSet.sValue:= CONCAT(CONCAT(LogicalDevice.sObjectName, '/'), CONCAT(CONCAT(THIS^.sObjectName, '.'), ds01.sObjectName));

(* Example: Adjust publishers multicast address by use of IED's Tag property value *)
mac:= THIS^.gocb01.DstAddress.macAddr;// Get current address
mac.b[5]:= TO_BYTE(IED.Tag);// Modifiy last digit
THIS^.gocb01.DstAddress.macAddr:= mac;// Set new address

(* Example: Adjust publishers APPID by use of IED's Tag property value *)
gocb01.DstAddress.APPID.nValue:= WORD#16#0060 + TO_WORD(IED.Tag);

(* Forward IED reference to all data-sets *)
Init:= TRUE;
Init:= Init AND ds01.Init(IED:=IED);

Im Beispielcode oben wird die letzte Stelle der MAC-Adresse von „DstAddress“ gleich dem Wert der „Tag“-Eigenschaft gesetzt. Falls eine komplett andere MAC-Adresse für die zwei Publisher konfiguriert werden soll dann kann die „Tag“-Eigenschaft auch auf folgende Weise verwendet werden:

IF IED.Tag = 1 THEN
    THIS^.gocb01.DstAddress.sAddr:='01-0C-CD-01-02-56';
ELSIF IED.Tag = 2 THEN
    THIS^.gocb01.DstAddress.sAddr:='01-0C-CD-01-01-78';
END_IF

Netzwerkadapter-Funktionsbaustein FB_SubGroupNameGse

Eine steigende Flanke an der booleschen Variablen „bSubscribe“ (Initialwert ist bereits „TRUE“) aktiviert beim Start der SPS alle Subscriber in der Subscriber-Gruppe. Eine steigende Flanke an der booleschen Variablen „bUnsubscribe“ deaktiviert alle Subscriber in der Gruppe. In der übrigen Zeit muss die „Execute“ Methode der Subscriber-Gruppe und des Netzwerkadapters zyklisch aufgerufen werden. Dies ist notwendig damit die GOOSE-Nachrichten empfangen und an die Subscriber-Instanzen weitergegeben werden.

FUNCTION_BLOCK FB_SubGroupNameGse IMPLEMENTS I_GseLinkStatusEventSink
VAR_INPUT
    fbAdapter   : FB_GseAdapterClass := (ipLinkStatus:=THIS^);
END_VAR
VAR
    eLinkStatus : E_GseLinkStatus;
    bSuccess    : BOOL;
    ipError     : I_ServiceErrorClass;
    bSubscribe  : BOOL := TRUE; (* Rising edge enables subscriber GoCB's *)
    bUnsubscribe: BOOL; (* Rising edge disables subscriber GoCB's *)
END_VAR
bSuccess:= fbAdapter.Execute(ipError=>ipError); (* Execute network adapter *)

IF bSubscribe THEN (* Enable subscriber GoCB's *)
    bSubscribe:= FALSE;
    bSuccess:= fbSubGroupName.Enable(ipAdapter:=fbAdapter, ipError=>ipError);
ELSIF bUnsubscribe THEN (* Disable subscriber GoCB's *)
    bUnsubscribe:= FALSE;
    bSuccess:= fbSubGroupName.Disable(ipError=>ipError);
ELSE (* Execute subscriber GoCB's *)
    bSuccess:= fbSubGroupName.Execute(ipError=>ipError);
END_IF

Netzwerkadapter-Funktionsbaustein FB_PubGroupNameGse

Eine steigende Flanke an der booleschen Variablen „bStart“ (Initialwert ist bereits „TRUE“) aktiviert beim Start der SPS alle Publisher in der Publisher-Gruppe. Eine steigende Flanke an der booleschen Variablen „bStop“ deaktiviert alle Publisher in der Gruppe. Bei einer steigenden Flanke an der booleschen Variablen „bUpdate“ wird die „Update“-Methode der Publisher-Gruppe aufgerufen. Die „bUpdate“-Variable wird aber nur „TRUE“ wenn die „MapSimuPubData“-Methode auch „TRUE“ zurückliefert, weil die Daten von mindestens einen Publisher geändert oder aktualisiert wurden. In der übrigen Zeit muss die „Execute“ Methode der Publisher-Gruppe und des Netzwerkadapters zyklisch aufgerufen werden. Dies ist notwendig damit die Publisher-Instanzen ihre GOOSE-Nachrichten senden können.

FUNCTION_BLOCK FB_PubGroupNameGse IMPLEMENTS I_GseSystemClockEventSink, I_GseLinkStatusEventSink
VAR_INPUT
    fbAdapter   : FB_GseAdapterClass := (ipSystemClock:=THIS^, ipLinkStatus:=THIS^);
END_VAR
VAR
    eLinkStatus : E_GseLinkStatus;
    bSuccess    : BOOL;
    ipError     : I_ServiceErrorClass;
    bStart      : BOOL := TRUE; (* Rising edge starts publishing of GOOSE data *)
    bStop       : BOOL; (* Rising edge stops publishing of GOOSE data *)
    bUpdate     : BOOL; (* Rising edge updates published GOOSE data *)
    bSync       : BOOL := TRUE; (* Rising edge synchronizes the GSE system clock to external time *)
    tSync       : T_UtcTime := String_TO_UtcTime(in:='UT#2019-07-12-12:00:00.000000000|000|3'); (* External (test) time *)
    fbClock     : FB_GseSystemClock;
END_VAR
IF bSync THEN (* Synchronize clock time to external time source *)
    bSync:= FALSE;
    bSuccess:= fbClock.SetToUtcTime(in:=tSync);
ELSE (* Execute clock instance *)
    fbClock.Execute();
END_IF

(* Map/simulate GOCB's data-set member values: 'IED4Name.IED4NameLD1.LLN0.ds01' and/or 'ARRAY OF IED6Name[1..Max_GROUP_IED6Name].IED6NameLD1.LLN0.ds01' *)
bUpdate:= fbPubGroupName.MapSimuPubData(ipClock:=fbClock);

bSuccess:= fbAdapter.Execute(ipError=>ipError); (* Execute network adapter *)

IF bStart THEN (* Start publishing of GOOSE data *)
    bStart:= FALSE;
    bSuccess:= fbPubGroupName.Start(ipAdapter:=fbAdapter, ipError=>ipError);
ELSIF bStop THEN (* Stop publishing of GOOSE data *)
    bStop:= FALSE;
    bSuccess:= fbPubGroupName.Stop(ipError=>ipError);
ELSIF bUpdate THEN (* Update published GOOSE data *)
    bUpdate:= FALSE;
    bSuccess:= fbPubGroupName.Update(ipError=>ipError);
ELSE (* Execute publisher GoCB's *)
    bSuccess:= fbPubGroupName.Execute(ipError=>ipError);
END_IF

Simulation der Publisher-Daten im Beispielprojekt

Wenn die boolesche Variable „bSimulation“ den Wert „TRUE“ hat, dann werden in der Methode „MapSimuPubData“ einige sich verändernde Publisher-Daten simuliert. Z. B. ein Zählerwert „iLiveCounter“ oder einige Quality-Flags.

Zusätzlich wurde dort zu Testzwecken ein sehr einfacher Datenkonzentrator implementiert. Einige Subscriber-Daten der IEDs der Subscriber-Gruppe werden bei Wertänderung in die Publisher-Daten umkopiert. Bei einer Wertänderung wird zusätzlich noch eine boolesche Variable wie z. B. „bUpdate_GROUP_IED4Name_IED4NameLD1_LLN0_gocb01“ auf „TRUE“ gesetzt. Die „Update“-Methode kann über diese Variable erkennen, dass ein Update der Publisher-Daten des Steuerblocks „gocb01“ durchgeführt werden soll.

Test der Subscriber-Gruppe

In dem Zip-Archiv befinden sich noch weitere ICD-Dateien, die zu Test- oder Simulationszwecken der Subscriber-Gruppe verwendet werden können:

Publisher_IED1Name.icd
Publisher_IED2Name.icd
Publisher_IED3Name.icd
Publisher_CH1_To_CH8.icd

Diese Dateien können Sie in einem Dritthersteller Tool zur Simulation der „IED1Name“, „IED2Name“, „IED3Name“ und „CH1“..“CH8“ Publisher verwenden. Außerdem können Sie aus diesen Dateien auch ein TwinCAT Publisher-Projekt erstellen. Die Subscriber in diesem Beispielprojekt können die Daten dieser Publisher empfangen.

Test der Publisher-Gruppe

In dem Zip-Archiv befinden sich noch zwei weitere ICD-Dateien, die beim Test der Publisher-Gruppe in diesem Beispielprojekt verwendet werden können:

Subscriber_CNT1_To_CNT2.icd
Subscriber_IED4Name.icd

Diese Dateien können Sie in einem Dritthersteller Tool zur Simulation der „CNT1“.. „CNT8“ und „IED4Name“ Subscriber verwenden. Die gesendeten Daten der Publisher-Gruppe in diesem Beispielprojekt können von diesen Subscribern empfangen werden.