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

news2024/11/19 3:35:32

前言
此前,我写过一个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软件中目前还不支持自定义这种数据类型,所以要用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位数据,n=4;把两个32位整
数,复制给同样大小的结构体或16位整数数组,n=8;
当操作数S或D为位元件时,位元件的地址必须按字节对齐,否则会发生寻址错误;例如,MCPY M1 M15
K1,会报“无效变量地址,访问的变量不存在”错误。

实际应用:
在这里插入图片描述
这样转换后的数据,在通过socket发送到上位机后,上位机端使用字节转浮点指令,如python中可以使用:

data_float=struct.unpack('f',datarecv[0:4])[0] 

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

二、上位机侧程序

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

Imports System.Net.Sockets  

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

   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接收

 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,所以最好在新线程中使用。注意上述代码中的后面几行:

'将解析的数据通过委托的方式传递给主线程,以更新主线程的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()   

      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与上位机通讯演示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1521234.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三.查找(顺序/二分)

目录 7-顺序查找(列表查找) 1-什么是列表查找 代码: 8-二分查找介绍(Binary Search) 查找元素3详细思路: 9-二分查找代码 10-线性查找与二分查找比较 运行时间-装饰器 比较代码: 11-排序介绍 7-顺序查找(列表查找) 1-什么是列表查找 查找:在一些数据元素…

MAC M芯片 Anaconda安装

Anaconda安装 1.M芯片下载AnaConda 1.M芯片下载AnaConda https://www.anaconda.com/download 安装完成 conda的版本是24.1.2

预备知识:深入理解接口测试!

实验简介 随着移动互联网甚至物联网的触角深入到人们生活的每个场景,每个角落,伴随而来的便是企业对其软件系统接口定义和研发,以便于进行数据传输和交换。由此导致目前企业急需大量专职接口测试工程师,因为接口测试天然具备自动…

机试:偶数分解

题目描述: 代码示例: #include <bits/stdc.h> using namespace std; int main(){ // 算法思想1:遍历小于该偶数的所有素数,存入数组中,遍历数组找出两个数之和等于偶数的数int n;cout << "输入样例" << endl;cin >> n;int nums[n];int k …

Python内存管理与垃圾回收机制:深入理解与优化【第138篇—RESTful API】

Python内存管理与垃圾回收机制&#xff1a;深入理解与优化 在Python编程中&#xff0c;内存管理与垃圾回收机制是至关重要的主题。了解Python如何管理内存和处理垃圾回收对于编写高效、稳定的程序至关重要。本文将深入探讨Python中的内存管理和垃圾回收机制&#xff0c;包括内…

CSS 【详解】响应式布局(明天内容)

响应式布局&#xff1a; 同一页面在不同的屏幕上有不同的布局&#xff0c;即一套代码自适应不同的屏幕。 常用 单位&#xff1a; 像素&#xff08;px&#xff09;&#xff1a;像素是最常用的长度单位&#xff0c;它表示屏幕上的一个物理像素点。例如&#xff0c;width: 200px; …

Bean的作用域、Bean的自动装配、注解自动装配 (Spring学习笔记五)

1、Bean 的作用域 官网上显示有六种 1、Bean的作用域默认的是singleton&#xff08;单例模式的实现&#xff09; 也可以显示的设置&#xff08;单例模式的实现&#xff09; <!--用scope可以设置Bean的作用域--><bean id"user2" class"com.li.pojo.Us…

C++的类和对象(七):友元、内部类

目录 友元 友元函数 友元类 内部类 匿名对象 拷贝对象时的一些编译器优化 再次理解类和对象 友元 基本概念&#xff1a;友元提供了一种突破封装的方式&#xff0c;有时提供了便利&#xff0c;但是友元会增加耦合度&#xff0c;破坏了封装&#xff0c;所以友元不宜多用&…

simulink平面五杆机构运动学仿真

1、内容简介 略 68-可以交流、咨询、答疑 2、内容说明 simulink平面五杆机构运动学仿真 [ 摘 要 ] 以 MATLAB 程序设计语言为平台 , 以平面可调五杆机构为主要研究对象 , 给定机构的尺寸参数 , 列出所 要分析机构的闭环矢量方程 , 使用 MATLAB 软件中 SIMULINK 仿真工…

测试环境搭建整套大数据系统(十一:docker部署superset,无密码登录嵌入html,http改为https)

