Troubleshooting OSCAT ACTUATOR_3P Stuck in Calibration Mode

Jason IP5 min read
Other ManufacturerOther TopicTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Symptom: ACTUATOR_3P Hangs in Calibration Mode

The OSCAT ACTUATOR_3P function block (oscat building library, tested on Phoenix Contact ILC controllers under PC Worx Express) shows two distinct failure patterns in the field:

  • The block stops driving the actuator and freezes with STATUS = 101 and the position output stuck at 255 (full heating / open). Forcing the physical outputs still moves the actuator, which proves the wiring and drive hardware are healthy and the fault sits inside the FB.
  • After a cold start the block never starts at all: STATUS walks through 103 → 104 → 100, but the output stays locked at 0 with no error status raised.

The first pattern correlates with expiry of the calibration timer; the second correlates with a zero external-time parameter. Both are parameter-driven, not hardware-driven.

Root Cause: Auto-Calibration Never Completes

ACTUATOR_3P declares these defaults as VAR_INPUT CONSTANT:

T_RUN  : TIME := t#60s;
T_EXT  : TIME := T#10s;
T_CAL  : TIME := t#600s;
T_DIAG : TIME := T#10d;

Auto-calibration starts as soon as T_CAL > T#0s has elapsed — by default after 600 s (10 min) — and this happens independently of the SWITCH_AVAIL input. The calibration run only terminates when the END_POS end switch is reached. On an installation without end switches (SWITCH_AVAIL not active), END_POS never comes, the calibration never ends, and the block remains in STATUS 101 with the output pinned at one end. Because the calibration fires on a timer regardless of process needs, it can also drive the actuator at the worst possible moment (e.g., a heating-valve actuator opening fully during a winter ventilation start-up, triggering frost protection).

Note a documentation mismatch: the manual describes a CAL_RUNTIME parameter that does not exist as an input; the actual parameter is T_CAL, a TIME value (default 600 s).

Fix: Parameterize the Block Correctly

  1. Set T_CAL := T#0s to block the auto-calibration mode entirely.
  2. Set T_DIAG := T#0s to block the auto-diagnosis as well.
  3. Keep T_EXT > T#0s. With T_EXT := T#0s the actuator does not run after a cold start: STATUS cycles 103 → 104 → 100 while the output stays at 0, and no error status is output. If you must use a zero value here, treat the resulting silent standstill as expected (if undocumented) behavior and check T_EXT first during diagnosis.

With T_CAL and T_DIAG at T#0s and T_EXT above zero, a test program that previously hung within hours has run continuously for more than a day. The trade-off: with auto-calibration disabled and no end switches, nothing re-synchronizes the internally calculated position with the real actuator position, so verify drift on your process (see below).

Verify Library Dependencies and FB Version

Library nesting: ACTUATOR_3P lives in the building library (building_100), which itself requires oscat_basic_333 as a sub-library inside the building library project — not only in your application project. Open the building library as a project and check the linked libraries at the top of the project tree. An outdated oscat_basic_330 linked instead of 333 has been confirmed to cause abnormal behavior in related OSCAT blocks on the same ILC platform; after correcting the library, re-test before concluding the FB itself is defective.

FB version: Version 2.0 matches the CoDeSys reference code. A version 2.1 of unknown origin circulates with different logic in the end-switch correction:

(* V2.0 - reference code *)
IF SWITCH_AVAIL AND END_POS THEN
    POS := SEL_BYTE(POS > BYTE#127, BYTE#0, BYTE#255);
    next_cal := tx + T_CAL;
END_IF;

(* V2.1 - divergent variant *)
IF SWITCH_AVAIL AND END_POS THEN
    POS := SEL(POS > BYTE#127, BYTE#0, BYTE#255);
    last_cal := tx;
END_IF;

Check the version in Help/FU and in the revision history of the source. If your library contains 2.1, either trace its origin or rebuild the building library with the 2.0 code restored, then re-import the rebuilt library into the application project.

Verification and Residual Risks

  1. Confirm the FB reports version 2.0 and that oscat_basic_333 (not 330) is linked inside the building library project.
  2. Apply T_CAL := T#0s, T_DIAG := T#0s, T_EXT > T#0s; download and cold-start the controller.
  3. Monitor STATUS over at least the former T_CAL interval: the block must not enter STATUS 101, and the position output must track commanded movement instead of latching at 0 or 255.
  4. Long-term, compare indicated position against process conditions. A block calculating 20–25 % one day and 80–85 % under identical conditions the next day signals that calculated and actual position have drifted apart.

Two residual risks remain even with correct parameters. First, without end switches the internal position model is purely calculated; drive the actuator to a defined end position after a cold start (a run of roughly 1.25 × T_RUN in the intended direction is sufficient margin to guarantee reaching the stop) if your process tolerates it. Second, rule out actuator-side faults before blaming the FB: aging capacitors on 3-point actuators can randomize the start direction, and a simple watchdog FB that maps position 255 to a permanent open signal and 0 to a permanent close signal will expose this — a faulty actuator ends up at the wrong end stop shortly after the fault occurs. If your loop uses the PI block RLT30_FB_CTRL_PI, be aware its I-part has also been observed hanging in the same installation; test controller and actuator FB independently so the two faults are not conflated.

FAQ

Why does OSCAT ACTUATOR_3P get stuck at STATUS 101 with output 255?

STATUS 101 is calibration mode. Auto-calibration starts whenever T_CAL > T#0s elapses (default t#600s), regardless of SWITCH_AVAIL, and it only ends when the END_POS end switch is reached — without end switches it never ends and the output latches. Set T_CAL := T#0s to block it.

How do I disable auto-calibration and auto-diagnosis on ACTUATOR_3P?

Parameterize T_CAL := T#0s to block auto-calibration and T_DIAG := T#0s to block auto-diagnosis (default T_DIAG is T#10d). Both are VAR_INPUT CONSTANT parameters, so set them at the instance and rebuild/download.

Why does ACTUATOR_3P not run after a cold start with the output stuck at 0?

This occurs when T_EXT is parameterized to T#0s: STATUS walks 103 → 104 → 100 but the output never leaves 0 and no error status is raised. Keep T_EXT above zero (default T#10s).

Back to blog