Client - Dynamic created DataSets (CreateDataSet, DeleteDataSet)

This sample shows the use of the "CreateDataSetReq" and "DeleteDataSet" methods of the client function block.

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

The example described here uses the state machine that is described in the "General Client project structure" chapter. The States 0, 1, 11 and 100 are identical to the state machine described there. Other states were modified for the example or new states were also added.

General information about the dynamic DataSets

The instances of the static DataSets, which are always available during runtime, are either configured by the user in TwinCAT Telecontrol Configurator or imported from an ICD file. The PLC project generation later creates the necessary PLC code for the instantiation of these DataSets. This code also includes the configuration of the DataSet members and the assignment of the DataSet to a logical node in the IEC 61850 data model. The configuration of the static DataSets must not be changed at runtime of the PLC program and the DataSets can also not be deleted.

Sometimes, however, you want to create a DataSet dynamically and use it only for a short time (e.g. as long as the communication connection is up). During this time you may want to monitor some measured values with the help of a report and when the connection is no longer present then remove/delete this DataSet from the data model again.

With the help of the client methods: "CreateDataSetReq" and "DeleteDataSetReq" DataSets can be created, configured and deleted dynamically (at runtime). The dynamically created DataSets can be configured as either "persistent" or "non-persistent" DataSets. The "non-persistent" DataSets are permanently assigned to a client-server connection and only exist as long as the connection is not interrupted. The "non-persistent" DataSets of a client-server connection are not visible for another client-server connection. I.e. a client cannot see or delete the "non-persistent" DataSets of another client. A non-persistent DataSet can only be deleted by the client that created it or is automatically deleted when that client is disconnected.

The "persistent" DataSets, on the other hand, are visible to all clients and can also be deleted by another client at a later time. However, this is not recommended as the creator client may not notice and may try to continue accessing this DataSet. The "persistent" DataSets are not automatically deleted when the connection is terminated and remain in the data model until they are explicitly deleted.

A dynamically created "persistent" or "non-persistent" DataSet, which is used, for example, by a report control block, cannot be deleted. I.e. as long as the control block Attribute: "DatSet" references this DataSet, this DataSet cannot be deleted. If you want to delete such a DataSet, then the attribute "DatSet" must reference another DataSet or the "DatSet" reference must be deleted (e.g. an empty string deletes the "DatSet" reference).

In a client project and after a TwinCAT restart or a reset of the TwinCAT PLC, all "persistent" and "non-persistent" DataSets on the client side are automatically deleted. On the server side, however, the "persistent" DataSets may remain because they could not be explicitly deleted.

The static DataSets are basically also "persistent" DataSets. They differ from the dynamically generated DataSets in that they cannot be deleted.

For each DataSet that you want to create dynamically at a later time (at runtime), you need an instance of the function block: "FB_AcsiCommonDataSetClass". These instances are manually added to the PLC project beforehand during PLC programming. However, they are not yet linked to the client data model. The PLC application can then later use these instances at runtime to create the dynamic DataSets on the server side. Only then are these instances also linked to the data model on the client side. The DataSet members can also be preconfigured. The method "CreateDataSetReq" needs as first parameter: "ipDataSet" an interface pointer to such a preconfigured DataSet object. The second parameter: "ipLogicalNode" determines whether a "persistent" or "non-persistent" DataSet should be created. Only the "persistent" DataSets are linked to a logical node. In this case, this parameter must be valid. For a "non-persistent" DataSet this parameter is zero. On success, a dynamic DataSet is created on the server side and the preconfigured DataSet instance is linked to the data model on the client side. The method "DeleteDataSetReq" needs as first parameter: "ipDataSet" an interface pointer to a DataSet object (which was already added to the data model before). If successful, the DataSet is then deleted from the data model on the server side and the link between the DataSet and the data model is also deleted on the client side.

Sample project

In the zip archive there is an ICD configuration file. This file can be used, for example, to simulate a server using third-party software or to create a new or modified TwinCAT project with TwinCAT Telecontrol Configurator.

In the FB_IEDClient function block and State 10, several IF instructions are listed that activate commands (method calls) of the client function block. Each command in the IF statement is activated by a rising edge at one of the Boolean variables. The Boolean variables are defined in the declaration part of the FB_IEDClient function block. For test purposes, the user can set the values of the Boolean variables to "TRUE" in the online view and in this way activate the command execution. After that, the system switches to state 11, where the method "ipResult.Execute()" is called in further PLC cycles until the command processing has been completed. This is the case if "ipResult.IsBusy()" returns FALSE.

Following the successful execution of a command, the state machine is set to State 0. If several of the Boolean variables are set to "TRUE", then the topmost IF statement is processed first with the respective command. Some of the Boolean variables are listed in the tables below. In addition, they contain the method names and a description of the function.

The sample uses two preconfigured instances of the "FB_AcsiCommonDataSetClass" function block. The instance: "fbNonPersistent" to create a "non-persistent" DataSet and the instance: "fbPersistent" to create a "persistent" DataSet. The names of the DataSets have already been preconfigured to "NonPersistentDataSet" and "PersistentDataSet" in the declaration part using the "sObjectName" property.


fbNonPersistent: FB_AcsiCommonDataSetClass:=(sObjectName:='NonPersistentDataSet');
fbPersistent: FB_AcsiCommonDataSetClass:=(sObjectName:='PersistentDataSet');

In the IF statement, just before enabling the "CreateDataSetReq" method and if not already done, the DataSet members are added to the DataSets. However, this can also be outsourced to a separate routine which is called, for example, once at program start.


