Problem Overview
The Omron CP1E returns an IC (Undefined Command) end code when a Host Link C-Mode master transmits the R# Timer/Counter SV Read command over the built-in RS-232C port. The exact failure transaction looks like:
TX: @00R#TIMH001028*<CR>
RX: @00IC4A*<CR>
The IC byte (ASCII 0x49 0x43) is the standard C-Mode completion code for Undefined Command. It indicates the CP1E Host Link firmware rejected the command identifier itself, not the operand. Operators frequently confuse this with a parity, framing, or FCS error because the unit number, FCS, and * terminator look correct; in fact the entire frame is parsed correctly and the slave simply has no implementation for R# in C-Mode.
This article documents the affected CP1E command set, the exact error response decoding, and the two proven workarounds (MOV-to-DM with RD/WD, and CP1L comparison) that allow reliable Timer/Counter SV exchange with CP1E targets using any Host Link master (CX-Programmer AutoOnline, Indusoft Web Studio, RealTerm, or a custom C/Python client).
R#). CP1L, CP1H, CJ2M, and CS1 platforms are not affected.Host Link C-Mode Command Reference for CP1E
The CP1E implements a subset of the C-Mode command set defined in the CP1E CPU Unit Software User's Manual (W480). The relevant Timer/Counter commands and their CP1E support status are summarized below.
| Command | Code | Function | CP1E Support |
|---|---|---|---|
| R# | R# | Timer/Counter SV Read | Not supported (returns IC) |
| W# | W# | Timer/Counter SV Write | Not supported (returns IC) |
| RC | RC | Timer/Counter PV Read | Supported |
| WC | WC | Timer/Counter PV Write | Supported |
| RD | RD | DM Area Read | Supported |
| WD | WD | DM Area Write | Supported |
| RR | RR | CIO/IR Area Read | Supported |
| WR | WR | CIO/IR Area Write | Supported |
| RX | RX | Work (W) Area Read | Supported |
| WX | WX | Work (W) Area Write | Supported |
| RH | RH | HR Area Read | Supported |
| WH | WH | HR Area Write | Supported |
| RJ | RJ | AR Area Read | Supported |
| WJ | WJ | AR Area Write | Supported |
| RE | RE | EM Area Read (banks 0-3) | Supported on CP1E-N/NA |
| WE | WE | EM Area Write (banks 0-3) | Supported on CP1E-N/NA |
| RL | RL | EM Bank Read | Supported |
| WL | WL | EM Bank Write | Supported |
| SC | SC | Status Read | Supported |
| MF | MF | Status Write | Supported |
| KS | KS | Forced Set | Supported |
| KR | KR | Forced Reset | Supported |
| FK | FK | Multi-forced Status | Supported |
| KC | KC | Forced Set/Reset Cancel | Supported |
| TS | TS | Test Set | Supported |
| RS | RS | Test Read | Supported |
| MM | MM | Read PLC Model | Supported |
| AB | AB | Abort | Supported |
| FINS Wrapper Header | Supported (with C-Send wrapper) |
Operators familiar with the CJ/CS/CP1L command set expect R# to return the set value (SV) of a Timer or Counter. On CP1E, the slave firmware rejects this command with IC regardless of operand validity, timer number range, or instruction type token.
Root Cause: Why R# Returns IC on CP1E
The CP1E firmware intentionally omits the R# and W# C-Mode commands to reduce code size on the low-cost 14/20/30/40-point platform. The CP1E is positioned as a price-optimized CP1L sibling; the Host Link stack was trimmed to retain only the area-access commands and the forced I/O commands. The CP1E Host Link stack returns IC as soon as the second byte of the command field is # (0x23) — it never reaches operand validation.
The CP1L and CP1H do implement R#, and they additionally validate the operand token against the actual ladder instruction type. Field testing on CP1L shows the following token-to-instruction mapping:
| Host Link Token | Instruction Type | Expected Instruction in Ladder |
|---|---|---|
| TIM | BCD 100-ms timer (standard) | TIM N (BCD SV) |
| CNT | BCD counter (standard) | CNT N (BCD SV) |
| TIMH | BCD 10-ms high-speed timer | TIMH N (BCD SV) |
| TIMX | Binary 100-ms timer | TIMX N (binary SV) |
| CNTX | Binary counter | CNTX N (binary SV) |
| TIMHX | Binary 10-ms high-speed timer | TIMHX N (binary SV) |
If the token in the C-Mode frame does not match the actual instruction type in the ladder on CP1L, the response shifts from a valid SV payload to C-Mode end code 16 (0x10) with the form @00R$0016*. On CP1E, however, the frame never reaches the operand validation step because the command identifier itself is not recognized.
IC Error Response Decode
The slave always replies in the form:
@<unit><command_echo><end_code><FCS>*<CR>
For the failing R# transaction the byte breakdown is:
| Byte | Hex | ASCII | Meaning |
|---|---|---|---|
| 1 | 0x40 | @ | Start of frame |
| 2-3 | 0x30 0x30 | 00 | Unit number 00 |
| 4 | 0x49 | I | End code high byte: 0x49 = 'I' |
| 5 | 0x43 | C | End code low byte: 0x43 = 'C' (Undefined Command) |
| 6-7 | 0x34 0x41 | 4A | FCS for the body 00IC |
| 8 | 0x2A | * | End of frame delimiter |
| 9 | 0x0D | <CR> | Carriage return terminator |
The C-Mode end code IC is defined in the Omron Host Link reference (W342) as Undefined Command. To distinguish "command missing from firmware" from "command rejected by operand validation", send a known-good command such as RD; if RD returns data and only R# returns IC, the firmware is rejecting the command identifier itself, not the data.
Workaround 1: MOV Timer SV to DM and Use RD Command
The most reliable workaround for SV read/write on CP1E is to copy the timer SV into a DM word at the top of every scan, then expose that DM word to the Host Link master using the RD and WD C-Mode commands. This pattern is also the recommended practice for any HMI integration because it isolates the HMI from ladder internals: the HMI only reads/writes DM, and the ladder maintains the timer registers.
Ladder Implementation
LD P_On
MOV(021) T10SV D0
Where:
-
T10SVis the timer set-value operand (the source address that follows the timer number on a TIM/TIMH instruction). For TIMX/TIMHX the operand address is the same; the value is stored as binary. -
D0is any unused DM word. Reserve a non-overlapping block (e.g. D0-D99) and document the mapping in the project HMI tag list.
For a CP1E-N14/N20 with 1k DM, the valid range is D0-D9999. For CP1E-NA20 with 8k DM, the full range is available. To trigger the timer SV change from the master, place an OUT to the timer operand from the HMI DM word:
LD P_On
MOV(021) D0 T10SV
This bidirectional MOV ensures the HMI master can write D0 and the timer picks up the new value on the next scan. Note: writing the SV while the timer is active does not reset the in-progress count; the new SV takes effect the next time the timer coil is energized.
Read Frame from Master
TX: @00RD0000000105*<CR>
RX: @00RD00000064*<CR>
The RD command reads 10 DM words starting at D0 (head address 0000, count 0010 in hex). The CP1E returns the data segment with the SV of T10 in the first word. FCS calculation for the TX frame:
Body (excluding @ and *): 00RD0000000105
Bytes: 0x30 0x30 0x52 0x44 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x31 0x30 0x35
XOR: 0x30
FCS ASCII: "30"
Write Frame from Master
TX: @00WD00000064*<CR>
RX: @00WD00*<CR>
This writes decimal 100 (0x0064) into D0. The CP1E echoes a normal completion response @00WD00* with end code 00 (Normal Completion). FCS for the TX body: 0x30 XOR 0x30 XOR 0x57 XOR 0x44 XOR 0x30 XOR 0x30 XOR 0x30 XOR 0x30 XOR 0x30 XOR 0x30 XOR 0x36 XOR 0x34 = 0x30 → FCS "30".
Workaround 2: Use Counter PV Read/Write (RC/WC) for Health Verification
While RC and WC read/write the present value (PV), they are still useful as a sanity check during commissioning. A read of RC0001 after the timer expires must return 0000 (no counts accumulated), confirming the wiring and the Host Link port itself are healthy. A read of RC0010 returns the elapsed count for timer T10.
TX: @00RC00010057*<CR>
RX: @00RC00000000*<CR>
If RC returns data correctly but R# returns IC, the CP1E firmware is rejecting R# at the command identifier level and you must use the MOV-to-DM workaround.
FCS Algorithm and Python Implementation
The Frame Check Sequence is a single-byte XOR of every ASCII byte in the body, between the leading @ and the trailing *. The result is transmitted as two ASCII hex characters, most-significant nibble first. The C-Mode FCS uses the same algorithm as the FINS Host Link header FCS.
def fcs(body: str) -> str:
"""Compute Omron Host Link C-Mode FCS as two ASCII hex chars."""
x = 0
for ch in body:
x ^= ord(ch)
return f"{x:02X}"
def build_frame(unit: int, command: str, params: str) -> bytes:
body = f"{unit:02d}{command}{params}"
return f"@{body}{fcs(body)}*\r".encode("ascii")
# Example: read DM0-DM9 from unit 0
print(build_frame(0, "RD", "0000000105"))
# b'@00RD000000010530*\r'
A mismatch between master and slave FCS causes the slave to discard the frame silently. If the master does not see a reply within 1 second, check the FCS before suspecting the command set. The CP1E User's Manual (W480) confirms that an FCS error is reported as end code 03 (0x03) when the FCS is the only wrong byte in an otherwise valid frame; if the FCS is correct but the command identifier is unknown, the response is end code IC.
CP1E Serial Port Configuration
The CP1E has one or two serial ports depending on the model. The integrated RS-232C port is the default Host Link target. CP1E-NA20 adds a second port slot for an optional RS-232C/RS-485 board.
| Model | RS-232C Port 1 | Port 2 Option | Ethernet Option |
|---|---|---|---|
| CP1E-N14DR-A/D | Built-in | CP1W-CIF11/12 | CP1W-CIF41 |
| CP1E-N20DR-A/D | Built-in | CP1W-CIF11/12 | CP1W-CIF41 |
| CP1E-N30DR-A/D | Built-in | CP1W-CIF11/12 | CP1W-CIF41 |
| CP1E-N40DR-A/D | Built-in | CP1W-CIF11/12 | CP1W-CIF41 |
| CP1E-N60DR-A/D | Built-in | CP1W-CIF11/12 | CP1W-CIF41 |
| CP1E-NA20DR-A/D | Built-in | CP1W-CIF11/12 + RS-232C | CP1W-CIF41 |
For Host Link (C-Mode) the built-in port must be configured through CX-Programmer as follows:
| Parameter | Recommended Value | CX-Programmer Path |
|---|---|---|
| Port | RS-232C (built-in) | PLC → Serial Port 1 → Settings |
| Communications Mode | Host Link (SYSWAY) | Mode drop-down |
| Baud Rate | 9600 bps (default) | Baud drop-down |
| Data Bits | 7 | Data Bits drop-down |
| Stop Bits | 2 | Stop Bits drop-down |
| Parity | Even | Parity drop-down |
| Unit Number | 00 (default) | Unit Number field |
| End Code | Enable | End Code checkbox |
| Send Wait Time | 0 ms default | Send Wait field |
| Receive Wait Time | 0 ms default | Receive Wait field |
Settings must match on both sides. A common fault is leaving the PLC at 19,200 bps while the HMI driver defaults to 9,600; in that case the slave does not hear the master at all and the master times out (no response at all, not even IC).
RS-232C Cable Wiring for CP1E Host Link
The CP1E built-in RS-232C port is a D-Sub 9 male with the standard Omron CP1 pin assignment. For Host Link to a PC D-Sub 9 male (or via a USB-RS232 adapter with Prolific or FTDI chipset), the cable must implement a null-modem crossover plus the handshake loopback that the CP1E requires for Host Link RTS/CTS handshake.
| CP1E Pin (Male) | Signal | Direction | PC Pin (Female) | Notes |
|---|---|---|---|---|
| 1 | FG (Frame Ground) | — | Housing | Connect shield to both metal shells |
| 2 | SD (TXD) | → | 2 (RXD) | Cross to PC RX |
| 3 | RD (RXD) | ← | 3 (TXD) | Cross to PC TX |
| 4 | RS (RTS) | → | 5 (CTS) | Loop to PC CTS |
| 5 | CS (CTS) | ← | 7 (RTS) | Loop to PC RTS |
| 6 | 5V supply | — | — | Do not connect to PC |
| 7 | DR (DSR) | ← | 4 (DTR) | Loop to PC DTR |
| 8 | ER (DTR) | → | — | Optional, drives PC DCD |
| 9 | SG (Signal Ground) | — | 5 (SG) | Common reference |
The compact summary used by field technicians is:
2 ↔ 2
3 ↔ 3
4-5 bridged
7-8 bridged
9 ↔ 5
This wiring is for a straight-through D-Sub to D-Sub cable when one end is a CP1E and the other end is a standard PC COM port. The CP1E expects the loopback 4-5 and 7-8; without it the slave does not see clear-to-send and the master receives no reply. Pin 6 (5V supply) must never be tied to a PC pin because the CP1E sources 5V on that pin and PC RS-232 receivers expect ±3 to ±15V levels.
For USB-RS232 adapters (Prolific PL2303, FTDI FT232), the loopbacks must be present at the PLC end, not inside the adapter cable. In addition, on Indusoft Web Studio's OMPLC driver the DTS (Data Terminal Ready) pin must be disabled in the advanced settings so the driver does not hold DTR high and break the loopback on the PC side. This is the single most common cause of "no response from PLC" with Indusoft and similar HMI/SCADA stacks.
Indusoft Web Studio OMPLC Driver Settings
The OMPLC driver in Indusoft Web Studio is the most common Host Link master for CP1E installations. Two settings cause most "No response from PLC" failures:
- Communication tab → Baud Rate: must match the PLC setting (default 9600).
- Communication tab → Advanced → DTS pin: must be disabled. With DTS enabled the driver asserts DTR high, which combined with the loopback in the CP1E cable trips the slave's handshake check.
- Main Driver Settings → PLC Unit Number: must match the PLC unit number (default 00).
-
Main Driver Settings → Header / Footer: must be Host Link C-Mode (not FINS, not Modbus). The C-Mode header is the literal
@; FINS uses 0x80 etc.
The same principles apply to other HMI/SCADA drivers: any driver that hard-drives DTR/RTS without honoring the loopback will break CP1E Host Link. Always test with a dumb terminal program first to confirm the cable and PLC port before blaming the driver.
Verification Procedure
- Connect the PC to the CP1E using the cable wiring above. Open CX-Programmer and confirm AutoOnline succeeds on the COM port.
- Open a terminal (RealTerm, PuTTY, Hercules). Set 9600, 7, 2, E, NoFlowControl.
- Type the body
00RD0000000105and compute the FCS. The full TX is@00RD000000010530*<CR>. - Confirm the RX is a valid
@00RD...response (any reply within 200 ms confirms port, baud, and wiring). - Send the failing command
@00R#TIMH001028*<CR>and confirm the response is@00IC4A*<CR>. This reproduces the issue and confirms the firmware is rejecting the command. - In CX-Programmer, add the rung
LD P_On MOV T10SV D0and write to PLC. - Send
@00RD000000010530*<CR>again. Confirm the SV now returns in the response data starting at D0. - Send
@00WD0000006430*<CR>to overwrite the SV. Confirm the timer fires at the new value in the ladder simulation or by running with the new SV. - Cycle power to the CP1E and re-issue
RDto confirm the value persists (DM is retained through power cycles on CP1E-N and CP1E-NA).
Troubleshooting Matrix
| Symptom | Probable Cause | Corrective Action |
|---|---|---|
| No response at all | Baud/parity mismatch, cable loopback missing, wrong COM port | Verify 9600,7,2,E on both; check 4-5 and 7-8 loopbacks; check Windows Device Manager |
| No response at all, port LED blinks | Loopback OK but driver holding DTR | Disable DTS in OMPLC driver or equivalent HMI driver |
| FCS error response | FCS miscalculated by master | Recompute XOR of body bytes; transmit as ASCII hex |
| IC (Undefined Command) | Command not implemented on CP1E | Use RD/WD with MOV-to-DM as documented in this article |
| End code 16 (0x10) | Timer type token mismatch (TIM vs TIMX, etc.) | Match token to actual ladder instruction type |
| End code 14 (0x0E) | Parameter range error | Verify address range and count do not exceed area limits |
| End code 03 (0x03) | FCS transmission error | Recompute FCS |
| End code 01 (0x01) | Unit number mismatch during multi-drop | Match unit number on PLC and master |
| End code 04 (0x04) | Frame length error | Limit command body to 280 characters |
| End code 02 (0x02) | Unsupported command (alternate code for IC on some models) | Same as IC: replace R#/W# with RD/WD |
| Indusoft "No response from PLC" | DTR held high; loopback broken on PC side | Disable DTS in OMPLC driver advanced settings |
| AutoOnline fails but terminal works | CX-Programmer baud-rate auto-negotiation failed | Set baud manually in CX-Programmer auto-online dialog |
| Reads return garbage | Word-count mismatch (count in hex but RX expecting decimal or vice versa) | Confirm word count is 4-hex-digit value, ASCII, in the same encoding the PLC returns |
| Partial response then timeout | PLC scan time exceeded 1 s; or buffer overrun | Reduce request volume; add Send Wait Time in PLC port settings |
CP1E vs CP1L Host Link Differences
| Feature | CP1E | CP1L |
|---|---|---|
| R# (Timer SV Read) | No (returns IC) | Yes |
| W# (Timer SV Write) | No | Yes |
| Built-in RS-232C | Yes (port 1) | Yes (port 1) + optional port 2 |
| Ethernet option (CP1W-CIF41) | Yes (option board slot) | Yes (option board slot) |
| FINS over Host Link | Yes via C-Send wrapper | Yes |
| DM area size | 1k (N) / 8k (NA) | 32k (L14/L20) / 32k (L30/L40/L50/L60) |
| EM area | Banks 0-3 on NA models | Banks 0-7 |
| TIM/TIMX/TIMH/TIMHX token validation | Not reachable (R# absent) | Yes, end code 16 on mismatch |
| Multi-drop RS-485 host link | Via CP1W-CIF12 | Via CP1W-CIF12/CIF11 |
Engineers porting code from CP1L to CP1E must audit the C-Mode command list and replace every R#/W# with the MOV-to-DM pattern. This pattern is also the recommended practice for any HMI integration because it isolates the HMI from ladder internals: the HMI only reads/writes DM, and the ladder maintains the timer registers. The CP1E firmware revision does not change this behavior; R# is absent on all CP1E firmware revisions published to date.
Host Link Multi-Drop Considerations
CP1E supports multi-drop Host Link on RS-485 via the CP1W-CIF12 option board (port 2). In multi-drop mode, each slave must have a unique unit number 00-31, and only the addressed slave responds. The unit number is configured in CX-Programmer under PLC Settings → Serial Port 2 → Host Link → Unit Number. Common faults include duplicate unit numbers (causing both slaves to transmit simultaneously and corrupting frames), and selecting port 1 for Host Link when port 2 is wired for RS-485. To diagnose multi-drop problems, isolate each slave on a point-to-point RS-232 link first, then bring up RS-485 one slave at a time.
CX-Programmer Auto-Online Specifics
CX-Programmer version 9.0 and later (including 9.03 referenced in field reports) supports AutoOnline over CP1E Host Link. AutoOnline automatically negotiates baud by sending a sequence of MM commands at 9,600 then 19,200 then 38,400 then 115,200. If AutoOnline fails but a terminal program at 9,600 succeeds, the cause is one of:
- CX-Programmer not configured to the correct COM port (Tools → Communications Setup).
- Network driver interfering with the COM port (Cisco VPN, Zscaler, etc.).
- PLC in a different run mode preventing AutoOnline from completing the first
MMhandshake (rare; CP1E must be in Run or Monitor, not Program).
Safety and Lockout Considerations
FAQ
Why does CP1E return IC for R# when CP1L returns the SV value?
The CP1E firmware intentionally omits the R# Timer/Counter SV Read C-Mode command to reduce code size on the low-cost 14/20/30/40-point platform. CP1L implements R#; CP1E does not. Use the MOV-to-DM workaround described above.
Can I make the CP1E accept R# by changing a PLC setting?
No. There is no CX-Programmer setting, DIP switch, or peripheral option that enables R# on CP1E. The command is not present in the firmware and is absent in every published CP1E firmware revision.
Will the W# Timer SV Write command work on CP1E if R# does not?
No. Both R# and W# are omitted together on CP1E. W# also returns IC. The replacement for W# is WD (DM Write) into a DM word that the ladder MOVs into the timer operand on every scan.
What serial cable do I need between a PC and the CP1E built-in RS-232C port?
Use a D-Sub 9 male to D-Sub 9 female cable with the 2-2/3-3 crossover plus 4-5 and 7-8 loopbacks documented in the wiring table above. A USB-to-RS232 adapter (Prolific PL2303 or FTDI FT232) with a null-modem adapter also works. Indusoft's OMPLC driver requires DTS disabled.
Do I need a ladder program on the CP1E to respond to Host Link commands?
No. As long as the serial port is configured for Host Link mode in CX-Programmer, the CP1E firmware automatically responds to RD, WD, RR, WR, RC, WC, RH, WH, RJ, WJ, MM, SC, MF, KS, KR, FK, KC, and the FINS commands. No ladder is required.
Why does my terminal receive no reply at all instead of an IC error?
No reply means the slave never parsed the frame. The most likely causes are baud/parity/data bit mismatch, missing RTS/CTS loopback, or the HMI driver holding DTR high in software. Verify 9600,7,2,E on both sides, then test with a known-good terminal program before suspecting the firmware.
Does the same workaround apply to CP1E-NA20 with the Ethernet option board?
For Ethernet use FINS/TCP, not Host Link C-Mode. The R# command is still absent on CP1E-NA20 firmware even when accessed over Ethernet. The MOV-to-DM workaround is still the correct approach; use FINS commands 0101 (Memory Area Read) and 0102 (Memory Area Write) over TCP port 9600 instead of C-Mode RD/WD.