TwinCAT3 实时核中ADS实现C++ server、clinet数据传输

embedded/2024/9/18 23:06:49/ 标签: EtherCAT

一、基本概念

ADS :Automation Device Specification,ADS设备间进行通信的协议规范。协议定义了ADS device之间如何寻址对方、ADS device之间可以执行哪些操作、执行这些操作需要哪些参数,以及操作完成后如何返回结果等。从编程角度看,协议涵盖了AMS netID,port number(二者用于寻址ADS device)以及AdsReadWriteInd、AdsReadWriteRes、AdsReadWriteReq、AdsReadWriteCon、AdsReadReq……等一系列函数(用于在ADS device之间传输数据)。

ADS device:具备ADS接口的软件模块。 下图是从倍福官网拷贝的,从图中可以看出,所有的ADS device连接在ADS Router Engine上,那么通过ADS通讯时,是如何识别通讯的ADS device双方呢?这就涉及到后面提到的AMS了。

AMS :Automation Message Specification,指定了ADS数据的交互格式。从编程的角度,需要关心Ams NetId、Ams Prot,二者用于寻址通讯双方的 ADS device。

AMS NetId:默认的AMS NetId是本机IP地址后面加上.1.1,比如192.168.56.1.1.1。但是,AMS NetId与IP地址是没有任何关系的,可以通过下面步骤改成其他值。

AMS Port:通过AMS NetId只能找到对应的PC或控制器,PC或控制器中可能运行很多ADS device,所以还需要AMS Port识别具体的ADS device。AMS Port与linux、Windows中的端口一样,用于识别应用程序,每个应用程序分配有唯一的端口号,port的范围见参考资料4。

Route :通讯的server、client双方必须配置路由信息,路由包含路由名称、AmsNetId、对方的ip地址、路由类型。 TwinCAT 3中添加路由操作如下:

TwinCAT device:装有TwinCAT runtime的PC或控制器。

实时核:TwinCAT可以设置共享实时核、独占实时核,用于对运行时间要求严格的任务。

二、Server与Client通讯模型

与非实时ADS通讯不同,实时核中通信双方不能阻塞,需要采用异步的方式,TwinCAT提供的实时核通信接口见参考资料3。ADS通讯模型是Client-Server模式,客户端发起请求,服务端进行响应。

图中的Req()可以是AdsReadWriteReq、AdsReadReq、AdsWriteReq、AdsReadStateReq等等。
这些函数都有对应的Ind()、Res()、Con(),比如AdsReadWriteReq--AdsReadWriteInd--AdsReadWriteRes--AdsReadWriteCon等等,见参考资料3。

以Client读写Server端的变量为例,流程如下:

1)Client端申请一个AMS port,其他的ADS device(比如Server)可通过该port识别到该Client。

并且获取服务端的AMS NetId和AMS Port。

// State transition from PREOP to SAFEOPHRESULT CClient::SetObjStatePS(PTComInitDataHdr pInitData)
{/** Client端的端口范围是32768–65535,* m_AmsPort 的值不要与其它ADS device Client用的端口重复。*/WORD m_AmsPort = 33275;AmsAddr m_Addr;HRESULT hr = S_OK;IMPLEMENT_ITCOMOBJECT_EVALUATE_INITDATA(pInitData);hr = SUCCEEDED(hr) ? InitAmsPort(m_spSrv, m_AmsPort) : hr;m_Addr.netId = AmsGetNetId(); //服务端AMS NetIdm_Addr.port = 25100; //服务端AMS Port// cleanup on failureif (FAILED(hr)) {ShutdownAmsPort();}m_Trace.Log(tlVerbose, FLEAVEA "hr=0x%08x", hr);return hr;
}

2)Server端申请一个AMS Port,用于识别本ADS device。

// State transition from PREOP to SAFEOPHRESULT CModule1::SetObjStatePS(PTComInitDataHdr pInitData)
{/** Server端的端口范围是25000–25999,* m_AmsPort 的值不要与其它ADS device Server用的端口重复。*/WORD m_AmsPort = 25100;m_Trace.Log(tlVerbose, FENTERA);HRESULT hr = S_OK;IMPLEMENT_ITCOMOBJECT_EVALUATE_INITDATA(pInitData);hr = SUCCEEDED(hr) ? InitAmsPort(m_spSrv, m_AmsPort) : hr;// cleanup on failureif (FAILED(hr)) {ShutdownAmsPort();}m_Trace.Log(tlVerbose, FLEAVEA "hr=0x%08x", hr);return hr;
}

3)与Client端需获取Server端的AMS NetId、Port不同,Server端不需要获取Clinet的这些信息。因为TwinCAT采用的是请求-响应的方式,请求发送至Server端时,是含有Client端的AMS NetId、Port这些信息的。