ELSIF bCreateDataSet_NonPersistent THEN
    bCreateDataSet_NonPersistent:= FALSE;
    IF fbNonPersistent.nMembers = 0 THEN
        bSuccess:= fbNonPersistent.AddMember(ipData:=fbIED.IEDLD1.XCBR1.Pos.stVal, eFc:=E_AcsiFc.ST_);
        bSuccess:= fbNonPersistent.AddMember(ipData:=fbIED.IEDLD1.LLN0.Mod_.stVal, eFc:=E_AcsiFc.ST_);
    END_IF
    bSuccess:= fbConnection.CreateDataSetReq(ipDataSet:=fbNonPersistent, ipLogicalNode:=0, hUser:=0, ipSink:=0, nInvokeID=>nInvokeID, ipResult=>ipResult);
    state:= SEL(bSuccess, 100, 11);
ELSIF bCreateDataSet_Persistent THEN
    bCreateDataSet_Persistent:= FALSE;
    IF fbPersistent.nMembers = 0 THEN
        bSuccess:= fbPersistent.AddMember(ipData:=fbIED.IEDLD1.MMXU1.TotW.mag.f, eFc:=E_AcsiFc.MX);
        bSuccess:= fbPersistent.AddMember(ipData:=fbIED.IEDLD1.LLN0.Beh.stVal, eFc:=E_AcsiFc.ST_);
    END_IF
    bSuccess:= fbConnection.CreateDataSetReq(ipDataSet:=fbPersistent, ipLogicalNode:=fbIED.IEDLD1.LLN0, hUser:=0, ipSink:=0, nInvokeID=>nInvokeID, ipResult=>ipResult);
    state:= SEL(bSuccess, 100, 11);

Variable name

Method name

Description

bCreateDataSet_NonPersistent

CreateDataSetReq

A rising edge at this variable enables the command to create a dynamic "non-persistent" DataSet with the name: "NonPersistentDataSet" (object reference: '@NonPersistent').

bCreateDataSet_Persistent

CreateDataSetReq

A rising edge at this variable enables the command to create a dynamic "persistent" DataSet with the name: "PersistentDataSet" (object reference: 'IEDLD1/LLN0.PersistentDataSet'). On success, the new DataSet is associated with the logical node "LLN0".

bDeleteDataSet_NonPersistent

DeleteDataSetReq

A rising edge at this variable enables the command to delete a dynamic "non-persistent" DataSet with the name: "NonPersistentDataSet".

bDeleteDataSet_Persistent

DeleteDataSetReq

A rising edge at this variable enables the command to delete a dynamic "persistent" DataSet with the name: "PersistentDataSet".

bEnable_urcb101_NonPersistent

urcb101.Client.EnableReq

A rising edge at this variable enables the report control block instance for unbuffered reports: "urcb101". The reports should transfer the DataSet members of the previously dynamically created "non-persistent" DataSet: "fbNonPersistent". Internally, the attribute "DatSet" of the report control block is set accordingly (the string references the dynamically created DataSet).

bEnable_urcb101_Persistent

urcb101.Client.EnableReq

A rising edge at this variable enables the report control block instance for unbuffered reports "urcb101". The reports should transfer the DataSet members of the previously dynamically created "persistent" DataSet: "fbPersistent". Internally, the attribute "DatSet" of the report control block is set accordingly (the string references the dynamically created DataSet).

bEnable_urcb101_DS1

urcb101.Client.EnableReq

A rising edge at this variable enables the report control block instance for unbuffered reports "urcb101". The reports should transfer the DataSet members of the static DataSet: "DS1". Internally, the attribute "DatSet" of the report control block is set accordingly (the string references the static DataSet).

bDisable_urcb101

urcb101.Client.DisableReq

A rising edge at this variable disables the report control block instance for unbuffered reports "urcb101". The transmission of the reports is then stopped.

bSetDataValues_urcb101_DatSet

SetDataValuesReq

As long as "DatSet" references a dynamically created DataSet, this DataSet cannot be deleted again. To be able to delete a dynamically created DataSet, it must not be used by any control block and must not be referenced by the "DatSet". A rising edge at this variable describes the attribute value: "IEDLD1/LLN0.RP.urcb101.DatSet" with an empty string.

bGetDataSetDirectory_NonPersistent

GetDataSetDirectoryReq

A rising edge at this variable enables the command to read the DataSet member configuration of the previously dynamically created "non-persistent" DataSet: "fbNonPersistent". The DataSet members are enumerated.

bGetDataSetDirectory_Persistent

GetDataSetDirectoryReq

A rising edge at this variable enables the command to read the DataSet member configuration of the previously dynamically created "persistent" DataSet: "fbPersistent". The DataSet members are enumerated.

bGetDataSetDirectory_DS1

GetDataSetDirectoryReq

A rising edge at this variable enables the command to read the DataSet member configuration of the static DataSet: "DS1". The DataSet members are enumerated.

Small test

After the program start, when the connection to the server is established, first write the value TRUE into the Boolean variable: "bCreateDataSet_NonPersistent". On success, a new dynamic "non-persistent" DataSet is created. This DataSet can then be used by the report control block instance for unbuffered reports. If you write the value TRUE in the variable "bEnable_urcb101_NonPersistent" then you enable the sending of the reports with the "non-persistent" DataSet member data. Stop sending the reports by writing the value TRUE in the variable: "bDisable_urcb101". However, the dynamic "non-persistent" DataSet is still used by the attribute: "DatSet" of the report control block instance "urcb101" and cannot be deleted yet. Write the value TRUE into the Boolean variable "bSetDataValues_urcb101_DatSet". Now the dynamic "non-persistent" DataSet can be deleted. Set the value TRUE in the variable: "bDeleteDataSet_NonPersistent".