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:

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.

Example: machine with Microsoft Expression Blend 1:

2. Creating a user interface

The interface settings are stored in file Window1.xaml.

Example: machine with Microsoft Expression Blend 2:

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.

Example: machine with Microsoft Expression Blend 3:

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);

The method CreateVariableHandle was used for linking the variable hSwitchWrite.

int TcAdsClient.CreateVariableHandle(string variableName);

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.

Download:

Expression Blend example