Overview: What "Object-Oriented" Means in a PLC Context
Object-oriented programming (OOP) in PLCs is a structured approach to organizing control logic through modular, reusable, and clearly bounded code units. Unlike PC software where classes, inheritance, and polymorphism are first-class language features, PLC OOP borrows these concepts and adapts them to the deterministic, scan-based, real-time execution model required by industrial automation.
The PLCopen Guidelines for Object Orientation extend the IEC 61131-3 model to introduce object-oriented design choices on top of Program Organization Units, Function Blocks, and methods. As Control Engineering's PLC OOP article explains, the goal is to organize and simplify program elements using objects, methods, and properties — not to reproduce a Java or C# class hierarchy verbatim.
OMRON Controller Families and Programming Tools
| Family | Typical Models | Programming Tool | OOP Capability |
|---|---|---|---|
| NJ/NX Machine Automation Controllers | NJ101-9020, NJ301-1200, NJ501-1500, NX102-9000, NX502-1500 | Sysmac Studio (1.40+) | Full FB encapsulation, methods, properties, ST, libraries |
| CP1 Compact PLCs | CP1H-X40DT-D, CP1L-EM30DT-D, CP1E-E20DR-A | CX-Programmer 9.x | FB instances, ST, no methods/properties |
| CJ2 Modular PLCs | CJ2M-CPU31, CJ2M-CPU35, CJ2H-CPU68 | CX-Programmer 9.x | FB instances, ST, no native methods |
| CS1 Modular PLCs | CS1G-CPU42H, CS1H-CPU65H, CS1D-CPU65S | CX-Programmer 9.x | FB instances, ST, no native methods |
| Power PMAC Motion Controllers | CK3M-CPU301, CK3W-AX2323 | Power PMAC IDE + ECAT Studio | Script-based; OOP-style structuring possible but not native to the scripting language |
For OOP-style development, the NJ/NX series with Sysmac Studio is the recommended platform. CP1, CJ2, and CS1 controllers support Function Blocks and Structured Text, but their programming environments lack the method and property bindings introduced in IEC 61131-3 Third Edition.
IEC 61131-3 Foundations: POUs, FBs, Methods, Properties
The IEC 61131-3 standard defines four programming languages: Ladder Diagram (LD), Function Block Diagram (FBD), Structured Text (ST), and Instruction List (IL — deprecated). It also defines the Program Organization Unit (POU) as the basic building block, with three types: PROGRAM, FUNCTION_BLOCK, and FUNCTION.
FUNCTION_BLOCK is the closest PLC equivalent of a class. It has:
- Input, output, and in-out variables (the FB's interface)
- Internal variables (the FB's private state)
- An algorithm body in any of the IEC languages
- Zero or more methods (added in IEC 61131-3 Third Edition)
- Zero or more properties (added in IEC 61131-3 Third Edition)
Each FB instance in OMRON's environment holds its own copy of the internal variables — the FB is the "class," and the instance is the "object." This is the core encapsulation mechanism available on every OMRON PLC that supports FBs.
Methods in Sysmac Studio (NJ/NX)
A method is a procedure bound to a Function Block that operates on that FB's instance data. In Sysmac Studio, methods are written in ST or Ladder and exposed through the FB's interface. They are called using dot notation: myMotorInstance.Start();
Methods differ from external subroutines because:
- They have implicit access to the FB's internal variables
- They can return a value of any IEC data type
- They can be called from programs, other FBs, or event tasks
- They appear in the call graph of the FB, simplifying online debugging
Properties in Sysmac Studio
A property exposes a getter and optionally a setter for a value tied to FB instance state. myHeater.TemperatureSetpoint := 75.0; reads or writes the FB's internal setpoint variable. Properties are syntactic sugar over methods but improve code readability when the exposed value is logically an attribute rather than an action.
Properties are defined with three components in Sysmac Studio: a backing variable (internal VAR), a getter method (read-only or read/write), and an optional setter method. The runtime overhead of a property read is approximately the same as a direct variable access on NJ501 series controllers.
Function Blocks: The Core OOP Pattern in OMRON
For CP1, CJ2, CS1, NJ, and NX platforms, Function Blocks are the workhorse of structured, reusable code. An FB is created in CX-Programmer or Sysmac Studio by defining its variable table (input, output, in-out, internal) and its body, then instantiating it in a program.
Defining an FB: MotorController Example
Consider a MotorController FB that wraps start, stop, fault reset, and overload logic. In Sysmac Studio (ST syntax):
FUNCTION_BLOCK MotorController
VAR_INPUT
StartCmd : BOOL;
StopCmd : BOOL;
FaultReset : BOOL;
OverloadInput : BOOL;
END_VAR
VAR_OUTPUT
Running : BOOL;
Fault : BOOL;
AtSpeed : BOOL;
END_VAR
VAR
State : INT := 0; // 0=Idle,1=Starting,2=Running,3=Stopped,4=Faulted
RunTimer : TON;
END_VAR
// State machine body in Ladder or ST follows
Each instance maintains its own State and RunTimer. The same FB can be used for 50 different motors by creating 50 instances, each with a unique instance name and allocated memory.
Instance Memory and Task Allocation
On CP1H, an FB instance consumes a symbol table entry plus the internal variable memory. For a CPU with 32 Kwords of DM and 20 Ksteps of program memory (e.g., CP1H-XA40DT-D), FBs share the global DM area. Engineers must track instance memory manually because CX-Programmer versions older than 9.81 do not show instance variable allocation per FB in the project tree.
On NJ/NX, Sysmac Studio manages instance memory automatically. Variables are AT-specified to memory areas (e.g., AT %I0.0.0 for an NX-EC0122 EtherCAT input) and the compiler tracks usage. A typical NJ501-1300 has 2 MB of variable memory, supporting thousands of FB instances.
Structured Text for OOP-Style Algorithms
ST is the IEC 61131-3 Pascal-derived language that supports the syntax needed for OOP-like design: CASE, FOR, WHILE, IF...ELSIF, function/FB calls, and arrays/structures. While ST itself is not object-oriented, it is the language typically used for FB bodies and method bodies where OOP principles are applied.
Example: State Machine in ST
METHOD PUBLIC RunStateMachine : BOOL
VAR
LocalTimeout : TIME;
END_VAR
CASE State OF
0: // Idle
IF StartCmd AND NOT Fault THEN
State := 1;
RunTimer(IN := FALSE);
END_IF;
1: // Starting
RunTimer(IN := TRUE, PT := T#3S);
IF RunTimer.Q THEN
Running := TRUE;
State := 2;
END_IF;
2: // Running
IF OverloadInput THEN
Fault := TRUE;
Running := FALSE;
State := 4;
ELSIF StopCmd THEN
Running := FALSE;
State := 3;
END_IF;
3: // Stopped
RunTimer(IN := FALSE);
IF NOT StopCmd AND NOT StartCmd THEN
State := 0;
END_IF;
4: // Faulted
IF FaultReset THEN
Fault := FALSE;
State := 0;
END_IF;
END_CASE;
RunStateMachine := Running;
This single method encapsulates the full state machine. Multiple MotorController instances each carry their own State, RunTimer, and output variables — true instance-level encapsulation.
Implementing Methods and Properties in NJ/NX
Sysmac Studio version 1.20 and later supports methods and properties on FBs, aligning with IEC 61131-3 Third Edition. The method and property definitions are stored as part of the FB symbol in the project tree under the "Programming" → "POUs" node.
Adding a Method to an FB
- Right-click the FB in the Multiview Explorer and select "Add" → "Method."
- Name the method (e.g.,
Start,Stop,ResetFault). - Choose the implementation language (ST or Ladder).
- Define the method's local variables and return type (BOOL, INT, REAL, STRING, etc.).
- Implement the method body. The method has implicit access to the FB's VAR, VAR_INPUT, and VAR_OUTPUT sections.
- Compile and download. The method is part of the FB and travels with the instance.
Calling Methods
// In a program section (ST)
IF bStartRequest THEN
Motor1.Start(); // Call Start method on Motor1 instance
bStartRequest := FALSE;
END_IF;
IF bResetRequest THEN
Motor1.ResetFault(); // Call ResetFault method
END_IF;
nSetpoint := Motor1.SpeedSP; // Read property
Motor1.SpeedSP := 1200; // Write property
bRunning := Motor1.IsRunning; // Read BOOL property
Inheritance and Polymorphism: Practical Patterns
OMRON PLCs do not implement class inheritance. However, two patterns emulate inheritance effectively.
Pattern 1: Composition with Interface FBs
Define a "base" FB containing common variables and methods, then include an instance of that FB inside the "derived" FB. Access the base methods through the instance name.
FUNCTION_BLOCK BaseIO
VAR
RawInput : BOOL;
END_VAR
METHOD PUBLIC ReadInput : BOOL
ReadInput := RawInput;
END_METHOD
END_FUNCTION_BLOCK
FUNCTION_BLOCK DerivedSensor
VAR
Base : BaseIO; // Composition (acts as inheritance)
CalGain : REAL := 1.0;
END_VAR
METHOD PUBLIC ReadScaled : REAL
ReadScaled := Base.ReadInput() * CalGain;
END_METHOD
END_FUNCTION_BLOCK
Composition adds a level of indirection but avoids the inheritance vs. memory trade-off that ladder programmers complained about. On NJ501 series, the cost of an extra instance variable slot is negligible.
Pattern 2: Interface Convention Through Naming
Define naming and method conventions (e.g., all pump FBs must implement Start, Stop, GetStatus) and use a generic wrapper FB that holds an array of references or iterates over a named instance group. This is closest to "polymorphism" in PLC land — the same wrapper code calls the same-named method on each instance, even though the implementations differ.
For example, a PlantSupervisor FB that loops over Conveyor1.Start(), Pump1.Start(), Valve1.Start() in sequence does not require an inheritance hierarchy — it requires only that each FB implement the method by the same name. Sysmac Studio's auto-complete and IntelliSense make this pattern feasible at the development level.
Library Management and Versioning
Reusable FBs in OMRON are packaged as libraries. Sysmac Studio uses .slr (Sysmac Library Repository) files; CX-Programmer uses .cxf or .cxl files. Library management is critical for OOP-style reuse because library updates must not break existing projects.
Library Lifecycle
- Author: Create FBs in a dedicated library project. Use Sysmac Studio's "Create Library" function (Project → Library → Create).
-
Version: Increment the library version field (e.g., 1.0.0 → 1.1.0). Add a
_CHANGELOG.txtor a method that returns version info. - Distribute: Export to a repository (OMRON's Sysmac Library portal, internal SVN/Git repository).
- Consume: Reference the library in a project; the FB instances become available in the toolbox.
- Update: When a new library version is published, project users see a notification and can accept or defer the update.
OMRON publishes validated libraries for motion, safety, vision, and process control on the OMRON industrial automation portal. Third-party vendors also publish FB libraries following the same .slr mechanism, which simplifies vendor integration in mixed-vendor systems.
Library Reference Modes
Sysmac Studio supports two library reference modes:
-
Reference: Project links to the external
.slrfile path. Updates are picked up automatically when the file is replaced. -
Embedded: The library is copied into the project
.csmfile. The project is self-contained, but updates require a manual re-import.
For multi-developer teams, use Reference mode with a shared network drive or Git LFS to ensure all team members see the same FB definitions.
Performance and Memory Considerations
OOP-style code trades memory for maintainability. Engineers must understand the cost of each FB instance and method call before designing a large system.
Scan-Time Impact
On NJ501 series, a typical FB instance adds 0.5–5 µs of scan time per call, depending on the number of internal variables, TON/TOF timers used, and whether the FB contains nested FB calls. A state-machine FB with 20 internal variables and three timers costs approximately 2–4 µs per scan on an NJ501-1300 at a 2 ms task period. Method call overhead on the same controller is 0.1–0.5 µs per invocation, comparable to a function call on the same platform.
| Item | CP1H-Y20DT-D | CJ2M-CPU35 | NJ501-1500 |
|---|---|---|---|
| Program memory | 20 Ksteps | 60 Ksteps | 20 MB |
| DM / variable area | 32 Kwords | 160 Kwords | 2 MB variable memory |
| FB instances supported (typical) | ~200 | ~2,000 | ~10,000+ |
| Method call overhead | N/A (no methods) | N/A (no methods) | 0.1–0.5 µs |
| ST execution speed | 1.6 µs/instruction | 0.04 µs/instruction | 0.003 µs/instruction |
| Min task period | 1 ms | 0.5 ms | 0.25 ms (high-speed task) |
Memory Profiling Steps
- Open the project in Sysmac Studio and connect to the controller (online).
- Navigate to "Controller" → "Memory Allocation" to view current variable and program usage.
- Enable the task period monitor in "Configuraion and Setup" → "Task Settings."
- Run the machine through worst-case cycle (full product changeover, alarm reset, etc.).
- Note peak task time. If peak exceeds 70% of task period, refactor heavy FBs into slower tasks or split logic across periodic tasks.
Best Practices for OOP in OMRON PLCs
- One FB per physical asset. Wrap each motor, valve, sensor, or PID loop in its own FB. Avoid creating "god" FBs that handle 20 different functions.
- Keep the interface minimal. Expose only what callers need. Internal variables should remain internal — do not mark every variable as VAR_OUTPUT.
-
Use methods for actions, properties for state. Reserve
Start,Stop,Resetas methods. ExposeSpeedSP,Pressure,Statusas properties. - Reuse via libraries, not copy-paste. Centralize a motor FB in a library; reference it from every project. Update the library once, propagate everywhere.
- Version everything. Tag library releases with major.minor.patch. Document breaking changes in a method-accessible changelog.
- Limit nesting depth. FBs calling FBs calling FBs compounds scan time and obscures the call stack. Three levels of nesting is a practical limit.
- Test FBs in isolation. Use Sysmac Studio's simulation mode (NJ/NX) to verify FB logic without a physical rack. On CP1/CJ2, use CX-Simulator.
- Avoid global variables inside FBs. Globals defeat encapsulation. If two FBs need to share data, pass it explicitly through in-out parameters.
- Use retain attributes deliberately. Mark only the variables that must survive a power cycle as Retain. Non-retained variables initialize to default values on every cold start.
Troubleshooting OOP Code
| Symptom | Likely Cause | Resolution |
|---|---|---|
| "Undefined method" error at compile | Sysmac Studio version older than 1.20, or FB was upgraded in newer version | Update Sysmac Studio; refresh library references via Project → Library → Update |
| FB instance variables reset on power cycle unexpectedly | Internal variables not marked Retain | Check the Retain attribute on the VAR section; set to Retain for state that must survive power-off |
| Scan time increased after adding FBs | Excessive FB nesting, large state machines, or string operations in ST | Profile with Sysmac Studio's Task Period monitor; refactor heavy operations to background tasks |
| Library cannot be opened in older project | Library created with newer Sysmac Studio version | Recompile library targeting the minimum supported version; document minimum in release notes |
| Method returns unexpected value | Method called before FB inputs updated in scan | Verify scan order; place FB input assignments before method call in the program section |
| Property read returns stale value | Setter never invoked; backing variable updated directly bypassing the setter | Update backing variable only through the property setter; mark internal VAR as Protected where possible |
| Online edit of FB body fails | Controller in RUN mode without online edit support for that FB | Switch to PROGRAM mode, or download full project; verify Sysmac Studio 1.30+ for full online edit support |
CX-Programmer vs Sysmac Studio: OOP Feature Comparison
| Feature | CX-Programmer 9.x | Sysmac Studio 1.40+ |
|---|---|---|
| Function Block instances | Yes | Yes |
| Structured Text | Yes | Yes |
| Methods on FBs | No | Yes (IEC 61131-3 3rd Ed.) |
| Properties on FBs | No | Yes |
| FB inheritance | No | No (emulated via composition) |
| Library format | .cxf, .cxl | .slr |
| Integrated simulation | CX-Simulator (separate install) | Built-in simulator with virtual rack |
| Online edit of FB bodies | Limited | Yes, with change tracking |
| Version control integration | File-based, no native git | Project export to file set, import into git |
| ST debugging breakpoints | No | Yes (Sysmac Studio 1.25+) |
| 3rd party library marketplace | Limited | OMRON Sysmac Library portal |
Standards Reference
The OMRON implementation tracks IEC 61131-3 Third Edition, which is the international standard for PLC programming languages. Engineers specifying or auditing OOP code on OMRON should reference:
- IEC 61131-3:2013 — Programmable controllers, Part 3: Programming languages (Third Edition). The methods and properties definitions are in Section 6.5.2; the FUNCTION_BLOCK definition is in Section 6.5.1.
- PLCopen Guidelines for Object Orientation — Extension documents for OO concepts on top of IEC 61131-3, published by PLCopen.
OMRON's Sysmac Studio libraries published on the OMRON industrial automation portal conform to the OMRON FB Style Guide, which encodes the conventions described above as default templates. When auditing third-party libraries, verify that the FB signatures match the OMRON conventions for input ordering (Cmd, Status, Setpoint, Feedback) to ensure interchangeability across projects.
Practical Migration Path: CX-Programmer FBs to Sysmac Studio Methods
Engineers with existing CP1/CJ2/CS1 code can migrate to NJ/NX without rewriting the FB logic. The FB body, variable table, and instance names transfer directly. The migration steps are:
- Open the CX-Programmer project in Sysmac Studio using the Import CX-Project tool (File → Import → CX-Programmer Project).
- Sysmac Studio maps the existing FB instances and translates the ladder or ST body. Internal variables are preserved.
- Add methods to the imported FB that wrap the existing body logic. The original FB body becomes the default method (often
ExecuteorRun). - Expose critical state variables as properties for external read/write.
- Update library references to use the new
.slrfile instead of.cxf. - Compile, simulate, and download to the new NJ/NX controller.
The migration is largely mechanical. Most of the time is spent validating that the new method call points match the old program sequence. Existing ladder sections are preserved by Sysmac Studio as separate POU instances of the same FB.
Does OMRON support full OOP with class inheritance?
No. OMRON's IEC 61131-3 implementation on NJ/NX supports encapsulation (Function Blocks), methods, and properties, but not class inheritance. Engineers emulate inheritance through composition (an FB containing an instance of a "base" FB) or by enforcing naming conventions across sibling FBs.
What is the minimum Sysmac Studio version for methods and properties?
Sysmac Studio 1.20 introduced methods and properties for FBs on NJ-series controllers. Version 1.40 or later is recommended for current feature support, including the latest library format and integrated simulator improvements. Sysmac Studio 1.50 added extended debug features for FB methods, including per-method breakpoints and call-stack inspection.
Can I use Function Blocks on a CP1H or CJ2M PLC?
Yes. CP1, CP1H, CP1L, CJ1, CJ2, and CS1 controllers all support Function Block instances defined in CX-Programmer. However, these platforms do not support methods or properties on FBs — those features require NJ/NX with Sysmac Studio. The standard workaround for older platforms is subroutine-based "methods" that take the FB instance as an in-out variable, providing similar encapsulation without the syntactic sugar.
How much scan-time overhead does a typical FB add?
On an NJ501-1500, a state-machine FB with 20 internal variables and three TON timers adds approximately 2–4 µs per scan. On a CJ2M-CPU35, the same FB adds approximately 30–80 µs. Profile the actual cost using Sysmac Studio's task monitor or CX-Programmer's cycle time display — heavy nesting (3+ levels) compounds overhead and can push scan time beyond task period, causing task overruns.
Is OOP in PLCs faster or slower to develop than ladder?
For complex algorithms (state machines, math, batch logic, motion sequences), OOP-style FBs in Structured Text are typically 30–50% faster to develop and 3–5× easier to maintain than equivalent ladder. For simple discrete I/O logic (a single solenoid, an interlock), ladder remains more efficient. The productivity crossover is around 50–100 lines of logic per device — beyond that, FB+ST wins; below that, ladder wins on raw development time.