在Rockwell产品中使用socket通讯(作为客户端)
支持环境
Rockwell产品中使用5000软件进行编程的控制器有以下系列支持socket通讯:
- 1756-EN2T, 1756-EN2F, 1756-EN2TR, 1756-EN3TR ControlLogix® EtherNet/IP communication modules, 固件版本不低于 5.007
- 1756-EN2TP ControlLogix EtherNet/IP 通讯模块
- 1756-EWEB ControlLogix EtherNet/IP web server 模块, 固件版本不低于 4.006
- 1768-EWEB CompactLogix EtherNet/IP web server 模块, 固件版本不低于 1.002
- 5370 CompactLogix 1769-L3y Controllers : 1769-L30ER(M)(S), 1769-L30ER-NSE, 1769-L33ER(M)(S), 1769-L36ERM(S), 1769-L37ERM(S), 1769-L38ERM(S)
- 5370 CompactLogix 1769-L2y Controllers : 1769-L24ER-QB1B, 1769-L24ER-QBFC1B, 1769-L27ERM-QBFC1B
- 5370 CompactLogix 1769-L1y Controllers : 1769-L16ER, 1769-L18ER(M), 1769-L19ER
- 5380 CompactLogix 5069-L3z : 5069-L306ER(M)(S2), 5069-L310ER(M)(S2), 5069-L310ER-NSE, 5069-320ER(M)(S2), 5069-330ER(M)(S2), 5069-340ER(M)(S2), 5069-350ER(M)(S2),5069-380ER(M)(S2), 5069-3100ER(M)(S2)
- 5580 ControlLogix 控制器: 1756-L81E(S), 1756-L82E(S), 1756-L83E(S), 1756-L84E(S), 1756-L85E
编程
本文简单介绍socket通讯所涉及到的创建、连接、写入、读取、删除等过程。在以上所示的Rockwell产品中,使用message(MSG)指令进行编程。
数据类型
在编程之前,我们要先创建所需的数据类型,需要支持的数据类型包括REQUEST_PARAMETERS、OpenConnParams、WRT_DATA、READ_DATA_REQ、READ_RESP_STR。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!--Params for the OpenConnection Service--> <RSLogix5000Content SchemaRevision="1.0" SoftwareRevision="32.00" TargetName="OpenConnParams" TargetType="DataType" ContainsContext="true" ExportDate="Thu Sep 01 16:45:58 2022" ExportOptions="References NoRawData L5KData DecoratedData Context Dependencies ForceProtectedEncoding AllProjDocTrans"> <Controller Use="Context" Name="ModbusTCP_Master_R102"> <DataTypes Use="Context"> <DataType Name="SockAddr" Family="NoFamily" Class="User"> <Members> <Member Name="Family" DataType="INT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"> <Description> <![CDATA[Address Family Must be 2]]> </Description> </Member> <Member Name="Port" DataType="INT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"> <Description> <![CDATA[Port Number]]> </Description> </Member> <Member Name="Addr" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"> <Description> <![CDATA[IP Address]]> </Description> </Member> </Members> </DataType> <DataType Name="STR_4096" Family="StringFamily" Class="User"> <Members> <Member Name="LEN" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/> <Member Name="DATA" DataType="SINT" Dimension="4096" Radix="ASCII" Hidden="false" ExternalAccess="Read/Write"/> </Members> </DataType> <DataType Name="STR_OUT" Family="NoFamily" Class="User"> <Members> <Member Name="LEN" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/> <Member Name="BUFF" DataType="SINT" Dimension="480" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/> </Members> </DataType> <DataType Use="Target" Name="OpenConnParams" Family="NoFamily" Class="User"> <Description> <![CDATA[Params for the OpenConnection Service]]> </Description> <Members> <Member Name="Timeout" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/> <Member Name="DestAddr" DataType="STRING" Dimension="0" Radix="NullType" Hidden="false" ExternalAccess="Read/Write"/> </Members> </DataType> <DataType Use="Target" Name="READ_DATA_REQ" Family="NoFamily" Class="User"> <Members> <Member Name="Timeout" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/> <Member Name="BufLen" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/> </Members> </DataType> <DataType Use="Target" Name="READ_RESP_STR" Family="NoFamily" Class="User"> <Members> <Member Name="FromAddr" DataType="SockAddr" Dimension="0" Radix="NullType" Hidden="false" ExternalAccess="Read/Write"/> <Member Name="Buf" DataType="STR_4096" Dimension="0" Radix="NullType" Hidden="false" ExternalAccess="Read/Write"/> </Members> <Dependencies> <Dependency Type="DataType" Name="SockAddr"/> <Dependency Type="DataType" Name="STR_4096"/> </Dependencies> </DataType> <DataType Use="Target" Name="REQUEST_PARAMETERS" Family="NoFamily" Class="User"> <Members> <Member Name="Type" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"> <Description> <![CDATA[1 - TCP 2- UPD]]> </Description> </Member> <Member Name="Addr" DataType="SockAddr" Dimension="0" Radix="NullType" Hidden="false" ExternalAccess="Read/Write"/> </Members> <Dependencies> <Dependency Type="DataType" Name="SockAddr"/> </Dependencies> </DataType> <DataType Use="Target" Name="WRT_DATA" Family="NoFamily" Class="User"> <Members> <Member Name="Timeout" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/> <Member Name="ToAddr" DataType="SockAddr" Dimension="0" Radix="NullType" Hidden="false" ExternalAccess="Read/Write"/> <Member Name="Buffer" DataType="STR_OUT" Dimension="0" Radix="NullType" Hidden="false" ExternalAccess="Read/Write"/> </Members> <Dependencies> <Dependency Type="DataType" Name="SockAddr"/> <Dependency Type="DataType" Name="STR_OUT"/> </Dependencies> </DataType> </DataTypes> </Controller> </RSLogix5000Content> |
通讯路径
MSG指令的通讯路径都选择本地通讯的模块。
5570 和 5560 控制器
如果通过界面手动键入,输入 1,[以太网模块的插槽]
如果以编程方式加载到.PATH 字段,则应传入 $01$xx,其中 xx 是槽的十进制值的十六进制等效值(例如,十六进制中的插槽 12 将为 0C)。
5370 控制器
如果通过界面手动键入,输入 1,0
如果以编程方式加载到.PATH 字段,传入 $01$00
5380 控制器
线性/DLR模式
如果通过界面手动键入,输入 1,0
如果以编程方式加载到.PATH 字段,传入 $01$00
双 IP 模式
如果控制器处于双 IP 模式,则消息路径将与上述相同,但是 CREATE 消息的源需要具有套接字将要通信的端口的 IP
注意:’THIS’将不能用作 5380 控制器的路径,双 IP 模式应使用上面提供的路径
5580 控制器
如果通过界面手动键入,输入1,[控制器的插槽] 或者 THIS。THIS是软件预设的指向控制器的路径。
如果以编程方式加载到.PATH 字段,传入 $1F$00$00$00
程序编写
Socket创建
该指令创建一个Socket实例,并将实例号保存到目标元素内。该实例号用于后面所有针对该Socket实例的连接、写入、读取、删除等操作。
MSG指令的服务类型选择:Socket Create
源元素数据类型:REQUEST_PARAMETERS
.Type 1=TCP 2=UPD
.Addr.Family 必须设置为2
.Addr.Port 指定本地端口号,如果未指定端口号,则随机创建端口号
.Addr.Addr 只用于5380控制器的双IP模式,其他情况为0。输入需要作为通讯用的IP地址,该IP地址以16进制形式转换后写入此DINT内。如下图所示
Port A1: 192.168.1.200(选择此IP进行通讯)
Port A2: 10.10.10.44
目标元素数据类型:DINT 如果创建成功,返回Socket实例号
Socket连接
MSG指令的服务类型选择:OpenConnection
源元素数据类型:OpenConnParams
.Timeout 连接超时
.DestAddr 目标地址 该地址以”
xxx.xxx.xxx.xxx?port=xxx”的形式填写
源元素数据长度[MSG.REQ_LEN]:目标地址”
xxx.xxx.xxx.xxx?port=xxx”所有字符数量 +8
实例[MSG.Instance]:创建Socket的实例号
Socket写入
MSG指令的服务类型选择:WriteSocket
源元素数据类型:WRT_DATA
.Timeout 超时时间 ms,可选500
.ToAddr.Family 必须为2
.ToAddr.Port 无需修改 ,0即可
.ToAddr.Addr 无需修改, 0即可
.Buffer.LEN 写入的数据长度
.Buffer.BUFF 写入数据的缓存区
可以使用COP指令,将STR_462类型的数据复制到.Buffer内。
源元素数据长度[MSG.REQ_LEN]:写入的数据长度 +16
目标元素数据类型:DINT 如果写入成功,返回写入的数据长度
实例[MSG.Instance]:创建Socket的实例号
Socket读取
MSG指令的服务类型选择:ReadSocket
源元素数据类型:READ_DATA_REQ
.Timeout 超时时间,无需修改,0即可
.BufLen 缓冲区大小,对应目标元素数据类型的长度,本例为484
目标元素数据类型:READ_RESP_STR
.FromAddr.Family
.FromAddr.Port 来源端口
.FromAddr.Addr 来源地址
.Buf 读取的数据缓存区
实例[MSG.Instance]:创建Socket的实例号
可以使用如下的代码进行数据读取。为了防止在读取一次数据时不完整,将每次读取到的数据写入到一个缓存地址内,该缓存地址为多次读取之后的字符连接而成。再根据逻辑需要把这个缓存区清空(使用DELETE命令)。
Socket删除
最终把该Socket实例进行删除
MSG指令的服务类型选择:DeleteSocket
实例[MSG.Instance]:创建Socket的实例号
坐等大佬D盘更新,祝大佬全家福寿安康
有公众号之类的吗,之前这个网站打不开了
[…] 关于使用Change…
[…] 关于使用Functi…
谢谢提醒,已删 :)