4)Client通过AdsReadWriteReq发送一个读写Server端的请求。

int nErr;
ULONG test_data;
ULONG InvokeId = 0x00000001;
ULONG IndexGroup = 0x08;
ULONG IndexOffset = 0x09;
ULONG cbReadLength = sizeof(test_data);
ULONG cbWriteLength = 0;/** m_Addr,服务端的AMS NetId、AMS Port* InvokeId是一个ULONG数值,用于代表Client端的这个请求。* 因为实时核ADS通讯不能阻塞,是异步的,所以Client端收到Server端的响应时,* 需要通过invoke id响应对应的是哪个请求。** IndexGroup、IndexOffset用于识别具体的命令。比如服务端识别出0x08、0x09后,* 就将数值拷贝到test_data中。* cbReadLength,读数据的长度,本例中是都一个ULONG类型的数值,读到test_data* 变量中。* cbWriteLength,写数据的长度,本例中只读不写,该参数可忽略。
nErr = AdsReadWriteReq(m_Addr, InvokeId, IndexGroup, IndexOffset, cbReadLength, cbWriteLength, & test_data);

5)Server端收到Client的请求,自动触发AdsReadWriteInd函数执行。

AdsReadWriteInd通过解析参数indexGroup、indexOffset,执行对应的处理操作,填充Client端请求的数据。还有重要的一点,需要执行AdsReadWriteRes(rAddr, invokeId, ADSERR_NOERR, cbReadLength, pData)把响应发送给Client端。

enum Module1IndexGroups : ULONG
{Module1IndexGroup1 = 0x00000001,Module1IndexGroup2 = 0x00000002,IG_OVERWRITE = 0x00000003,ServerIndexGroup8 = 0x00000008
};enum Module1IndexOffsets : ULONG
{Module1IndexOffset1 = 0x00000001,Module1IndexOffset2 = 0x00000002,ServerIndexGroup9 = 0x00000009
};void CModule1::AdsReadWriteInd
(AmsAddr& rAddr,ULONG invokeId,ULONG indexGroup,ULONG indexOffset,ULONG cbReadLength,ULONG cbWriteLength,PVOID pData
)
{m_Trace.Log(tlVerbose, FENTERA "oid=0x%08x, invokeId=%d, indexGroup=0x%08x, indexOffset=0x%08x, cbReadLength=%d, cbWriteLength=%d, pData=0x%p",m_objId.value, invokeId, indexGroup, indexOffset, cbReadLength, cbWriteLength, pData);switch(indexGroup){case ServerIndexGroup8:switch (indexOffset){case ServerIndexGroup9:// TODO: add custom code here     // override counter with value provided by ADS-clientunsigned long* pCounter = (unsigned long*)pData;//m_Counter = *pCounter;*pCounter = 8234;AdsReadWriteRes(rAddr, invokeId, ADSERR_NOERR, cbReadLength, pData);break;}break;default:__super::AdsReadWriteInd(rAddr, invokeId, indexGroup, indexOffset, cbReadLength, cbWriteLength, pData); break;}m_Trace.Log(tlVerbose, FLEAVEA);
}

7)Client收到Server端的响应,自动触发AdsReadWriteCon函数执行。

函数的参数@cbLength,服务端响应数据的长度。
                  @pData,响应数据的起始地址。

void  CClient::AdsReadWriteCon(AmsAddr& rAddr, ULONG invokeId, ULONG nResult, ULONG cbLength, PVOID pData)
{if (nResult == S_OK && invokeId == ClientIndexGroup1) {m_bCount_client = *(int*)pData;m_Trace.Log(tlAlways, FNAMEA "AdsReadWrite for ads-variable getHdl got invokeid=0x%08x and nresult=0x%08x", invokeId, nResult);} else {m_Trace.Log(tlAlways, FNAMEA "AdsReadWrite for ads-variable getHdl failed nresult=0x%08x - retrying", nResult);}
}

三、参考资料

1,ADS、AMS、Router官网说明

 手册左侧:TwinCAT 3 --> Technologies --> ADS --> AmsNAT --> Introduction 

ADS (Automation Device Specification) is the TwinCAT communication protocol that specifies the interaction between two ADS devices. For example, it defines what operations can be executed on another ADS device, what parameters are necessary for that and what return value is sent after execution.

AMS (Automation Message Specification) specifies the exchange of the ADS data. A major component of the communication protocol is the AmsNetId. This is specified in the AMS/ADS package for the source and target device. An ADS device can be explicitly addressed using the AmsNetId.

route between two devices must be setup in TwinCAT so that they can communicate. This route is configured on both sides and typically contains the route name, the AmsNetId and the address of the communication partner as well as the type of connection. The configuration of new routes and an overview of existing routes in a TwinCAT system are shown in the following figure.

2, ADS device官网说明

手册左侧:TwinCAT 3 --> Technologies --> ADS --> ADS Basics --> ADS device concept 

The TwinCAT system architecture allows the individual modules of the software (e.g. TwinCAT PLC, User HMI, ...) to be treated as independent devices: For every task there is a software module ("Server" or "Client"). The servers in the system are the executing working "devices" in the form of software, whose operating behaviour is exactly like that of a hardware device. For this reason we can speak of "virtual" devices implemented in the software. The "clients" are programs which request the services of the "servers", e.g. a visualisation, or even a "programming device" in the form of a program. It is thus possible for TwinCAT to grow, since there can always be new servers and clients for tasks such as camshaft controllers, oscilloscopes, PID controllers etc. 

3,ADS实时核函数官网说明

手册左侧:TwinCAT 3 --> TE1000 XAE --> C/C++ --> Programming Reference  --> ADS Communication

  • AdsReadDeviceInfo
  • AdsRead
  • AdsWrite
  • AdsReadWrite
  • AdsReadState
  • AdsWriteControl
  • AdsAddDeviceNotification
  • AdsDelDeviceNotification
  • AdsDeviceNotification

4,AMS Port官网说明

手册左侧:TwinCAT 3 --> Technologies --> ADS --> ADS Basics --> ADS device indentification

The unique identification of ADS devices is implemented with the aid of two identifiers:

  • PortNr
  • NetId

http://www.ppmy.cn/embedded/109996.html

相关文章

【JavaSE】Java基本数据类型缓存池

new Integer(18) 、 Integer.valueOf(18) 、Integer.valueOf(300) 的区别 new Integer(18) :每次都会创建一个新对象Integer.valueOf(x): x in [-128, 127]:使用缓存池中的对象x not in [-128, 127]:创建新对象 Integer缓存池大…

【深度学习】【OnnxRuntime】【C++】模型转化、环境搭建以及模型部署的详细教程

【深度学习】【OnnxRuntime】【C】模型转化、环境搭建以及模型部署的详细教程 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【OnnxRuntime】【C】模型转化、环境搭建以及模型部署的详细教程前言模型转换--pytorch转onnxWindows平…

Vue 的常用指令以及相关修饰符的含义

Vue 的常用指令 插值表达式 {{ }} 用来在 Vue 模板中插入变量。 <div id"app">{{ message }} </div>new Vue({el: #app,data: {message: Hello Vue!} })v-text v-text 指令用来设置元素的文本内容。 <div id"app"><span v-text&…

centos挂载fat32和ntfs文件系统u盘

centos挂载u盘 一、 挂载fat32文件系统u盘1. 查看u盘的文件系统2. 查看系统是否识别到u盘3. 挂载fat32文件系统u盘 二、挂载ntfs文件系统u盘1. 检查u盘文件系统&#xff08;忽略&#xff09;2. 查看系统是否识别到u盘3. 挂载ntfs文件系统3.1. 下载ntfs-3g组件3.2. 挂载u盘 一、…

如何在DPDK中实现协议解析?

在 DPDK 中实现协议解析涉及几个步骤&#xff0c;包括初始化环境、配置网卡、接收数据包、解析数据包并处理数据包。下面将详细介绍这些步骤以及如何在 DPDK 中实现基本的协议解析。 初始化 DPDK 环境 首先&#xff0c;你需要初始化 DPDK 环境&#xff0c;加载 EAL (Ethernet…

Softmax回归--分类--有监督

输出和类别的维度一样。 一、当我们想将先线性层的输出直接视为概率&#xff0c;存在一些问题&#xff1a; 1.不能限制输出数字总和为1。 2.不能保证都是正数。 所以会使用softmax进行归一化。 二、交叉熵损失 交叉熵是一个衡量两个概率分布之间差异的很好的度量&#xff0…

Hadoop安全管理之Ranger

Apache Ranger 是一个开源项目&#xff0c;专门为大数据平台提供集中化的安全管理框架。它提供了对 Hadoop 生态系统和其他大数据存储系统的访问控制、权限管理、审计等功能&#xff0c;确保数据的安全性和合规性。通过 Apache Ranger&#xff0c;管理员可以在一个中心化的界面…

分类预测|基于雪消融优化BP神经网络的数据分类预测Matlab程序SAO-BP 多特征输入多类别输出 含基础程序

分类预测|基于雪消融优化BP神经网络的数据分类预测Matlab程序SAO-BP 多特征输入多类别输出 含基础程序 文章目录 一、基本原理二、实验结果三、核心代码四、代码获取五、总结 一、基本原理 SAO-BP模型结合了雪消融优化算法&#xff08;SAO&#xff09;和BP神经网络。以下是详细…

Linux和C语言(Day08)

一、周练习 1.题目一&#xff1a;&#xff08;25分) 1.题目描述&#xff1a;输入终值&#xff0c;输出所有能被7整除的数值及其和 2.评分要求 根据接收值准确定义变量类型(2分)提示并输入终值(2分)阅读题目确定循环要素:起始值、终值、步长(3分&#xff09;循环判断指定范围内…

使用微调OneKE来实现识别人名、公司名、和产品名称

简介 公司做个大模型助手&#xff0c;需要提取用户query中的人名、公司名和产品名称来进行问答。目前我使用的是bertcrf模型 开源cluer数据自造的数据&#xff0c;训练数据18w&#xff0c;测试数据1.3w。 目前这个方案有些瓶颈&#xff0c;主要表现如下&#xff1a; 1、产品名…

QT之QML学习四:Qt开启终端窗口,以及qml自定义Button聚焦矩形框去除

开发环境&#xff1a; 1、Qt 6.7.2 2、Pyside6 3、Python 3.11.4 4、Windows 10 前言&#xff1a;开启中端窗口的好处就是能够看到各种Debug信息以及能够看到各种报错信息。 最终效果如下 QT之QML学习四&#xff1a;Qt开启终端窗口&#xff0c;以及qml自定义Button聚焦矩形…

html 关于select动态加载数据以及动态分组

1.select动态加载方法 <select id"mySelect1" style"width: 120px;"></select> 通过id获取元素 for (obj of wentiname) { //js创建optgroup标签 let optgroupdocument.createElement("optgroup"); …

fileinput pdf编辑初始化预览

var $fileLinkInput $(#file_link_full); $fileLinkInput.fileinput({language: zh,uploadUrl: <?php echo Yii::$app->urlManager->createUrl([file/image, type > work_file]);?>,initialPreview: [defaultFile],initialPreviewAsData: true,initialPrevie…

Opencv实现提取卡号(数字识别)

直接开始 实行方法 解析命令行参数&#xff1a;使用argparse库来解析命令行输入&#xff0c;确保用户提供了输入图像和模板图像的路径。 读取模板图像&#xff1a;使用cv2.imread()函数读取模板图像的路径&#xff0c;并显示原始图像。 图像预处理&#xff1a; 将图像转换为…

迁移学习与知识蒸馏对比

应用场景不同 迁移学习&#xff1a;通常用于不同但相关的任务之间的知识迁移。特别是当目标任务的数据量不足时&#xff0c;可以从一个已经在大规模数据上训练好的模型中获取有用的特征或参数。典型场景包括计算机视觉任务&#xff0c;比如你在ImageNet上训练了一个ResNet&…

--数据库--

制作工人薪资管理系统 #include <myhead.h> #include <sqlite3.h> typedef struct {int gh;char name[20];double salary; }Worker;int do_insert(sqlite3 *ppdb) {Worker work;printf("请输入插入的工号&#xff1a;");scanf("%d",&work.…

udp的广播,多播,单播 demo

enum class EMsgType:uint8_t { EMSGT_SINGLE,//单播 EMSGT_MULTICAST,//多播 EMSGT_BROADCAST,//广播 }; sendSocket new QUdpSocket(this); sendSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, 1); sendSocket->bind(QHostAddress::AnyIPv4, 0,QUdpSoc…

解决Django会话中的竞态条件

Django 会话中的竞态条件&#xff08;race condition&#xff09;问题通常发生在多个请求几乎同时修改同一个会话数据时&#xff0c;导致数据丢失或数据不一致。这种情况在需要频繁更新会话数据的场景&#xff08;如实时聊天应用、并发请求处理等&#xff09;中尤为常见。 1、问…

python-新冠病毒

题目描述 假设我们掌握了特定时间段内特定城市的新冠病毒感染病例的信息。在排名 i 的当天有 i 个案例&#xff0c;即&#xff1a; 第一天有一例感染第二天有两例感染第三天有三例感染以此类推...... 请计算 n 天内的感染总数和每天平均感染数。 输入 整数 n 表示天数&…

手机如何切换网络IP地址:‌方法详解与操作指南‌

在当今的数字化时代&#xff0c;‌网络IP地址作为设备在网络中的唯一标识&#xff0c;‌扮演着至关重要的角色。‌对于手机用户而言&#xff0c;‌了解如何切换网络IP地址不仅有助于提升网络体验&#xff0c;‌还能在一定程度上保护个人隐私。‌本文将详细介绍手机切换网络IP地…