By Andy Burleigh
By Andy Burleigh
(OOP), with its clear modular structure, is an exciting programming methodology emerging in the area of automation and controls. Many programmers, particularly those who are versed in the IEC 61131-3 standard, stand to gain numerous advantages by becoming more familiar with OOP.
It is not uncommon for IEC 61131-3 (2nd Edition) to be referred to as ‘almost object oriented.’ This evaluation is due to the Function Block idiom, which is the core of software re-use in IEC 61131 development. However, it is not the only feature of the standard that is important to constructing robust and re-usable solutions: additional Program Organization Unit (POU) types, user defined data types and scoped variable declarations all contribute to modular solutions.
Of course there is far more to OOP than code re-use. While the current standard does include reusable Function Blocks and Data Structures as ‘objects,’ there is no syntax that allows the code designer to clearly define Interfaces or Classes. In IEC terms: the formal interface of a Function Block is not itself reusable. Code sections or sub-routines have no definition outside of their implementation (although some of us squeeze ‘extra meaning’ into IEC ACTIONs) and there is no facility provided to construct an extension into an existing Function Block. The Function Block is definition and implementation rolled into one and new features always require modification of the original.
The 3rd Edition of the IEC 61131-3 standard will have its final release in February, 2013 and it will take a step forward to provide the designer with the necessary syntax to clearly express these separate ideas – an Interface defines the Properties and Methods of a Class, a Class is defined by a Function Block that Implements an Interface, and an Object is created by instantiation of that Function Block.
Interfaces are designed to clearly define the data (attributes) and logic (methods) an object needs, and this definition is separate from one or more implementations of that model. Furthermore, new interfaces can combine existing ones and implementations can be extended. This means that with the 3rd Edition, IEC 61131-3 now includes its own encapsulation, inheritance and polymorphic features and is Object Oriented.
IEC 61131-3, 2nd Edition
A great benefit for programmers working in an IEC environment is the flexibility of the system. This is in large part due to the many languages and data types supported and, of course, the POU type Function Block is significant as well.
The languages of the IEC 61131-3 standard can be used together within one solution, this includes: Instruction List (IL), Ladder Diagram (LD), Function Block Diagram (FBD), Structured Text (ST) and Sequential Function Chart (SFC). While each language addresses particular program design requirements, perhaps the most tangible and practical benefit is that the programmer can construct logic in the language most comfortable to them.
The base data types are also defined, and as a ‘strongly typed’ environment there is protection against memory errors caused by incorrect type assignments. User defined data types are also supported as Data Structures, Enumerations and ranged sub-types.
Today, Data Structures are the primary methodology for implementing an Interface: a TYPE STRUCT can be defined that contains the formal inputs to a POU, another can be defined that contains the formal outputs. ARRAY declarations are supported for both the base and user-defined data types.
These features are used together to simplify logic and create easily re-usable software components. A common design template takes advantage of the fact that a Function Block is a data type and, therefore, can be instantiated in an array. Here, constant definitions are used to easily control the boundaries within which ‘objects’ are created and updated.
NUM_CONV : INT := 4;
arrMachineConveyors : ARRAY[1..NUM_CONV] OF FB_CONVEYOR;
FOR i : = 1 TO NUM_CONV BY 1 DO
This sample code simplifies the addition and removal of conveyors. Changing the Constant instantiates the additional FB_CONVEYORs, and loops are automatically adjusted to update the resized array. Sequence control logic may have to be modified to accommodate the total number of conveyors, but there is no need to modify the conveyor code. Because the code particular to a conveyor is contained in a Function Block, changes are easily implemented, and this Function Block is easily exported and imported between projects.
Potential reusability constraints
A common theme for automation programmers is the need to successfully adapt to technological change. A frequent occurrence is that the vendor of an existing component develops a variation – perhaps some new conveyors in the solution change to have three stop positions and others control/move under a vibrating hopper. The programmer has a choice at this moment – how does one add code to the solution for these new, but similar cases?
Programmers can modify the existing FB_CONVEYOR – perhaps the evaluation of a ‘ConveyorType’ input parameter will cause the code to branch conditionally in one or more places. Alternatively, they can create a new Function Block, perhaps by copying FB_CONVEYOR under a new name, “FB_CONVEYOR2” and carrying out the necessary modifications.
The drawback to the first option is that directly modifying FB_CONVEYOR could introduce unplanned behaviour in the existing conveyor system. Also, care must be taken so that the FB_CONVEYOR Function Block maintains readability. Imagine that this design strategy continues and, over time, this one Function Block is supporting 15 different configurations of the conveyor – ease of readability and maintainability can suffer greatly.
The second option enables the programmer to ensure that there will be no effect on existing components when the new Function Block is implemented and the new design starts from a ‘known-good’ code base. Unfortunately changes are often required even in ‘known-good’ code and now that we’ve copied and pasted code between Function Blocks, the programmer must evaluate all changes and apply them to every copy, if needed in this case. Imagine that we have 15 variants of the conveyor Function Block and a change request must be applied to all of them – there is little chance that the same logical modification will work for all – ease of readability and maintainability can be negatively impacted this way as well.
IEC 61131-3, 3rd Edition
Sticking with the conveyor example, the 3rd Edition of the IEC 61131-3 standard enables new options for the system designer. For example, one can choose to model an Interface that describes a conveyor. The Interface describes the data (Properties) and the actions (Methods) that an object will implement. The Interface is purely a definition so no code is implemented in the Interface:
PROPERTY P_FWD : BOOL
PROPERTY P_BWD : BOOL
METHOD M_MoveForward : BOOL
METHOD M_MoveReverse : BOOL
A Function Block that implements the conveyor Interface can now be created. In this Function Block data and method handlers will be written to perform the actions required of the ‘Parent’ object:
FUNCTION_BLOCK FB_ITFConveyor IMPLEMENTS ITF_Conveyor
This function block can be instantiated and used in code as was done in the past. For example, using the familiar ARRAY syntax:
arrMachineConveyors :ARRAY[1..NUM_CONV] OF FB_ITFConveyor;
With the implementation of FB_ITFConveyor prepared and tested, the programmer can turn now to the ‘special’ cases, and extend or reuse the existing functionality as needed:
FUNCTION_BLOCK FB_3PositionConveyor EXTENDS FB_ITFConveyor;
FUNCTION_BLOCK FB_VibratingConveyor EXTENDS FB_ ITFConveyor;
The new IEC keyword EXTENDS indicates that a newly declared Function Block includes the functionality of a ‘Parent’ Function Block. In this case FB_VibratingConveyor inherits the capabilities of FB_ITFConveyor. The ‘Child’ Function Block can optionally use the functionality of its ‘Parent’ and be implemented with additional features, or a combination of new and existing features.
For instance, FB_VibratingConveyor, when asked to move forward may turn on its output to agitate the feeding hopper before executing its Parent’s MoveForward method. Perhaps this conveyor is not permitted to move backwards, so its MoveReverse method overrides the Parent method and stops forward motion but performs no steps to move backwards. A key advantage is that the Child has complete access to the functionality of the Parent, but cannot modify the functionality of the Parent.
In this design scenario pre-existing code remains unchanged even though new functionalities have been added that leverage pre-existing code. Ease of readability and maintainability are preserved. This saves considerable amounts of time during new development, enhances code quality and preserves backwards compatibility.
The addition of object orientation in IEC 61131-3, 3rd Edition has been undertaken with the same care that guided the definition of the programming languages, data types and functions in the original standard. Just like coding in a particular language is not required, neither is the creation and use of Interfaces. Interface implementations can be done in multiple languages. Existing code can be moved forward and does not have to be redesigned to use Interfaces. New code can be implemented in exactly the same way as before.
The discussion here has focused primarily on new IEC elements for code reuse, but the standard includes much more than this, technically and in spirit. The software model is a simplified one – generic enough that implementers of the standard can create distinctive products and users of those products can develop world class solutions. From this point of view the best intellectual asset of IEC 61131-3 is its openness to full design freedom.
Considering the advancements made by the 3rd Edition, the IEC 61131-3 standard continues to provide automation developers with the best tools available to realize their most innovative ideas.
Andy Burleigh is an applications specialist with Beckhoff Canada. This article originally appeared in the November/December issue of Manufacturing AUTOMATION.