MSG — EtherNet/IP

Description
Section titled “Description”With the protocol set to eip, MSG reads or writes a tag by name in an Allen-Bradley Logix controller (CompactLogix, ControlLogix, Micro800 with the CIP Data Table service) over EtherNet/IP explicit messaging. The rung’s rising edge queues the request; a client service runs the TCP connection a little on every scan, so the logic never waits on the network. The reply lands in the Local array, or the Local array is written to the PLC’s tag, and the optional status tag reports the result. Use it to hand production counts, recipes and status between an Arduino and a Logix PLC without any tag mapping on the PLC side. Do not use it for I/O-style cyclic data: it is one request per rung edge, and each transfer is a full round trip.
Operands
Section titled “Operands”| Operand | Type | Format | Valid Range | Required | Description |
|---|---|---|---|---|---|
| Direction | Choice | read / write |
— | Yes | Read the PLC tag into Local, or write Local into the PLC tag. |
| Protocol | Choice | eip |
Selected for you when the device is an EtherNet/IP peer | Yes | |
| Port | Comm port | Ethernet |
The port an Ethernet shield provides | Yes | |
| Device | Network peer | Name | An Ethernet Device under the Ethernet port with Protocol = EtherNet/IP and a valid IP address | Yes | Supplies IP, TCP port (44818) and the CPU slot for the route. |
| Local data | Tag | INT, DINT or REAL array, or Buf[n] |
Window must fit; the type must match the PLC tag | Yes | INT ↔ Logix INT, DINT ↔ DINT, REAL ↔ REAL. The CIP type sent comes from this tag. |
| Length | INT | 1 to what fits one frame | Build error above the limit | Yes | Elements transferred. |
| Remote tag | Text | Logix tag name, optionally .member or [index] |
Letters, digits, underscore | Yes | The PLC-side tag, e.g. Line_Counts or Recipe[2]. Case as in the PLC. |
| Status (opt) | CONTROL tag | Name | One per MSG | No | EN queued, DN success, ER failure, POS = CIP general status (0 = OK, 255 = transport failure). |
Scan Behavior
Section titled “Scan Behavior”Prescan
Section titled “Prescan”Nothing. No connection exists until the first message is queued.
Rung-condition-in is false
Section titled “Rung-condition-in is false”Nothing new. A queued or in-flight transfer continues. The edge memory is armed.
Rung-condition-in is true
Section titled “Rung-condition-in is true”On the rising edge the request is queued; with a status tag, EN = 1, DN = ER = 0. The client service then, over the following scans: opens the TCP session if none is open (one bounded 200 ms connect attempt, retried every 2 s while the PLC is unreachable), registers the session, sends the CIP Read Tag or Write Tag inside an Unconnected Send routed to the CPU slot, and waits up to one second for the reply. On success a read is unpacked element by element into Local and DN = 1; a write sets DN = 1. On a CIP error, a type or length mismatch, or a timeout, nothing is copied, ER = 1 and POS holds the status; the socket is dropped so the next attempt starts clean.
Postscan
Section titled “Postscan”Nothing.
| Outcome | EN | DN | ER | POS | Local |
|---|---|---|---|---|---|
| Queued / in flight | 1 | 0 | 0 | last | unchanged |
| Success | 0 | 1 | 0 | 0 | updated (read) |
| PLC refused (unknown tag 0x04, type mismatch 0xFF ext 0x2107, …) | 0 | 0 | 1 | CIP general status | unchanged |
| No reply / no connection | 0 | 0 | 1 | 255 | unchanged |
Status Tag Members
Section titled “Status Tag Members”| Member | Data type | Set by | Cleared by | Description |
|---|---|---|---|---|
EN |
BOOL | Rung edge | Service on completion | Queued or in flight. |
DN |
BOOL | Service on success | Next rung edge | Last transfer succeeded. |
ER |
BOOL | Service on failure | Next rung edge | Last transfer failed. |
POS |
DINT | Service | — | CIP general status of the last transfer; 0 = OK, 255 = transport failure. |
Example
Section titled “Example”Scenario: A line PLC keeps four production counters in a DINT array tag Line_Counts. An Arduino behind a W5100 Ethernet shield reads them on demand and flags success or failure for the operator display.
Network tree: Eth — W5100 Ethernet Shield on SPI, static IP 192.168.1.177. PLC — Ethernet Device under Ethernet, Protocol EtherNet/IP, IP 192.168.1.20, port 44818, slot 0.
Tags:
Read_PLC— Read PLC counts, BOOLPLC_Data— Line counts from the PLC, DINT[4]Plc_Sts— PLC message status, CONTROLPlc_Ok,Plc_Fault— BOOL
Rung 1:
—|XIC Read_PLC|———[MSG READ EIP Device PLC Local PLC_Data Length 4 Remote tag Line_Counts Status Plc_Sts]———Rung 2:
——┬——|XIC Plc_Sts.DN|———(OTE Plc_Ok)——————┬—— └——|XIC Plc_Sts.ER|———(OTE Plc_Fault)———┘
Scan 1 — Read_PLC = 0. Nothing queued. Plc_Sts.EN = 0.

Scan 2 — Read_PLC = 1 (rising edge). The request is queued: Plc_Sts.EN = 1, DN = ER = 0. A few scans later, on hardware, the reply arrives: PLC_Data = the four counters, Plc_Sts.DN = 1, EN = 0, and rung 2 energizes Plc_Ok.


Values before and after: PLC_Data 0,0,0,0 → the PLC’s Line_Counts; Plc_Sts.DN 0 → 1. In the simulator nothing is transferred; Figure 4 was taken with Plc_Sts.DN set by hand in the Tag Browser, which is why the read rung above it is still lit.
See Also
Section titled “See Also”- MSG — the instruction and its dialog
- MSG — Modbus TCP — the same shape for Modbus peers
- MSG — DF1 — the serial route into SLC / MicroLogix / CompactLogix CH0
- Adding Network Devices — the Ethernet shield and the peer
- Communication Instructions — Category index
Types must match the PLC tag. The CIP element type is taken from the Local tag: INT, DINT or REAL. Reading a Logix DINT into an INT array is refused by the PLC and reported as ER with POS 255 and extended status 0x2107. A BOOL or STRING Local is a build error.
Tag names, not addresses. Controller-scope tags are named as they appear in Studio 5000. Program-scope tags need the Program:MainProgram. prefix. Array elements and structure members work: Recipe[2], Motor.Speed.
Route and slot. The request is wrapped in an Unconnected Send to 1,<slot>, the backplane route a real Logix MSG uses. A CompactLogix with embedded Ethernet answers with slot 0. Leave the peer’s “Connected” style options off; this is unconnected messaging only.
One peer per project, within the socket budget. Each client holds one socket. A W5100 has four sockets, a W5500 eight, and the board’s own EtherNet/IP server (when enabled on the shield) takes two.
Memory. The client needs about 600 bytes of frame buffer. It builds and runs on an Uno with a warning, but a Mega, STM32, Pico or Teensy is where it belongs alongside a real program.
Length limit. A transfer must fit one CIP frame; the build reports the limit for the Local type. Split a large block across several MSGs.
Verified against a 1769-L23E in both directions over a Mega with a W5100 shield.
Applies to LadderIDE >=1.2.2 · Last reviewed 2026-09-11 · Screenshots verified 2026-09-11