当前位置: 首页 > news >正文

康耐视智能相机(Insight)通过ModbusTCP发送字符串到倍福(BECKHOFF)PLC中

文章目录

  • 1.背景
  • 2.分析
  • 3.实现
    • 3.1.PLC的ModbusTCP_Server
      • 3.1.1.安装TF6250-Modbus-TCP
      • 3.1.2.PLC设置
    • 3.2.智能相机的ModbusTCP_Client
      • 3.2.1.了解ModbusTCP的协议
      • 3.2.2.根据协议写代码
        • 3.2.2.1.纯函数代码
        • 3.2.2.2.脚本代码
      • 3.2.3.非脚本处理时的代码逻辑图
      • 3.2.4.关于代码的问题及解答
  • 4.总结

1.背景

目前有个需求,要求康耐视智能相机(Insight)在每次触发完成作业后,将一串字符串通过ModbusTCP发送至倍福的PLC中。此时PLC作为Modbus的server,智能相机作为Modbus的client,智能相机主动发送数据给PLC(写PLC的Modbus的保持寄存器(Holding Registers))。
目前已经实现了,效果如下:
在这里插入图片描述代码我已经上传到这里了【康耐视智能相机ModbusTCP发送字符串代码 】,不需要下载积分。造福大家。

2.分析

主要有两部分的功能要实现:PLC的ModbusTCP_Server的实现、智能相机的ModbusTCP_Client的实现。
有了server和client,通讯起来就没啥问题了。至于其中涉及的实时性的问题,暂时先不考虑。

3.实现

经过查阅资料,倍福PLC作为ModbusTCP Server的设置过程很简单,而智能相机的设置过程则非常麻烦。下面来详细介绍。

3.1.PLC的ModbusTCP_Server

3.1.1.安装TF6250-Modbus-TCP

根据从这里【TwinCAT 3 Modbus TCP使用方法】查阅得到的资料,只要下载并安装TF6250-Modbus-TCP这个软件包即可。
在这里插入图片描述
在这里插入图片描述
TF6250-Modbus-TCP的下载地址为【TF6250 | TwinCAT 3 Modbus TCP】,下载的时候需要先登录倍福的账号,没有的话注册一个即可,就是它要求的密码复杂度比较高,要字母+数字+特殊符号+大小写。
在这里插入图片描述具体安装步骤,可以查看前面提到的那个网站的【TwinCAT 3 Modbus TCP使用方法.docx】
在这里插入图片描述

3.1.2.PLC设置

首先,先激活一下试用
在这里插入图片描述在这里插入图片描述
然后写程序
在这里插入图片描述

PROGRAM MAIN
VARarr1 AT %MB0:ARRAY[1..2] OF WORD; (*保持寄存器 起始地址为12288 (0x3000)*)arr2 AT %MB10:ARRAY[1..2] OF BYTE; (**)str1 AT %MB0: STRING;byteArr1 AT %MB0:ARRAY[0..9] OF BYTE;byteArr2 AT %MB0:ARRAY[1..10] OF BYTE;
END_VAR

为了方便观察,这里准备了字符串以及byte数组,这样子的话,既可以看到字符串,又可以看到字符串对应的16进制值。
在这里插入图片描述
至此,ModbusTCPServer的设置已经完成了,内存的映射等其他操作,系统已经帮忙处理了。
在这里插入图片描述

这里需要注意的是,modbus寄存器与PLC的地址对应关系。这个关系我们可以通过查阅官方文档【TF6250 | TwinCAT 3 Modbus TCP Default Configuration】得知:
在这里插入图片描述保持寄存器对应的是Output registers
在这里插入图片描述所以我们读写保持寄存器时,地址偏移要设置成12288(0x3000)。前面的文档有说要+1,但是我测试不用加1也行,可能具体得看实际情况吧。
在这里插入图片描述
ok,倍福PLC这边已经设置完成了,这时其实就已经可以用你趁手的Modbus调试工具测试一下与PLC的通讯了。我这边测试的话,貌似slave ID设置成0、1或者其他任意值都可以。
在这里插入图片描述

