Event driven reading
Download
Language / IDE | Unpack the example program |
---|---|
Visual C# | |
Visual Basic (for .NET Framework) | |
Delphi Prism (Embarcadero Prism XE2, Oxygene for .NET) | |
Delphi for .NET (Borland Developer Studio 2006) |
Task
There are 7 global variables in the PLC. Each of these PLC variables is of a different data type. The values of the variables should be read in the most effective manner, and the value with its timestamp is to be displayed on a form.
Description
In the form's load event, a connection to each of the PLC variables is created with the TcAdsClient.AddDeviceNotification() method. The handle for this connection is stored in a array.
The parameter TransMode specifies the type of data exchange. AdsTransMode.OnChange has been selected here. This means that the value of the PLC variable is only transmitted if its value within the PLC has changed (see the AdsTransMode data type). The parameter cycleTime indicates that the PLC is to check whether the corresponding variable has changed every 100 ms. MaxDelay allows to collect notification for a specified interval. If the maxDelay elapse, all notifications will be send at once.
When the PLC variable changes, the TcAdsClient.AdsNotification() event is called. The parameter e of the event handling method is of the type AdsNotificationEventArgs and contains the time stamp, the handle, the value and the control in which the value is to be displayed. The connections are released again in the closing event by means of the TcAdsClient.DeleteDeviceNotification() method. It is essential that you do this, since every connection established by TcAdsClient.AddDeviceNotification() uses resources.
You should also choose appropriate values for the cycle time, since too many write / read operations load the system so heavily that the user interface becomes much slower.
Advice: Don't use time intensive executions in callbacks (OnNotification()).
C# program
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using TwinCAT.Ads;
namespace Sample03
{
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.TextBox tbInt;
private System.Windows.Forms.TextBox tbDint;
private System.Windows.Forms.TextBox tbSint;
private System.Windows.Forms.TextBox tbLreal;
private System.Windows.Forms.TextBox tbReal;
private System.Windows.Forms.TextBox tbString;
private System.Windows.Forms.Label label11;
private System.Windows.Forms.TextBox tbBool;
private System.ComponentModel.Container components = null;
private TcAdsClient tcClient;
private int[] hConnect;
private AdsStream dataStream;
private BinaryReader binRead;
public Form1()
{
InitializeComponent();
}
protected override void Dispose( bool disposing ) ...
private void InitializeComponent() ...
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
dataStream = new AdsStream(31);
//Encoding is set to ASCII, to read strings
binRead = new BinaryReader(dataStream, System.Text.Encoding.ASCII);
// Creaste instance of class TcAdsClient
tcClient = new TcAdsClient();
// PLC1 Port: TwinCAT2=801, TwinCAT3=851
tcClient.Connect(801);
hConnect = new int[7];
try
{
hConnect[0] = tcClient.AddDeviceNotification("MAIN.boolVal",dataStream,0,1,
AdsTransMode.OnChange,100,0,tbBool);
hConnect[1] = tcClient.AddDeviceNotification("MAIN.intVal",dataStream,1,2,
AdsTransMode.OnChange,100,0,tbInt);
hConnect[2] = tcClient.AddDeviceNotification("MAIN.dintVal",dataStream,3,4,
AdsTransMode.OnChange,100,0,tbDint);
hConnect[3] = tcClient.AddDeviceNotification("MAIN.sintVal",dataStream,7,1,
AdsTransMode.OnChange,100,0,tbSint);
hConnect[4] = tcClient.AddDeviceNotification("MAIN.lrealVal",dataStream,8,8,
AdsTransMode.OnChange,100,0,tbLreal);
hConnect[5] = tcClient.AddDeviceNotification("MAIN.realVal",dataStream,16,4,
AdsTransMode.OnChange,100,0,tbReal);
hConnect[6] = tcClient.AddDeviceNotification("MAIN.stringVal",dataStream,20,11,
AdsTransMode.OnChange,100,0,tbString);
tcClient.AdsNotification += new AdsNotificationEventHandler(OnNotification);
}
catch(Exception err)
{
MessageBox.Show(err.Message);
}
}
private void OnNotification(object sender, AdsNotificationEventArgs e)
{
DateTime time = DateTime.FromFileTime(e.TimeStamp);
e.DataStream.Position = e.Offset;
string strValue = "";
if( e.NotificationHandle == hConnect[0])
strValue = binRead.ReadBoolean().ToString();
else if( e.NotificationHandle == hConnect[1] )
strValue = binRead.ReadInt16().ToString();
else if( e.NotificationHandle == hConnect[2] )
strValue = binRead.ReadInt32().ToString();
else if( e.NotificationHandle == hConnect[3] )
strValue = binRead.ReadSByte().ToString();
else if( e.NotificationHandle == hConnect[4] )
strValue = binRead.ReadDouble().ToString();
else if( e.NotificationHandle == hConnect[5] )
strValue = binRead.ReadSingle().ToString();
else if( e.NotificationHandle == hConnect[6] )
{
strValue = new String(binRead.ReadChars(11));
}
((TextBox)e.UserData).Text = String.Format("DateTime: {0},{1}ms; {2}",time,time.Millisecond,strValue);
}
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
try
{
for(int i=0; i<7; i++)
{
tcClient.DeleteDeviceNotification(hConnect[i]);
}
}
catch(Exception err)
{
MessageBox.Show(err.Message);
}
tcClient.Dispose();
}
}
}
PLC program
PROGRAM MAIN
VAR
boolVal : BOOL;
intVal : INT;
dintVal : DINT;
sintVal : SINT;
lrealVal : LREAL;
realVal : REAL;
stringVal : STRING(10);
END_VAR
PROGRAM MAIN
VAR
;
END_VAR