0

I am using TwinCAT I/O 2.11 on Windows XP SP2. With the .NET-Library "TwinCAT.ADS" I already managed to read and write Inputs/Outputs (mapped objects from the device on the EtherCAT bus). But of course this only works when TwinCAT is in Freerun or Realtime Mode.

My question is now: I can set the TwinCAT Mode manually. But how can I set the TwinCat Mode (Freerun, Realtime, ...) with a Win32 program? I did not find an appropriate function in TwinCAT.ADS. Does there exist such a function?

froeschli
  • 2,692
  • 2
  • 28
  • 55
user3297416
  • 133
  • 7

3 Answers3

0

I have found a solution: The namespace TCatSysManagerLib (from file C:\TwinCAT\Io\AddIns\TCatSysManagerLib.dll) provides a class called ITcSysManager, which enables you to access the system manager functions from TwinCAT.

user3297416
  • 133
  • 7
0

I only have some experience with TwinCAT3, but the library is the same.

In TwinCAT3 we differ between Modes RUN and CONFIG. To switch between both modes you will need the TCatSysManagerLib, thats true. But there is (especially for TwinCAT3) no method for switching back to CONFIG mode (yet...but Beckhoff is working on it).

In case that you want to do this, you will need to go via the AmsPort.SystemService which is 10000.

Here an example how to switch from RUN to CONFIG mode:

public void setConfigMode()
{
    TcAdsClient client = new TcAdsClient();
    StateInfo mode = new StateInfo();

    client.Connect((int)AmsPort.SystemService);
    mode.AdsState = AdsState.Reconfig;
    client.WriteControl(mode);

    client.Dispose();
}

And here the opposite way from CONFIG to RUN mode (Using TCatSysManagerLib): --> only for TwinCAT3

public void setRunMode()
{
    // _solution_path, _solution_name must be replaced by your solution path and solution name
    Type t = System.Type.GetTypeFromProgID("VisualStudio.DTE.10.0");
    EnvDTE80.DTE2 dte2 = (EnvDTE80.DTE2)System.Activator.CreateInstance(t);
    dte2.MainWindow.Visible = false; //keep TwinCAT window closed
    Solution4 solution4 = (Solution4)dte2.Solution;
    EnvDTE.Project project = null;
    solution4.Open(Path.Combine(_solution_path, _solution_name + ".sln").ToString());
    project = (EnvDTE.Project)solution4.Projects.Item(1);
    ITcSysManager5 sysmanager5 = (ITcSysManager5)project.Object;
    sysmanager5.StartRestartTwinCAT();
    dte2.Quit();
}

or (I have not tried):

public void setRunMode()
{
    TcAdsClient client = new TcAdsClient();
    StateInfo mode = new StateInfo();

    client.Connect((int)AmsPort.SystemService);
    mode.AdsState = client.ReadState().AdsState;
    mode.AdsState = AdsState.Reset;
    client.WriteControl(mode);

    client.Dispose();
}
Chris
  • 63
  • 6
0

I have implemented a solution based on the answer from @ChrisKo. The following WinForms code operates on the premise, that a Form exists with the name Form1 which has three buttons named _runButton, _configButton and _exitButton. The project should have a reference to TwinCAT.Ads.dll.

using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using TwinCAT.Ads;

namespace TwinCatStateREader
{
    public partial class Form1 : Form
    {
        private TcAdsClient _tcClient;

        private TcAdsClient _tcSystemClient;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                _tcClient = new TcAdsClient();
                _tcClient.Connect(851);

                _tcSystemClient = new TcAdsClient();
                _tcSystemClient.Connect((int)AmsPort.SystemService);

                if (_tcSystemClient.ReadState().AdsState != AdsState.Run)
                {
                    _configButton.Enabled = false;
                    _runButton.Enabled = true;
                }
                else
                {
                    _runButton.Enabled = false;
                    _configButton.Enabled = true;
                }
            }
            catch (AdsErrorException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


        private void _exitButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                _tcClient.Disconnect();
                _tcClient.Dispose();

                _tcSystemClient.Disconnect();
                _tcSystemClient.Dispose();
            }
            catch (AdsErrorException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void _configButton_Click(object sender, EventArgs e)
        {
            _configButton.Enabled = false;
            _tcSystemClient.WriteControl(new StateInfo(AdsState.Reconfig, _tcSystemClient.ReadState().DeviceState));

            if (WaitForState(AdsState.Config, 3000))
            {
                _runButton.Enabled = true;
            }
            else
            {
                _configButton.Enabled = true;
            }
        }

        private void _runButton_Click(object sender, EventArgs e)
        {
            _runButton.Enabled = false;
            _tcSystemClient.WriteControl(new StateInfo(AdsState.Reset, _tcSystemClient.ReadState().DeviceState));

            if (WaitForState(AdsState.Run, 3000))
            {
                _configButton.Enabled = true;
            }
            else
            {
                _runButton.Enabled = true;
            }
        }

        private bool WaitForState(AdsState state, int timeOutInMilliSeconds)
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();

            while (stopwatch.ElapsedMilliseconds <= timeOutInMilliSeconds)
            {
                try
                {
                    if (_tcSystemClient.ReadState().AdsState == state)
                    {
                        return true;
                    }
                }
                catch (AdsErrorException)
                {
                    // This can happen while ADS changes state and we try to read it
                }
                finally
                {
                    Thread.Sleep(20);
                }
            }

            stopwatch.Stop();
            return false;
        }
    }
}

Notice that this solution uses two ads clients which connect to different ports (851 / 10000)

froeschli
  • 2,692
  • 2
  • 28
  • 55