网站开发基本流程ppt,网络整合营销的目的是什么,做影视网站,网站建设页面生成前言 此前#xff0c;我写过一个VB.net环境下与西门子PLC通讯案例的博文#xff1a; VisaulStudio2022下用VB.net实现socket与西门子PLC进行通讯案例#xff08;优化版#xff09; 最近项目上会用到汇川PLC比较多#xff0c;正好有个项目有上位机通讯需求#xff0c;于是…前言 此前我写过一个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_listenPLC作为服务器端时监听客户端指令 2、TCP_acceptPLC作为服务器端时在开启了监听模式后用于监测客户端的连接指令。如果检测到有客户端请求连接则会产生一个connected_socket,并存储在队列里这个connected_socket就是客户端的请求后面的收发数据都用它进行。 3、TCP_connectPLC作为客户端时与服务器连接的指令。 4、TCP_receive:当连接成功建立后使用此指令从远程设备接收数据。 5、TCP_send同上发送数据。 6、TCP_close用于关闭监听或者连接。
下面以PLC作为服务器端为例来说明一下指令具体如何使用
1、TCP_listen 如上图这个指令的触发位Execute其实使用上升沿脉冲即可当触发后Active位会变成ON。 其中左侧的socket接口根据汇川官方文档是应该填写sSocekt数据类型的,详细如下 但是目前Autoshop软件中目前还不支持自定义这种数据类型所以要用INT[20]数组来代替实例中如下 port接口是填写本地端口后可以直接填写常数如2000在PLC中表示为K2000即十进制2000。也可以使用变量只要将数据类型设置为DINT即可。但官方文档有提示尽量不要使用特殊端口号如502。 至于右侧的其他状态位如buzyerrorerrorid只要监控指令运行状态的按照数据类型分配个变量就行了后面的其他指令都会有这些变量就不再多做说明。
2、TCP_accept 当监听开启后就需要用accept来监测客户端的连接请求。 如上图这个指令左侧有一个ListeningSocket参数这里填写和TCP_listen指令一样的数据即可。 其右侧有一个Connected位如果客户端发起了连接请求且无故障那么这个位将会变为ON。同时右侧还有一个Connected_socket参数这个参数也是sSocket类型此处也是用INT[20]数组来代替。但要注意这个和TCP_listen不能是同一个这个相当于是服务器端监听到了客户端产生的客户端反馈。 accept指令可以多次使用以接收多个客户端的连接。本例只按照一个客户端连说明。
3、TCP_receive 此指令用于接收远程设备本例中就是客户端发送的数据其左侧接口有一个Socket参数此处填写前面accept指令右侧的Connected_socket一样的数据即可。 接着是Buffer即数据接收过来存放在哪里 你可以自己新建一个buffer区buffer区是一个连续数组汇川PLC支持两种数据类型 INT[0…n]或者Byte[0…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位数据n4把两个32位整 数复制给同样大小的结构体或16位整数数组n8 当操作数S或D为位元件时位元件的地址必须按字节对齐否则会发生寻址错误例如MCPY M1 M15 K1会报“无效变量地址访问的变量不存在”错误。 实际应用 这样转换后的数据在通过socket发送到上位机后上位机端使用字节转浮点指令如python中可以使用
data_floatstruct.unpack(f,datarecv[0:4])[0] 转换后和PLC发送的数据是一致的。
二、上位机侧程序 上位机侧采用的是VB.net语言编写其中socket通讯方面使用的是System.Net.Sockets库直接导入即可
Imports System.Net.Sockets 说一下几个关键步骤 1、socket连接 Private Sub socket_client_connect() Tryip 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 IfCatch ex As ExceptionConsole.WriteLine(ex.Message)MsgBox(ex.Message vbCrLf 请检查IP设置或目标PLC是否保持通讯正常,MsgBoxStyle.OkOnly, tips!)End TryEnd Sub使用socket.connect()函数向服务器发送连接请求可以使用socket.connected状态位来判断连接是否成功。
2、socket接收 Private Sub socket_client_recvievedata() 定义接收区字节数组Dim recbyt(1024) As Byte循环接收While TrueTryDim reclength soc_client.Receive(recbyt, 200, SocketFlags.None)recvdata Encoding.GetEncoding(gb2312).GetString(recbyt)Dim tt1 As Test_datarecvdata 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)将解析的数据通过委托的方式传递给主线程以更新主线程的UIDim socket_invoke_1 As New socket_invoke(AddressOf socket_recv_data_invoke)Me.Invoke(socket_invoke_1, tt1)Catch ex As ExceptionExit SubMsgBox(ex.Message, MsgBoxStyle.OkOnly, tips!)End TryEnd WhileEnd Sub接收数据使用socket.receive()为了循环接收可以使用while指令但是如果直接使用会阻塞主线程即UI所以最好在新线程中使用。注意上述代码中的后面几行
将解析的数据通过委托的方式传递给主线程以更新主线程的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()即可。 Private Sub socket_client_senddata() TryIf soc_client.Connected Thensoc_client.Send(sendbytes_client, 200, SocketFlags.None)End IfCatch ex As ExceptionMsgBox(ex.Message, MsgBoxStyle.YesNoCancel, tips!)End TryEnd Sub视频演示 汇川PLC与上位机通讯演示