ADS communication related knowledge and test of Beckhoff Twincat 3

Introduction to ADS

YapethsDY 2020/08/27 PM

  • Twincat system architecture based on ADS

In the Beckhoff TwinCAT system, the working mode of each software module (such as TwinCAT PLC, TwinCAT NC, Windows application, etc.) is similar to the hardware device, they can work independently, and the information exchange between each software module is completed through TwinCAT ADS. Therefore, each ADS device can exchange data and information. (Get and official ppt)

  • ADS communication protocol overview

The ADS communication protocol is located in the application layer of the network communication protocol

  • Device identification of ADS communication protocol

Each ADS device has its own unique AdsAmsNetID and AdsPort port number, which are also its two most important attributes.

• AdsPort specifies the communication virtual device (ADS server), which is different and fixed, while the port of the ADS client application is variable. The default port is 851 when the plc program is created.
• AdsAmsNetId specifies the ADS router and is an extension of the TCP IP address. When the IP of a PC is "192.168.10.10", AdsAmsNetId is "192.168.10.10.1.1".

  • ADS communication method

  1. Asynchronous (Asynchronous)

The ADS client sends an ADS request to the ADS server, while the client continues its work. After the ADS server processes the request, it sends the response to the client in the form of a Call-back function.

      2. Notification method (Notification)

The ADS client sends an ADS request to the ADS server, and the ADS server continuously sends responses to the client in the form of a Call-back function until the client cancels the request.
These two communication methods are highly efficient, but require complex client programs.
Advantages: Will not cause system blockage.
Disadvantages: It is not guaranteed that every request will be returned.

       3. Synchronous mode (Synchronous)

The ADS client sends an ADS request to the ADS server, and the client program stops executing during the communication process until it gets a response from the ADS server.
This communication method does not require a complicated client program, but its round-robin communication method brings a relatively large load to the system, so the communication efficiency is low.
Advantages: can return results instantly.
Disadvantage: If the communication fails, the system will be blocked.

  • How ADS accesses variables

1. Address method

The address of a PLC variable is composed of two parts: GroupIndex and OffsetIndex. The former is generally different from the register type and is generally constant. The latter is the offset address of the variable, which is the address of the variable in the PLC.

2. Variable name method

Each variable in the TwinCAT ADS device has a handle (Handle). To access the variable by using the variable name, you first need to get the handle of the variable.


test environment:

  • Twincat 3 development platform
  • windows 7 environment
  • VS 2015 c# development IDE

First, clarify the calling process in the .net environment, the loading of the ADS component library will not be repeated


There are two ways to test


 

 

/******************************************************************************
* 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();//日志记录对象声明  
}                                                                  
//后续还需要初始化变量名与句柄的对应关系  比较冗余就不写了

Although this writing method is simple, it is a waste of resources. It is necessary to add a timer to the main thread or the interface refresh thread. Some variables that do not need to be read in a short period of time also become high priority, which is very wasteful. , Tomorrow will increase the way of event triggering or json registration to read, of course, it still depends on the variable name to operate.

happy ending!

 

 

Guess you like

Origin blog.csdn.net/Ding86341631/article/details/108259212