倍福控制器(Beckhoff Twincat 3)的ADS通讯相关知识及测试
ADS简介
YapethsDY 2020/08/27 PM
基于ADS的twincat系统架构
在Beckhoff TwinCAT 系统中,各个软件模块(如TwinCAT PLC、TwinCAT NC、Windows 应用程序等)的工作模式类似于硬件设备,它们能够独立工作,各个软件模块之间的信息交换通过TwinCAT ADS 而完成。因此各个ADS 设备之间都能够交换数据和信息。(获取与官方ppt)
ADS通讯协议概述
ADS通讯协议位于网络通讯协议的应用层
ADS通讯协议的设备标识
每台ADS设备都有各自不同的AdsAmsNetID和AdsPort端口号,也是其最重要的两个属性。
• AdsPort 指定通信的虚拟设备(ADS server),各不相同且固定不变,而ADS客户端应用程序的port则是可变的。创建plc程序的时候默认端口为851。
• AdsAmsNetId 指定ADS路由器,是TCP IP地址的扩展。一台PC的IP为“192.168.10.10”时,AdsAmsNetId就是“192.168.10.10.1.1”。
ADS通讯方式
- 异步方式(Asynchronous)
ADS 客户端向ADS 服务器发送ADS 请求,同时客户端继续自己的工作。ADS 服务器处理请求后,把响应以Call-back 函数方式发给客户端。
2.通知方式(Notification)
ADS 客户端向ADS 服务器发送ADS 请求,ADS 服务器以Call-back 函数的方式不断向客户端发送响应,直到客户端取消该请求。
这两种通讯方式的效率高,但需求复杂的客户端程序。
优点:不会造成系统堵塞。
缺点:不能确保每次请求都有返回。
3.同步方式(Synchronous)
ADS 客户端向ADS 服务器发送ADS 请求,在通讯过程中客户端程序停止执行,直到获得ADS 服务器返回的响应。
这种通讯方式不需求复杂的客户端程序,但其轮循的通讯方式给系统带来比较大的负载,因此通讯效率较低。
优点:能即时返回结果。
缺点:如果通讯故障会造成系统堵塞。
ADS访问变量的方式
1.地址方式
一个PLC变量的地址由两部分组成:GroupIndex和OffsetIndex,前者一般区别与寄存器类型,一般为常量。后者为变量的偏移地址,在PLC中为该变量的地址。
2.变量名方式
在TwinCAT ADS设备中每个变量都有一个句柄(Handle),适用变量名访问变量首先需要得到该变量的句柄。
测试环境:
- Twincat 3开发平台
- windows 7 环境
- VS 2015 c#开发IDE
首先明确下.net环境下的调用流程,ADS组件库的加载不做赘述
分两种方式来进行测试
/******************************************************************************
* ProjectName: AdsProject
* Description: ADS通讯类,主要完成以下功能
* 1.与ADS设备连接,断开
* 2.同步通讯(读/写变量)的方法
* ClassName: ADSInteractionHMI
* CLRVersion: .NET Framework 4.5及以上
* Author: YapethsDY
* NameSpace: ADSInteractionHMI
* MachineName: ThinkPad T460
* CreateTime: 2020/08/27 晚
* UpdatedTime: Null
* others: 未来待实现通过订阅方式获取变量值变更的方法
* 那样看起来不需要浪费多余的资源
* Others
* Copyright(C) All rights reserved
*******************************************************************************/using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using TwinCAT.Ads;namespace ADSInteractionHMI
{class ADSOperation{private TcAdsClient ADSClient = new TcAdsClient() ;//ADS通讯打开public int ADSOpen(string[] adsTagsNameArray){int iRet = -1;int Index = 0;ADSClient = new TcAdsClient();try{ADSClient.Connect(ADS.AMSNetId, ADS.AMSNetPort);for (Index = 0; Index < ADS.ADSTagsCount; Index++){MessageBox.Show("句柄创建成功");//创建变量存储指定的句柄ADS.adsHandleArray[Index] = ADSClient.CreateVariableHandle(adsTagsNameArray[Index]);}iRet = 0;}catch (System.Exception ex){//异常日志记录LogHelper.ErrorLog(null, ex);iRet = -1;}return iRet;}//ADS读取public int ADSRead(int Handle, ref object Value, Type type){object tmp = 0;int iRet = -1;try{tmp = ADSClient.ReadAny(Handle, type);iRet = 0;}catch (System.Exception ex){iRet = -1;Debug.WriteLine(ex.Message);Debug.WriteLine("ADSClient.ReadAny异常"); MessageBox.Show(ex.Message);}if (0 == iRet){Value = tmp;}return iRet;}//ADS写入public int ADSWrite(int Handle, object Value){int iRet = -1;try{ADSClient.WriteAny(Handle, Value);iRet = 0;}catch (System.Exception ex){iRet = -1;Debug.WriteLine(ex.Message);Debug.WriteLine("ADSClient.WriteAny异常");MessageBox.Show(ex.Message);}return iRet;}//ADS关闭public int ADSClose(){int Index = 0;try{//删除创建的句柄for (Index = 0; Index < ADS.ADSTagsCount; Index++){ADSClient.DeleteVariableHandle(ADS.adsHandleArray[Index]);}}catch (System.Exception ex){//异常日志记录LogHelper.ErrorLog(null, ex);}finally{//资源释放ADSClient.Dispose();}return 0;}}
}//**********************************************************************************
class ADS{public static bool ADSok = false; //ADS连接/断开状态public const string AMSNetId = "192.168.10.10.1.1"; //本地AMSNetID public const int AMSNetPort = 851; //建的PLC工程默认端口号public const int ADSTagsCount = 10; //相关联的变量总数public static ADSOperation ADSOperation = new ADSOperation();//ADS通讯客户端对象明public static ADSCommunication ADSCommunication = new ADSCommunication();//ADS通讯public static string[] adsTagsNameArray = new string[ADSTagsCount];//ADS变量的名称public static int[] adsHandleArray = new int[ADSTagsCount]//所需读取的ADS变量句柄数组public static LogRecord tcLogRecord = new LogRecord();//日志记录对象声明
}
//后续还需要初始化变量名与句柄的对应关系 比较冗余就不写了
这种写法虽然说简单,但资源浪费严重,需要在主线程或着界面刷新线程中添加定时器,有的不需要在很短周期内读取的变量也变得优先级很高,显得很浪费,明天会增加事件触发或者json注册的方式来读取,当然了还是依靠变量名来操作。
happy ending!
倍福控制器(Beckhoff Twincat 3)的ADS通讯相关知识及测试相关推荐
- 倍福(Beckhoff)嵌入式控制器PLC
仅供参考,请勿直接照搬(江南大学物联网工程学院19级PLC作业一)! 摘要:与家喻户晓的西门子相比,倍福(Beckhoff)并不为众人所知,虽然二者都是德国品牌,但风格却截然不同.西门子不管是通信协议 ...
- twincat不使用倍福控制器情况下的实时性测试
twincat本质上由两部分组成,xar是一个runtime,可以理解为一个实时系统,xae是一个开发环境,两者可在同一计算机也可以在两个不同计算机. twincat并非依赖倍福控制器才能做实时控制, ...
- 倍福模块维修倍福控制器维修CX1030-0123
倍福模块维修倍福控制器维修CX1030-0123 倍福模块维修倍福控制器CX2030-0122维修CX2010CX1030 BECKHOFF倍福模块维修CX2030-0111嵌入式控制器维修CX203 ...
- 倍福--控制器型号含义
本文介绍倍福PLC如何看CX控制器CPU是多少核的 列举TwinCAT3与TwinCAT2相比的那些功能有了更大的扩展? 回答: 开放易扩展的开发平台 支持32位,64位操作系统以及多核CPU 支持I ...
- 倍福--控制器使用率和程序负载率查看
基于CX2040做测试,将时间片和PLC扫描周期调到最低,测试CPU运行情况. 操作流程 1.1. 倍福Beckhoff 1.1.1. 控制器硬件 硬件用的是CX2040控制器,安装的是Win7系统T ...
- 倍福--控制器添加路由
在做CX控制器之间的Ads通讯时,需要算过户添加路由,本文讲解相互添加路由的方法. 操作流程 1.1. 在TwincAT中添加 如果两台CX控制器通过网线连接了,在Twincat中连接上控制器之后,选 ...
- 学习倍福PLC需要掌握以下几个方面的知识:
PLC基础知识:了解PLC的基本构成.工作原理.通信协议等. 编程语言:倍福PLC主要使用Ladder Logic和Instruction List两种编程语言,需要掌握它们的语法.结构和编程方法. ...
- 倍福控制器报1804错误解决方法
1.问题描述:现场的一台机器正常运行一段时间后,启动时候显示这个错误. 2.错误说明:提示没有下载程序,这个报错一般和激活故障1804同时出现,程序切运行后会出现. 解决办法:需要进入到控制器本地路径 ...
- 倍福控制器连接松下EtherCAT伺服注意事项
松下伺服型号:MADHT1505BA3 将该伺服相应的XML文件放到用来做配置的PC的C:\TwinCAT\Io\EtherCAT路径下,把硬件扫描上来. 在伺服驱动器的'Startup'下点右键添加 ...
最新文章
- activiti 工作流_activiti工作流引擎入门
- RabbitMQ指南(下)
- 未定义的引用_Rust 引用和借阅
- 巧解C语言运算符的优先级和结合性
- mysql数据库恢复策略_MySQL 备份和恢复策略(一)
- JAVA读取本地图片并展示
- E2: A Framework for NFV Applications, SOSP' 15
- 斯坦福大学自然语言处理第二课“文本处理基础(Basic Text Processing)”
- 输出阻抗与输入阻抗详解
- 马化腾的马氏建议:“小步快跑 快速迭代”
- OC中内存管理(转)
- S3C2440驱动开发(一)
- Vue3动态加载图片
- 视觉SLAM十四讲学习笔记——第十三讲 实践:设计SLAM系统
- 收购艾瑞咨询,亚信科技如何释放1+1>2的发展效应?
- SQL中除法计算保留整数或几位小数(除法那些事儿!)
- 牛客练习赛31 C.无畏死灵术士莉莲娜与锁链面纱(期望dp)
- RTX 2060 12GB 参数
- SSL_ERROR_BAD_CERT_DOMAIN 部署 ssl证书后仍显示潜在风险
- VB作业之字母大小写的转换
热门文章
- 【RS】关于路由器ping不通直连的几种原因(1)
- 如何学好人力资源管理?方法及书籍推荐
- SSM jsp页面发送数据到servlet报400错误
- 华为交换机开启 DAI功能
- 使用CURL检测Clinet侧发起的HTTP请求各阶段时间
- ansible group_vars和host_vars
- 2020年中国首席营销官调查:“宅经济”助推企业加速内容营销布局
- SQL 截取日期年份和月份
- python中国大学慕课平台_中国大学MOOC(慕课)_Python程序设计_题库及答案
- vue3 + typescript + antd-design-vue(3.x)Modal.form()