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 gain read/write access to either the implementation or declaration area of a POU, using the ITcPlcImplementation or ITcPlcDeclaration interfaces, as shown in the following example.
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.ImplementationXmlWhen comparing the two interfaces, you will notice that the accessible properties differ in both interfaces. For example, the ITcPlcImplementation interface offers a "Language" property that ITcPlcDeclaration does not. The reason for this is that, according to IEC, the declaration area is not based on a real programming language (e.g. ST), so this property would not make sense if it were used in the 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 carried out using the CreateChild() method of the ITcSmTreeItem interface. The parameters of this method must be interpreted differently depending on the POU type. In the following table you will find the information required to create different POU types. Please note that the vInfo parameter may be a string if more than one parameter is required. In [...] reference is made to each array position and whether it is optional or not.
Tree Item | Type | Parameter "nSubType" | Parameter "vInfo" |
|---|---|---|---|
Program | POU | 602 | [0, optional]: IEC programming language, as defined by IECLANGUAGETYPES. ST (Structured Text) is used by default. |
Function | POU | 603 | [0]: IEC programming language, as defined by IECLANGUAGETYPES. |
Function block | POU | 604 | [0, optional]: IEC programming language, as defined by IECLANGUAGETYPES. ST (Structured Text) is used by default. |
Action | POU | 608 | [0, optional]: IEC programming language, as defined by IECLANGUAGETYPES. ST (Structured Text) is used by default. |
Method | POU | 609 | [0, optional]: IEC programming language, as defined by IECLANGUAGETYPES. ST (Structured Text) is used by default. |
Property | POU | 611 | [0]: IEC programming language as defined by IECLANGUAGETYPES |
Retrieve property | POU | 613 | [0, optional]: IEC programming language, as defined by IECLANGUAGETYPES. ST (Structured Text) is used by default. |
Set property | POU | 614 | [0, optional]: IEC programming language, as defined by IECLANGUAGETYPES. ST (Structured Text) is used by default. |
Transition | POU | 616 | [0, optional]: IEC programming language, as defined by IECLANGUAGETYPES. ST (Structured Text) is used by default. |
UML class diagram | POU | 631 | No vInfo parameter required, "Null" can be used. |
Enum | DUT | 605 | [0, optional]: May contain declaration text if applicable |
Struct | DUT | 606 | [0, optional]: May contain declaration text if applicable |
Union | DUT | 607 | [0, optional]: May contain declaration text if applicable |
Alias | DUT | 623 | [0, optional]: May contain declaration text if applicable |
Interface | Interface | 618 | [0, optional]: Extend type |
Property | Interface | 612 | [0]: Return type |
Retrieve property | Interface | 654 | No vInfo parameter required, "Null" can be used. |
Set property | Interface | 655 | No vInfo parameter required, "Null" can be used. |
Method | Interface | 610 | [0]: Return type |
Global variables | GVL | 615 | [0, optional]: May contain declaration text if applicable |
PLC folder | Folder | 601 | No vInfo parameter required, "Null" can be used. |
Parameter list | PL | 629 | [0, optional]: May contain declaration text if applicable |
Visualization | Visualization | 619 | No vInfo parameter required, "Null" can be used. |
Example: The following code snippet shows how the vInfo parameter can be used to create a function block "FB_Test", with the keywords "Extends" and/or "Implements", depending on the value of the Boolean variables bExtends and bImplements. The extended library is ADSRDSTATE and the implemented interface is 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 parameter vInfo only contains one value (marked with [0] in the table above), then you should not create an array of size 1, but simply a normal 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.
PLCopen XML import/export
You can also import/export PLC elements in PLCopen XML via the ITcPlcIECProject interface. Methods and properties of this interface can only be executed directly on a PLC project node, e.g.:
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 a PLC project has already been added to the TwinCAT configuration, which is referenced via the plcProject object. This reference is converted into the object importexport of type ITcPlcIECProject, which is then used to export the POUs POUProgram and POUFunctionBlock (both are located in the PLC folder "MyPOUs") to an XML file and then import them again.
The available options for the 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().
