Problem Overview
When encapsulating MC_Power, MC_MoveJog, MC_MoveAbsolute, or any other PLCopen motion control function block inside a user-defined Function Block (FB) on a SIMATIC S7-1200 (for example CPU 1214C DC/DC/DC or CPU 1214FC) programmed with TIA Portal V15.1, the compile passes cleanly and the download to the target completes without complaint. Within seconds, however, the CPU's ERROR LED starts flashing red, the RUN LED goes dark, and the diagnostic buffer records an entry similar to:
Event ID 16#80B1
"Access error (data block type) DB1 in FB1 - Processing will continue (no OB processing)"
Cyclic OB execution is suspended. The CPU behaves as if a non-fatal class error has been promoted to a hard fault: a STOP->RUN transition, MRES, or power cycle is required to clear the state. The same MC blocks, when dropped directly into OB1, run perfectly. The fault is therefore not a motion problem, hardware problem, or wiring problem; it is a data-type problem introduced by the wrapper FB.
Symptom Stack
| Layer | Observed Behavior |
|---|---|
| Compile | No error, no warning. Block consistency OK. |
| Download to target | Transfer completes; RUN LED may briefly turn green. |
| CPU front panel | ERROR LED flashes red; RUN LED off or flashing red. |
| Diagnostic buffer | Event ID 16#80B1, text "Data block type mismatch" or "Access error (data block type)". |
| Online & Diagnostics | Class "Programming error", OB1 halted, no further cyclic execution. |
| Axis Control Panel | Disconnected — TO not reachable while CPU is in error state. |
Root Cause: Datatype Mismatch
The PLCopen motion control FB family on S7-1200 is generated from the Siemens technology-object runtime. Every MC block exposes an Axis input typed as a derived User-Defined Type based on the abstract UDT TO_Axis. The hierarchy, as compiled into the motion control library, is:
TYPE TO_Axis
// abstract base, contains common fields:
// VersionNumber, InternalToInterface, etc.
END_TYPE
TYPE TO_PositioningAxis EXTENDS TO_Axis
// positioning-specific fields:
// Position, Velocity, StatusWord, ErrorWord, ...
END_TYPE
TYPE TO_SpeedAxis EXTENDS TO_Axis
// speed-only fields:
// Velocity, StatusWord, ...
END_TYPE
TYPE TO_ExternalEncoder EXTENDS TO_Axis
// encoder fields:
// Position, StatusWord, ...
END_TYPE
When you drag a technology object from the project tree directly onto the Axis input of an MC block that lives in OB1, TIA Portal performs compile-time type resolution. The TO's instance-DB number is stored in the call environment together with its UDT fingerprint (a 16-byte version stamp at the start of the DB). The MC block's internal code dereferences the DB header, finds the expected UDT signature, validates it, and runs.
When the MC block is moved inside a wrapper FB and the wrapper FB declares an input of type DB_ANY, the connection becomes a generic DB-number reference. TIA Portal stores the DB number but loses the UDT fingerprint because DB_ANY is by definition untyped. At runtime, the firmware attempts to validate the block header as a TO_PositioningAxis (or whichever specific UDT is required), reads the version stamp at DBB 0..7, and finds the header of a regular instance DB rather than a technology object DB. The mismatch is logged as event 16#80B1 and the OB is suspended.
Why DB_ANY Feels Right but Is Wrong
DB_ANY is the correct datatype for passing an arbitrary instance DB to blocks such as DPRD_DAT, DPWR_DAT, PEEK / POKE, or the data-log instructions that need a DB number but no schema. Motion control FBs are not generic-data consumers; they are tightly coupled to the technology-object schema and require a UDT that matches the axis variant. The S7-1200 firmware performs a strict runtime check; there is no implicit conversion from DB_ANY to a UDT-typed reference.
Siemens S7-1200 Motion Control Architecture
Understanding why the firmware check exists requires a quick tour of the S7-1200 motion control subsystem. The relevant components are:
-
Technology Objects (TOs) — DBs with the UDT
TO_PositioningAxis,TO_SpeedAxis, orTO_ExternalEncodergenerated by the "Add new object" wizard under Technology objects > Motion Control in the TIA project tree. - MC Instruction Library — Blocks under Instructions > Technology > Motion Control, each typed against the specific TO UDT. The library is regenerated on each TIA Portal upgrade; the V15.1 library uses firmware target V4.3 and higher.
- PTO / Pulse Train Output — Hardware interface (onboard CPU outputs or signal-board outputs such as SB 1222 DQ4) bound to the TO via the axis configuration editor. Up to four PTOs are supported on a CPU 1214, depending on the firmware version and signal-board configuration.
- Axis Control Panel — Online commissioning tool that exercises jog, homing, and absolute moves without requiring any PLC code. Used to validate that the axis hardware and TO configuration are correct before connecting MC blocks.
- Trace / Scope — TIA's built-in signal trace, capable of recording axis variables at 1 ms resolution on S7-1200 firmware V4.2 and higher.
Reference documentation: SIMATIC S7-1200 Motion Control V15.1 Function Manual; SIMATIC S7-1200 Programmable Controller System Manual (V15.1); PLCopen Technical Committee 2 — Motion Control.
Correct Resolution: Declare Inputs as TO_Axis
The fix is to declare the wrapper FB's axis input with the actual UDT that the MC block expects. There are three valid approaches. Pick the one that matches your code-reuse strategy.
Approach 1 — Use TO_Axis (Generic Axis)
Use the abstract base type when a single FB must work with positioning, speed, and external-encoder axes interchangeably.
- Open FB1 in TIA Portal.
- In the FB interface, change the input
Axis_NamefromDB_ANYtoTO_Axis. - Save and compile. The MC blocks inside FB1 accept the input because
TO_PositioningAxis,TO_SpeedAxis, andTO_ExternalEncoderall inherit fromTO_Axis. - At the call site of FB1 in OB1, drag the technology object from the project tree onto the
Axis_Nameinput. TIA Portal performs an implicit downcast to the correct UDT and the firmware check passes.
Example FB1 interface declaration in SCL (compiled output of the TIA Portal editor):
FUNCTION_BLOCK FB_AxisController
VAR
AxisName : TO_Axis; // accepts any axis variant
PowerInst : MC_Power;
MoveRelInst : MC_MoveRelative;
MoveAbsInst : MC_MoveAbsolute;
JogInst : MC_MoveJog;
ResetInst : MC_Reset;
bEnable : BOOL;
fDistance : LREAL;
fVelocity : LREAL;
END_VAR
BEGIN
PowerInst(Axis := AxisName, Enable := bEnable);
// MoveRelInst(Axis := AxisName, Distance := fDistance, Velocity := fVelocity, Execute := bEnable);
// MoveAbsInst(Axis := AxisName, Position := fDistance, Velocity := fVelocity, Execute := bEnable);
END_FUNCTION_BLOCK
Approach 2 — Use the Specific Axis Variant
If the FB is dedicated to a single axis type, use the more restrictive type. This enables compile-time type checks and prevents the FB from being wired to the wrong technology object class.
VAR
AxisName : TO_PositioningAxis; // restricts to positioning axes only
END_VAR
Attempting to connect a TO_SpeedAxis to this input produces a compile error in the message window: "The data types of the actual parameter and the formal parameter do not match." This is the safest pattern in machine-builder code where a wrapper FB is intended for one motion type.
Approach 3 — Multi-Instance via Static VAR (No External Input)
If only one axis is ever used inside FB1, declare the MC blocks as multi-instance statics in the FB's Static section, drag the technology object directly into each MC block's Axis input, and eliminate the external axis input altogether. This was the original workaround used to clear the error in the field report.
FUNCTION_BLOCK FB_AxisStatic
VAR
PowerInst : MC_Power; // multi-instance, no external Axis input
bEnable : BOOL;
END_VAR
BEGIN
PowerInst(Enable := bEnable); // Axis wired directly to "Axis1" TO inside the block
END_FUNCTION_BLOCK
The TO reference is resolved at compile time inside the multi-instance's input. There is no DB_ANY indirection, so the runtime type check passes unconditionally. The cost is that the FB can only drive one specific axis; you cannot reuse it for "Axis2" without a project re-edit.
Why Multi-Instance Matters
Placing MC blocks in the static section of an FB creates a multi-instance. The instance DB created when FB1 is called holds all of the MC block's internal data plus FB1's own static tags. The TO reference is resolved once, at compile time, inside the multi-instance's input. This is the recommended pattern for the S7-1200 and is documented in the TIA Portal help under Multi-instances in FBs.
| Storage Class | Resolution Mechanism | Type Safety | Multi-Axis Support |
|---|---|---|---|
| Multi-instance static | Compile-time, in-block | Strong (compile-time) | One axis per FB call; use array of FBs for many |
| FB input typed as TO_Axis | Compile-time, at call site | Strong (compile-time + runtime UDT check) | Yes — pass any axis at call time |
| FB input typed as specific UDT (TO_PositioningAxis) | Compile-time, at call site | Strongest (compile-time type match) | Yes, but only matching axis variants |
| FB input typed as DB_ANY | Untyped pointer at runtime | None — fails MC block validation | Yes, but broken |
| FB input typed as INT (DB number) | Manual interpretation | None | Yes, but broken |
FB Call Site Wiring
After the datatype change, OB1 wires the technology object to the FB input. Two wiring methods work:
-
Drag-and-drop — Drag the technology object from the project tree (or from the "Technology objects" folder in the PLC tags) onto the FB instance's
Axis_Nameinput. TIA Portal stores the full TO reference, including the UDT fingerprint. - Symbolic assignment — Use the symbolic name of the TO in SCL or STL. The assignment operator resolves the TO at compile time.
Do not pass the absolute DB number (e.g. DB_ANY from a global DB of INT values) under any circumstance; this is the path that produces the original error.
Verification Procedure
- After the datatype change, perform a full compile of the S7-1200 station. The message window must show "0 errors, 0 warnings."
- Download the project in RUN mode. TIA will prompt to stop the CPU if the interface change requires it.
- Watch the CPU's ERROR LED — it must remain off.
- Open Online & Diagnostics > Diagnostic buffer. Confirm no new entries with event ID 16#80B1 or class "Programming error / Data block type mismatch".
- Place FB1 in OB1 with the technology object connected to the
Axis_Nameinput. - Set
bEnable := TRUEvia a watch table. - Use the Axis Control Panel (or a
MC_MoveJoginstance) to verify the drive follows the command. ConfirmMC_Power.Status= TRUE andMC_Power.Error= FALSE. - Run a controlled move with
MC_MoveRelativeorMC_MoveAbsoluteand verify the actual position matches the command within the configured positioning tolerance. - Trigger an error scenario (e.g. disable the drive enable input on the drive side) and verify
MC_Power.Error= TRUE andMC_Power.ErrorIDreports a sensible motion-control error code. - Recover with
MC_Resetand confirm the axis returns to operable state.
Related Error Codes and Their Meaning
| Event ID | Meaning | Typical Cause |
|---|---|---|
| 16#0071 | MC block internal error | Axis not configured in TO tree |
| 16#80B1 | Data block type mismatch | DB_ANY passed where TO_Axis expected (this article's root cause) |
| 16#8090 | TO not found / version incompatible | TO deleted but reference remains; project upgraded from V13 SP1 without TO conversion |
| 16#80A1 | Axis already enabled by another MC_Power | Two MC_Power instances point to the same TO |
| 16#80C3 | Axis not enabled (MC_Power.Status = FALSE) | Power enable not asserted or hardware enable missing |
| 16#80C4 | Homing required | Absolute move issued before homing or after restart |
| 16#80C5 | Homing in progress | Move command issued while homing is active |
| 16#80D0 | Encoder value range overflow | Modulo configuration error or high travel distance |
Event IDs are taken from the S7-1200 Motion Control V15.1 Function Manual diagnostic-event table. The complete list runs from 16#8000 through 16#80FF; consult the manual for the full map.
Common Pitfalls and Edge Cases
-
Dropping the technology object into a tag of type INT. This compiles but produces a runtime crash identical to
DB_ANY. Always use a UDT from the Motion Control palette. -
Reusing the same FB instance DB across multiple MC blocks expecting different axis types. Mixing
TO_PositioningAxisandTO_ExternalEncoderin the same instance is not supported and produces a UDT-incompatibility error at compile time only if you are lucky. - Forgetting to update the technology object DB number after copying FB code from another project. The DB number is project-scoped and must be regenerated or remapped through the project tree.
- Using TIA Portal V13 SP1 or V14 projects without running the TO upgrade tool. The TO UDT hierarchy was reorganized in V15.0. Projects created in V13 SP1 with MC blocks require a one-time conversion via the "Upgrade technology objects" command under the project-tree context menu.
- Calling the wrapper FB from a different priority class (e.g. OB35 cyclic interrupt) without re-evaluating motion semantics. MC blocks can be called from any OB, but the technology object's update tick is tied to the configured servo/POU cycle. Mismatched cycle times cause jitter or following errors.
- Using a global DB field of type TO_Axis to share the axis between FBs. This works but creates a single global handle; calling two MC blocks that each expect exclusive ownership of the TO can lead to event 16#80A1 (axis already enabled).
- Renaming a technology object in the project tree without updating the symbolic references. Symbolic references in SCL and the ladder editor follow the rename, but DB-number references stored in instance data do not. Use "Rewire" or "Compile all" after any rename.
Firmware Version Notes
The S7-1200 motion control subsystem has evolved across firmware versions. The behaviour described in this article is consistent from firmware V4.1 onward, with these notable milestones:
| Firmware | TIA Portal | Relevant Change |
|---|---|---|
| V4.0 | V13 SP1 | Initial PLCopen Part 2 support; original TO UDT layout. |
| V4.1 | V14 | Improved diagnostics; clearer error messages for UDT mismatches. |
| V4.2 | V14 SP1 | Trace / scope at 1 ms for axis variables; new modulo configuration. |
| V4.3 | V15 / V15.1 | TO UDT hierarchy extended; S7-1200 supports up to 4 PTOs and 4 encoders. |
| V4.4 | V16 | ProDiag support for motion blocks; OPC UA exposure of TO variables. |
| V4.5 | V17 | Increased number of supported TOs to 12; enhanced torque-diminished homing. |
The CPU 1214C originally shipped with firmware V4.0; current production is V4.4 or higher. Always check the firmware version in Online & Diagnostics > General before assuming a specific behaviour.
S7-1500 Differences
The S7-1500 motion control subsystem uses the same PLCopen FB interface and the same TO UDT concept, but with significant extensions:
- TO counts — S7-1500 supports up to 32 axes on a CPU 1515 and up to 128 on a CPU 1518, compared with 4 to 12 on S7-1200.
- Synchronous operations — S7-1500 supports cams, cam tracks, and the full PLCopen Part 4 synchronization profile. S7-1200 supports only Part 1 (single-axis motion) and a subset of Part 2 (electronic gearing).
-
Datatype handling — The same
TO_Axis/TO_PositioningAxis/TO_SpeedAxishierarchy applies. The fix described in this article transfers directly: declare wrapper FB inputs as the correct UDT and the runtime UDT check passes. -
Axis alarms — S7-1500 exposes axis alarms in the PLC alarm view; S7-1200 returns the error via
MC_xxx.ErrorIDonly.
If you are porting an S7-1200 program that contains the wrapper FB to an S7-1500, the FB interface does not need to change. The TO UDT is the same.
Array-of-Axis Pattern for High Axis Counts
For machines with many similar axes, an array of wrapper FB instances provides scalable, maintainable code. Declare an array of the wrapper FB and an array of TO references, then loop through the array in OB1:
VAR PUBLIC
AxisController : ARRAY[1..4] OF FB_AxisController;
AxisRefs : ARRAY[1..4] OF TO_PositioningAxis;
bEnable : ARRAY[1..4] OF BOOL;
END_VAR
// OB1:
FOR i := 1 TO 4 DO
AxisController[i](
AxisName := AxisRefs[i],
bEnable := bEnable[i]
);
END_FOR;
Each call of FB_AxisController uses a different element of AxisRefs. The compiler emits a multi-instance data block that contains all four FB instances plus their MC block statics, scaled by the array bound. This pattern is the recommended approach for indexing-based motion control and is documented in the TIA Portal help under FB multi-instances in arrays.
Hardware Variants and PTO Limits
The CPU 1214 family includes several hardware variants. The PTO count and encoder support depend on the variant and on whether a signal board is installed:
| CPU | Order Number (example) | Onboard PTOs | With SB 1222 | Firmware at Delivery |
|---|---|---|---|---|
| CPU 1214C DC/DC/DC | 6ES7214-1AG40-0XB0 | 4 | 4 (SB shared with onboard) | V4.4 |
| CPU 1214C DC/DC/Rly | 6ES7214-1HG40-0XB0 | 4 | 4 | V4.4 |
| CPU 1214FC DC/DC/DC (fail-safe) | 6ES7214-1AF40-0XB0 | 4 | 4 | V4.4 |
| CPU 1214C AC/DC/Rly | 6ES7214-1BG40-0XB0 | 4 | 4 | V4.4 |
The four onboard PTOs are fixed to specific output bytes. The signal-board PTOs share output resources with the onboard PTOs and must be configured under Device configuration > Pulse generators. If the project demands more than four axes, step up to a CPU 1215 or CPU 1217, or move to the S7-1500 platform.
Troubleshooting Matrix
| Symptom | Likely Cause | Diagnostic Step | Fix |
|---|---|---|---|
| ERROR LED red, 16#80B1 | DB_ANY passed where TO_Axis expected | Inspect FB interface in editor; check input datatype | Change input to TO_Axis or specific UDT |
| Compile error "Data types do not match" | Wrong UDT or generic INT | Hover over the red squiggle in editor | Use the specific TO UDT required by the MC block |
| ERROR LED red, 16#8090 | TO deleted from project tree | Compare project tree to FB interface | Recreate TO or rewire FB to an existing TO |
| MC_Power.Status stays FALSE, no error | Hardware drive enable missing | Check drive wiring and configuration | Enable drive-side enable input; check PTO wiring |
| Axis following error in trace | Closed-loop tuning or mechanical binding | Inspect trace recording of position vs command | Adjust axis dynamics; verify mechanical installation |
| MC_Power.Error = TRUE after recovery | Error condition not cleared | Check MC_Power.ErrorID and ErrorInfo | Issue MC_Reset after fixing root cause |
FAQ
What does the "Access error (data block type)" diagnostic message mean on an S7-1200?
It means the firmware tried to interpret a data block as a UDT that does not match the block's actual type. In motion-control FBs this almost always traces to a DB_ANY input where a TO_Axis is required. The error is event ID 16#80B1 and halts OB execution until a STOP->RUN transition.
Can I pass a technology object to a function block using DB_ANY?
No. MC_Power and the other PLCopen MC blocks are compiled against the TO UDT and perform a runtime type check. Use TO_Axis, TO_PositioningAxis, TO_SpeedAxis, or TO_ExternalEncoder as the FB input type. DB_ANY strips the UDT fingerprint and breaks the check.
Why does MC_Power work in OB1 but not inside my wrapper FB?
When the block sits in OB1, the technology object is wired directly and the type check is resolved at compile time. Inside a wrapper FB, the input is a parameter and must be declared with a UDT that survives the indirection. DB_ANY loses the UDT fingerprint and the runtime check fails.
Do I need a separate instance DB for each FB that contains MC blocks?
Yes. Each call of the wrapper FB must have its own instance DB (single-instance or multi-instance) so that the MC blocks' static tags do not collide. Multi-instance statics inside the FB share the parent instance DB and are the recommended pattern. Arrays of FBs in a multi-instance DB scale to many axes without DB explosion.
Which TIA Portal version introduced the strict TO_Axis type check?
The behaviour has been in place since S7-1200 motion control V4.1 firmware, paired with TIA Portal V14. TIA Portal V15.1 enforces it at compile time and surfaces clearer diagnostic messages compared to V13 SP1, where the error often appeared as a generic "OB processing error" without a clear pointer to the data type.