<.Net>VisaulStudio2022下用VB.net实现socket与汇川PLC进行通讯案例(Eazy521)

前言

此前,我写过一个VB.net环境下与西门子PLC通讯案例的博文:
VisaulStudio2022下用VB.net实现socket与西门子PLC进行通讯案例(优化版)

最近项目上会用到汇川PLC比较多,正好有个项目有上位机通讯需求,于是就自己这边先测试了一下汇川PLC和上位机通过socket进行数据通讯。

配置:

平台:windows

工具:visual studio 2022

语言:VB.net

通讯协议:socket

PLC型号:汇川Eazy521系列

固件版本:6.1.2.0

PLC软件:汇川Autoshop V4.8.2.4

其实,与PLC进行通讯来说,上位机侧的程序几乎不用改变,主要是PLC端的使用有些不同,像西门子、信捷的PLC,在进行socket通讯时,虽然使用协议都是一样的,但不同厂家,其编程指令和PLC程序写出来是不一致的,其中还涉及数据类型的转换。

本篇将侧重于介绍汇川PLC这边的设置及编程,上位机将在之前的基础上稍作修改。

一、PLC侧设置

汇川PLC进行socket协议通讯的指令,在它的工具箱-通讯指令-以太网指令下:

大致介绍下指令:

1、TCP_listen:PLC作为服务器端时,监听客户端指令

2、TCP_accept:PLC作为服务器端时,在开启了监听模式后,用于监测客户端的连接指令。如果检测到有客户端请求连接,则会产生一个connected_socket,并存储在队列里,这个connected_socket就是客户端的请求,后面的收发数据,都用它进行。

3、TCP_connect:PLC作为客户端时,与服务器连接的指令。

4、TCP_receive:当连接成功建立后,使用此指令从远程设备接收数据。

5、TCP_send:同上,发送数据。

6、TCP_close:用于关闭监听或者连接。

下面,以PLC作为服务器端为例,来说明一下指令具体如何使用:

1、TCP_listen:

如上图,这个指令的触发位Execute,其实使用上升沿脉冲即可,当触发后,Active位会变成ON。

其中,左侧的socket接口,根据汇川官方文档,是应该填写sSocekt 数据类型的,详细如下:

但是目前Autoshop软件中目前还不支持自定义这种数据类型,所以要用INT20数组来代替,实例中如下:

port接口是填写本地端口后,可以直接填写常数,如2000,在PLC中表示为K2000,即十进制2000。也可以使用变量,只要将数据类型设置为DINT即可。但官方文档有提示,尽量不要使用特殊端口号,如502。

至于右侧的其他状态位如buzy,error,errorid,只要监控指令运行状态的,按照数据类型,分配个变量就行了,后面的其他指令,都会有这些变量,就不再多做说明。

2、TCP_accept:

当监听开启后,就需要用accept来监测客户端的连接请求。

如上图,这个指令左侧有一个ListeningSocket参数,这里填写和TCP_listen指令一样的数据即可。

其右侧有一个Connected位,如果客户端发起了连接请求,且无故障,那么这个位将会变为ON。同时,右侧还有一个Connected_socket参数,这个参数也是sSocket 类型,此处也是用INT20数组来代替。但要注意,这个和TCP_listen不能是同一个,这个相当于是服务器端监听到了客户端,产生的客户端反馈。

accept指令可以多次使用,以接收多个客户端的连接。本例只按照一个客户端连说明。

3、TCP_receive:

此指令用于接收远程设备(本例中就是客户端)发送的数据,其左侧接口有一个Socket参数,此处填写前面accept指令右侧的Connected_socket一样的数据即可。

接着是Buffer,即数据接收过来,存放在哪里?

你可以自己新建一个buffer区,buffer区是一个连续数组,汇川PLC支持两种数据类型:

INT0...n或者Byte0...n,使用哪种看自己需要,一般常用byte即可。

接下来是Size参数,因为我们不一定需要所有发送过来的数据,所以可设置接收数据长度,但要注意,Size的值不能超过buffer区的大小。

