Accessing, creating and handling PLC POUs
This chapter explains in-depth how to access PLC objects, for example POUs, Methods, Transitions, Properties, and how to access their corresponding implementation and declaration areas to handle PLC code. It also covers how to import/export PLC objects in PLCopen XML. The following list shows all chapters in this article:
- General information about PLC objects
- Accessing the implementation / declaration area of a POU
- Accessing Sub-POUs (Actions, Properties, ...)
- Creating PLC objects
- PLC access modifier
- Importing / Exporting PLCopen XML
- Import existing POUs (templates)
General information about PLC objects
Although every tree item is considered to be of type ITcSmTreeItem, some items need to be casted to a more special interface to gain access to all of their methods and properties, for example POUs which need to be casted to the interface ITcPlcPou to get access to their unique methods and properties.
Code snippet (C#):
ITcSmTreeItem plcPousItem = systemManager.LookupTreeItem("TIPC^PlcGenerated^PlcGenerated Project^POUs");
ITcSmTreeItem newFb = plcPousItem.CreateChild("FB_TEST", 604, "", IECLANGUAGETYPES.IECLANGUAGE_ST);
ITcPlcPou fbPou = (ITcPlcPou)newFb;
Code snippet (Powershell):
$plcPousItem = $systemManager.LookupTreeItem("TIPC^PlcGenerated^PlcGenerated Project^POUs")
$newFb = $plcPousItem.CreateChild("FB_TEST", 604, "", 6)
In this example, the POU MAIN is being created in a PLC-Project. The object programPou references this POU and can now be used to access specific methods and properties of the POU by using the corresponding method/property of the ITcPlcPou interface.
Accessing the implementation / declaration area of a POU
You can also get read/write access to either the implementation or declaration area of a POU by using the interfaces ITcPlcImplementation or ITcPlcDeclaration, as the following example shows.
Code snippet (C#):
ITcPlcDeclaration fbPouDecl = (ITcPlcDeclaration) fbPou;
ITcPlcImplementation fbPouImpl = (ITcPlcImplementation) fbPou;
string decl = fbPouDecl.DeclarationText;
string impl = fbPouImpl.ImplementationText;
string implXml = fbPouImpl.ImplementationXml;
Code snippet (Powershell):
$decl = $newFb.DeclarationText
$impl = $newFb.ImplementationText
$implXml = $newFb.ImplementationXml
When comparing both interfaces, you will notice that the accessible properties in both interfaces differ from each other. For example the ITcPlcImplementation interface offers a property "Language" whereas ITcPlcDeclaration doesn't. This is because, according to IEC, the declaration area is not based on a real programming language (e.g. ST), therefore this property does not make sense when used on a declaration area.
Accessing Sub-POUs (Actions, Properties, ...)
POUs may have more sub-items like Methods, Transitions, Actions and Properties. It is important to understand that not every sub-item of a POU also has both an implementation and a declaration area. Actions and Transitions, for example, only have an implementation area. Therefore, casting to one of the interfaces mentioned above is only valid if the corresponding sub-object has this area. The following table gives an overview about which areas are available in the different types of POUs.
Tree Item |
Type |
Declaration Area |
Implementation Area |
---|---|---|---|
Program |
POU |
Yes |
Yes |
Function |
POU |
Yes |
Yes |
Function Block |
POU |
Yes |
Yes |
Action |
POU |
No |
Yes |
Method |
POU |
Yes |
Yes |
Property (Get/Set) |
POU |
Yes |
Yes |
Transition |
POU |
No |
Yes |
Enum |
DUT |
Yes |
No |
Struct |
DUT |
Yes |
No |
Union |
DUT |
Yes |
No |
Alias |
DUT |
Yes |
No |
Interface |
Interface |
Yes |
No |
Property (Get/Set) |
Interface |
Yes |
Yes |
Global variables |
GVL |
Yes |
No |
Creating PLC-Objects
The creation of PLC-Objects is simple and can be achieved via the CreateChild() method of the ITcSmTreeItem interface. Depending on the type of POU, the parameters of this method need to be interpreted differently. The following table gives the necessary information to be able to create different POU types. Please note that the vInfo parameter may be a string array, if more than one parameter is needed. Each array position and whether it is optional or not, is marked as [...] below.
Tree Item | Type | Parameter "nSubType" | Parameter "vInfo" |
---|---|---|---|
Program | POU | 602 | [0, optional]: IEC programming language, as definied by IECLANGUAGETYPES. By default, ST (Structured Text) is used. |
Function | POU | 603 | [0]: IEC programming language, as definied by IECLANGUAGETYPES. |
Function Block | POU | 604 | [0, optional]: IEC programming language, as definied by IECLANGUAGETYPES. By default, ST (Structured Text) is used. |
Action | POU | 608 | [0, optional]: IEC programming language, as definied by IECLANGUAGETYPES. By default, ST (Structured Text) is used. |
Method | POU | 609 | [0, optional]: IEC programming language, as definied by IECLANGUAGETYPES. By default, ST (Structured Text) is used. |
Property | POU | 611 | [0]: IEC programming language, as definied by IECLANGUAGETYPES |
Property Get | POU | 613 | [0, optional]: IEC programming language, as definied by IECLANGUAGETYPES. By default, ST (Structured Text) is used. |
Property Set | POU | 614 | [0, optional]: IEC programming language, as definied by IECLANGUAGETYPES. By default, ST (Structured Text) is used. |
Transition | POU | 616 | [0, optional]: IEC programming language, as definied by IECLANGUAGETYPES. By default, ST (Structured Text) is used. |
Enum | DUT | 605 | [0, optional]: May contain declaration text |
Struct | DUT | 606 | [0, optional]: May contain declaration text |
Union | DUT | 607 | [0, optional]: May contain declaration text |
Alias | DUT | 623 | [0, optional]: May contain declaration text |
Interface | Interface | 618 | [0, optional]: Extending type |
Property | Interface | 612 | [0]: Return data type |
Property Get | Interface | 654 | No vInfo parameter is needed and "null" can be used. |
Property Set | Interface | 655 | No vInfo parameter is needed and "null" can be used. |
Method | Interface | 610 | [0]: Return data type |
Global variables | GVL | 615 | [0, optional]: May contain declaration text |
PLC Folder | Folder | 601 | No vInfo parameter is needed and "null" can be used. |
Parameter List | PL | 629 | [0, optional]: May contain declaration text |
UML Class Diagram | POU | 631 | --- |
Example: The following code snippet shows how to use the vInfo parameter to create a Functionblock "FB_Test" with the keywords extends and/or implements, depending on the value of the bool variables bExtends and bImplements. The extended library is ADSRDSTATE and the implemented interface ITcADI.
Code snippet (C#):
string[] vInfo;
bool bExtends = true;
bool bImplements = true;
if (bExtends && bImplements)
{
vInfo= new string[5];
}
else
{
if (bExtends || bImplements)
{
vInfo= new string[3];
}
else
{
vInfo= new string[1];
}
}
vInfo[0] = language.AsString();
if (bExtends && bImplements)
{
vInfo[1] = "Extends";
vInfo[2] = "ADSRDSTATE";
vInfo[3] = "Implements";
vInfo[4] = "ITcADI";
}
else
{
if (bExtends)
{
vInfo[1] = "Extends";
vInfo[2] = "ADSRDSTATE";
}
else
{
if (bImplements)
{
vInfo[1] = "Implements";
vInfo[2] = "ITcADI";
}
}
}
ITcSmTreeItem newPOU = parent.CreateChild("FB_Test", 604,
"", fbVInfo);
Please note If the paramerter vInfo includes only one value (marked as [0] in the table above), you shouldn't create an array of size 1, instead just use a regular variable. Example: When using nSubType 618 (Interface), you should use vInfo as follows. |
Code snippet (C#):
ITcSmTreeItem interface1 = pou.CreateChild("NewInterface1", 618, "", null); // no expansion type
ITcSmTreeItem interface2 = pou.CreateChild("NewInterface2", 618, "", "ITcUnknown"); // expands ITcUnknown interface
PLC access modifier
The following access modifiers are valid and may be used as a vInfo parameter, as shown in the table above: PUBLIC, PRIVATE, PROTECTED, INTERNAL.
Importing / Exporting PLCopen XML
You can also import/export PLC elements in PLCopen XML, which can be achieved via the ITcPlcIECProject interface. Methods and properties of this interface can only be executed directly on a PLC project node, for example:
Code snippet (C#):
ITcSmTreeItem plcProject =
systemManager.LookupTreeItem("TIPC^PlcGenerated^PlcGenerated
Project");
ITcPlcIECProject importExport = (ITcPlcIECProject)
plcProject;
importexport.PlcOpenExport(plcOpenExportFile,
"MyPous.POUProgram;MyPous.POUFunctionBlock");
importExport.PlcOpenImport(plcOpenExportFile,
(int)PLCIMPORTOPTIONS.PLCIMPORTOPTIONS_NONE);
Code snippet (Powershell):
$plcProject = $systemManager.LookupTreeItem("TIPC^PlcGenerated^PlcGenerated
Project")
$plcProject.PlcOpenExport(plcOpenExportFile, "MyPous.POUProgram;MyPous.POUFunctionBlock")
$plcProject.PlcOpenImport(plcOpenExportFile,0)
This code snippet assumes that there is already a PLC project added to the TwinCAT configuration, which will be referenced via the object plcProject. This reference is casted to the object importexport of type ITcPlcIECProject, which is then used to export the POUs POUProgram and POUFunctionBlock (both reside in the PLC folder "MyPOUs") into an XML file and then import them again.
The available options for import are: None (0), Rename (1), Replace (2), Skip (3)
Import existing POUs (templates)
PLC templates are available in two units: You can either use the complete PLC project as a whole or each POU individually as a template. The later is covered in this chapter. One of the reasons a developer may choose individual POUs as templates, is that it is easier to build a pool of existing functionalities and encapsulate them in separate POUs, e.g. different function blocks covering different sorting algorithms. Upon project creation, the developer simply chooses which functionality he needs in his TwinCAT project and accesses the template tool to retrieve the corresponding POU and import it to his PLC project.
Code snippet (C#):
ITcSmTreeItem plcProject = systemManager.LookupTreeItem("
TIPC^PlcGenerated^PlcGenerated Project");
plcProject.CreateChild("NameOfImportedPOU", 58, null, pathToPouFile);
plcProject.CreateChild(null, 58, null, stringArrayWithPathsToPouFiles);
Code snippet (Powershell):
$plcProject = $systemManager.LookupTreeItem(“TIPC^PlcGenerated^PlcGenerated Project")
$plcProject.CreateChild("NameOfImportedPOU", 58, $null, $pathToPouFile)
$plcProject.CreateChild($null, 58, $null, $stringArrayWithPathsToPouFiles)
Please note: A POU template file may not only be a .TcPou file but also the corresponding files for DUTs and/or GVLs. The example above demonstrates two common ways to import POU template files. The first is to import a single file, the second to import multiple files at once by storing the file paths to a string array and using this string array as the vInfo parameter of CreateChild().