3.2.智能相机的ModbusTCP_Client

智能相机这边就相当的麻烦了。因为我们用的相机的固件版本比较低,不直接支持Modbus(貌似新的固件版本也只是支持ModbusServer,而非ModbusClient),得靠我们自己通过TCPDevice根据Modbus的协议来手动编码。
在这里插入图片描述行吧,那就自己手动搞呗。

3.2.1.了解ModbusTCP的协议

首先,了解一下ModbusTCP的协议,【Modbus TCP协议说明】、【ModbusTCP数据帧】、【如何看懂Modbus数据帧?】。了解其报文结构是非常重要的,因为只有了解其协议规定,我们才能确定为了达到我们的效果需要发送多长的数据,每个数据又应该是如何取值。
在这里插入图片描述简单地说,我们可以总结modbusTCP的数据帧有以下几个特点

1.与通过串口发送的数据帧相比,不用携带校验码。这个应该是因为底层TCP/IP通讯本身就已经是可靠通讯(自带校验及重发)。挺好,我们不用再用CRC16算法来算效验码了。
2.与通过串口发送的数据帧相比,要在前面增加7个字节的MBAP报文头。
3.报文头中的事务处理标识需要累加。实际上,经过测试,不累加也行。后面的程序我都没有对其累加。

3.2.2.根据协议写代码

ok,我们动手。
经过测试,将字符串转化成需要发送出去的数据这部分,代码有两种实现方式:一种是纯利用智能相机提供的函数进行处理,另外一种是通过js脚本实现。
建议先用纯函数实现,然后再用脚本实现,这样理解起来会更加深刻。

3.2.2.1.纯函数代码

先直接放出程序,再依次解释每个函数的作用。
在这里插入图片描述

左侧文字代码说明
'待发送的字符串EditString(255)字符串控件,可以在运行时输入字符串
'字符串长度Len(J26)获取字符串的长度
'长度是否为奇数Mod(J27,2)判断是否为奇数
'减少最后一个字符的字符串Left(J26, J27-1)原来的字符串移除最后一个字符形成的字符串
'最后一个字符Right(J26,1)原来字符串的最后的那个字符
'偶数长度部分的字符串If(J28,J29,J26)原来字符串的的偶数长度部分的字符串,比如字符串长度为5,那么取前面4个;假如为6,那就全取。
'编码1(偶数部分的字符串)BStringf(0, “%~s”, J31)把字符串编码成Binary结构体
'编码2(2byte的0)BStringf(0, “%h”, 0)长度为2,且两个数据都是0的Binary结构体
'编码3(0,字符)BStringf(0, “%c%s”, 0, J30)长度为2,第1个字节为0,第2个字节为字符串最后一个字符,的Binary结构体
'最终发送的编码(奇数长度时)BStringf(0,“%b%b”,J32,J34)字符长度为奇数时,最终需要发送的Binary数据结构体;偶数部分+0+最后一个字符
'最终发送的编码(偶数长度时)BStringf(0,“%b%b”,J32,J33)字符长度为偶数时,最终需要发送的Binary数据结构体;偶数部分+ 0 + 0
'实际需要发送的编码$If(J28,J35,J36)根据原始字符串的长度是奇数还是偶数,确定发送的Binary数据结构体;
'需要发送的编码长度BLen(J37)实际需要发送的编码的长度
'计算Modbus的数据长度1 + 1 + 2 + 2 + 1 + J381设备ID+1字节功能码+2字节寄存器地址+2字节寄存器数量+1字节寄存器数据长度+寄存器数据本身的长度
'手动触发发送Button(“触发”,-1)按钮,触发发送
'设备TCPDevice(“127.0.0.1”,502,0,4,1000,255)设备,IP:127.0.0.1,端口:502,modbus(二进制)发送
'读写QueryDevice(M29,M30,0,0,0,0,0,M26,0,0x10,0x30,0,0,J38/2,J38,J37)发送数据,且读取接收到的数据。M26是【'计算Modbus的数据长度】;0是slaveID;0x10表示写保持寄存器;0x30 0x00表示PLC的寄存器地址; J38/2表示寄存器的数量,因为我们的数据长度是以字节为单位的,而寄存器是16bit大小的,可以存储2个字节,因此要除以2; J38要写到n个寄存器的数据的大小;,J37,要写到n个寄存器的数据。
3.2.2.2.脚本代码

