Integrate ScopeViewControl into User Applications

To get a flexible and re-usable tool the Scope2 is built in a Component-based manner. E.g. the ScopeView and the ScopeServer are separate parts of Scope2. Furthermore, the ScopeView is based on the ScopeViewControl, which is accessible from the .NET-component 'ScopeViewControlLib' coming along with the Scope2 - installation. This library enables you to easily build own C#, VB.Net or WPF applications.

MS VisualStudio

Use the Designer of MS VisualStudio to easily add ScopeViewControls to your project:

The linker may ask for some additional libraries ('TcAdsScope2Communications', 'SimpleHelper' ) if the application is compiled:

C# Sample-Project

The following steps will introduce you how to build a simple ScopeViewControl application.

Open a new Windows forms application and add a ScopeViewControl and a toolbar containing the pictured buttons to the form. A double-click inserts an event-handler to each button. Set the Dock property of the ScopeViewControl to Fill.

Load Configuration

It is possible to use method calls or an existing configuration file (.sv2) to configure the empty ScopeViewControl.

The C# - sample illustrates how to load a configuration in a click-event-handler.

private string filename = @"ScopeTest.sv2";

private void button_Load_Click(object sender, EventArgs e)
{
    FileInfo finfo = new FileInfo(filename);
    if (!finfo.Exists)
    {
    MessageBox.Show(this, "File not found! Please use the 'New' buttons to create a config.\r\n
        Once a config is created and saved it can be load using the 'Load' -Button!", "File not found!", 
        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }
    else
    {
    // delete old configuration
    while (scopeViewControl1.Charts.Count > 0)
    {
        scopeViewControl1.DeleteChart(scopeViewControl1.Charts[0]);
    }
    // load configuration
    scopeViewControl1.LoadScopeConfig(filename);

    foreach (ScopeViewControlChannel channel in scopeViewControl1.ConnectedChannels)
    {
        channel.Acquisition.AmsNetId = AmsNetId.Local;
    }
    }
}

Build Configuration programmatically

The ScopeViewControl provides Methods for all featuers used in the ScopeView2, too. Use the separate Api documentation for details: ScopeViewControlLib

Add elements

All ScopeView2 elements can be added by a call from the next higher element.

Settings (Appearance)

Each element contains a 'Style' property to grant access to appearance settings like color or line width. Use the 'Settings' windows in ScopeView2 as a reference.

private void ChangeChannelSettings(ScopeViewControlChannel channel)
{
    if (scopeViewControl1.Charts.Count == 0)
    {
    MessageBox.Show(this, "Please create a chart first!", "No chart connected!", 
        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }
    else if (scopeViewControl1.Charts[0].Axes.Count == 0)
    {
    MessageBox.Show(this, "Please create an YAxis first!", "No axis connected!", 
        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }
    else if (scopeViewControl1.Charts[0].Axes[0].Channels.Count == 0)
    {
    MessageBox.Show(this, "Please create a Channel first!", "No channel connected!", 
        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }
    else
    {
    channel.Style.LineColor = Color.Red;
    channel.Style.MarkColor = Color.DarkRed;
    channel.Style.LineWidth = 2;
    }
}

Acquisition

A channel furthermore contains an 'Acquisiton' property to connect a channel to a system variable.

private void SetAcquisition(ScopeViewControlChannel channel)
{
    if (scopeViewControl1.Charts.Count == 0)
    {
    MessageBox.Show(this, "Please create a chart first!", "No chart connected!", 
        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }
    else if (scopeViewControl1.Charts[0].Axes.Count == 0)
    {
    MessageBox.Show(this, "Please create an YAxis first!", "No axis connected!", 
        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }
    else if (scopeViewControl1.Charts[0].Axes[0].Channels.Count == 0)
    {
    MessageBox.Show(this, "Please create a Channel first!", "No channel connected!", 
        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }
    else
    {
    // AmsNetId and AmsPort are part of the TwinCAT.Ads.dll located in the ScopeView insallation folder.
    channel.Acquisition.AmsNetId = AmsNetId.Local;
    channel.Acquisition.TargetPort = (int)AmsPort.PlcRuntime1;
    channel.Acquisition.IsSymbolBased = true;
    channel.Acquisition.SymbolName = "SIGNALS.TREPPE";
    channel.Acquisition.DataType = DataTypeConverter.AdsToScope2Datatype(AdsDatatypeId.ADST_INT16);
    channel.Acquisition.SampleTime = (uint)(10 * TimeSpan.TicksPerMillisecond);
    }
}

Operate a Recording

The ScopeviewControl property 'Operating' holds all methods and properties to operate a recording. It is possible to select the record mode and length as well as start and stop options. Start and stop or save methods provide full access to handle the recorded data.

private void button_StartRecord_Click(object sender, EventArgs e)
{
    try
    {
    // discard old record
    if (scopeViewControl1.State == ScopeViewControlStates.REPLY)
        scopeViewControl1.Operating.DisConnect(false);

    // start new record
    if (scopeViewControl1.State == ScopeViewControlStates.CONFIG)
        scopeViewControl1.Operating.StartRecord();

    // start charts in runmode
    if (scopeViewControl1.State == ScopeViewControlStates.CONNECTED)
        scopeViewControl1.Operating.StartAllDisplays();
    }
    catch (Exception err)
    {
    MessageBox.Show(this, err.Message, "Error on start record!", 
        MessageBoxButtons.OK, MessageBoxIcon.Error);
    }

}
    
private void button_StopRecord_Click(object sender, EventArgs e)
{
    try
    {
    if (scopeViewControl1.State == ScopeViewControlStates.RECORD)
        scopeViewControl1.Operating.StopRecord();
     }
    catch (Exception err)
    {
    MessageBox.Show(this, err.Message, "Error on stop record!", 
        MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

private void button_Save_Click(object sender, EventArgs e)
{
    try
    {
    // save data if a record was finished
    if (scopeViewControl1.State == ScopeViewControlStates.REPLY)
    {
        File.Create("ExportData.svd").Close();
        scopeViewControl1.Operating.SaveData("ExportData.svd");
    }
    // or save only the configuration
    else
    {
        File.Create(filename).Close();
        scopeViewControl1.SaveScopeConfig(filename);
    }
    }
    catch (Exception err)
    {
    MessageBox.Show(this, err.Message, "Error on save!", 
        MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

Operate Charts

Each connected chart contains a toolbox to provide control to the user. However it is possible to use the 'ChartOperating' property and its members, too. In addition each a property to hide the time and the toolbar is located in there.

private void button_Run_Click(object sender, EventArgs e)
{
    if (scopeViewControl1.State != ScopeViewControlStates.RECORD)
    {
    MessageBox.Show(this, "Only possible if a record is running!", "Run not possible!", 
        MessageBoxButtons.OK, MessageBoxIcon.Exclamation); 
    }
    if (scopeViewControl1.State == ScopeViewControlStates.RECORD)
    scopeViewControl1.Charts[0].ChartOperating.StartDisplay();
}

private void button_Pause_Click(object sender, EventArgs e)
{
    if (scopeViewControl1.State != ScopeViewControlStates.RECORD)
    {
    MessageBox.Show(this, "Only possible if a record is running!", "Pause not possible!", 
        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }
    if (scopeViewControl1.State == ScopeViewControlStates.RECORD)
    scopeViewControl1.Charts[0].ChartOperating.StopDisplay();
}

private void toolStripButtonDelChart_Click(object sender, EventArgs e)
{
    if (scopeViewControl1.Charts.Count == 0)
    {
    MessageBox.Show(this, "No chart is connected!", "Nothing to delete!", 
        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }
    else if (scopeViewControl1.State == ScopeViewControlStates.RECORD)
    {
    scopeViewControl1.Operating.StopRecord();
    scopeViewControl1.Operating.DisConnect(false);
    }
    else if (scopeViewControl1.State == ScopeViewControlStates.REPLY)
    {
    scopeViewControl1.Operating.DisConnect(false);
    }
    else
    {
    scopeViewControl1.DeleteChart(scopeViewControl1.Charts[scopeViewControl1.Charts.Count - 1]);
    }

The full sample code in a VS2008 project: ScopeViewControlIntegration.zip

This sample uses variables from the PLC project: Scope2Signals.zip