Simotion OOP: Declaring Classes in the ST Unit Interface Section
In SIMOTION programming, an ST source file is organized as a UNIT with two distinct declaration sections: INTERFACE and IMPLEMENTATION. The placement of a CLASS declaration inside one section or the other controls its visibility to other units in the project. Declaring a class in the INTERFACE section exports it; declaring it in the IMPLEMENTATION section keeps it private. This behavior implements the IEC 61131-3 third edition scope rules and is fundamental to organizing OOP code in SIMOTION SCOUT and SIMOTION inside TIA Portal.
This reference covers the technical rationale, the compiler rules, the USES mechanism, the relationship to OOP interfaces, and field-proven patterns for organizing class libraries in SIMOTION.
1. ST Unit Structure in SIMOTION
Every ST source file compiled by the SIMOTION compiler is wrapped in a UNIT envelope. The minimum valid structure looks like this:
UNIT MyUnit;
INTERFACE
// Exported declarations: visible to other units via USES
END_INTERFACE
IMPLEMENTATION
// Local declarations: visible only inside this unit
END_IMPLEMENTATION
END_UNIT.
The compiler enforces a strict order: INTERFACE always precedes IMPLEMENTATION, and the unit terminator END_UNIT. (note the terminating period) must close the file.
The following declaration types may appear in either section:
| Declaration | Allowed in INTERFACE | Allowed in IMPLEMENTATION |
|---|---|---|
FUNCTION_BLOCK |
Yes (exported) | Yes (local) |
FUNCTION |
Yes (exported) | Yes (local) |
CLASS (OOP, IEC 61131-3 3rd ed.) |
Yes (exported) | Yes (local) |
INTERFACE (OOP interface) |
Yes (exported) | Yes (local) |
PROGRAM |
No | No (top-level only) |
VAR_GLOBAL |
Yes (with CONSTANT or RETAIN attributes) | Limited |
TYPE aliases |
Yes | Yes |
The choice of section determines scope. The compiler emits visibility metadata into the unit's symbol table, and downstream units that include this unit will only see the INTERFACE portion.
2. Why a Class Is Declared in the INTERFACE Section
The CLASS keyword introduces an object-oriented class as defined in IEC 61131-3 3rd edition. SIMOTION OOP supports:
- Class declaration with
EXTENDS(single inheritance) -
METHOD,PROPERTY, andVARinPUBLIC,PRIVATE,PROTECTED, andINTERNALaccess sections - Class instantiation via
fbInstance : CLASS_NAME;followed byfbInstance := fbInstance$ClassName(); -
INTERFACEdeclarations (pure abstract classes) - Polymorphic dispatch via interface references (see section 7)
A class must be visible (declared) in the INTERFACE section of its unit if any other unit in the program needs to:
- Instantiate it (
obj := obj$ClassName();) - Declare a variable or instance of the class type
- Call its
PUBLICmethods or read/write itsPUBLICproperties - Extend it via
EXTENDS - Reference it through an OOP
INTERFACEvariable
Without an INTERFACE declaration, the class is local to its unit. The compiler will reject any cross-unit reference with error F1101 "Type 'XYZ' is not exported by unit 'ABC'" (or the equivalent localized message in SIMOTION SCOUT). Removing the class from INTERFACE and placing it only in IMPLEMENTATION makes it inaccessible outside the unit, even if other units include this unit via USES.
3. The USES Statement: Importing an Exported Class
To consume a class exported by another unit, the consuming unit must declare a USES clause that names the source unit. The USES statement appears at the top of the consuming unit, before any INTERFACE or IMPLEMENTATION block content.
USES ValveControlLib; // Imports all INTERFACE exports from ValveControlLib
UNIT MyConsumerUnit;
INTERFACE
VAR
MyValve : ValveControl; // Class declared in ValveControlLib INTERFACE
END_VAR
END_INTERFACE
IMPLEMENTATION
// MyValve instantiation and method calls
END_IMPLEMENTATION
END_UNIT.
Key rules for USES:
- The referenced unit must be compiled in the same SIMOTION device or in a referenced library.
- Only the
INTERFACEsection symbols become visible;IMPLEMENTATIONsymbols remain hidden. - Circular
USESdependencies are rejected by the compiler (error F1102). - The order of
USESstatements matters only when two units export symbols with identical names; the laterUSESshadows the earlier (with a compiler warning).
4. INTERFACE vs. IMPLEMENTATION: Decision Matrix
Use the following matrix to decide where each class belongs:
| Requirement | INTERFACE | IMPLEMENTATION |
|---|---|---|
| Class is referenced by programs in other units | Required | Not allowed |
| Class is only used by code inside its own unit | Optional (but harmless) | Recommended |
| Class is part of a published library | Required (for all public classes) | Used for helper/internal classes |
| Class is referenced by an OOP interface variable in another unit | Required | Not allowed |
| Class extends another class from a different unit | Required | Not allowed |
A common SIMOTION library pattern is to declare all public, reusable classes in INTERFACE and all implementation helpers in IMPLEMENTATION. For example, the ValveControl class with error reporting (chapter 4.5.7.2 of the Michael Braun reference text) is exported, while a private ValveStateHelper class used internally by ValveControl methods stays local.
5. Concrete Example: ValveControl with Error Reporting
The following example mirrors the structure of the canonical "ValveControl with Error Reporting" sample (chapter 4.5.7.2 of "Object-Oriented Programming with SIMOTION", ISBN 9783895784569, Publicis MCD). It demonstrates a class exported via INTERFACE and consumed by an MCC unit or ST program in another unit.
Unit ValveControlLib — the library that owns the class:
UNIT ValveControlLib;
INTERFACE
CLASS ValveControl
VAR
bIsOpen : BOOL := FALSE;\li bError : BOOL := FALSE;\li nErrorCode : DINT := 0;\li END_VAR
METHOD PUBLIC Open : BOOL
VAR_INPUT
bForce : BOOL := FALSE;
END_VAR
END_METHOD
METHOD PUBLIC Close : BOOL
END_METHOD
METHOD PUBLIC ResetError : BOOL
END_METHOD
PROPERTY PUBLIC State : STRING
GET
IF bError THEN State := 'ERROR';
ELSIF bIsOpen THEN State := 'OPEN';
ELSE State := 'CLOSED';
END_IF;
END_GET
END_PROPERTY
END_CLASS
END_INTERFACE
IMPLEMENTATION
METHOD PUBLIC ValveControl : BOOL
// (Destructor / class body override if needed)
END_METHOD
METHOD PUBLIC ValveControl.Open : BOOL
// implementation omitted for brevity
END_METHOD
METHOD PUBLIC ValveControl.Close : BOOL
// implementation omitted for brevity
END_METHOD
METHOD PUBLIC ValveControl.ResetError : BOOL
bError := FALSE;
nErrorCode := 0;
ResetError := TRUE;
END_METHOD
END_IMPLEMENTATION
END_UNIT.
Unit ValveUser — a consumer in a different unit:
USES ValveControlLib;
UNIT ValveUser;
INTERFACE
VAR_GLOBAL
g_Valve1 : ValveControl;
END_VAR
END_INTERFACE
IMPLEMENTATION
// g_Valve1 := g_Valve1$ValveControl(); // typically auto-instantiated by runtime
END_IMPLEMENTATION
END_UNIT.
Removing the CLASS ValveControl block from INTERFACE in ValveControlLib would cause the compiler to fail when processing ValveUser with a "type not exported" error. The class would still be usable inside ValveControlLib, but invisible elsewhere.
6. INTERFACE Section and OOP Interfaces (Distinct Concepts)
SIMOTION's OOP extension (IEC 61131-3 3rd edition) introduces the INTERFACE keyword as a class type that contains only abstract methods and properties. The example chapter 4.5.5 "Interfaces as reference to classes" demonstrates using an OOP interface to decouple consumers from concrete implementations:
INTERFACE IValveController
METHOD Open : BOOL END_METHOD
METHOD Close : BOOL END_METHOD
PROPERTY State : STRING END_PROPERTY
END_INTERFACE
A class then implements the interface with IMPLEMENTS:
CLASS ValveControl IMPLEMENTS IValveController
// ... methods, properties, plus IMPLEMENTS binding ...
END_CLASS
Consumers can declare variables of type IValveController and assign any class that implements it. This enables polymorphic dispatch. The OOP INTERFACE itself, like a class, must be declared in the unit's INTERFACE section to be visible to other units. The two meanings of "interface" remain independent:
| Aspect | ST Unit INTERFACE section | OOP INTERFACE |
|---|---|---|
| Defined by | IEC 61131-3 source organization | IEC 61131-3 3rd edition OOP |
| Controls | Unit symbol visibility | Polymorphic class contract |
| Keyword |
INTERFACE ... END_INTERFACE
|
INTERFACE ... END_INTERFACE
|
| Can contain | Any exportable declaration | Only abstract methods and properties |
| Location | Top of UNIT | Inside INTERFACE or IMPLEMENTATION section |
Both may coexist in the same unit. The OOP interface is itself an exportable type and follows the same visibility rules as a class — declare it in the unit INTERFACE if consumers need to reference it.
7. Compiler Diagnostics and Error Codes
When class visibility is misconfigured, the SIMOTION compiler reports specific errors. The exact wording varies by SCOUT version, but the canonical forms are:
| Error Code | Message | Cause | Resolution |
|---|---|---|---|
| F1101 | Type 'X' is not exported by unit 'Y' | Consuming unit references a class that is not in the source unit's INTERFACE | Move the CLASS declaration to INTERFACE, recompile the source unit, then the consumer |
| F1102 | Circular USES dependency detected | Unit A uses B, B uses A (directly or transitively) | Refactor: extract shared types into a third base unit |
| F1103 | Duplicate type definition in USES chain | Two imported units export the same type name | Rename the class or use qualified references |
| W1104 | USES statement shadows earlier import | Two USES exports share a symbol name | Qualify the reference or rename the symbol |
| F1140 | Class 'X' cannot EXTENDS class 'Y' from a non-exported unit | Parent class is local to its unit | Export the parent class via INTERFACE |
Always compile library units before their consumers. In multi-programmer projects, enforce a build order in the SCOUT project or in the CI pipeline to surface these errors early.
8. Best Practices for Class Organization in SIMOTION
Field-proven organization rules for SIMOTION ST libraries:
- One concept per unit. Combine a tightly-coupled set of classes (interface + concrete implementation + factory) in a single unit, exported together.
- Declare public API in INTERFACE, helpers in IMPLEMENTATION. Keep helper classes, internal types, and constants local to reduce coupling.
- Avoid deep USES chains. More than three levels of indirection causes compile-time slowdown and obscures the dependency graph.
-
Use OOP interfaces for swappable behavior. When a class family (e.g., different valve types) shares a contract, define an OOP
INTERFACEand have each variant implement it. Reference the interface in the consumer unit'sINTERFACEsection. - Never place PROGRAMs in INTERFACE. Programs are top-level execution units and belong in the MCC chart or the program organization unit (POU) folder.
- Document the INTERFACE contract. Add a comment block above each exported class describing its lifecycle, threading model, and required initialization sequence.
-
Version your library units. Add a
VAR_GLOBAL CONSTANTblock at the top ofINTERFACEwith a version identifier (e.g.,c_LibVersion : STRING := '2.3.1';) so consumers can assert compatibility at compile time.
9. Verification: Confirming Class Export
After declaring a class in INTERFACE and adding a USES clause in the consumer, verify the export with these steps:
- In SIMOTION SCOUT, open the Project Navigator and select the library unit.
- Choose Compile > Check Consistency. The build should complete without F1101/F1140 errors.
- Open the consumer unit, place the cursor on a reference to the imported class, and press F2 (Go to definition). The IDE should jump to the exported class in the source unit's INTERFACE section. If it does not, the import failed.
- Open the Symbol Browser in the consumer unit and confirm the imported class appears with its full unit-qualified name (e.g.,
ValveControlLib.ValveControl). - Cross-compile the device. If the runtime download succeeds, the visibility chain is intact.
For SIMOTION inside TIA Portal, the equivalent steps are: right-click the device > Compile > Software (rebuild), then inspect the Type tab in the program info to confirm the imported classes are listed.
10. Common Pitfalls and Edge Cases
Engineers learning SIMOTION OOP frequently encounter the following issues:
Forgetting the terminating period in END_UNIT. The compiler expects END_UNIT. with a period. A semicolon or no terminator produces a cryptic parse error and may mask the real visibility issue.
Mixing MCC and ST units. MCC charts cannot directly instantiate a class declared in an ST unit's IMPLEMENTATION section. Always export via INTERFACE if MCC or another ST unit needs to interact with the class.
Library upgrades breaking consumers. Adding a method to an exported class is binary-compatible. Removing or renaming an exported class is not. Document the INTERFACE surface as a public API and treat changes with semantic-versioning discipline.
Confusing unit INTERFACE with namespace. SIMOTION units are not C#-style namespaces. Two units may export symbols with the same name; the last USES wins unless qualified. Use descriptive class names to avoid collisions.
Confusing unit INTERFACE with OOP INTERFACE. Already covered, but it bears repeating: a class declared in a unit's IMPLEMENTATION section is not the same as a class implementing an OOP interface. The OOP interface itself is a class type and follows the same export rules as any other class.
11. Reference Resources
For further study, the canonical printed reference for SIMOTION OOP is:
- Michael Braun, "Object-Oriented Programming with SIMOTION: Practical Introduction with Numerous Examples", Publicis MCD, ISBN 9783895784569. Chapter 4.5.5 covers "Interfaces as reference to classes"; chapter 4.5.7.2 covers the "ValveControl with Error Reporting" example (programming with interfaces).
- IEC 61131-3:2013 (third edition), section 6.5.5 defines the OOP extensions including
CLASS,INTERFACE,EXTENDS,IMPLEMENTS, and access specifiers. - Siemens SIMOTION SCOUT online help, topic "ST source file structure" and "USES statement".
- Siemens SIMOTION programming and operating manual, entry ID 109751706 in the Siemens Industry Online Support portal.
FAQ
What is the difference between the INTERFACE and IMPLEMENTATION sections in a Simotion ST unit?
The INTERFACE section contains exported declarations (classes, function blocks, functions, types, variables with CONSTANT/RETAIN) that are visible to other units that include this unit via USES. The IMPLEMENTATION section contains local declarations visible only inside the unit. A class must be in INTERFACE to be instantiated, extended, or referenced from other units.
How does the USES statement enable a consumer unit to use an exported class?
A USES clause at the top of the consuming unit names the source unit (e.g., USES ValveControlLib). The compiler then makes all INTERFACE symbols of that unit, including classes, available for declaration, instantiation, and method calls. The IMPLEMENTATION symbols of the imported unit remain hidden regardless of USES.
Is the ST unit INTERFACE section the same as the OOP INTERFACE keyword?
No. The ST unit INTERFACE section is a source-organization construct that controls symbol export. The OOP INTERFACE is a class type containing only abstract methods and properties, used for polymorphic dispatch via IMPLEMENTS. Both share the keyword but serve different purposes; an OOP interface itself follows the same export rules as any class.
What compiler error appears if a class is referenced cross-unit without being in INTERFACE?
The compiler reports F1101 "Type 'X' is not exported by unit 'Y'" (or the localized equivalent). The fix is to move the CLASS declaration from IMPLEMENTATION to INTERFACE in the source unit, recompile it, and rebuild the consumer.
Can a class be instantiated by an MCC chart if it is only declared in IMPLEMENTATION?
No. MCC charts and other ST units can only reference classes that are exported via the source unit's INTERFACE section. Move the CLASS declaration to INTERFACE and recompile the library unit before attempting to use the class from MCC or a different ST source.
Where in the Michael Braun book is the canonical example for this topic?
Chapter 4.5.5 "Interfaces as reference to classes" and chapter 4.5.7.2 "ValveControl with Error Reporting" in "Object-Oriented Programming with SIMOTION" (Publicis MCD, ISBN 9783895784569) demonstrate class export via INTERFACE and the OOP interface contract.