Detect state changes in TwinCAT router and PLC with Delphi

From TwinCAT.Ads.NET version >= 1.0.0.15

Task

Detect state changes in TwinCAT router and TwinCAT 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 TwinCAT-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.

 

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

namespace Sample08;

interface

uses
  System.Drawing,
  System.Collections,
  System.Collections.Generic,
  System.Windows.Forms,
  System.ComponentModel,
  System.IO,
  TwinCAT.Ads;

type
  /// <summary>
  /// Summary description for MainForm.
  /// </summary>
  MainForm = partial class(System.Windows.Forms.Form)
  private
    tcClient:TcAdsClient;
    adsStream : AdsStream;
    binRead : BinaryReader;
    hNotification : Int32;

    method tcClient_AdsNotification(sender: Object; e: AdsNotificationEventArgs);
    method tcClient_AmsRouterNotification(sender: Object; e: AmsRouterNotificationEventArgs);
    method MainForm_Load(sender: System.Object; e: System.EventArgs);
    method MainForm_FormClosing(sender: System.Object; e: System.Windows.Forms.FormClosingEventArgs);
  protected
    method Dispose(disposing: Boolean); override;
  public
    constructor;
  end;

implementation

{$REGION Construction and Disposition}
constructor MainForm;
begin
  //
  // Required for Windows Form Designer support
  //
  InitializeComponent();

  //
  // TODO: Add any constructor code after InitializeComponent call
  //
end;

method MainForm.Dispose(disposing: Boolean);
begin
  if disposing then begin
    if assigned(components) then
      components.Dispose();

    //
    // TODO: Add custom disposition code here
    //
  end;
  inherited Dispose(disposing);
end;
{$ENDREGION}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
method MainForm.MainForm_Load(sender: System.Object; e: System.EventArgs);
begin
  try
    // Create instance
    tcClient := new TcAdsClient();
    // Connect the client to the local PLC
    tcClient.Connect(801);

    adsStream := new AdsStream(2);          // Stream storing the ADS state of the PLC
    binRead := new BinaryReader(adsStream);      // Reader to read the state data
    // Add TwinCAT Router notification event handler
    tcClient.AmsRouterNotification += tcClient_AmsRouterNotification;

    // Add TwinCAT PLC device notification
    hNotification := tcClient.AddDeviceNotification( 
          Int32( AdsReservedIndexGroups.DeviceData ), // Index group of the device state
        Int32( AdsReservedIndexOffsets.DeviceDataAdsState ), // Index offsset of the device state 
        adsStream,// Stream to store the state
        AdsTransMode.OnChange,// Transfer mode: transmit state on change
        0,// Transmit changes immediately
        0, Nil);

    // Register callback to react on state changes of the local PLC
    tcClient.AdsNotification += tcClient_AdsNotification

  except
    On err : AdsErrorException do
       MessageBox.Show(err.Message, err.Source)
  end;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
method MainForm.MainForm_FormClosing(sender: System.Object; e: System.Windows.Forms.FormClosingEventArgs);
begin
  try
    // Remove TwinCAT PLC notification event handler
    tcClient.DeleteDeviceNotification(hNotification);
    tcClient.AdsNotification -= tcClient_AdsNotification;
    // Remove TwinCAT Router notification event handler
    tcClient.AmsRouterNotification -= tcClient_AmsRouterNotification;
    // Close connection
    tcClient.Dispose()
  except
    On err : AdsErrorException do
       MessageBox.Show(err.Message, err.Source)
  end;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
method MainForm.tcClient_AmsRouterNotification(sender: Object; e: AmsRouterNotificationEventArgs);
begin
   txtRouterState.Text := e.State.ToString();
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
method MainForm.tcClient_AdsNotification(sender: Object; e: AdsNotificationEventArgs);
begin
  if (e.NotificationHandle = hNotification) then
    txtPLCState.Text := AdsState(binRead.ReadInt16()).ToString();
end;

end.

 

Download

Language / IDE

Unpack the sample program

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

Sample08.exe