XIO (Examine If Open) is the normally-closed contact instruction in ladder logic: it passes logical continuity when the bit it examines is 0 (OFF), and blocks continuity when the bit is 1.
Join 1900+ learners practicing PLC programming
How it works
XIO inverts the question XIC asks. It examines a bit and conducts only while that bit is 0 — the ]/[ symbol (a contact with a slash) mirrors the normally-closed contact of a hardwired relay. Like XIC, it evaluates against the input image captured at the top of the scan, it can examine any BOOL in the controller, and it only ever reads.
The place XIO confuses everyone exactly once is the stop circuit. Stop buttons and safety interlocks are wired normally closed on purpose: current flows through them while everything is healthy, so the input bit sits at 1 — and an XIO on a bit that is 1 blocks continuity. That is why the standard motor rung puts an XIC on an NC-wired stop input (true while healthy), and would only use an XIO if the stop were wired normally open. The pairing of physical wiring and instruction choice is the part everyone gets wrong once.
Work it through slowly, because interviews love this one. Wire a normally-closed stop button to input Stop_PB. Untouched, the button conducts → the bit is 1 → an XIC Stop_PB is true → the motor rung has continuity. Press the button → the circuit opens → the bit drops to 0 → the XIC goes false → the motor drops out. The NC button therefore pairs with an XIC, and the program still reads naturally ("stop not pressed"). Use an XIO on that same input and your motor would only run while someone holds the stop button down — the classic backwards stop circuit.
So when is XIO the right choice? Whenever the logic genuinely is "act while this bit is off": run a heater while the at-temperature bit is 0, sound an alarm while the pump-running feedback is 0 but the pump command is 1, enable a gate while the fault bit is clear. XIO on fault and status bits is everyday, uncontroversial ladder style.
Across vendors
| Platform | Name / syntax | Notes |
|---|---|---|
| Allen-Bradley (Studio 5000 / RSLogix) | XIO | Instruction mnemonic XIO tag — e.g. XIO Fault_Bit. Drawn as ]/[ on the rung. |
| IEC 61131-3 (CODESYS, OpenPLC) | NC contact | The graphical normally-closed contact -|/|- in LD. Structured Text: IF NOT Fault_Bit THEN …; Instruction List: LDN Fault_Bit. |
| Siemens (TIA Portal) | NC contact | The -|/|- element in LAD; in STL the AN (AND NOT) / ON (OR NOT) instructions, e.g. AN "Fault_Bit". |
| Mitsubishi (GX Works) | LDI / ANI / ORI | LDI X0 loads a normally-closed contact (Load Inverse); ANI / ORI extend in series/parallel. |
Same story as XIC: the XIO name is Allen-Bradley-specific, the normally-closed contact concept is universal. Every dialect evaluates it the same way — true while the bit is 0.
In practice
| Cycle_Start At_Position Advance_Cyl | |-----] [----------]/[------------------------( )-----|
The cylinder advances while the cycle is started and the At_Position limit switch has not yet made. The XIO on At_Position conducts while the bit is 0; the moment the cylinder reaches the switch, the bit goes to 1, the XIO opens, and the Advance_Cyl output drops on that same scan. "Do something until a condition becomes true" is the natural home of XIO.
| Pump_Cmd Fdbk_Delay.DN Pump_Fail | |----] [-----------] [------------------------( )----| | Pump_Cmd Pump_Running TON Fdbk_Delay | |----] [-----------]/[----------------[ PRE 3000 ms ]--|
The alarm logic: the pump has been commanded on (XIC Pump_Cmd) but the running feedback has not appeared (XIO Pump_Running) — if that mismatch persists for 3 seconds, a TON times out and the Pump_Fail alarm sets. The XIO is doing the real work: it converts "no feedback" (bit = 0) into rung continuity so the timer can measure how long the absence lasts.
Without the timer, the alarm would chatter during the half-second the contactor takes to pull in — pairing an XIO with an on-delay timer is the standard debounce for discrepancy alarms.
Gotchas
Putting an XIO on a normally-closed stop button
An NC stop button reads 1 while healthy, so it pairs with an XIC. Programming an XIO "because stop should be closed" gives you a motor that only runs while the stop button is held. Match the instruction to the bit state, not to the button style.
Forgetting that a broken wire looks like "pressed" — or like "healthy"
NC wiring is used for safety precisely because a broken wire reads 0, the same as pressed, failing safe with an XIC. Invert that logic with an XIO and a broken wire silently reads as "run permitted". Fail-safe analysis must include the instruction choice.
Double negatives that nobody can read
XIO Not_Ready, XIO Fault_Cleared_Not … stacked inversions work but are unmaintainable. Name bits for their true state (Ready, Fault) and let XIC/XIO provide the single inversion.
Using XIO to build a one-shot by hand
The old XIC-input-XIO-storage two-rung trick still appears in legacy code. It works, but a single ONS (or OSR/R_TRIG) instruction is clearer and immune to rung-order mistakes.
Drop the instruction on a rung in the browser simulator, toggle the inputs, and watch the rung state, accumulator values and outputs update scan by scan.
Questions
XIO stands for Examine If Open — the Allen-Bradley name for the normally-closed contact instruction. It is true (passes rung continuity) while the examined bit is 0 and false while the bit is 1. Like XIC it is read-only: it never writes the bit.
A stop button wired normally closed (the correct, fail-safe wiring) reads 1 while unpressed — so the ladder uses an XIC on it: true while the bit is 1, dropping the rung when the button is pressed or a wire breaks. An XIO on a stop input is only correct if the button is wired normally open, which sacrifices broken-wire detection.
A normally-closed contact: two parallel vertical bars with a diagonal slash through them — ]/[ — with the tag name above. The slash is the visual cue that the evaluation is inverted relative to the plain ] [ XIC contact.
Functionally an XIO is "NOT bit" applied to rung continuity, and IEC Structured Text writes it exactly that way (IF NOT Fault THEN). In ladder the inversion is packaged into the contact itself, so no separate NOT element is needed for simple bit tests.