EtherNet/IP 是工业自动化领域广泛使用的实时以太网协议,尤其在与 PLC、HMI、驱动器等设备通信时,依赖明确的实例(Instance)寻址机制。在 CODESYS 平台上集成 EtherNet/IP 适配器(如使用 EtherNet/IP Adapter 或第三方厂商提供的 EIP Adapter 库)时,一个隐蔽但高频出现的问题是:多个设备或配置项被分配了相同的 Instance ID,导致主站(Scanner)连接请求被从站(Adapter)主动拒绝,表现为“Connection refused”、“No response from adapter”或“Invalid instance”等日志错误,且无明确报错指向 Instance ID 冲突。
该问题不触发编译错误,不中断下载流程,也不在设备启动阶段抛出异常,而是在运行时首次建立显式/隐式连接时失败——因此极易被误判为网络配置、IP 地址、防火墙或硬件故障,排查耗时长、成本高。本文提供一套纯软件层面、无需额外工具、仅靠 CODESYS 工程本身即可完成的完整检查与修复路径,覆盖从识别现象、定位冲突源、验证 Instance 分配逻辑,到修正配置与预防复发的全部环节。
一、理解 Instance ID 在 EtherNet/IP 中的作用
EtherNet/IP 将设备资源建模为对象(Objects),每个对象包含若干实例(Instances)。标准对象如 Identity Object(Class 1)、Message Router(Class 3)、Assembly Object(Class 4)、Connection Manager(Class 2)等,均以 Instance 0 为“类模板”,Instance 1 为默认实例。用户自定义数据(如输入/输出映射区、参数块)通常通过 Assembly Object 实现,其每个 Assembly 实例对应一组固定长度的数据缓冲区(如 32 字节输入 + 32 字节输出),由唯一的 Instance ID 标识。
关键规则如下:
- Instance ID 必须全局唯一:在同一 EtherNet/IP 设备(即同一 CODESYS 运行实例)内,所有对象的所有实例 ID 不得重复。
- Instance ID 范围为 1–65535:Instance 0 保留给类定义,不可用于实际数据映射。
- CODESYS EtherNet/IP Adapter 库会自动注册实例:当用户添加
EIP_AssemblyInput或EIP_AssemblyOutput功能块时,库内部调用CIP_RegisterAssembly(),并传入用户指定的InstanceID参数;若该值已被占用,底层 CIP 协议栈将拒绝注册,并静默忽略该功能块——此时功能块看似“在线”,实则未生效。
因此,“连接拒绝”的本质不是网络不通,而是从站侧根本未为该 Instance 建立可用的数据端点。
二、快速确认是否为 Instance ID 冲突
执行以下三步,可在 2 分钟内完成初步判定:
-
查看 CODESYS 设备日志
打开Device > Online > Device Log,筛选关键词EIP或CIP。若存在类似以下条目,则高度疑似冲突:
CIP: RegisterAssembly failed - Instance 101 already exists
EIP Adapter: Failed to register output assembly, instance ID 205 occupied
CIP Error 0x01: Invalid Parameter (at instance registration) -
检查所有 EIP 功能块的
InstanceID参数值
在项目浏览器中,展开Application > Program或Library Instances,查找所有类型为EIP_AssemblyInput、EIP_AssemblyOutput、EIP_Scanner(若用作从站)、EIP_ExplicitMsg的实例。
逐一双击打开属性窗口,记录每个实例的InstanceID字段值。重点关注:- 是否有多个实例使用相同数字(如都设为
100); - 是否存在
InstanceID = 0(非法,将被忽略); - 是否使用了保留实例(如
1、2、3—— 这些通常被 Identity、Message Router、Assembly 类自身占用)。
- 是否有多个实例使用相同数字(如都设为
-
启用 CODESYS 内置诊断模式(无需修改代码)
在Device > Device Properties > EtherNet/IP Adapter配置页中,勾选Enable diagnostic output,并将Diagnostic level设为Verbose。重启设备后,再次查看 Device Log。此时会输出每条 Assembly 注册的完整过程,例如:
Registering input assembly: InstanceID=101, Size=64 bytes → OK
Registering output assembly: InstanceID=101, Size=64 bytes → FAILED (duplicate)
此输出可直接锁定冲突点。
若以上任一条件成立,即可确认问题根源为 Instance ID 重复。
三、系统化扫描所有已注册 Instance ID(离线+在线双校验)
手动比对易漏,需结构化检查。以下方法完全基于 CODESYS IDE 内置功能,无需外部脚本。
(1)导出所有 EIP 实例配置(离线扫描)
- 右键点击项目根节点 > Export > Export Project as XML…
- 保存为
project_export.xml。 - 用文本编辑器(如 VS Code)打开该 XML 文件,搜索关键词
<InstanceID>。 - 使用正则查找匹配所有赋值行(示例正则:
<InstanceID>(\d+)</InstanceID>),提取全部数值,粘贴至 Excel 或在线去重工具。 - 检查是否存在重复数字。若发现重复,记下对应
<Name>和<TypeName>,即可定位具体功能块。
✅ 提示:CODESYS 导出的 XML 中,每个 POUs 实例均含
<Properties>节点,其中<Property Name="InstanceID">明确声明值。
(2)运行时动态枚举(在线验证)
在 PLC 程序中临时插入诊断逻辑(调试结束后删除):
PROGRAM CheckEIPInstances
VAR
i: INT := 0;
instanceList: ARRAY[1..100] OF UINT; // 假设最多 100 个 Assembly
count: UINT := 0;
isDuplicate: BOOL;
END_VAR
// 遍历所有已知 EIP 实例(需按实际命名调整)
IF EIP_In1.InstanceID > 0 THEN
instanceList[count + 1] := EIP_In1.InstanceID; count := count + 1;
END_IF
IF EIP_Out1.InstanceID > 0 THEN
instanceList[count + 1] := EIP_Out1.InstanceID; count := count + 1;
END_IF
IF EIP_Out2.InstanceID > 0 THEN
instanceList[count + 1] := EIP_Out2.InstanceID; count := count + 1;
END_IF
// ... 继续添加其他实例
// 检查重复(简单两层循环)
isDuplicate := FALSE;
FOR i := 1 TO count DO
FOR j := i + 1 TO count DO
IF instanceList[i] = instanceList[j] THEN
isDuplicate := TRUE;
// 触发报警或写入诊断变量
Diag_DuplicateInstance := instanceList[i];
END_IF
END_FOR
END_FOR
将 Diag_DuplicateInstance 添加到在线监视表,运行后立即显示冲突 ID。
四、修复步骤:从分配到验证的闭环操作
确认冲突后,按顺序执行以下操作:
-
停止所有 EIP 相关任务
切换 到Online > Login,点击Stop按钮,确保 PLC 处于停止状态。 -
统一重置 Instance ID 分配策略
制定清晰编号规则(推荐):- 输入 Assembly:
100–199 - 输出 Assembly:
200–299 - 参数配置 Assembly:
300–399 - 自定义诊断 Assembly:
400–499✅ 优势:预留空间、语义明确、便于后期扩展。
- 输入 Assembly:
-
批量修改 InstanceID 参数
- 在项目浏览器中,按住
Ctrl键多选 所有EIP_AssemblyInput实例; - 右键 > Properties;
- 在属性窗口中,点击
InstanceID行,输入 新值(如101,102,103…),回车; - 同法处理
EIP_AssemblyOutput(起始201),确保无交叉、无跳空、无重复。
- 在项目浏览器中,按住
-
清除旧注册缓存(关键!)
CODESYS 运行时会缓存已注册的 Instance。即使修改了配置,旧实例仍可能驻留内存。
必须执行:- 点击
Device > Reset > Reset All(非“Reset Runtime”); - 确认 清除全部运行时状态;
- 重新下载 整个工程(包括 Bootproject)。
- 点击
-
验证注册成功
下载完成后,点击Online > Login启动;
立即打开Device Log,搜索Registering.*OK;
确认每条 Assembly 均显示→ OK,且无FAILED或already exists字样;
最后,在Online > Browse Variables中展开EIP_Adapter对象,检查Status.RegisteredAssemblies数值是否等于你配置的总数。
五、预防机制:避免未来再次发生
| 措施 | 操作方式 | 效果 |
|---|---|---|
| 启用 CODESYS 变量命名规范检查 | Tools > Options > Editors > ST Editor > Enable naming convention,设置前缀如 EIP_IN_ / EIP_OUT_,并关联 InstanceID 值(如 EIP_IN_101) |
强制命名体现 ID,人工审查效率提升 80% |
| 创建 Instance ID 分配表(Excel) | 维护一张共享表格,列:功能描述、方向、Instance ID、占用状态、备注;每次新增前查表申请 | 杜绝跨工程师冲突 |
| 使用 CODESYS 全局常量管理 | 在 Global Variables 中定义:EIP_IN_BASE : UINT := 100; EIP_OUT_BASE : UINT := 200;,所有实例 InstanceID := EIP_IN_BASE + 1 |
修改基址即可批量偏移,零手动计算错误 |
六、附录:常见 Instance ID 占用对照表(CODESYS 默认)
| Instance ID | 对象类型 | 说明 | 是否可覆盖 |
|---|---|---|---|
1 |
Identity Object | 设备基本信息(Vendor ID, Device Type) | ❌ 禁止修改 |
2 |
Message Router | 显式消息路由入口 | ❌ 禁止修改 |
3 |
Connection Manager | 管理显式/隐式连接生命周期 | ❌ 禁止修改 |
4 |
Port Object | 物理端口状态 | ❌ 禁止修改 |
100–199 |
User Assembly (Input) | 推荐范围 | ✅ 安全可用 |
200–299 |
User Assembly (Output) | 推荐范围 | ✅ 安全可用 |
65535 |
Reserved | CIP 协议保留 | ❌ 禁止使用 |
⚠️ 注意:某些第三方 EIP 库(如 HMS Anybus SDK 封装版)可能额外占用
500–599,请查阅对应库文档。
七、典型错误案例还原与纠正
场景:用户配置了两个 EIP_AssemblyOutput,分别命名为 Motor_Speed_Ref 和 Valve_Position_Cmd,InstanceID 均设为 1。
现象:设备上线后,HMI 可读取状态但无法下发指令;Wireshark 抓包显示 Scanner 发送 ForwardOpen 请求,Adapter 返回 0x0101(Path segment error)。
根因:Instance 1 被 Identity Object 占用,第二个 EIP_AssemblyOutput 注册失败,对应输出缓冲区始终为 0。
纠正:
- 将
Motor_Speed_Ref.InstanceID改为201; - 将
Valve_Position_Cmd.InstanceID改为202; - 执行
Reset All+ 重新下载; - 验证 Device Log 中两条均显示
Registering output assembly: InstanceID=201 → OK。
重置设备状态后,重新下载工程,观察 Device Log 中所有 Assembly 注册结果均为 OK,且 Status.RegisteredAssemblies 数值与配置数量一致。

暂无评论,快来抢沙发吧!