EtherNet/IP Device Auto-Discovery: How Edge Gateways Identify PLCs on the Plant Floor [2026]
Walk onto any modern plant floor and you'll find a patchwork of controllers — Allen-Bradley Micro800 series running EtherNet/IP, Modbus TCP devices from half a dozen vendors, maybe a legacy RTU on a serial port somewhere. The edge gateway sitting in that control cabinet needs to figure out what it's talking to, what protocol to use, and how to pull the right data — ideally without a technician manually configuring every register.
This is the device auto-discovery problem, and solving it well is the difference between a two-hour commissioning versus a two-day one.
The Discovery Sequence: Try EtherNet/IP First, Fall Back to Modbus
The most reliable approach follows a dual-protocol detection pattern. When an edge gateway powers up and finds a PLC at a known IP address, it shouldn't assume which protocol that device speaks. Instead, it runs a detection sequence:
Step 1: Attempt EtherNet/IP (CIP) Connection
EtherNet/IP uses the Common Industrial Protocol (CIP) over TCP port 44818. The gateway attempts to create a connection to a known tag — typically a device_type identifier that the PLC firmware exposes as a readable tag.
Protocol: ab-eip
Gateway: 192.168.1.100
CPU: micro800
Tag: device_type
Element Size: 2 bytes (uint16)
Element Count: 1
Timeout: 2000ms
If this connection succeeds and returns a non-zero value, the gateway knows it's talking to an EtherNet/IP device and can proceed to read the serial number components.
Step 2: If EtherNet/IP fails, try Modbus TCP
If the CIP connection returns an error (typically error code -32, indicating no route to host at the CIP layer), the gateway falls back to Modbus TCP on port 502.
For Modbus detection, the gateway reads input register 800 (address 0x300320 in the full Modbus address space — function code 4). This register holds the device type identifier by convention in many industrial equipment families.
Protocol: Modbus TCP
Port: 502
Function Code: 4 (Read Input Registers)
Start Address: 800
Register Count: 1
Step 3: Extract Serial Number
Once the device type is known, the gateway reads serial number components. Here's where things get vendor-specific. Different PLC families store their serial numbers in completely different register locations:
| Device Type | Protocol | Month Register | Year Register | Unit Register |
|---|---|---|---|---|
| Micro800 PLC | EtherNet/IP | Tag: serial_number_month | Tag: serial_number_year | Tag: serial_number_unit |
| GP Chiller (1017) | Modbus TCP | Input Reg 22 | Input Reg 23 | Input Reg 24 |
| HE Chiller (1018) | Modbus TCP | Holding Reg 520 | Holding Reg 510 | Holding Reg 500 |
| TS5 TCU (1021) | Modbus TCP | Holding Reg 1039 | Holding Reg 1038 | Holding Reg 1040 |
Notice the inconsistency — even within the same protocol, each device family stores its serial number in different registers, uses different function codes (input registers vs. holding registers), and sometimes the year/month/unit ordering isn't sequential in memory. This is real-world industrial automation, not a textbook.
Serial Number Encoding: Packing Identity into 32 Bits
Once you have the three components (year, month, unit number), they're packed into a single 32-bit serial number for efficient transport:
Byte 3 (bits 31-24): Year (0x00-0xFF)
Byte 2 (bits 23-16): Month (0x00-0xFF)
Bytes 1-0 (bits 15-0): Unit Number (0x0000-0xFFFF)
This encoding allows up to 65,535 units per month per year — more than sufficient for any production line. A serial number of 0x18031A2B decodes to: year 0x18 (24), month 0x03 (March), unit 0x1A2B (6699).
Validation Matters
A serial number where the year byte is zero is invalid — it almost certainly means the PLC hasn't been properly commissioned or the register read returned garbage data. Your gateway should reject these and report a "bad serial number" status rather than silently accepting a device with identity 0x00000000.
The Configuration Lookup Pattern
Once the gateway knows the device type (e.g., type 1018 = HE Central Chiller), it needs to load the right tag configuration. The proven pattern is a directory scan:
- Maintain a directory of JSON configuration files (one per device type)
- On detection, scan the directory and match the
device_typefield in each JSON - Load the matched configuration, which defines all tags, their data types, read intervals, and batching behavior
{
"device_type": 1018,
"version": "2.4.1",
"name": "HE Central Chiller",
"protocol": "modbus-tcp",
"plctags": [
{
"name": "supply_temp",
"id": 1,
"type": "float",
"addr": 400100,
"ecount": 2,
"interval": 5,
"compare": true
},
{
"name": "compressor_status",
"id": 2,
"type": "uint16",
"addr": 400200,
"interval": 1,
"compare": true,
"do_not_batch": true
}
]
}
Key design decisions in this configuration:
compare: truemeans only transmit when the value changes — critical for reducing bandwidth on cellular connectionsdo_not_batch: truemeans send immediately rather than accumulating in a batch — used for status changes and alarms that need real-time deliveryintervaldefines the polling frequency in seconds — fast-changing temperatures might be 5 seconds, while a compressor on/off status needs sub-second readsecount: 2for floats means reading two consecutive 16-bit Modbus registers and combining them into an IEEE 754 float
Handling Modbus Address Conventions
One of the trickiest aspects of Modbus auto-discovery is the address-to-function-code mapping. Different vendors use different conventions, but the most common maps addresses to function codes like this:
| Address Range | Function Code | Register Type |
|---|---|---|
| 0–65536 | FC 1 | Coils (read/write bits) |
| 100000–165536 | FC 2 | Discrete Inputs (read-only bits) |
| 300000–365536 | FC 4 | Input Registers (read-only 16-bit) |
| 400000–465536 | FC 3 | Holding Registers (read/write 16-bit) |
When you see a configured address of 400100, the gateway strips the prefix: the actual Modbus register address sent on the wire is 100, using function code 3.
Register Grouping Optimization
Smart gateways don't read one register at a time. They scan the sorted tag list and identify contiguous address ranges that share the same function code and polling interval. These get combined into a single Modbus read request:
Tags at addresses: 400100, 400101, 400102, 400103, 400104
→ Single request: FC3, start=100, count=5
But grouping has limits. Exceeding ~50 registers per request risks timeouts, especially on Modbus RTU over slow serial links. And you can't group across function code boundaries — a tag at address 300050 (FC4) and 400050 (FC3) must be separate requests, even though they're "near" each other numerically.
Multi-Protocol Detection: The Real-World Sequence
In practice, a gateway on a plant floor often needs to detect multiple devices simultaneously — a PLC on EtherNet/IP and a temperature control unit on Modbus RTU via RS-485. The detection sequence runs in parallel:
- EtherNet/IP detection happens over the plant's Ethernet network — standard TCP/IP, fast, usually succeeds or fails within 2 seconds
- Modbus TCP detection uses the same Ethernet interface but different port (502) — also fast
- Modbus RTU detection happens over a serial port (
/dev/ttyUSB0or similar) — much slower, constrained by baud rate (typically 9600–115200), with byte timeouts around 50ms and response timeouts of 400ms
The serial link parameters are critical and often misconfigured:
Port: /dev/ttyUSB0
Baud Rate: 9600
Parity: None ('N')
Data Bits: 8
Stop Bits: 1
Slave Address: 1
Byte Timeout: 50ms
Response Timeout: 400ms
Getting the parity wrong is the #1 commissioning mistake with Modbus RTU. If the slave expects Even parity and the master sends None, every frame will be rejected silently — no error message, just timeouts.
Connection Resilience: The Watchdog Pattern
Discovery isn't a one-time event. Industrial connections drop — cables get unplugged during maintenance, PLCs get rebooted, network switches lose power. A robust gateway implements a multi-layer resilience strategy:
Link State Tracking: Every successful read sets the link state to "up." Any read error (timeout, connection reset, broken pipe, bad file descriptor) sets it to "down" and triggers a reconnection sequence.
Connection Error Counting: For EtherNet/IP, if you get three consecutive error-32 responses (no CIP route), stop hammering the network and wait for the next polling cycle. For Modbus, error codes like ETIMEDOUT, ECONNRESET, ECONNREFUSED, or EPIPE trigger a modbus_close() followed by reconnection on the next cycle.
Modbus Flush on Error: After a failed Modbus read, always flush the serial/TCP buffer before the next attempt. Stale response bytes from a partial read can corrupt subsequent responses.
Configuration Hot-Reload: The gateway watches its configuration files with stat(). If a file's modification time changes, it triggers a full re-initialization — destroy existing PLC tag handles, reload the JSON configuration, and re-establish all connections. This allows field engineers to update tag configurations without restarting the gateway service.
What machineCDN Brings to the Table
machineCDN's edge infrastructure handles this entire discovery and connection management lifecycle automatically. When you deploy a machineCDN gateway on the plant floor:
- It auto-detects PLCs across EtherNet/IP and Modbus TCP/RTU simultaneously
- It loads the correct device configuration from its library of supported equipment types
- It manages connection resilience with automatic reconnection and buffer management
- It optimizes Modbus reads by grouping contiguous registers and minimizing request count
- Tag data flows through a batched delivery pipeline to the cloud, with store-and-forward buffering during connectivity gaps
For plant engineers, this means going from "cable plugged in" to "live data flowing" in minutes rather than days of manual register mapping.
Key Takeaways
- Always try EtherNet/IP first — it's faster and provides richer device identity information than Modbus
- Don't hardcode serial number locations — they vary wildly across equipment families, even from the same vendor
- Validate serial numbers before accepting a device — zero year values indicate bad reads
- Group Modbus reads by contiguous address and function code, but cap at 50 registers per request
- Implement connection watchdogs — industrial networks are unreliable; your gateway must recover automatically
- Flush after errors — stale buffer bytes from partial Modbus reads are the silent killer of data integrity
The device discovery problem isn't glamorous, but getting it right is what separates an IIoT platform that works in the lab from one that survives on a real plant floor.