Example: machine with Microsoft Expression Blend
Microsoft Expression Blend is a program for creating program interfaces for C# and Visual Basic. In this example an interface created with the program is linked with the Machine example. The programming language C# was used.
Required software:
- Microsoft .NET Framework Version 3.0, for further information please refer to www.microsoft.com
- Microsoft Expression Blend, for further information please refer to www.microsoft.com
- Microsoft Visual Studio 2005
- TwinCAT 2.10
First steps ...
Program development with Microsoft Expression Blend and integration of the TwinCAT ADS .NET component is described based on an example.
1. Create new project:
Start Expression Blend and create a new interface via Menu -> File -> New Project... . The 'Create New Application' dialog box opens and the type, name, location and programming language can be selected. In this case please select 'Standard Application' as the type, 'Machine' as the name and 'C#' as the programming language.
2. Creating a user interface
The interface settings are stored in file Window1.xaml.
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
Once the interface has been created, add a reference called TwinCAT.Ads.dll via the menu --> Project --> Add Reference.
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, which can be displayed in Visual Studio. 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 the declarations.
private TcAdsClient tcClient;
private AdsStream dataStream;
private BinaryReader binReader;
private int hEngine;
private int hDeviceUp;
private int hDeviceDown;
private int hSteps;
private int hCount;
private int hSwitchNotify;
private int hSwitchWrite;
The first method is the load method. It is used to generate instances of different classes and create a link to port 801.
//-----------------------------------------------------//This is called first when the program is started//-----------------------------------------------------private void Load(object sender, EventArgs e)
{
try
{
// Create a new instance of the AdsStream class
dataStream = new AdsStream(7);
// Create a new instance of the BinaryReader class
binReader = new BinaryReader(dataStream);
// Create a new instance of the TcAdsClient class
tcClient = new TcAdsClient();
// Linking with local PLC - runtime 1 - port 801
tcClient.Connect(801);
}
catch
{
MessageBox.Show("Fehler beim Laden");
}
//...
The variables in the Load method are then linked and linked with a method (see "Write method 'tcClient_OnNotification'"), 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);
}
}
Linking PLC variables:
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: Interval in the data stream.
- length: Length in the data 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 'tcClient_OnNotification':
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.Foreground = new SolidColorBrush(Colors.Red);
}
else
{
DeviceUp_LED.Foreground = new SolidColorBrush(Colors.White);
}
}
else if(e.NotificationHandle == hDeviceDown)
{
if (binReader.ReadBoolean() == true)
{
DeviceDown_LED.Foreground = new SolidColorBrush(Colors.Red);
}
else
{
DeviceDown_LED.Foreground = new SolidColorBrush(Colors.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.IsChecked = true;
}
else
{
optSpeedSlow.IsChecked = true;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Lastly, we require two methods for making the machine faster or slower. 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);
}
}
To ensure that the methods are called for the right event, select DocumentRoot in the Design view, click add under Events and select loaded, and select the Load method.
The same applies for the two radio button, although in this case select the event 'Click' and the method 'optSpeedFast_Click' or 'optSpeedSlow_Click_Click'.
Delete notifications and handles:
In the Close event of the window the links are activated again with the method DeleteDeviceNotification().
private void Close(object sender, EventArgs 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 program Machine_Final.pro should start on runtime system 1, and the created C# program Machine.exe can be tested.