EtherNet/IP PLC Integration
What TwinEdge expects from a connected Allen-Bradley PLC, how assets and tags are identified, and how raw CIP values are processed into dashboard readings.
Connection Requirements
| Parameter | Value |
|---|---|
| Protocol | EtherNet/IP — CIP explicit messaging over TCP |
| Port | 44818 |
| Transport | TCP |
| Connection model | Stateless — a new TCP session is opened per read batch and closed after |
| Timeout | 5 seconds (configurable per asset) |
TwinEdge connects directly to the PLC's EtherNet/IP port using CIP explicit messaging. No EDS file, no ControlLogix backplane slot routing, and no I/O adapter is required — only the controller's IP address and port 44818.
Compatible hardware: CompactLogix (1769-L series), ControlLogix (1756), MicroLogix 1100/1400 with EtherNet/IP adapter, Micro850. Any Rockwell controller that supports CIP explicit messaging will work.
How the System Identifies an Asset
An asset in TwinEdge corresponds to a physical machine or piece of equipment (e.g., a pump, blower, or compressor). Each asset is registered with:
- A unique
asset_id(e.g.,Pump_ENIP_001) — the identifier used throughout the system - An
asset_type(e.g.,centrifugal_pump) — determines which ML models and alert templates apply - A
protocolvalue ofethernetip— tells the system which adapter to use - A
connectionblock with the PLC IP address, port, and timeout - A
sensorslist — the specific PLC tags to read and what to call them internally
Note: The asset_id is set once at provisioning time. It does
not come from the PLC — it is assigned in TwinEdge and used to label all data, OPC UA nodes,
and dashboard readings.
Tag Identification
Each sensor mapped to an asset has a corresponding CIP tag on the PLC. The system reads tags by name using CIP explicit messaging.
Tag Name Format
The tag name in TwinEdge must match exactly what is in the PLC (case-sensitive on some firmware versions).
Pump_VibrationX → controller-scope scalar tag (name only)
Pump_Status[0] → element 0 of an array tag (DINT[])
Program:MainProgram.PumpSpeed → program-scope tag (full path required)
The system does not use I/O addressing (e.g., Local:0:I.Data)
or ladder logic alias tags. Only symbolic controller tags are read.
Controller-Scope vs Program-Scope Tags
In Studio 5000 / RSLogix 5000, every tag lives in one of two places:
Controller-scope tags are defined at the top level of the controller and visible to all programs. These are the standard choice for anything meant to be read externally — HMIs, SCADA, historians, and TwinEdge.
Controller
└── Controller Tags
├── Pump_VibrationX ← read with just the tag name
├── Pump_Temperature
└── Pump_Status
Program-scope tags are defined inside a specific program and local to that program's logic — equivalent to a local variable inside a function. Reading them externally requires the full prefixed path.
Controller
└── Tasks
└── MainTask
└── MainProgram
└── Program Tags
├── PumpSpeed ← internal logic variable
└── LocalSetpoint
Tag Discovery (Live Browse)
When provisioning a new asset via the dashboard, the system queries the PLC's
Symbol Object (CIP class 0x6B). This is Rockwell's standard
controller tag table, returning both controller-scope and program-scope tags with their data types.
| Group | Path prefix | Description |
|---|---|---|
| Controller Tags | Controller | Global tags, accessible from all programs |
| Program Tags | Program:<name> | Scoped to a specific program (e.g., Program:MainProgram) |
Practical rule: When receiving a tag list from the PLC programmer, ask whether each tag is a Controller Tag or a Program Tag in Studio 5000. If it is under a Program folder, use the full path. If it is under Controller Tags, use the name as-is.
Configuring Program-Scope Tags
If a tag you need is program-scoped, write the full Program:<name>.<TagName>
path in the sensor definition:
# Controller-scope tag — name only
- name: vibration_x
tag: Pump_VibrationX
type: REAL
unit: mm/s
# Program-scope tag — full path required
- name: pump_speed
tag: "Program:MainProgram.PumpSpeed"
type: REAL
unit: rpm
Warning: Without the prefix, the CIP read will look for a controller-scope tag of that name, not find it, and return no value. The sensor will show as missing in the dashboard.
Sensor-to-Tag Mapping
Each sensor entry links an internal sensor name (used by the dashboard, ML, and alerts) to a PLC tag name (what gets sent over CIP).
Mapping Structure
sensors:
- name: vibration_x # Internal name — used in dashboard and ML
tag: Pump_VibrationX # CIP tag name on the PLC
type: REAL # CIP data type (see table below)
unit: mm/s # Engineering unit label (display only)
scale_factor: 1.0 # Multiplier applied after reading
offset_value: 0.0 # Added after scaling
sample_rate_hz: 10 # How often to poll this tag (per second)
If no tag is specified, the system falls back to using the name
field as the tag name.
Array Element Access
For integer status words or any tag backed by a PLC array, specify the element index:
- name: status_word
tag: Pump_Status # Array tag name (no brackets here)
type: DINT
element: 0 # Reads Pump_Status[0]
The system appends [element] to the tag name before sending the CIP read request.
Supported CIP Data Types
The PLC tag's data type must be declared in the asset configuration so the system converts the raw bytes correctly.
| CIP Type | PLC Description | How It Is Processed |
|---|---|---|
REAL | 32-bit IEEE 754 float | Read as-is, converted to float |
LREAL | 64-bit IEEE 754 double | Read as-is, converted to float |
DINT | 32-bit signed integer | Cast to int, then to float |
INT | 16-bit signed integer | Cast to int, then to float |
SINT | 8-bit signed integer | Cast to int, then to float |
BOOL | Boolean (1 bit) | true → 1.0, false → 0.0 |
All values are normalized to float internally. If the PLC returns a list or array wrapper around the value, the system automatically unwraps the first element.
STRING tags are not supported in the data pipeline. Status/mode indicators
should use BOOL or DINT instead.
Value Processing Pipeline
Once a raw value is received from the PLC, it passes through these steps before appearing in the dashboard or being evaluated for alerts:
Scale Factor and Offset
Use scale_factor and offset_value when the PLC stores a raw count
rather than an engineering value:
engineering_value = (raw_plc_value × scale_factor) + offset_value
Example: PLC stores pressure as raw ADC counts (0–4095 = 0–10 bar):
scale_factor: 0.00244 # 10 / 4095
offset_value: 0.0
If the PLC already stores values in engineering units — as most modern Allen-Bradley programs
do — leave both at defaults: scale_factor: 1.0, offset_value: 0.0.
Calculated Values
Sensors derived from multiple tags are defined as calculated_values.
These are computed after all raw tags have been read and scaled.
calculated_values:
- name: pressure_differential
formula: "pressure_outlet - pressure_inlet"
unit: bar
- name: vibration_magnitude
formula: "sqrt(vibration_x^2 + vibration_y^2 + vibration_z^2)"
unit: mm/s
Calculated values use internal sensor names (not PLC tag names) in their formulas.
Polling and Timing
| Setting | Default |
|---|---|
| Poll interval | 1000 ms (1 Hz) |
| Connection timeout | 5000 ms |
| Error retry delay | 5000 ms |
Individual sensors can override the default poll rate via sample_rate_hz.
All sensors in an asset are read together in a single CIP batch per poll cycle — set the
poll interval to match the fastest sensor's required sample rate.
OPC UA Namespace Layout
After reading from the PLC, sensor values are written into the OPC UA server namespace so that downstream services can subscribe to them:
Node names in the OPC UA tree are the internal sensor names, not the PLC tag names.
Alert Thresholds
Alerts reference internal sensor names and calculated values:
alerts:
- name: high_vibration
trigger: "vibration_magnitude > 8.0" # Uses calculated value
severity: critical
- name: high_temperature
trigger: "temperature > 95" # Uses internal sensor name
severity: critical
The alert engine never interacts with the PLC directly — it evaluates the already-processed and scaled values from the sensor pipeline.
Diagnosing a Real PLC Connection
When connecting to a live Allen-Bradley PLC, verify these points:
-
1Tag names match exactly
CIP tag reads are case-sensitive on some firmware. Confirm tag names in RSLogix / Studio 5000 match the asset sensor config exactly.
-
2Tags are at the correct scope
Program-scoped tags require the full
Program:<name>.TagNamepath. If browsing shows tags under a Program folder, update thetagfield accordingly. -
3Data type must match
If a tag is
DINTon the PLC butREALin the config, conversion will produce incorrect values. Align thetypefield with the PLC. -
4Check scale_factor if readings look like raw counts
If readings are large integers rather than engineering values, the PLC is storing raw ADC or scaled integers. Calculate and set the appropriate
scale_factor. -
5Port 44818 must be reachable
Verify the PLC's EtherNet/IP port is not blocked by a managed switch ACL or VLAN separation between the edge device and the OT network.
-
6One TCP session per poll
The system opens and closes a TCP connection on every poll cycle. If the PLC has a maximum concurrent connection limit (common on older MicroLogix hardware), increase the poll interval to reduce connection frequency.