右侧参数,done代表指令接收完成,可以使用这个状态位来编写一些逻辑程序,如数据传送等。

还有一个ReceivedSize参数,表示实际接收的数据长度,虽然设置了数据接收长度,但发过来的数据可能小于设置值,比如设置了10字节,但发送过来的只有2个字节,这个长度就是实际长度,会显示在ReceivedSize中。

4、TCP_send:

此指令用于发送数据,与TCP_receive指令类似,其左侧的Socket参数,填写accept指令右侧的Connected_socket一样的参数。

buffer填写自定义的发送数据缓冲区,Size为发送长度,右侧的sentsize标识实际发送的数据长度。

5、TCP_close:

关闭指令非常简单,用于关闭socket连接,但要注意,本例是将PLC作为服务器端,所以关闭连接时,除了要关闭服务器的监听socket,还需要关闭客户端的请求socket(假如已成功建立连接)。

以上就是汇川PLC端的程序编写,汇川的官方文档也给了示例,但实际使用时,会涉及数据转换问题,这里提一个注意点:

我这边使用时,需要在PLC这边将浮点数(32位)发送到上位机,但我们在前面说了,TCP_send的buffer区只能是Byte\[\]或者INT\[\]这两种,所以,就需要将浮点数先转为整数类型或者字节类型。

但是,如果你直接使用汇川的INT或者DINT这个指令,它会将浮点数转换为四舍五入后的整数,并不是真正的无损转换。

我在指令文档找了半天,才发现汇川要实现将浮点数完全转换为字节,需要使用MCPY 这个指令。

官方解释:

该指令是较为高阶的应用,需谨慎使用!

该指令是数据复制操作,数据本身无变化,可以实现内存复制拷贝;如果使用巧妙,可以实现类型变换的操

作。

n是待复制的数据的长度,以字节为单位,比如,两个16位数据赋值给一个32位数据,n=4;把两个32位整

数,复制给同样大小的结构体或16位整数数组,n=8;

当操作数S或D为位元件时,位元件的地址必须按字节对齐,否则会发生寻址错误;例如,MCPY M1 M15

K1,会报"无效变量地址,访问的变量不存在"错误。

实际应用:

这样转换后的数据,在通过socket发送到上位机后,上位机端使用字节转浮点指令,如python中可以使用:

python 复制代码
data_float=struct.unpack('f',datarecv[0:4])[0] 

转换后和PLC发送的数据是一致的。

二、上位机侧程序

上位机侧采用的是VB.net语言编写,其中socket通讯方面使用的是System.Net.Sockets库,直接导入即可:

vbnet 复制代码
Imports System.Net.Sockets  

说一下几个关键步骤:
1、socket连接

vbnet 复制代码
   Private Sub socket_client_connect()        

       Try
           ip = IPAddress.Parse(TextBox1.Text)
           port = Integer.Parse(TextBox2.Text)
           ipe = New IPEndPoint(ip, port)
           soc_client.Connect(ipe)
           Console.WriteLine("connect ok")
           If soc_client.Connected Then

               '如果连接成功,状态变为绿色
               huayuan(PictureBox1, Color.LimeGreen)


               '如果连接成功,则启动数据接收,为了防止阻塞线程,采用新线程
               Dim th1 As New Thread(AddressOf socket_client_recvievedata)  '多线程
               th1.Start()                               '线程启动,防止socket阻塞

           End If

       Catch ex As Exception

           Console.WriteLine(ex.Message)
           MsgBox(ex.Message + vbCrLf +
                  "请检查IP设置或目标PLC是否保持通讯正常?",
                  MsgBoxStyle.OkOnly, "tips!")

       End Try

   End Sub

使用socket.connect()函数向服务器发送连接请求,可以使用socket.connected状态位来判断连接是否成功。

2、socket接收

