Example: machine with Microsoft Visual C#
Microsoft Visual Studio 2005 is a development environment for creating C# projects. The machine example is used for familiarisation with the integration of the TwinCAT ADS .NET component with the programming language C#.
Required software:
- Microsoft .NET Framework Version 2.0, for more information click here
- Microsoft Visual Studio 2005
- TwinCAT 2.10
Before you can start the C# program, TwinCAT and the PLC program must be active. If Microsoft Visual Studio 2005 is not installed on your computer, please install Microsoft .NET Framework Version 2.0. This sets up the required DLLs on your system.
First steps...
Step by step familiarisation with the development of a C# program and integration of the TwinCAT ADS .NET component based on an example.
1. Create new project:
Start Visual Studio 2005. Create a new project by clicking File -> New -> Project in the menu. A new project based on different templates can be created via the dialog box 'New Project'. Under 'Project Types' select the programming language Visual C#, and under the templates select 'Windows Application'. Enter a new name for your project, in this case please enter 'Machine'. Then select the directory path for your project under 'Location'.
2. Creating a user interface
First create an interface in the design mode of the form 'frmMachine' with the Toolbox. The settings for the different controls (such as 10 labels, 2 radio buttons, 1 progress bar, 1 picture box, group box...) can be viewed and set in the Visual Studio Properties window.
// Group fields (group box)
grpDevice.Text = "";
grpCount.Text = "";
grpSpeed.Text = "Speed";
// Labels
lblMachine.Text = "Machine";
lblDeviceDown.Text = "Device Down";
lblDeviceUP.Text = "Device Up";
lblCount.Text = "0";
lblCountLabel.Text = "Count:";
lblSteps.Text = "Steps:";
lbl100Procent.Text = "100%";
lbl0Procent.Text = "0%";
// These are the DeviceDown and DeviceUp arrows with a different font and size (label)
DeviceDown.Text = "ê";
DeviceDown.Font = new System.Drawing.Font("Wingdings", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(2)));
DeviceUp.Text = "é";
DeviceUp.Font = new System.Drawing.Font("Wingdings", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(2)));
// Progress bar
prgSteps.Name = "prgSteps";
// Option fields (radio button)
optSpeedSlow.Text = "slow";
optSpeedFast.Text = "fast";
In the upper left you see the two outputs that are also output to the Bus Terminals. The bottom left shows the variable for counting the workpieces. The cycle speed of the motor can be changed via the 'Speed' field on the right. The 'Steps' display shows the number of cycles that are output on output 1.
3. Adding a reference
First a reference called TwinCAT.Ads.dll must be added. The TwinCAT ADS .NET component is integrated via the menu -> Project -> Add Reference. To check whether the reference was actually integrated, you can call up the Solution Explorer (CTRL + W + S).
4. Edit source text
Once the interface has been created and the TwinCAT ADS component has been integrated, you can change to the C# source text. The required namespaces 'System.IO' and 'TwinCAT.Ads' are added in the top row of the source text.
using System.IO;
using TwinCAT.Ads;
This is followed by declarations within the frmMachine class.
privateTcAdsClient tcClient;
privateAdsStream dataStream;
privateBinaryReader binReader;
private int hEngine;
private int hDeviceUp;
private int hDeviceDown;
private int hSteps;
private int hCount;
private int hSwitchNotify;
private int hSwitchWrite;
The method 'frmMachine_Load' is started when the Windows application is called. This method is linked by linking the 'Load' event of the form with the method in the Properties window. It is used to generate instances of different classes and create a link with runtime system 1 of the TwinCAT.Ads component via port 801.
//-----------------------------------------------------//This is called first when the program is started//-----------------------------------------------------private void frmMachine_Load(object sender, EventArgs e)
{
try
{
// Create a new instance of the AdsStream class
dataStream = newAdsStream(7);
// Create a new instance of the BinaryReader class
binReader = newBinaryReader(dataStream);
// Create a new instance of the TcAdsClient class
tcClient = newTcAdsClient();
// Linking with local PLC - runtime 1 - port 801
tcClient.Connect(801);
}
catch
{
MessageBox.Show("Fehler beim Laden");
}
//...
Linking PLC variables:
In the frmMachine_Load event of the form, a connection to each variable in the PLC is created via the TcAdsClient.AddDeviceNotification()method. The handle for this connection is stored in an array. The TransMode parameter specifies the data exchange type. In this case AdsTransMode.OnChange is used to specify that the PLC variable is only transferred if the value in the PLC has changed (see AdsTransMode). The parameter cycleTime determines how often the PLC should check whether the corresponding variable has changed. The variables are then linked with a method 'tcClient_OnNotification' (that still has to be written), which is called when a variable changes.
try
{
// Initialising of PLC variable monitoring
hEngine = tcClient.AddDeviceNotification(".engine", dataStream, 0, 1, AdsTransMode.OnChange, 10, 0, null);
hDeviceUp = tcClient.AddDeviceNotification(".deviceUp", dataStream, 1, 1, AdsTransMode.OnChange, 10, 0, null);
hDeviceDown = tcClient.AddDeviceNotification(".deviceDown", dataStream, 2, 1, AdsTransMode.OnChange, 10, 0, null);
hSteps = tcClient.AddDeviceNotification(".steps", dataStream, 3, 1, AdsTransMode.OnChange, 10, 0, null);
hCount = tcClient.AddDeviceNotification(".count", dataStream, 4, 2, AdsTransMode.OnChange, 10, 0, null);
hSwitchNotify = tcClient.AddDeviceNotification(".switch", dataStream, 6, 1, AdsTransMode.OnChange, 10, 0, null);
// Retrieving of the "switch" handle. This is required for writing the value
hSwitchWrite = tcClient.CreateVariableHandle(".switch");
// Creating an event for changes in the PLC variable values
tcClient.AdsNotification += newAdsNotificationEventHandler(tcClient_OnNotification);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Definition:
The method 'AddDeviceNotification()' was used for linking the variables.
public int AddDeviceNotification(string variableName, AdsStream dataStream, int offset, int length, AdsTransMode transMode, int cycleTime, int maxDelay, object userData);
- variableName: Name of the PLC variable.
- dataStream: Data stream receiving the data.
- offset: Data interval in the stream.
- length: Data length in the stream.
- transMode: Event if the variable changes.
- cycletime: Time (in ms) after which the PLC server checks whether the variable has changed.
- maxDelay: Latest time (in ms) after which the event has finished.
- userData: Object that can be used for storing certain data.
The method 'CreateVariableHandle' was used for linking the variable 'hSwitchWrite'.
int TcAdsClient.CreateVariableHandle(string variableName);
- variableName: Name of the PLC variable.
Write method:
A method that does not exist yet was referred to above. This method ('tcClient_OnNotification') is written next. The method is called if one of the PLC variables has changed.
//------------------------------------------------//This is called if one of the PLC variables changes//------------------------------------------------private void tcClient_OnNotification(object sender, AdsNotificationEventArgs e)
{
try
{
// Setting the position of e.DataStream to the position of the current required value
e.DataStream.Position = e.Offset;
// Determining which variable has changedif(e.NotificationHandle == hDeviceUp)
{
//Adapting the colours of the diagrams to match the variablesif (binReader.ReadBoolean() == true)
{
DeviceUp_LED.ForeColor = Color.Red;
}
else
{
DeviceUp_LED.ForeColor = Color.White;
}
}
else if(e.NotificationHandle == hDeviceDown)
{
if (binReader.ReadBoolean() == true)
{
DeviceDown_LED.ForeColor = Color.Red;
}
else
{
DeviceDown_LED.ForeColor = Color.White;
}
}
else if(e.NotificationHandle == hSteps)
{
// Setting the progress bar to the current step
prgSteps.Value = binReader.ReadByte();
}
else if(e.NotificationHandle == hCount)
{
// Displaying the "count" value
lblCount.Text = binReader.ReadUInt16().ToString();
}
else if(e.NotificationHandle == hSwitchNotify)
{
// Selecting the correct radio buttonif (binReader.ReadBoolean() == true)
{
optSpeedFast.Checked = true;
}
else
{
optSpeedSlow.Checked = true;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Lastly, we require two methods for setting the machine to fast or slow. They are used to switch a virtual switch by writing a value to the PLC variable 'switch'.
//------------------------------------------------------//This is called if the 'slow' field is selected//------------------------------------------------------private void optSpeedFast_Click(object sender, EventArgs e)
{
try
{
tcClient.WriteAny(hSwitchWrite, true);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//------------------------------------------------------//This is called if the 'fast' field is selected//------------------------------------------------------private void optSpeedSlow_Click(object sender, EventArgs e)
{
try
{
tcClient.WriteAny(hSwitchWrite, false);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Last but not least we need to ensure that the methods 'optSpeedFast_Click' and 'optSpeedSlow_Click' are called for the right event. To this end switch to Design view, select the radio button 'optSpeedFast', click on 'Click' under Events in the Properties window and select the method 'optSpeedFast_Click'. Proceed accordingly for the radio button 'optSpeedSlow' and the method 'optSpeedSlow_Click'.
Delete notifications and handles:
In the frmMachine_FormClosing event of the form the links are activated again with the method DeleteDeviceNotification().
//------------------------------------------//is called when the program is terminated//------------------------------------------private void frmMachine_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
// Delete notifications and handles
tcClient.DeleteDeviceNotification(hEngine);
tcClient.DeleteDeviceNotification(hDeviceUp);
tcClient.DeleteDeviceNotification(hDeviceDown);
tcClient.DeleteDeviceNotification(hSteps);
tcClient.DeleteDeviceNotification(hCount);
tcClient.DeleteDeviceNotification(hSwitchNotify);
tcClient.DeleteVariableHandle(hSwitchWrite);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
tcClient.Dispose();
}
The PLC programMachine_Final.proshould start on runtime system 1, and the created C# programMachine.execan be tested.