一&#xff1a;安装docker 参考文档 https://blog.csdn.net/weixin_43446246/article/details/136554243 二&#xff1a;安装superset 下载镜像。 拉取镜像&#xff08;docker pull amancevice/superset&#xff09; 查看镜像是否下载完成&#xff08;docker images&#xf…

精读《精通 console.log》

1 引言 本周精读的文章是 Mastering JS console.log like a Pro&#xff0c;一起来更全面的认识 console 吧&#xff01; 2 概述 & 精读 console 的功能主要在于控制台打印&#xff0c;它可以打印任何字符、对象、甚至 DOM 元素和系统信息&#xff0c;下面一一介绍。 c…

Vue 3 + TypeScript 项目中全局挂载并使用工具函数

一、proxy方式 1.封装日期选择工具函数&#xff1a; 在untils文件夹下新建index.ts,并导出工具函数 /*** 获取不同类型日期* param&#xff1a;类型 dateVal: 是否指定*/ export function getSystemDate(param: any, dateVal: any) {let systemDate dateVal ? new Date(da…

【NC223888】红色和紫色

题目 红色和紫色 博弈论&#xff0c;想得出来思路就简单&#xff0c;想不出来就难。一般使用猜测法。 思路 如果小红随意取一个格子涂色&#xff0c;那么小紫怎么涂色才是她的最优选择呢&#xff1f; 假设小紫只能选择小红涂色的格子的相邻格子或者是最近斜对角的一个格子涂色…

回归学术圈,何恺明MIT第一堂AI课

大家好&#xff0c;3月7日&#xff0c;麻省理工学院电气工程与计算机科学系副教授何恺明&#xff0c;迈上讲台&#xff0c;并成功地进行了他人生中的首堂教学课程。 第一堂课 课程官网&#xff1a;https://advances-in-vision.github.io/ 作为麻省理工学院&#xff08;MIT&am…

【算法篇】七大基于比较的排序算法精讲

目录 排序 1.直接插入排序 2.希尔排序 3.直接选择排序 4.堆排序 5.冒泡排序 6.快速排序 7.归并排序 排序 排序算法的稳定性&#xff1a;假设在待排序的序列中&#xff0c;有多个相同的关键字&#xff0c;经过排序后&#xff0c;这些关键字的先后顺序不发生改变&#…

动态规划8, 摆动序列,最长递增子序列,最长数对链

本次的题与动态规划7 的题有相似与共通之处&#xff0c;建议先去看 动态规划7&#xff1a;动态规划7 摆动序列 什么是摆动序列&#xff1f; 就像这种&#xff1a; 一个数&#xff0c;一个下降&#xff0c;上升&#xff0c;来回上升下降都可以叫摆动序列。 思路&#xff1a; …

政安晨:【深度学习处理实践】(八)—— 表示单词组的两种方法:集合和序列

咱们接着这个系列的上一篇文章继续&#xff1a; 政安晨&#xff1a;【深度学习处理实践】&#xff08;七&#xff09;—— 文本数据预处理https://blog.csdn.net/snowdenkeke/article/details/136697057 机器学习模型如何表示单个单词&#xff0c;这是一个相对没有争议的问题…

分析基于解析物理模型的E模式p沟道GaN高电子迁移率晶体管(H-FETs)

来源&#xff1a;Analyzing E-Mode p-Channel GaN H-FETs Using an Analytic Physics-Based Compact Mode&#xff08;TED 24年&#xff09; 摘要 随着近期对用于GaN互补技术集成电路&#xff08;ICs&#xff09;开发的p沟道GaN器件研究兴趣的激增&#xff0c;一套全面的模型…

算法笔记 连载中。。。

HashMap&#xff08;会根据key值自动排序&#xff09; HashMap<String, Integer> hash new HashMap<>() hash.put(15,18) hash.getOrDefault(ts, -1) //如果ts(key)存在&#xff0c;返回对应的value 否则返回-1 hashMap1.get(words1[i])1会报错&#xff0c;因…

快速高效地数据分析处理:QtiPlot for Mac中文直装版 兼容M

QtiPlot 是一个用于数据分析和可视化的跨平台科学应用程序。由于其多语言支持&#xff0c;QtiPlot 被积极用于世界各地学术机构的教学。许多研究科学家信任 QtiPlot 来分析他们的数据并发布他们的工作结果。来自各个科学领域和行业的数千名注册用户已经选择了 QtiPlot 来帮助他…