Sample Chapter
Sample Chapter
Industrial Programming
This chapter describes two different interpretations of the term “Object Oriented Programming”, how one
interpretation is a subset of the other, and how the subset provides many of the benefits of object-based
programming without the complexity. This chapter goes on to provide examples of plant objects, how those
objects are used in a control Program, and how this programming technique is a natural and intuitive way to control
plant and equipment objects.
Also, this chapter provides some history on the evolution from traditional PLC programming to object-based
programming, introduces new techniques for mapping I/O and configuring objects in an object-based environment,
describes best-practices for PLC design, and shows how designs can be perfected before being deployed to the field
using system-level simulation.
The lab for this chapter is exploring and simulating several completed discrete, batch, and continuous OOIP designs;
and building your own OOIP design.
Object Oriented Programming uses the full suite of OOP techniques, is primarily text based, and is primarily the
domain of highly educated computer scientists. Object Oriented Industrial Programming only utilizes
Encapsulation, Composition, and Abstraction, uses these to build systems from self-contained reusable Function
Blocks, is primarily graphics-based, and is usable by controls engineers and plant technicians with minimal training.
212 The Book of CODESYS
Industrial controls software engineering has unique requirements for high reliability and for ease of use by a broad
spectrum of users. Those are the reasons why graphical languages have been the mainstay of industrial controls
programming and industrial controls engineers tend to wait for the latest trends in computer science to mature
before adoption (such as symbolic addressing and data structures which both matured for 20 years before entering
the industrial controls mainstream).
Object Oriented Programming (OOP) began to be used by computer scientists in the 1990s but has been slow to be
adopted into the Industrial Controls world due to its complexity and the lack of a supporting graphical language
environment. Fortunately, tool vendors like CODESYS are beginning to address those issues.
To benefit from Object Oriented Industrial Programming, controls programmers need only master three OOP
concepts: Encapsulation, Composition, and Abstraction. These are all covered in detail in this and the POUs
chapters.
OOIP provides the benefits of OOP but in a way that is familiar to industrial programmers and is maintainable by
industrial programmers. It is the best of both worlds: the productivity of OOP with the simplicity and reliability of
traditional PLC programming.
Object Oriented Programming (OOP) works well for the libraries created by highly trained computer scientists, such
as the libraries created by the programmers at CODESYS. These libraries can then be used by controls engineers
who don’t need to know or understand complexities contained in the library.
Visualization and Alarming also have their versions of OOIP which are discussed in their respective chapters later in
this book.
Chapter Eleven: Object Oriented Industrial Programming 213
Object Oriented
Industrial
Programming
(OOIP) simplifies
the design of your
plant or equipment
and makes it much
easier and more
likely to reuse
control objects on
future designs.
Your plant or
equipment is made
of objects (motors,
actuators, sensors,
etc.); the control
for your plant or
equipment should
be too!
Just as a motor is a completely self-contained object which does not require assembly or modification, the control
for that motor should be a self-contained object which does not require assembly or modification. In software
terms, this is known as Encapsulation. Everything that is required to control a motor is encapsulated inside the
motor control block. Just drop it into the design and it works. Just as the plant or equipment designer doesn’t need
to be a motor design expert to specify and install a motor, the control designer doesn’t need to be a motor control
expert to configure and use the motor control block.
Reusing control blocks in your control code should be just as easy as reusing physical equipment in your plant.
Physical equipment objects are specified, purchased, and installed – Control objects are placed, wired, and
configured. The thought process is the same, and both can, in fact, be done in parallel. In the future, equipment
manufacturers may well supply the OOIP control blocks for their equipment along with the physical equipment.
This centralized task-oriented approach was a big advancement over the flat approach, but it suffered from the
need to modify each list or task when new functionality was added to the program. In addition, task-oriented
programming often made it difficult to see the flow of information and to understand the cause-and-effect
relationships in the control code. These drawbacks made programming more difficult to design and more
complicated for plant technicians to maintain.
OOIP turns the task-oriented process on its side as shown in this graphic. Instead of the functionality being spread
out amongst many tasks, the functionality is contained inside “Objects”. A single object performs everything that is
associated with an input (reading, scaling, filtering, alarming, persistence, etc.), and that single object is reused for
each input. To accommodate another input, simply add and configure another input object. Same with output
objects (such as motors and valves).
In OOIP, since all the control is encapsulated inside the object, all that is necessary to add additional functionality is
to add another self-contained block. No separate lists, processes, global variables to update and maintain (or forget
to update).
The difference between task-based control and object-based control can be compared to different forms of
governments. Task-based control is analogous to a strong centralized government where new functionality must
register with the Federal Bureau of Scaling, and the Federal Bureau of Alarms, and such. Object-based is analogous
to a decentralized government where new functionality is self-supporting and can largely take care of itself.
Since industrial control plants consist of objects (such as: motors, conveyors, valves, and sensors), Object Oriented
Programming is a natural choice for industrial controls – perhaps even more than the computer science
programming for which OOP was originally created! It may have been more natural for OOP to have been invented
in the PLC world and then spread to the IT world, instead of the other way around.
Chapter Eleven: Object Oriented Industrial Programming 215
Abstraction is where detail is grouped by level in a hierarchy so that the programmer only needs to deal with the
relevant level of complexity at any one level of the design. Composition is where Objects instantiate other Objects
to build and logically partition large hierarchical systems. Interfaces provide a standardized means of interacting
with the next level in the hierarchy. In the Mustang analogy from the previous chapter, the Mustang has an engine,
which has a starter, which has an armature, which has copper wire, which is mined and refined at certain locations
around the world as shown in this graphic. Abstraction allows you to leave the nested complexity of the engine and
the mining of its copper to others where that level of detail is appropriate for their level in the hierarchy. You only
need to know the Interfaces to engine – the ignition switch and the gas pedal.
Control Objects can be designed to correspond to the objects in the plant in such a way that the control program
begins to look similar to the physical plant design as shown in this graphic. Notice the one-to-one correspondence
between the physical objects and the Control Objects.
The plant has four physical sensors for level, horsepower, temperature, and pressure – the control has four
AnalogInput objects matching those four sensors. The plant has two motors and two valves – the control has two
motor objects (MotorRev and VFD) and two Valve objects (and a Human object, which is explained later).
Due to this one-to-one correspondence, the plant design tool and the control design tool might one day be one-in-
the-same. And suppliers of equipment might also provide the control block for that piece of equipment. It will
become just as easy to configure and use an equipment control block as it is to specify and purchase a physical
piece of equipment.
Notice this design has a “Human” object (lower-right corner). In this case, the plant had a human operation
(dumping a bag of chemical into the mixer). In the control design, the human plant object is treated just like any
other plant object. In this case, when the recipe calls for the chemical to be added, the control toggles the
ManualOperation_PI input, and the Human control object signals the operator through the HMI. When the human
is done, he/she responds to the HMI, which triggers the “Completed_PO” output which signals the control code to
continue to the next step.
Chapter Eleven: Object Oriented Industrial Programming 217
The beauty of this approach of encapsulating all the functionality in an object, is that the object can then itself be
used as a self-contained and self-reliant building block. This is illustrated in this graphic where the mixer Program in
the previous page is converted into a reusable object and then used to make a three-mixer plant. If the individual
mixing tanks are not identical, then configuration inputs are added to modify the behavior of instance to
accommodate those differences.
This is somewhat analogous to building a high-rise building. The single mixing tank is the first floor. It represents a
firm foundation onto which to build the next floor – the three-mixer plant. This then could become the firm
foundation on which to build the next level of the plant. In this way a plant of any complexity can be built just like a
high-rise of any number of floors can be built as long as the floors below are properly designed. Since each object is
self-contained and self-reliant, the complexity remains constant as the Program grows, instead of growing
exponentially as with traditional PLC programming.
Let's use a motor controller as another example. Since the motor controller is totally self-contained, we drop it into
the design, wire up its “Run” Program input to whatever control tells the motor to run, configure its parameters
(including mapping its physical I/O), and we are done. Since the motor controller is totally self-contained and self-
reliant, it handles all its own alarming, restarting, and such. In many cases, the level that uses the motor controller
doesn’t even need to know if the motor actually started. That level just tells the motor to Run and that’s it.
Everything is handled internally.
That is, unless the next level up needs to know if the motor is responding, as would be the case if the system had a
redundant motor. However, in that scenario, the additional functionality would be abstracted away into an
additional layer of hierarchy. A new RedundantMotor Function Block would be created which instantiates two or
more Motor blocks along with the control logic to start a redundant motor if the current motor fails. Thus, the level
that instantiates the RedundantMotor doesn’t need to know or care what is happening inside the RedundantMotor
level. It just tells the RedundantMotor to run, and it is confident that the RedundantMotor will do what is
necessary to keep a motor running. The RedundantMotor is totally self-contained and totally self-reliant.
Are you beginning to see the beauty of Object Oriented Industrial Programming?
218 The Book of CODESYS
This graphic shows another example of an Object Oriented Industrial Design. The foundation of this high-rise
building is a Discrete Input module (proximity switches), and Motor Controllers. A control block is added to
complete this Elevator module which is the foundation for the next level of the high-rise, which consists of this
Elevator module plus three Conveyor modules and two Offloader modules. This container handler system could
then itself be used as a foundation for a bigger plant, and so on and so forth. Again, since everything is self-
contained and self-reliant, designs do not get bogged down with greater and greater complexity as the design
grows. The complexity is addressed at each level, so there is no limit to the number of levels that can be built.
Again, with OOIP just drop in the objects, wire them up, configure them, and be done. There is no secondary work
required such as adding the object’s tags to an Alarm Manager, or a Persistence Manager, or global variable lists, or
scaling lists, or filtering lists. Just drop it in and use it. Need another one? Just drop in a second one and use it.
Need 100? Just drop them in and use them. Getting the idea yet?
This approach was not necessary when PLC programs were small (a split-level ranch). But, as the power of PLCs
grows and the application for PLCs become more complex and demanding, OOIP provides a way to manage that
complexity to allow unlimited growth (a 200-story skyscraper).
Each of the levels of this design are explained in more detail on the next several pages.
Chapter Eleven: Object Oriented Industrial Programming 219
This graphic details the top-level of the material handling system described on the previous page. This is a block-
diagram of the plant. (Or this could be a block diagram of a section of the plant, since each level can stand on its
own – there is no way to know (except in CODESYS the top-level is a Program and all other levels are Function
Blocks.))
This level of the plant consists of an Elevator, three Conveyors, and two Offloaders. Each of these are completely
self-contained, self-reliant objects. Notice that the CFC toolbox “Input” items are used as a way of showing the
internal status of these modules at this level (these are not part of the module; they are CFC Inputs that are butted
up against the module’s box). Notice these use relative path names to reach down in and grab variables further
down in the hierarchy. Also note that these objects are declared as VAR_INPUT. Declaring these instances in this
way allows the simulator to access to the internal variables of the instance that would otherwise not be accessible
from this level (Note 1).
Because this is CFC, the underlying Function Block can be opened by double-clicking on the box. When online, the
underlying instance can also be opened by double-clicking on the box. This will open the editor for that particular
instance showing the values of the variables for that particular instance.
Notice that physical I/O has yet to be mentioned in this book. In fact, it won’t be mentioned for several more
chapters. In traditional PLC programming, the effort begins with the I/O tag list and proceeds from there. In OOIP
programming, the effort begins by determining and assembling the required functionality. Mapping the physical
I/O into that functionality is one of the last steps. In that way, when similar functionality is required in a different
plant or piece of equipment, it’s a simple matter to update the mapping with the new I/O. No rewriting the global
variable list and all the task-based services on which it relies. Reusability is maximized.
Note 1: At one time this syntax could be used to access variables in instances that are declared VAR:
(ADR(E1.Elevator_Seq.InConvStatus))^
Unfortunately, that wasn’t working as of SP16.
220 The Book of CODESYS
Double-clicking on the
ElevatorModule block opens the
editor for the next level of the
design – the Elevator’s Control and
Equipment Diagram (C&E). A C&E
consists of Input objects on the left
(proximity sensors, in this case),
Output objects on the right (motor
controllers, in this case), and a
Control Block in the middle.
In OOIP (and
programming
in general),
Function Block
VAR_INPUTS
and
VAR_OUTPUTs
are connected
to several
different types
of sources and
destinations.
Sometimes it
become
confusing
exactly which
I/O is intended
for which
source or
destination. A
naming convention is extremely helpful to address this issue. This author prefers this naming convention for
VAR_INPUTs and VAR_OUTPUTs:
- *._FI and *._FO: for physical inputs from field devices and outputs to field devices.
- *_PI and *_PO: these are the interconnections within the program. _POs from one block typically connect to
the *_PIs of the next, and vice versa.
- *_VI and *_VO: primarily intended for connections to the Visualization or HMI.
- *_CI: Configuration Inputs for adjusting the behavior of the object to meet the requirements of the
application. These are usually initialized with one of the techniques described in the POUs chapter.
Note: Some users prefer to place the naming convention in front of the variable so when IntelliSense or Input Assist
display variable names in alphabetical order, the variables are ordered by intended type of source or destination.
Using this or a similar naming convention makes it much easier to find the correct variable and much less likely to
use the wrong variable. For instance, when mapping the Analog Input object to the physical analog sensor in this
example, one would look for a variable ending in _FI (Input_FI in this case). Or, when looking for a tag for the
Visualization to indicate that an input is out of range, one would look for a variable ending in VO (Clamped_VO in
this case). Or, when looking to connect the analog output to the next programming object that needs that signal,
look for a variable ending in _PO (Output_PO or SmoothedOutput_PO in this case).
That having been said, there are exceptions to every rule. For instance, perhaps there is a reason the program
needs to know if the input was out of range, so it would be necessary to use Clamped_VO as a program output.
Exceptions can and will occur, but this covers the vast majority of cases and clears up the vast majority of possible
errors and confusion.
222 The Book of CODESYS
As we discussed in the Abstraction graphic earlier, try to partition your design into Function Blocks that have the
level of detail that is appropriate for that position in the hierarchy. Just like the engine, the top-level is made up of
the major components (alternator, starter, block, etc.). The next level down would be the pistons, cam shaft, etc.
Continuing down the pistons would be the rings. Partition your control designs in exactly the same way. The
engineer taking over your code will greatly appreciate it (as will you in two years if your memory is as bad as this
author’s). At every level, think what is important to the future user of this code to understand at this level of the
design. If it has more detail than is necessary at that level, move the functionality into a Function Block with a
descriptive name, and replace the code with that Function Block instance.
As a point of illustration as to why the concept of small building block and consistent level-of-detail is important,
one only needs to open a typical Ladder Logic design. Most LD design consists of dozens or hundreds of pages of
flat code, intermingling detailed design with high-level calls to other Function Blocks. This violates both the one-
page building-block rule and the separation-of-detail rule. It is much better to partition the design into multiple
layers, with the higher levels showing the overall functionality and interrelationships (the Block Diagram), and lower
levels showing the detailed implementation.
Other areas that could be argued violate the separation-of-detail rule are Hungarian notation and namespace
prefixes. Typically, the data type of a variable is only important when it is being declared. Some would argue that
prefixing the variable with its data type introduces unnecessary clutter to the code which makes the code more
difficult to read and understand. That detail is better left to a tooltip. Likewise, the library from which an object is
obtained is again usually only important when the object is being chosen. Prefixing the object with its library of
origin usually represents unnecessary clutter which makes the code difficult to read and understand. IEC 61131-3
and CODESYS desperately need a way to open namespaces for each POU so the library of origin can be handled in
the declaration area where that level of detail is important, not in every line of code where an element of the
library is used.
This concept will be revisited several times over the next few chapters (along with additional suggestions where
CODESYS could enhance the IDE help their customers use these best practices).
Chapter Eleven: Object Oriented Industrial Programming 223
Unfortunately, the traditional technique of hard-coding I/O and configurations is fundamentally incompatible with
OOIP. For instance, in this example we have a Plant which has two Reactors, each of which have two Augers, all
four of which have Shaft-Encoder interfaces which need a physical discrete input for the pulses from the physical
shaft encoder (Pulse_FI) and four configurations for the amount of material that is moved per pulse of the shaft-
encoder (PulsePerLiter_CI). If the physical input of the Auger were hard-coded to a global variable, all four augurs
would be hard coded to that single input. The Auger is not reusable. Same problem with the configuration. If that
is hard coded, then the Augur could only be used with augers of the same diameter, pitch, and encoder. The only
solution would be to make four copies of the Auger, hard code the I/O global variable and the configuration into
each of the four copies, make two copies of the Reactor and hard code two each of the Augers into each copy, and
hard code those two Reactor variations into the Plant. This is a laborious process, duplicate code is rampant,
nothing is reusable, and there are huge opportunities to introduce errors in the code.
224 The Book of CODESYS
Earlier, we drew the analogy that the older task-based approach is like a centralized government, where the newer
object-based approach is a society where individuals take care of themselves. Now, you might be thinking: “Even
the most ardent libertarian agrees there is a need for some level of government.” and “Not all 1964 Ford Mustangs
are identical. They have different features and options. How are these handled in OOIP?” and “How does global
I/O memory work with OOIP?” These are all very good questions. The first issue is addressed with Central Services,
the second with Configuration Parameters, and the third with Full-Path I/O Mapping as described below.
In this example, the first discrete I/O point is mapped to the PULSE_FI input in ShaftEncoder SE1, in Auger A1, in
Reactor R1, in the Plant Program, in the App Application. So, its full-path-name is App.Plant.R1.A1.SE1.Pulse_FI.
The second discrete input is connected to the second auger, so its full path name is App.Plant.R1.A2.SE1.Pulse_FI.
The third and fourth discrete inputs are mapped to the same augers except in the second reactor (R2). Because of
this I/O mapping technique, the Auger is now reusable. Notice, the naming convention (*_FI) to make it easier to
determine where to connect the physical I/O.
Unfortunately, CODESYS doesn’t offer something similar for setting configurations. Fortunately, ControlSphere has
created the Central Configuration and Persistence Service library (CCS) to address this issue. The CCS library
automatically creates a spreadsheet which is organized by FB type and has a row for each FB instance and a column
for each configuration input for that FB. The CCS library creates this CSV file containing the default values for the
configuration inputs. These values may be changed and the CSV file read back in to apply those changes.
In this example, each Shaft Encoder needs to know the number of pulses per liter of material. The CCS library
writes a CSV file which is grouped by Function Block type (ShaftEncoder), a header-line showing the names of all the
configurable inputs to the ShaftEncoder (PulsePerLiter_CI), a row containing a full-path-name to each Shaft Encoder
instance (App.Plant.R1.A1.SE1, etc.), and the default values for each configurable input in each instance of the
ShaftEncoder. The user can then change the default values to that which is appropriate for each instance (1000,
2000, 3000, and 4000 in this example). Then, the CSV file can then be read by the controller and the new values
Chapter Eleven: Object Oriented Industrial Programming 225
will be copied in their appropriate variables. This read operation can be performed automatically on startup, or can
be commanded by the control or HMI code.
If the Application includes Visualization which allows the operator to set configurations, that Visualization page
would change the configuration variable values and then write the CSV file so those changes become permanent
(will survive a power-cycle, equipment replacement, or even movement to a new plant or piece of equipment).
The OOP chapter will show how additional OOP techniques are used to implement CCS library.
Here is an example of a real configuration file compliments of Marine Hydraulics. Notice the CSV file is grouped by
FB type (CalcCylOIlOLoads, PumpControlFB, KiteRetieverSystem, SADECylinderSystemsFB, etc.). Notice within each
group there is a row for each instance of that FB. Also, notice there is a header row at the beginning of each
section containing the names of each of the configuration inputs, with the values of each configuration parameter
for each instance in cells below the header.
Marine Hydraulics has a mixture of configurations that are fixed for each boat, and some configurations which can
be changed by the operator through a Visualization. The programmer codes the boat-specific configurations into
the CSV file which is read on startup. The Visualization writes the configuration file after it makes any changes to
the operator-configurations so that those changes become permanent.
This shows the Power of Object Oriented Industrial Programming. Declare instance of your reusable Function
Blocks, create a Configuration CSV file with all the default values, update those values as appropriate, read the file
back into the project, and start your plant or equipment.
226 The Book of CODESYS
In this scenario, an I/O module would be a configurable reusable Function Block just like every other object we’ve
talked about in this chapter. It would have its own configuration for items like its name, CAN address, and such. It
would offer up its name and its I/O points to an I/O Mapping Central Service which would then coordinate with
each equipment instance to make the connections specified in the equipment’s CSV configuration.
Alternatively, the I/O mapping could be specified in the CSV configuration for the I/O module FB instance.
In either scenario, the CODESY I/O wouldn't be used at all. This gives the added benefit that I/O could now be
updated in an Online Change! Follow this link for a demo showing how this is done: https://ooip-
foundation.proboards.com/thread/9/configurable-mapping-allows-online-change
Note that functionality similar to the Central Configuration Services could be used to provide both a Central Alarm
Service and a Central I/O Service. In addition to simplifying the I/O mapping process, the Central I/O service would
provide the ability to reconfigure I/O in an Online Change (which is currently not possible and a significant issue
using CODESYS in applications which cannot be shut down for modification). These are examples of functionality
which is handled as an external manual post process in traditional PLC programming that could instead be built into
self-contained and self-reliant Function Blocks.
Chapter Eleven: Object Oriented Industrial Programming 227
The characteristics of a good Industrial Controls (IC) simulation environment look very similar to that of a good IC
development environment:
- Versatile and powerful programming languages
- Full featured language editors
- Full suite of debugging tools including:
٠ Code and data breakpoints
٠ Single-stepping, step-in, step-out, etc.
٠ Live Mode (to show instantaneous variable values, not just end of cycle values)
٠ Write and Force variables, and move the execution point
٠ Virtual digital oscilloscope which samples at the controller cycle time
- Built-in HMI for creating test control panels
- A complete controller runtime which runs as a service on the development computer
- Support for Object Oriented Industrial Programming (OOIP)
Fortunately, the CODESYS IDE and the CODESYS ControlWin soft PLC offer all these features and is just as good as a
simulation/verification environment as it is a development environment. With such an environment, creating the
simulation code is as easy as creating the original code. The next few pages will show how this is accomplished
using the CODESYS IDE.
228 The Book of CODESYS
The
simulation
code often
mirrors the
control code.
Here is the
simulation
code for the
container
handling
system
described
earlier in this
chapter. It
contains the
same blocks
as the control
code, except
this is using
the
simulation
version of each system block (notice the *_Sim in the name). (This diagram was actually a copy of the actual
system-level diagram with the names changed.)
Notice that this author prefers the simulation code to be totally separate from the control code. It’s stored in its
own separate folder and it has its own separate Task. The Task is usually set to run much faster than control code,
because the simulator is usually simulating something that is running in real-time. It’s advisable to select a cycle
time that is not an even sub-multiple of the control cycle time, so there is no chance some sort of synchronizing or
aliasing could conceal a control issue. (For instance, selecting 3ms simulation for a 20ms control cycle.)
With the control code as a separate entity in its own folder, it’s a simple matter to exclude or include the folder in
the build to add or remove the simulation code. This way, when the simulation is not being used, it is completely
out of the way, it takes no controller resources, nor could it possibly ever interfere with the control code.
Some engineers prefer to place the simulation code in the control code and have a global variable to enable and
disable the simulator. This often reduces or eliminates the I/O mapping step as described on the next page. But it
does use controller resources after the control code has been released to the field, and there is always the chance
the code could cause issues. There is no right answer with respect to the decision of where to place the simulation
code.
As was mentioned in the debugging chapter, one issue that occurs with simulation is what to do with the
configured physical I/O when simulating. This isn’t a problem when using Simulation built into the IDE because
Simulation ignores any configured I/O. But in many cases Simulation has limitations which force the use of
ControlWin (which does not ignore I/O). Some hardware vendors provide a version of ControlWin which accepts
and ignores the I/O from that vendor. That is the best solution when it is offered. Without that, the only way to
use ControlWin to simulate is to delete the I/O and change the device to ControlWin, then change the device back
to the actual device and paste the I/O back into the tree to run on the actual hardware with physical I/O.
Chapter Eleven: Object Oriented Industrial Programming 229
(Unfortunately, the naming convention was not used in this design. If it had been, the names on the left would be
appended with _FO and the ones on the right would be appended with “_FI”.)
The Motor_SIM accepts the Energize_Starter command and after Starting_Time has expired it sets the Starter_Aux
to true. Starting_Time can be changed by the simulator test sequence code to test the control code response when
the motor starts slower than expected or fails to start. These are a few rungs of LD.
The Conveyor_Sim records the time when the LoadingItem transitions to true, then knowing the length and speed
of the conveyor, activates the PhotoEye output when each item reaches the end of the conveyor. This requires a
dozen or so lines of ST code.
The Pusher_SIM cycles between activating the PusherExtended and PusherRetracted outputs to simulate an arm on
the end of a rotating cam with proximity switches on the two extremes. Another few lines of code.
In total, the entire Offloader simulator is a couple dozen or so lines of LD and ST code. A very small price to pay for
the confidence that the design is complete and correct before it is deployed to the field.
Be aware: To promote good coding techniques, variables that are declared as VAR are not accessible outside the
POU in which they are declared. Similarly, VAR_INPUTs and VAR_OUTPUTs declared inside a Function Block whose
instance is declared as a VAR are not accessible outside the POU in which the Function Block instance is declared.
CODESYS provides special access to the CODESY I/O Mapping tool (as well as to Visualization, Recipes, Trace, and
such) in order to be able to reach into variables inside Function Blocks that are declared as a VAR. Unfortunately,
your user-level simulator code will not have that same type of special access.
To allow your simulator code to “reach-into” and connect to VAR_INPUTs and VAR_OUTPUTs in instances of
Function Blocks, those instances must be declared as VAR_INPUT. (For instance, in this example the
ConveyorMotor Function Block instance must have been declared as VAR_INPUT.) (At one time it was possible to
use this syntax to allow a simulator to have the same access as I/O mapping and Visualization:
“(ADR(VarToReach))^” (where VarToReach is a VAR_INPUT or VAR_OUTPUT inside an instance of a Function Block
that is declared VAR). But, as of this writing, that trick no longer works. Hopefully, it will again someday.)
230 The Book of CODESYS
How do you know if your control system supports OOIP? Look for these capabilities:
- A means to create self-contained control objects which correspond to matching plant objects and carry out all
the functionality required for that plant object such as alarming, auditing, physical I/O, HMI I/O, scaling,
control, etc.
- A graphical editor allowing an unlimited number of instances of objects to be declared, instances of objects to
be interconnected in arbitrary fashions, and objects to instantiate other objects into a hierarchy of arbitrary
depth and complexity. During runtime, the editor should allow for simple navigation of the hierarchy such as
double-clicking on an instance of an object to descend into the project hierarchy and to navigate back.
- The ability to debug individual instances of objects during runtime, including: setting breakpoints within
individual instances, single-stepping into individual instances, and viewing/changing the private variables of an
instance of an object.
- A means for instances of the same objects to be differentiated by assigning unique values to the instance’s
configuration inputs anywhere the instance may be in the project hierarchy. Preferably, these configuration
values are sourced from a CSV/Excel file, SQL database, or via OPC UA. There must also be a way to search on
the values of these configuration variables during runtime (for instance, to search on an ISA tag name
configuration).
- The ability to map physical I/O to any variable in any instance anywhere in the project hierarchy (including
mapping a physical input point to multiple instances). Composite I/O such as from a fieldbus device must be
able to be mapped to individual variables, or to one or more data structure variables anywhere in the project
hierarchy. The tool must provide a way to trace the path of a signal from its input, through the logic, and to
the outputs it drives (likewise in reverse from the physical output back through the logic to the physical inputs
which influence that output).
- The capability to build hierarchical HMI objects which match the hierarchical control objects and the ability to
interconnect the two objects (and their potentially thousands of underlying interconnections) via the top-level
object’s instance name.
- The ability to print a “flattened” version of the hierarchical design showing the interconnections between the
object instances and the unique configuration values on each instance.
- The ability to implement Inheritance, Methods, Polymorphism, and Interfaces can be helpful.
- An active user community and lively forum where open-source Plant Objects and advice can be freely shared.