在这里插入图片描述
部分代码解释和上一小节一样,主要解释一下脚本部分

左侧文字代码说明
''将字符串通过脚本处理得到编码Script($J$47)通过脚本处理字符串。脚本的输入参数为字符串,返回处理完成的Binary结构体

脚本截图
在这里插入图片描述

脚本:

function Script() {
}
module.exports = Script;function stringToUint8ArrayWithSwap(str) {var dataArrLen = str.length;if (str.length % 2 !== 0) {dataArrLen += 1; // 奇数就补一个0}else{dataArrLen += 2; // 偶数就补两个0}var dataArray = new Uint8Array(dataArrLen); // 数据会默认初始化为0for (var i = 0; i < str.length; i++) {dataArray[i] = str.charCodeAt(i); // 将字符拷贝到数组中} // 每两个数据一组,交换组中的元素for (var i = 0; i < dataArrLen; i += 2) {// 交换位置 i 和 i+1 的数字[dataArray[i], dataArray[i + 1]] = [dataArray[i + 1], dataArray[i]];}return dataArray;
}Script.prototype.run = function (arg0) {return stringToUint8ArrayWithSwap(arg0)
}

3.2.3.非脚本处理时的代码逻辑图

在这里插入图片描述

3.2.4.关于代码的问题及解答

1.为啥要根据字符串长度的奇偶来执行不同的处理办法?
因为我们最终执行的modbus功能是写保持寄存器,而保持寄存器的大小为2字节,每次写的话都只能写n个寄存器(n为整数),也就是2n个字节的数据。所以,每次写的数据必须是偶数个数据才能填充完n个寄存器。不允许写半个寄存器。

2.为啥要 BStringf(0, “%~s”, J31) 中要选 %~s这种格式?
因为假如选了%s这种格式的话,数据是按小端发送过去的,但是,PLC那边接收到数据是按大端处理的,这就导致你发了字符串"123456"过去,PLC那边存储且显示出来的是"214365",每两个字节内部互相交换。
在这里插入图片描述

3.既然是大小端的问题,为啥不通过设置 BStringf中的第一个参数来处理?
因为它只对数值型数据,比如double、int等类型起作用,对字符串这种连续、独立、可变长度的类型无效。只能选%~s这种格式来处理。

3.字符长度为奇数时,为啥要将最后一个字符单独拿出来,然后插入一个0,然后再把这个字符补回去。
首先,补0是必须的,因为任何字符串都需要用0来作为结束符,不然无法确定一段字符在何处结束。至于为啥要把这个0补在最后一个字符的前面(插队),还是前面说的大小端的问题。我们发送过去的数据,PLC那边会每两个字节交替存储,比如说问哦我们发了 0x00 0x01两个数据过去,存在PLC寄存器的顺序会自动调整为0x01 0x00,而我们的0x00需要存放在物理地址的高位(也就是后面),因此需要做一个插入操作。

4.总结

通过底层的方式实现数据传输,学是能够学到好多东西,但是就是贼麻烦,且鲁棒性差。不知道为啥Modbus这么通用的功能,康耐视智能相机为啥就是不支持。


参考:
【TwinCAT 3 Modbus TCP使用方法】
【Modbus TCP协议说明】
【ModbusTCP数据帧】
【如何看懂Modbus数据帧?】

相关文章:

康耐视智能相机(Insight)通过ModbusTCP发送字符串到倍福(BECKHOFF)PLC中

文章目录 1.背景2.分析3.实现3.1.PLC的ModbusTCP_Server3.1.1.安装TF6250-Modbus-TCP3.1.2.PLC设置 3.2.智能相机的ModbusTCP_Client3.2.1.了解ModbusTCP的协议3.2.2.根据协议写代码3.2.2.1.纯函数代码3.2.2.2.脚本代码 3.2.3.非脚本处理时的代码逻辑图3.2.4.关于代码的问题及解…...

TIFS投稿记录(IEEE Transactions on Information Forensics Security)

毕竟是CCF A类期刊&#xff0c;TIFS审稿有点慢&#xff0c;记录最近一篇论文的投稿时间线。 2024年10月27日&#xff1a;提交。 2024年11月12日&#xff1a;分配DE。 2024年12月3日&#xff1a;AE与SAE还未分配。发邮件催了催。 2024年12月5日&#xff1a;SAE已分配。AE: Not A…...

极越汽车,加速跌落

文丨梅元知 9月&#xff0c;极越销量2605辆&#xff1b;10月进一步攀升到3107辆&#xff0c;尽管11月略有回落&#xff0c;销量跌至2485辆&#xff0c;但对于一个品牌影响力尚未完全建立、销售渠道有限的新品牌而言&#xff0c;这样的表现已实属不易。然而&#xff0c;就在看似…...

深入解析MySQL事务隔离级别与锁机制在银行账户业务中的应用

一、引言 在金融行业&#xff0c;尤其是银行账户业务中&#xff0c;数据的一致性和安全性至关重要。MySQL作为一种广泛使用的数据库&#xff0c;其事务隔离级别和锁机制在保证数据一致性方面发挥着重要作用。本文将针对银行账户查询与转账业务&#xff0c;探讨如何运用事务锁来…...

postman可以通的请求,前端通不了(前端添加Content-type,后端收不到请求)

接口完成之后,自己使用postman测试了一下,没有问题; 可是在和小组前端调试接口的时候,他却说访问不了; 信息如下:(我自己写的一个打印请求信息的拦截器) 发现报错信息是: Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported 也就是说…...

【Java计算机毕业设计】基于SSM+VUE宠物领养管理系统【源代码+数据库+LW文档+开题报告+答辩稿+部署教程+代码讲解】

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿 部署教程代码讲解代码时间修改教程 一、开发工具、运行环境、开发技术 开发工具 1、操作系统&#xff1a;Window操作系统 2、开发工具&#xff1a;IntelliJ IDEA或者Eclipse 3、数据库存储&#xff1a…...

排队论、负载均衡和任务调度关系

目录 排队论、负载均衡和任务调度关系 一、排队论 二、负载均衡 三、任务调度 四、总结 排队论、负载均衡和任务调度关系 排队论为负载均衡和任务调度提供了数学理论和方法支持 排队论、负载均衡和任务调度是三个相关但不同的概念。以下是对这三个概念的详细解释和它们之…...

智能客户服务:科技赋能下的新体验

在当今这个数字化时代&#xff0c;客户服务已经不仅仅是简单的售后服务&#xff0c;它已竞争的关键要素之一。随着人工智能、大数据、云计算等技术的飞速发展&#xff0c;智能客户服务正逐步改变着传统的服务模式&#xff0c;为企业和消费者带来了前所未有的新体验。 一、智能客…...

代码随想录第45天

115.不同的子序列 class Solution:def numDistinct(self, s: str, t: str) -> int:n1 len(s)n2 len(t)dp [[0] * (n1 1) for _ in range(n2 1)]for j in range(n1 1):dp[0][j] 1for i in range(1, n2 1):for j in range(1, n1 1):if t[i - 1] s[j - 1]:dp[i][j]…...

前端项目初始化搭建(二)

一、使用 Vite 创建 Vue 3 TypeScript 项目 PS E:\web\cursor-project\web> npm create vitelatest yf-blog -- --template vue-ts> npx > create-vite yf-blog --template vue-tsScaffolding project in E:\web\cursor-project\web\yf-blog...Done. Now run:cd yf-…...

3D 目标检测:从萌芽到前沿的技术演进之路

亲爱的小伙伴们&#x1f618;&#xff0c;在求知的漫漫旅途中&#xff0c;若你对深度学习的奥秘、JAVA 、PYTHON与SAP 的奇妙世界&#xff0c;亦或是读研论文的撰写攻略有所探寻&#x1f9d0;&#xff0c;那不妨给我一个小小的关注吧&#x1f970;。我会精心筹备&#xff0c;在…...

Apifox 产品更新|支持发布多个文档站、文档站支持 Algolia 搜索配置、从返回响应直接设置断言

看看本次 这次版本更新主要涵盖的重点内容&#xff0c;有没有你所关注的功能特性&#xff1a; 「发布文档」升级为「发布文档站」 支持发布多个文档站 文档站支持 Algolia 搜索配置 支持从返回响应直接设置断言 用户反馈优化 解决恢复退出 App 时未关闭的标签页可能导致内存…...

Linux内核结构及源码概述

参考&#xff1a;深入分析LINUX内核源码 深入分析Linux内核源码 (kerneltravel.net) Linux 是一个庞大、高效而复杂的操作系统&#xff0c;虽然它的开发起始于 Linus Torvalds 一个人&#xff0c;但随着时间的推移&#xff0c;越来越多的人加入了 Linux 的开发和对它的不断完善…...

《探索C++在3D重建中的算法与技术要点》

3D重建作为计算机视觉领域的重要技术&#xff0c;在诸多行业有着广泛应用&#xff0c;而C以其高效性和对底层硬件的良好控制&#xff0c;成为实现3D重建算法的常用语言。以下是利用C进行3D重建的一些常见算法和技术要点。 多视图立体视觉算法 多视图立体视觉是3D重建的基础算…...

【老白学 Java】数字格式化

数字格式化 文章来源&#xff1a;《Head First Java》修炼感悟。 很多时候需要对数字或日期进行格式化操作&#xff0c;来达到某些输出效果。Java 的 Formatter 类提供了很多扩展性功能用于字符串的格式化&#xff0c;只要调用 String 静态方法 format() &#xff0c;传入参数…...

useCallback和forwardRef的联合使用

文章目录 一、useCallback二、forwardRef 总结了useCallback、forwardRef中的deps&#xff0c;以及操作子组建时会遇到数据流不同步的问题 一、useCallback useCallback可以缓存函数&#xff0c;这样避免组建更新导致的函数重建&#xff1b;useCallback在函数更新以后会在deps中…...

C# .NET CORE 开发问题汇总

1. error MSB4803: .NET Core 版本的 MSBuild 不支持“ResolveComReference”。请使用 .NET Framework 版本的 MSBuild。 引用了一个COM组件, 使用donet 命令时,提示不支持, 可以先将项目设置为x86以构建, 将COM引用添加到核心项目中&#xff0c;构建它&#xff0c;在obj\x86\…...

【C语言】拆数字组成最大数

相信你是最棒哒&#xff01;&#xff01;&#xff01; 文章目录 题目描述 正确代码 法一注释版 简洁版 法二注释版 简洁版 题目描述 任意输入一个自然数&#xff0c;输出该自然数的各位数字组成的最大数。例如&#xff0c;输入 1593 &#xff0c;则输出为 9531 。 输入描述 …...

【Git系列】根据提交打印邮箱

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

Nginx在处理客户端请求的并发性发面是否依赖Linux的多线程原理

Nginx在处理客户端请求的并发性发面是否依赖Linux的多线程原理 Nginx 在处理客户端请求的并发性方面&#xff0c;并不依赖于 Linux 的多线程原理。 Nginx 的并发处理主要基于 事件驱动模型 和 异步非阻塞 I/O&#xff0c;而不是传统的多线程或多进程模型。 Nginx 的并发处理模…...

Python生成对抗神经网络GAN预测股票及LSTMs、ARIMA对比分析ETF金融时间序列可视化

全文链接&#xff1a;https://tecdat.cn/?p38528 本文聚焦于利用生成对抗网络&#xff08;GANs&#xff09;进行金融时间序列的概率预测。介绍了一种新颖的基于经济学驱动的生成器损失函数&#xff0c;使 GANs 更适用于分类任务并置于监督学习环境中&#xff0c;能给出价格回…...

深入了解C++中const的用法

文章目录 一、C中的const如何理解&#xff1f;二、C中的const与C语言中的const有何区别&#xff1f;三、const与指针、引用的结合使用 一、C中的const如何理解&#xff1f; 在C中&#xff0c;const是一个关键字&#xff0c;用来表示常量性&#xff0c;意在告诉编译器某些变量或…...

【Linux金典面试题(上)】41道Linux金典面试问题+详细解答,包含基本操作、系统维护、网络配置、脚本编程等问题。

大家好&#xff0c;我是摇光~&#xff0c;用大白话讲解所有你难懂的知识点 之前写了一篇关于 python 的面试题&#xff0c;感觉大家都很需要&#xff0c;所以打算出一个面试专栏。 【数据分析岗】Python金典面试题 这个专栏主要针对面试大数据岗位、数据分析岗位、数据运维等…...

利用Python实现多元回归预测汽车价格

引言: AI技术的热门使得大家对机器学习有了更多的关注,作为与AI技术息息相关的一门课程,从头了解基础的机器学习算法就显得十分有必要,如:梯度下降,线性回归等。 正文: 本文将讲解线性回归中多元回回归的案例 机器学习大致可以分为监督学习,非监督学习、半监督学习还…...

抓包软件fiddler和wireshark使用手册

fiddler官方文档 Fiddler 抓包教程1 Fiddler 抓包教程2 wireshark抓包学习 2添加链接描述 ip 过滤 ip.src_host ip.dst_host ip.addr mac 过滤 eth.src eth.dst eth.addr 端口过滤 tcp.port tcp.srcport tcp.dstport 协议类型过滤 arp dhcp 规则组合 and or...

初识三大 Observer

文章目录 ResizeObserver、MutationObserver和IntersectionObserver用MutationObserver实现图片懒加载MutationObserver 兼容性问题IntersectionObserver 应用MutationObserver和IntersectionObserver的区别IntersectionObserver 实例示例一&#xff1a;图片懒加载示例二&#…...

Eclipse MAT(Memory Analyzer Tool) 使用手册

参考&#xff1a;JAVA内存泄露使用MAT(Memory Analyzer Tool)快速定位代码 Eclipse MAT 1.15.0提示JDK版本最低需要使用17版本的&#xff0c;如果不想安装可以下载ZIP包&#xff0c;或者使用较低版本的MAT。 为了避免下载的17版本JDK和本地环境干扰&#xff0c;可以直接在MAT配…...

TongWe7.0-东方通TongWeb控制台无法访问 排查

**问题描述&#xff1a;**无法访问TongWeb的控制台 逐项排查&#xff1a; 1、控制台访问地址是否正确&#xff1a;http://IP:9060/console #IP是服务器的实际IP地址 2、确认TongWeb进程是否存在&#xff0c;执行命令&#xff1a;ps -ef|grep tongweb 3、确认TongWeb服务启动…...

Ariba Procurement: Administration_Master data

采购主数据集成Procurement Master Data Integration 注意&#xff1a;并非所有元素都是必需的&#xff0c;数据元素的名称可能根据ERP的不同&#xff0c;有所不同。 Types of Master Data Accounting 在SAP Ariba中的各种会计元素字段中&#xff0c;填充有效值选择列表。建…...

爬虫学习案例4

爬取猪八戒网站数据&#xff1a;2024-12-12 使用xpath解析元素&#xff0c;安装依赖库 pip install lxml使用selenium步骤我的上篇博客有提到&#xff0c;这里就不重复了 selenium使用博客导航 # 安装pip install lxml,使用xpath from lxml import etree import time from s…...