在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。

<?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的实例号

版权声明:本文内容来源于网络搜集无法获知原创作者,仅供个人学习用途,若侵犯到您的权益请联系我们及时删除。邮箱:1370723259@qq.com

发表评论