Twin object is .net representation of a complex PLC data type (STRUCT, UNION, FB, GVL, PRG). Each of these data structures is represented by a separate class of which name is the same as the name of the respective structure.
Each twin object implements two types of interfaces IOnline interface which exposes members with direct communication ability with the PLC system and IShadow interface with allows for an offline manipulation of object's data.
There is a separate class Plainer that is produced during the trans-piling process which is light (POCO like) representation of the same data structure, that can be is used in scenarios involving serialization.
Compiler supports PLC program structures of following POU types:
- PROGRAM (PRG)
- GLOBAL VARIABLE TABLE (GVL)
- STRUCTURE (STRUCT)
- ENUMERATION (ENUM)
- FUNCTION BLOCK (FB)
- UNION BLOCK (UNION)
Each of the mentioned is constructed and represented inside Inxton as several partial Classes plus corresponding interfaces. Please find more details in the sections below.
More about TwinCAT 3 data types can be found here.
NOTE: FUNCTION (FUN) are not compiled as the data of function block are temporary.
The compiler supports Members of POU declared in sections as well:
- VAR
- VAR_INPUT
- VAR_OUTPUT
Read more about the nature of TwinCAT 3 variable types and special variables is available here.
NOTE: Sections VAR_IN_OUT, VAR_STAT, VAR_TEMP are not supported at this time. It should be also noted that variables declared in declaration sections of Methods and Functions are also not supported as they represent temporary variables. Variable in declaration sections of methods are not compiled even when declared within VAR_INST section.
During the process of compilation, several partial classes and interfaces are being created. Each of the objects serves a specific purpose and its members are with a different relationship to PLC object. Having a Function block named FbPiston created at PLC side. The result of the compiler's effort is Onliner and Plain classes plus Online and Shadow interfaces. Please carefully analyze the sample below.
PLC code:
FUNCTION_BLOCK fbPiston ...
Inxton representation follows:
Onliner partial class
Onliner is having a name identical to POU's name.
public partial class fbPiston ...
IOnline interface
IOnline will prefix the POU's name with the 'I'.
public interface IfbPiston...
IShadow interface
IShadow will prefix the POU's name with 'IShadow' prefix.
public interface IShadowfbPiston ...
Plain objects
Vortex.Compiler trans-piles also light POCO like objects that represent each PLC block. These objects are typically used in serialization scenarios. The Plain object is POU's name prefixed with 'Plain'.
public partial class PlainfbShadow
Reads all variables (Primitive Twins) contained in this structure (TwinObject) and its children. The variable read from the controller is stored in LastValue property of Primitive Twin(s).
MainPlc.MAIN.DataStructure.Read();
Reads all variables (Primitive Twins) contained in this structure (TwinObject) and its children. The variable read from the controller is stored in LastValue property of Primitive Twin(s).
MainPlc.MAIN.DataStructure.Write();
You can store the data into shadow holders of Primitive twin. Shadow values can temporally hold the value that can be transferred from Online to shadow in a single shot by calling 'FlushOnlineToShadow()' method. Inversely you can transfer the data from Shadow holder to Online by calling 'FlushShadowToOnline()' method.
MainPlc.MAIN.DataStructure.FlushOnlineToShadow();
MainPlc.MAIN.DataStructure.FlushShadowToOnline();
You can create an instance of a plain object by invoking 'CreatePlainerType()' method. This will create a fresh instance of 'Plainer' type. To populate the newly created instance with online data you can invoke 'FlushOnlineToPlain()' inversely when you want to copy the data from 'Plainer' to Online variables you can call 'FlushOnlineToPlain()' method.
// Creates an empty instance of 'Plain' for 'DataStructure' type.
var plainDataStructure = MainPlc.MAIN.DataStructure.CreatePlainerType();
// Copies current online data into 'plainDataStructureObject'
MainPlc.MAIN.DataStructure.FlushOnlineToPlain(plainDataStructure);
In analogous way you can swap data between 'Shadow' holder using 'CopyPlainToShadow()' and 'CopyShadowToPlain()' on plainer type.
// Creates an empty instance of 'Plain' for 'DataStructure' type.
var plainDataStructure = MainPlc.MAIN.DataStructure.CreatePlainerType();
// Copy shadow data to plainer type.
plainDataStructure.CopyShadowToPlain(MainPlc.MAIN.DataStructure);
// Modif. plainer data.
plainDataStructure.Count++;
plainDataStructure.TimeStamp = DateTime.Now();
// Copy plainer back to Shadow.
plainDataStructure.CopyPlainToShadow(MainPlc.MAIN.DataStructure);