.net应用程序和TW3的ADS之间通讯
2016-02-02 15:38
567 查看
Beckhoff ADS (Automation DeviceSpecification)提供一个应用程序之间互相通信的接口,在TW3系统中,TwinCAT PLC,TwinCAT NC等被设计成虚拟的自动化设备,类似于实际的物理设备与设备之间通过基于TCP协议的路由来交换信息,参考下面的图示
ADS设备最重要的两个属性就是端口号和AdsAmsNetId
• AdsPortNr 指定通信的虚拟设备(ADS server),比如PLC,NC
• AdsAmsNetId 指定ADS路由器,是TCP IP地址的扩展
既然是基于TCP协议,那对照TCP/IP七层协议如下
接着看下ADS协议/报文的数据结构
在AMS Header中存放着上面提到的AMS NET ID和PORT
还有从PLC Read和Write变量时存放的变量地址和偏移量
ADS 设备之间的通讯有多种方式,不同方式有不同的特点。
1.一般的ADS 通讯(General ADS Services)
- 异步方式(Asynchronous)
ADS 客户端向ADS 服务器发送ADS 请求,同时客户端继续自己的工作。ADS 服务器处理请求后,把响应以Call-back 函数方式发给客户端。
- 通知方式(Notification)
ADS 客户端向ADS 服务器发送ADS 请求,ADS 服务器以Call-back 函数的方式不断向客户端发送响应,直到客户端取消该请求。PLC变量不更新,就不会向客户端相应,类似于OPC通信的订阅。
这两种通讯方式的效率高,但需求复杂的客户端程序。
优点:不会造成系统堵塞
缺点:不能确保每次请求都有返回
2.特殊的ADS 通讯(Specific ADS Services)
TwinCATADS 设备和Windows应用程序(例如VB、VC 应用程序等)之间的通讯除了可以采用一般的ADS 通讯方式外,还可以采用特殊的通讯方式,即同步通讯方式。
- 同步方式(Synchronous)
ADS 客户端向ADS 服务器发送ADS 请求,在通讯过程中客户端程序停止执行,直到获得ADS 服务器返回的响应。
这种通讯方式不需求复杂的客户端程序,但其轮循的通讯方式给系统带来比较大的负载,因此通讯效率较低。
优点:能即时返回结果
缺点:如果通讯故障会造成系统堵塞
TwinCAT ADS访问变量有两种方式:
1.地址方式
一个PLC变量的地址由两部分组成:GroupIndex和OffsetIndex:
GroupIndex一般用于区别寄存器类型,在TwinCAT ADS设备中为常量,具体内容可以参考Information System(后附常用的GroupIndex值)。
OffsetIndex为变量的偏移地址,在PLC中为该变量的地址。
2.变量名方式
在TwinCAT ADS设备中每个变量都有一个句柄(Handle)。
适用变量名访问变量首先需要得到该变量的句柄。(不同的高级语言方式略有不同)
测试中使用的异步通讯方式,通过变量名方式,代码如下
PLC代码:
PROGRAM MAIN
ADS设备最重要的两个属性就是端口号和AdsAmsNetId
• AdsPortNr 指定通信的虚拟设备(ADS server),比如PLC,NC
• AdsAmsNetId 指定ADS路由器,是TCP IP地址的扩展
既然是基于TCP协议,那对照TCP/IP七层协议如下
接着看下ADS协议/报文的数据结构
在AMS Header中存放着上面提到的AMS NET ID和PORT
还有从PLC Read和Write变量时存放的变量地址和偏移量
ADS 设备之间的通讯有多种方式,不同方式有不同的特点。
1.一般的ADS 通讯(General ADS Services)
- 异步方式(Asynchronous)
ADS 客户端向ADS 服务器发送ADS 请求,同时客户端继续自己的工作。ADS 服务器处理请求后,把响应以Call-back 函数方式发给客户端。
- 通知方式(Notification)
ADS 客户端向ADS 服务器发送ADS 请求,ADS 服务器以Call-back 函数的方式不断向客户端发送响应,直到客户端取消该请求。PLC变量不更新,就不会向客户端相应,类似于OPC通信的订阅。
这两种通讯方式的效率高,但需求复杂的客户端程序。
优点:不会造成系统堵塞
缺点:不能确保每次请求都有返回
2.特殊的ADS 通讯(Specific ADS Services)
TwinCATADS 设备和Windows应用程序(例如VB、VC 应用程序等)之间的通讯除了可以采用一般的ADS 通讯方式外,还可以采用特殊的通讯方式,即同步通讯方式。
- 同步方式(Synchronous)
ADS 客户端向ADS 服务器发送ADS 请求,在通讯过程中客户端程序停止执行,直到获得ADS 服务器返回的响应。
这种通讯方式不需求复杂的客户端程序,但其轮循的通讯方式给系统带来比较大的负载,因此通讯效率较低。
优点:能即时返回结果
缺点:如果通讯故障会造成系统堵塞
TwinCAT ADS访问变量有两种方式:
1.地址方式
一个PLC变量的地址由两部分组成:GroupIndex和OffsetIndex:
GroupIndex一般用于区别寄存器类型,在TwinCAT ADS设备中为常量,具体内容可以参考Information System(后附常用的GroupIndex值)。
OffsetIndex为变量的偏移地址,在PLC中为该变量的地址。
2.变量名方式
在TwinCAT ADS设备中每个变量都有一个句柄(Handle)。
适用变量名访问变量首先需要得到该变量的句柄。(不同的高级语言方式略有不同)
测试中使用的异步通讯方式,通过变量名方式,代码如下
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using TwinCAT.Ads; namespace TW3_ADS_test { public partial class Form1 : Form { private TcAdsClient tcAdsClient; //会有变量定义在类外面吗,比如说在CLASS Form1外面定义变量,共几个类用??? private int hander1, hander2,hd1,hd2,hd3,hd4; private AdsStream iStream; private AdsStream bStream; private AdsStream sStream; private AdsBinaryReader iBinaryReader; private AdsBinaryReader bBinaryReader; private AdsBinaryReader sBinaryReader; private AdsBinaryWriter sBinaryWriter; private bool[] b; /// <summary> /// Form1窗口构造函数,窗口初始化 /// </summary> public Form1() { InitializeComponent(); iStream = new AdsStream(3 * 2);//流数据必须赋值大小,否则报错:无法在流的结尾之外进行读取 bStream = new AdsStream(3); sStream = new AdsStream(7); iBinaryReader = new AdsBinaryReader(iStream); bBinaryReader = new AdsBinaryReader(bStream); sBinaryReader = new AdsBinaryReader(sStream); sBinaryWriter = new AdsBinaryWriter(sStream); try { //// Connect to local PLC - Runtime 1 - TwinCAT2 Port=801, TwinCAT3 Port=851 tcAdsClient = new TcAdsClient(); tcAdsClient.Connect(851); hander1 = tcAdsClient.CreateVariableHandle("MAIN.ivar"); hander2 = tcAdsClient.CreateVariableHandle("MAIN.bvar"); hd1 = tcAdsClient.CreateVariableHandle("MAIN.bvar[0]"); hd2 = tcAdsClient.CreateVariableHandle("MAIN.bvar[1]"); hd3 = tcAdsClient.CreateVariableHandle("MAIN.bvar[2]"); hd4 = tcAdsClient.CreateVariableHandle("MAIN.svar"); } catch(Exception ex) { MessageBox.Show("ADS设备连接失败,请确认变量名和PLC运行状态:"+ex.Message ); } } /// <summary> /// 圆形区域重绘 /// </summary> private void lightstate() { Graphics g; SolidBrush brush = new SolidBrush(Color.Green); SolidBrush redbrush = new SolidBrush(Color .Red ); g = CreateGraphics(); if (b[0]) g.FillEllipse(brush, 80, 80, 40, 40); else g.FillEllipse(redbrush ,80,80,40,40); if (b[1]) g.FillEllipse(brush, 220, 80, 40, 40); else g.FillEllipse(redbrush, 220, 80, 40, 40); if (b[2]) g.FillEllipse(brush, 350, 80, 40, 40); else g.FillEllipse(redbrush, 350, 80, 40, 40); } /// <summary> /// 初始化状态圆形区域 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Paint(object sender, EventArgs e) { Graphics g; SolidBrush brush = new SolidBrush(Color.Red); //Pen pen = new Pen( Color.Red,1); //画空心圆 g = CreateGraphics(); g.FillEllipse(brush,80,80,40,40); g.FillEllipse(brush, 220, 80, 40, 40); g.FillEllipse(brush, 350, 80, 40, 40); //g.DrawEllipse (pen,400,80,40,40); } /// <summary> /// 窗口Load事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Load(object sender, EventArgs e) { this .Paint +=new PaintEventHandler(Form1_Paint);//不是在VS里双击过来的事件,可以手动添加委托 timer1.Interval = 100; button4.Enabled = true; button5.Enabled = false; listBox1.Items.Clear(); } private void timer1_Tick(object sender, EventArgs e) { b = new bool[3]; try { tcAdsClient.Read(hander1, iStream); tcAdsClient.Read(hander2, bStream); tcAdsClient.Read( hd4 ,sStream ); iStream.Position = 0; //否则报错:无法在流的结尾之外进行读取 textBox1.Text = iBinaryReader.ReadInt16().ToString(); textBox2.Text = iBinaryReader.ReadInt16().ToString(); textBox3.Text = iBinaryReader.ReadInt16().ToString(); bStream.Position = 0; b[0] = bBinaryReader.ReadBoolean(); b[1] = bBinaryReader.ReadBoolean(); b[2] = bBinaryReader.ReadBoolean(); sStream.Position = 0; //TwinCAT.Ads.NET version >= 1.0.0.10: new method //listBox1.Items.Add( sBinaryReader .ReadPlcString(4) ); //TwinCAT.Ads.NET version < 1.0.0.10:old method listBox1.Items.Add(tcAdsClient .ReadAny ( hd4 ,typeof ( string ),new int []{7})); } catch( Exception ex ) { MessageBox.Show("读PLC数据错误"+ex.Message ); } lightstate(); } /// <summary> /// 开始读数据从PLC /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button4_Click(object sender, EventArgs e) { sBinaryWriter.WritePlcString( textBox1 .Text ,7 ); tcAdsClient.Write( hd4 ,sStream ); timer1.Enabled = true; button4.Enabled = false; button5.Enabled = true; } /// <summary> /// 停止和PLC的ADS通信 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button5_Click(object sender, EventArgs e) { timer1.Enabled = false; button4.Enabled = true; button5.Enabled = false; } private void button1_Click(object sender, EventArgs e) { if (b[0]) b[0] = false; else b[0] = true; } private void button2_Click(object sender, EventArgs e) { if (b[1]) b[1] = false; else b[1] = true; tcAdsClient.WriteAny( hd2 ,b[1] ); } private void button3_Click(object sender, EventArgs e) { if (b[2]) b[2] = false; else b[2] = true; } } }
PLC代码:
PROGRAM MAIN
VAR ivar:ARRAY[0..2]OF INT; bvar:ARRAY[0..2]OF BOOL; index:INT; svar:STRING:='test'; END_VAR
FOR index:=0 TO 2 DO ivar[index]:=500+index; END_FOR bvar[0]:=TRUE; bvar[2]:=TRUE;
相关文章推荐
- 改变FileUpload文件上传控件的显示方式,选择文件后自动上传
- 算法题12 数组中所有的逆序对
- 10个开发中常用的PHP代码样例
- SVN--下载、安装VisualSVN server 服务端和 TortoiseSVN客户端
- nhandled exception in thread started by <function wrapper at 0x035BA3F0>
- php通过字符串调用函数示例
- 特殊回文数
- 关于Calendar和java.util.Date.Date()一些笔记(知识不停累积中)。
- apktool(android app逆向)
- 【LCT】BZOJ 3669: [Noi2014]魔法森林
- ImageView.ScaleType详解(多图)
- iOS UITextField的属性、代理及通知
- Android自定义属性限制
- IPC(Inner Process Comunication)机制基本了解
- LightOJ--1149--Factors and Multiples(二分图好题)
- python中的with与@contextlib.contextmanager
- USB----调用过程和简单解释
- 基于webpack的模块化构建
- Selenium——selenium之利用excel实现参数化
- 字节、字、bit、byte的关系