Rockwell EtherNet/IP
通过 EtherNet/IP(CIP)连接 Allen-Bradley Logix 控制器:控制器标签名、字节偏移、CIP 原子类型和网络设备发现。
Rockwell EtherNet/IP 驱动通过 EtherNet/IP 和 Allen-Bradley / Rockwell 的 Logix 控制器(ControlLogix、CompactLogix)对话,用的是 CIP 标签寻址。你按 Logix 项目里声明的控制器标签名来寻址数值,完全不涉及寄存器映射。在 Connector 里的 Rockwell EtherNet/IP 驱动下面添加一台设备;面板只显示这个协议用得到的那些字段。
连接
| 字段 | 含义 | 默认值 |
|---|---|---|
| 主机 | 控制器以太网口的 IP 地址或主机名。 | 空 |
| 槽位 | 控制器插在机箱的第几位,从 0 数起。 | 0 |
| 轮询间隔(毫秒) | 整台设备的读取周期,供没有自己另作规定的点位使用。 | 1000 |
没有端口字段:EtherNet/IP 用它标准的 TCP 端口 44818。CIP 路由是背板加上槽位,所以控制器插在机箱哪一位都够得着;发现出来的控制器从槽位 0 开始,那个字段就是你改正它的地方。没有机架字段:CIP 路由里不带机架号。请求 10 秒之后超时。设备标题栏显示拼好的端点,例如 eip://192.168.0.10:0,地址后面那个数字就是槽位。
每个点位都可以设自己的轮询间隔(毫秒);点位填 0 就退回设备的间隔。
寻址
Rockwell 的点位靠点位“来源”卡片里的两个字段寻址:
| 字段 | 含义 | 接受的取值 | 默认值 |
|---|---|---|---|
| 控制器标签 | 控制器里声明的那个标签名。必填。 | 自由文本 | 空 |
| 标签内偏移(字节;BOOL 为位) | 这个值落在那个标签数据里的什么位置:一个字节偏移,或者对布尔点位来说是一个位偏移。 | 0–255 | 0 |
驱动按名字打开那个控制器标签,再从它的数据缓冲区里按偏移把值挑出来。对一个普通的原子标签,偏移保持 0。正是这个偏移让一个控制器标签能服务好几个通道:一个结构开头的 DINT 是偏移 0,四个字节之后的 REAL 是偏移 4,而对布尔点位来说,偏移数的是位而不是字节。
| 要读的东西 | 控制器标签 | 偏移 | 数据类型 |
|---|---|---|---|
控制器作用域的 DINT Counter |
Counter |
0 | Int32 |
Main 里程序作用域的一个 DINT |
Program:Main.Counter |
0 | Int32 |
REAL 数组的一个元素 Temps[2] |
Temps[2] |
0 | Float |
结构 Recipe 里的第二个 DINT |
Recipe |
4 | Int32 |
Flags 数据里的第 3 位 |
Flags |
3 | Boolean |
名字是整个送到控制器那里的,中间的点也在内,而同一个标签的读和写落在同一个地方。正因如此,Program:Main.Counter 这种程序作用域的名字才管用。带点的成员路径(MyUdt.Member)在控制器按名字发布那个成员时由控制器解析;控制器不发布时,就点名基础的控制器作用域标签,再用字节偏移伸进去,这条路永远走得通。“来源”卡片里那行只读的来源地址(总线)会随着你编辑显示拼好的地址。
数据类型
每一种 CIP 原子类型都能作为点位的数据类型:
| 数据类型 | CIP 类型 | 大小 |
|---|---|---|
| Boolean | BOOL | 位偏移处的 1 个位 |
| SByte | SINT | 1 字节 |
| Byte | USINT | 1 字节 |
| Int16 | INT | 2 字节 |
| UInt16 | UINT | 2 字节 |
| Int32 | DINT | 4 字节 |
| UInt32 | UDINT | 4 字节 |
| Int64 | LINT | 8 字节 |
| UInt64 | ULINT | 8 字节 |
| Float | REAL | 4 字节 |
| Double | LREAL | 8 字节 |
不支持结构和 UDT:只有上面那些原子类型能读能写,而字节偏移的存在,正是为了伸进它们里面去够成员。选择器里刻意没有 String:Logix 的 STRING 不是原子类型,而是一个由长度和一个 82 字节数组组成的结构,驱动既读不了也写不了。总线上的字节序就是 CIP 自己的小端序,由驱动自动处理;没有字节序选项。
写入
访问方式为读写或只写的点位可以被写。一次写入会先读那个控制器标签,改掉被寻址的那些字节(布尔则是被寻址的那个位),再写回去。新点位一开始是只读。
设备发现
Connector 的“发现设备”按钮会在本机所在的每一个网络上广播一个 CIP List Identity 请求,并一直听下去,直到有 10 秒没有新的回答为止。扫描期间它会把那些网络点出来,所以结果为零时你知道这个问题究竟发到哪里去了:一台装着给虚拟机、WSL 或 VPN 用的虚拟网卡的工作站,网络往往比操作员以为的多,候选项也可能是从其中某一个上来的。
承载不了这个请求的接口会被跳过:任何没有起来的接口、回环和隧道适配器,以及接口在没人应答 DHCP 时自己给自己取的那种地址(169.254.x.x)。只有确实是控制器自身身份回答的应答才成为候选设备,名字是 eip:// 加上它的地址;在 EtherNet/IP 端口上应答的其他任何东西都被忽略,并在诊断日志里说明。随后,扫描为每一个候选项读取控制器作用域的标签列表,把它的那些原子标签作为候选通道提供出来,每一个的偏移都是 0。
设备发现会把驱动轮询不了的东西丢掉:结构和 UDT 标签(含 Logix 的 STRING)被丢掉,Program:、Task: 和 Map: 这几类条目被跳过。一台不在本机所在网络上的控制器不会应答广播;请手工添加它。
需要知道的事
- 发往控制器的每一个请求都在 10 秒之后超时,而设备发现的监听窗口在沉默 10 秒之后关闭。
- 驱动把每一个控制器标签只打开一次,并在设备保持连接期间一直开着,所以带着几十个标签的控制器是在它已经有的会话上读的,而不是每读一次就开一次、关一次。读失败的那一次会放掉自己的标签,下一次读再按名字把它打开。
- 在 Logix 项目里给标签改名会悄悄把这个通道弄断;在配置的名字重新对上之前,这个点位读作质量不可用。