Detect state changes in TwinCAT router and PLC

Download

Language / IDE

Extract the sample program

Visual C#

Sample08.zip

Visual Basic (for .NET Framework)

-

Delphi Prism (Embarcadero Prism XE2, Oxygene for .NET)

Sample08.exe

Delphi for .NET (Borland Developer Studio 2006)

-

Task

Detect state changes in TwinCAT router and PLC.

Description

State changes in ADS devices can be detected effectively by registering callback functions to the devices. These functions are called on state changes of the ADS devices.

State changes in the TwinCAT router can be detected via the TcAdsClient.AmsRouterNotification in the TcAdsClient class . To detect state changes in the PLC an ADS Notification to the ADS status word must be registered.  Callback functions can be registered for both. These are called on state changes of the devices.

The following program monitors the state of the TwinCAT router and the PLC using the above techniques.

C# Program

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using TwinCAT.Ads;

namespace TwinCATAds_Sample08
{
  public partial class Form1 : Form
  {
    private TcAdsClient _tcClient = null;
    private AdsStream _adsStream = null;
    private BinaryReader _binRead = null;
    private int _notificationHandle = 0;

    public Form1()
    {
      InitializeComponent();
    }   

    private void Form1_Load(object sender, EventArgs e)
    {
      try
      {
    _tcClient = new TcAdsClient();


    // Connect to local PLC - Runtime 1 - TwinCAT2 Port=801, TwinCAT3 Port=851
    _tcClient.Connect(801);

    _adsStream = new AdsStream(2); /* stream for storing the ADS state of the PLC */
    _binRead = new BinaryReader(_adsStream); /* reader for reading the state */

    /* register callback function to detect state changes in the router  */
    _tcClient.AmsRouterNotification += new AmsRouterNotificationEventHandler(AmsRouterNotificationCallback);

    /* register an ADS notification an the ADS status word of the PLC  */
    _notificationHandle = _tcClient.AddDeviceNotification(
                 (int)AdsReservedIndexGroups.DeviceData, /* index group of the device state*/
                 (int)AdsReservedIndexOffsets.DeviceDataAdsState, /*index offset of the device state */
                 _adsStream, /* stream to store the state */
                 AdsTransMode.OnChange, /* transfer mode: transmit ste on change */
                 0, /* transmit changes immediately */
                 0,
                 null);

    /* register callback function to react on notifications */
    _tcClient.AdsNotification += new AdsNotificationEventHandler(OnAdsNotification);
      }
    catch (AdsErrorException ex)
      {
    MessageBox.Show(ex.Message);
      }
    }

    /* callback function called on state changes of the router */
    void OnAdsNotification(object sender, AdsNotificationEventArgs e)
    {
      if (e.NotificationHandle == _notificationHandle)
      {
    AdsState plcState = (AdsState)_binRead.ReadInt16(); /* state was written to the stream */
       _plcLabelValue.Text = plcState.ToString();
      }
    }

    /* Ccallback function called on state changes of the PLC */
    void AmsRouterNotificationCallback(object sender, AmsRouterNotificationEventArgs e)
    {
      _routerLabelValue.Text = e.State.ToString();
    }

    private void _exitButton_Click(object sender, EventArgs e)
    {
      this.Close();
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
      try
      {
    _tcClient.DeleteDeviceNotification(_notificationHandle);
    _tcClient.Dispose();
      }
      catch(AdsErrorException ex)
      {
    MessageBox.Show(ex.Message);
      }
    }
  }
}