vbnet 复制代码
 Private Sub socket_client_recvievedata()  

     '定义接收区字节数组
     Dim recbyt(1024) As Byte

     '循环接收
     While True

         Try
             Dim reclength = soc_client.Receive(recbyt, 200, SocketFlags.None)
             'recvdata = Encoding.GetEncoding("gb2312").GetString(recbyt)

             Dim tt1 As Test_data
             'recvdata = Encoding.ASCII.GetString(recbyt, 0, 30)

             '以下是对所接收的所有数据进行解析,可以根据实际情况变化
             '下面的仅作为参考
             'ax1.axis_status = BitConverter.ToInt16(recbyt, 0)
             'ax1.axis_xunhuanmoshi = BitConverter.ToInt16(recbyt, 2)
             'ax1.axis_runing = BitConverter.ToInt16(recbyt, 4)
             'ax1.axis_error = BitConverter.ToInt16(recbyt, 6)

             Console.WriteLine(reclength.ToString())

             'tt1.test1 = Encoding.GetEncoding("utf-8").GetString(recbyt)
             'tt1.test2 = Encoding.GetEncoding("utf-8").GetString(recbyt)
             tt1.temp_float1 = BitConverter.ToSingle(recbyt, 0)

             'Console.WriteLine(recdata1)

             '将解析的数据通过委托的方式传递给主线程,以更新主线程的UI
             Dim socket_invoke_1 As New socket_invoke(AddressOf socket_recv_data_invoke)

             Me.Invoke(socket_invoke_1, tt1)

         Catch ex As Exception
             Exit Sub
             MsgBox(ex.Message, MsgBoxStyle.OkOnly, "tips!")

         End Try


     End While

 End Sub

接收数据使用socket.receive(),为了循环接收,可以使用while指令,但是如果直接使用,会阻塞主线程即UI,所以最好在新线程中使用。注意上述代码中的后面几行:

vbnet 复制代码
'将解析的数据通过委托的方式传递给主线程,以更新主线程的UI
Dim socket_invoke_1 As New socket_invoke(AddressOf socket_recv_data_invoke) 

Me.Invoke(socket_invoke_1, tt1)

此处采用的是.Net中的委托,即为了不阻塞主线程,我们采用委托的形式,将socket循环接收的数据发送给UI,这样既可以传送数据,又不会阻塞线程。

3、socket发送数据

发送数据则非常简单,使用socket.send()即可。

vbnet 复制代码
  Private Sub socket_client_senddata()   

      Try

          If soc_client.Connected Then

              soc_client.Send(sendbytes_client, 200, SocketFlags.None)

          End If
      Catch ex As Exception

          MsgBox(ex.Message, MsgBoxStyle.YesNoCancel, "tips!")

      End Try

  End Sub

视频演示

汇川PLC与上位机通讯演示

相关推荐
文祐2 小时前
下载Visual Studio 2017 Build Tools version 15.9
ide·visual studio
CSharp精选营4 小时前
.NET 面试必问的 8 道 GC 题,建议收藏
.net·面试题·gc·c#面试题
cuijiecheng20185 小时前
Windows 下使用 GitHub Private Repository 管理私人 Visual Studio/C++ 项目
windows·github·visual studio
开开心心就好1 天前
二维码批量生成导出工具,离线可用完全免费
java·前端·人工智能·智能手机·github·excel·visual studio
重生之我复员之后重当黄毛1 天前
vscode配置c/c++环境
c语言·前端·visual studio
驰骋工作流1 天前
C#/.NET 开源BPM工作流引擎6大常用对比选型分析驰骋BPM驰骋低代码低代码工作流引擎
开源·c#·.net
淡海水2 天前
02-02-原理篇-分代GC
算法·unity·c#·游戏引擎·.net·gc
1-1=02 天前
.NET 依赖注入 续
.net
淡海水2 天前
02-03-原理篇-大对象堆
unity·c#·游戏引擎·.net·gc
LateFrames2 天前
WPF 升级选型:用 .NET 8 还是 .NET 10
.net·wpf·.net8·.net10