PCプラットフォームによる PCプラットフォームによる 産業用ソリューションプロバイダー 産業用ソリューションプロバイダー


採用情報


お問合せ

JapaneseEnglish

  • PP365

開発環境


■ RSW-ECATの制御プログラミング
RSW-ECATでは、あたかもI/Oポートに直結されたデバイスを扱うかのようにして多数のEtherCAT®スレーブ機器を制御できるよう配慮されています。
複雑なEtherCAT®マスターの初期化手続きは、数個のAPIコールで完了し、I/O関数もシンプルにデザインされています。
EtherCAT®の専門知識を持たずとも、I/Oデバイスの取り扱い経験があればすぐに制御プログラミングに集中できるのがRSW-ECAT-Masterの特長です。
RSW-ECATでの基本的な制御手順
RSW-ECATは基本的に以下の手順によってスレーブ機器の制御を実施します
①  マスターの初期化
アプリケーションは、まずRSW-ECAT-Masterとの接続を初期化します。
※初期化時、マスターステートはOPERATIONAL状態まで自動遷移します。
②  制御対象スレーブの検索
EtherCAT®スレーブには不揮発なID(VenderIDとProductID)が書き込まれています。
これをキーにして制御対象のスレーブの存在と位置を検索取得します。
③  マスターサイクル周期待ち
マスターサイクルを迎えるまで待機します。
④  入出力制御
RSW-ECATによって、EtherCAT®スレーブのI/O情報は連続する仮想のアドレス空間(VIOS)に再配置されています。 I/Oアドレス空間を扱うようにEtherCAT®スレーブ機器に対する入出力を制御し、I/Oスレーブからモーションスレーブまで様々なEtherCAT®スレーブ機器を制御します。
■ 開発環境
Visual Studio
対応バージョン  :  2012,2013,2015,2017,2019,2022
対応開発言語  :  C/C++, C#(.Net Framework4.5以上, .NET 6)

■ API一覧(一部抜粋)
初期化 WEhOpen() EtherCAT®通信開始
WEhClose() EtherCAT®通信終了
マスター制御 WEhRqState() マスターステート変更
WEhGetState() マスターステート取得
WEhWaitForCyclic() マスターサイクリック処理の待機
スレーブ検索/管理 WEhFindSlave() スレーブを検索
WEhGetSlaveStatus() スレーブステータス取得
WEhGetOnlineSlaveCount() 接続スレーブ数取得
ProcessData
アクセス
WEhReadByte() VIOS IN領域から8ビット読取
WEhWriteByte() VIOS OUT領域へ8ビット書込
WEhReadWord() VIOS IN領域から16ビット読取
WEhWriteWord() VIOS OUT領域へ16ビット書込
WEhReadDWord() VIOS IN領域から32ビット読取
WEhWriteDWord() VIOS OUT領域へ32ビット書込
ODアクセス WEhReadOD 指定スレーブの指定インデックスからデータを読み取ります。
WEhWriteOD 指定スレーブの指定インデックスへデータを書き込みます。
高レベルAPI HiWEhOpen EtherCAT®通信開始(初期化処理後、マスターステートをOperationalまで自動遷移させます)
HiWEhClose EtherCAT®通信終了
HiWEhStateChange マスターステートの変更要求を行い、実際にステートが変化するまで待機します。

■ サンプルプログラム

DIOスレーブ制御の事例

このサンプルはRSW-ECAT-Masterを使用し、OMRON Corporation社のディジタルI/Oスレーブ製品を制御するC#アプリケーションです。コード中のオフセットアドレス、値などについては、メーカーの製品仕様に準じます。

VS2012サンプルプロジェクト:RSWECATDOSample.zip
/*****************************************************************************
* Description        : RSW-ECAT-Master : DO プログラムサンプル
\*****************************************************************************/
using System;
using System.Threading;
using System.Runtime.InteropServices;
using RSWECAT_dotNet;


/*****************************************************************************
* main 処理
\*****************************************************************************/
class Program
{
    static void Main(string[] args)
    {
        EcatDIOProgram test = new EcatDIOProgram();
        test.StartTestDIO();                        // 処理実行
        Console.ReadLine();                         // 待機
        test.StopTestDIO();                         // 処理実行
    }
}

/*****************************************************************************
* DO 処理
\*****************************************************************************/
class EcatDIOProgram
{
    EcatHandler hEcat = null;
    ushort usReqState = 0, usNowState = 0;
    SLAVE_DETAIL stSlave;
    uint uiCount = 0;

    /*****************************************************************************
    * 開始処理
    \*****************************************************************************/
    public void StartTestDIO()
    {
        try
        {
            // RSW-ECAT初期化(RSW-ECAT API コール)
            // システムの初期化完了を待機するため複数回コールします。
            for (int i = 0; i < 5; i++)
            {
                try { hEcat = new EcatHandler(); }
                catch (EcatException er)
                {
                    if (i >= 5) { throw er; }
                }
                if (hEcat != null) { break; }
            }

            // Masterステートチェンジ要求 (RSW-ECAT API コール)
            // MST_OPERATIONAL : オペレーショナルへ遷移
            hEcat.WEhRqState(EcatHandler.MST_OPERATIONAL);

            // オペレーショナルへ遷移したかどうかの確認処理
            while (true)
            {
                // 現在の Masterステート状態取得 (RSW-ECAT API コール)
                hEcat.WEhGetState(ref usReqState, ref usNowState);

                // オペレーショナルへ遷移完了かをチェック
                if (usNowState == EcatHandler.MST_OPERATIONAL)
                {
                    break;
                }
                // ステートチェンジ待機用スリープ
                Thread.Sleep(500);
            }

            // ここからスレーブへのアクセス処理

            // スレーブ検索
            stSlave = new SLAVE_DETAIL();
            stSlave.fnAryClear();                                       // 必ず行う
            stSlave.uiSize = (uint)Marshal.SizeOf(stSlave);
            stSlave.uiVendorID = 131;
            stSlave.uiProductCode = 50;
            stSlave.uiInstance = 0;

            hEcat.WEhFindSlave(ref stSlave);

            // Callbackの登録
            hEcat.WEhSetEventCallBack(CallBack);
        }
        catch (EcatException er)
        {
            Console.WriteLine("<< EcatException >>");
            Console.WriteLine(" - ApiReturn:0x{0:x8}", er.uiApiReturn);
            Console.WriteLine(" - DotNetErr:0x{0:x8}", er.uiDotNetErr);
            Console.WriteLine(" - IntrErr  :0x{0:x8}", er.uiIntrErr);
            Console.WriteLine("\n( InnerExp info )\n" + er.expDotNet.ToString());
            Console.WriteLine("program end.");

            // RSW-ECAT 終了処理 (RSW-ECAT API コール)
            if (hEcat != null)
            {
                hEcat.WEhClose();
            }
        }
    }

    /*****************************************************************************
    * イベント発生時にコールされるメソッド
    \*****************************************************************************/
    private void CallBack(object sender, EcatHandler.EcatEventArgs e)
    {
        try
        {
            // イベント処理
            switch (e.Type)
            {
                // サイクリックイベント処理
                case EcatHandler.EcatEventType.Cyclic:
                    uiCount++;                                                  // イベント数のカウント

                    if (200 < uiCount)
                    {
                        uiCount = 0;

                        // ループ毎にON/OFF変換要求
                        if (0 != hEcat.WEhReadbackByte(stSlave.uiViosOutBaseOffset))
                        {
                            hEcat.WEhWriteByte(stSlave.uiViosOutBaseOffset, 0x00);
                        }
                        else
                        {
                            hEcat.WEhWriteByte(stSlave.uiViosOutBaseOffset, 0xFF);
                        }
                    }
                    break;

                // 診断イベント
                case EcatHandler.EcatEventType.DiagEvent:
                    break;

                // イベント待機処理にて例外発生
                case EcatHandler.EcatEventType.Exception:
                    hEcat.WEhRqState(EcatHandler.MST_INIT);                     // INITへ(サイクリックイベントの停止)
                    hEcat.WEhClose();                     // INITへ(サイクリックイベントの停止)
                    return;
            }
        }
        catch (EcatException er)
        {
            // エラー処理
        }
    }


    /*****************************************************************************
    * 終了処理
    \*****************************************************************************/
    public void StopTestDIO()
    {
        try
        {
            // 回線クローズ(RSW-ECAT API コール)
            hEcat.WEhClose();
        }
        catch (EcatException er)
        {
            Console.WriteLine("<< EcatException >>");
            Console.WriteLine(" - ApiReturn:0x{0:x8}", er.uiApiReturn);
            Console.WriteLine(" - DotNetErr:0x{0:x8}", er.uiDotNetErr);
            Console.WriteLine(" - IntrErr  :0x{0:x8}", er.uiIntrErr);
            Console.WriteLine("\n( InnerExp info )\n" + er.expDotNet.ToString());
            Console.WriteLine("program end.");

            // RSW-ECAT 終了処理 (RSW-ECAT API コール)
            if (hEcat != null)
            {
                hEcat.WEhClose();
            }
        }
    }

}

DIOスレーブ制御の事例(高レベルAPI使用版)

上記のサンプルを高レベルAPIを使用して実装した場合は、下記となります。
RSW-ECAT初期化時にOPERATIONAL状態まで自動遷移するため、Masterステートチェンジ要求、およびOPERATIONALへの遷移確認処理が不要となります。

VS2012サンプルプロジェクト:RSWECATDOSample2.zip
/*****************************************************************************  
* Description        : RSW-ECAT-Master : DO プログラムサンプル                        
\*****************************************************************************/
using System;
using System.Threading;
using System.Runtime.InteropServices;
using RSWECAT_dotNet;


/*****************************************************************************  
* main 処理                                                                     
\*****************************************************************************/
class Program
{
    static void Main(string[] args)
    {
        EcatDIOProgram test = new EcatDIOProgram();
        test.StartTestDIO();                        // 処理実行
        Console.ReadLine();                         // 待機
        test.StopTestDIO();                         // 処理実行
    }
}

/*****************************************************************************  
* DO 処理                                                                       
\*****************************************************************************/
class EcatDIOProgram
{
    EcatHandler hEcat = null;
    SLAVE_DETAIL stSlave;
    uint uiCount = 0;

    /***************************************************************************** 
    * 開始処理
    \*****************************************************************************/
    public void StartTestDIO()
    {
        try
        {
            // RSW-ECAT初期化(RSW-ECAT API コール)  ※内部でOperationalまで自動遷移します。
            hEcat = new EcatHandler(30000);      // 本サンプルでは、タイムアウト値に30秒指定[単位:ms]

            // ここからスレーブへのアクセス処理 

            // スレーブ検索                                                        
            stSlave = new SLAVE_DETAIL();
            stSlave.fnAryClear();                                       // 必ず行う
            stSlave.uiSize = (uint)Marshal.SizeOf(stSlave);
            stSlave.uiVendorID = 131;
            stSlave.uiProductCode = 50;
            stSlave.uiInstance = 0;

            hEcat.WEhFindSlave(ref stSlave);

            // Callbackの登録
            hEcat.WEhSetEventCallBack(CallBack);
        }
        catch (EcatException er)
        {
            Console.WriteLine("<< EcatException >>");
            Console.WriteLine(" - ApiReturn:0x{0:x8}", er.uiApiReturn);
            Console.WriteLine(" - DotNetErr:0x{0:x8}", er.uiDotNetErr);
            Console.WriteLine(" - IntrErr  :0x{0:x8}", er.uiIntrErr);
            Console.WriteLine("\n( InnerExp info )\n" + er.expDotNet.ToString());
            Console.WriteLine("program end.");

            // RSW-ECAT 終了処理 (RSW-ECAT API コール)                                
            if (hEcat != null)
            {
                hEcat.HiWEhClose(false);
            }
        }
    }

    /***************************************************************************** 
    * イベント発生時にコールされるメソッド
    \*****************************************************************************/
    private void CallBack(object sender, EcatHandler.EcatEventArgs e)
    {
        try
        {
            // イベント処理
            switch (e.Type)
            {
                // サイクリックイベント処理
                case EcatHandler.EcatEventType.Cyclic:
                    uiCount++;                                                  // イベント数のカウント

                    if (200 < uiCount)
                    {
                        uiCount = 0;

                        // ループ毎にON/OFF変換要求
                        if (0 != hEcat.WEhReadbackByte(stSlave.uiViosOutBaseOffset))
                        {
                            hEcat.WEhWriteByte(stSlave.uiViosOutBaseOffset, 0x00);
                        }
                        else
                        {
                            hEcat.WEhWriteByte(stSlave.uiViosOutBaseOffset, 0xFF);
                        }
                    }
                    break;

                // 診断イベント
                case EcatHandler.EcatEventType.DiagEvent:
                    break;

                // イベント待機処理にて例外発生
                case EcatHandler.EcatEventType.Exception:
                    hEcat.WEhRqState(EcatHandler.MST_INIT);     // INITへ(サイクリックイベントの停止)
                    hEcat.HiWEhClose(false);                    // INITへ(サイクリックイベントの停止)
                    return;
            }
        }
        catch (EcatException er)
        {
            // エラー処理
        }
    }


    /***************************************************************************** 
    * 終了処理
    \*****************************************************************************/
    public void StopTestDIO()
    {
        try
        {
            // 回線クローズ(RSW-ECAT API コール)
            hEcat.HiWEhClose(false);
        }
        catch (EcatException er)
        {
            Console.WriteLine("<< EcatException >>");
            Console.WriteLine(" - ApiReturn:0x{0:x8}", er.uiApiReturn);
            Console.WriteLine(" - DotNetErr:0x{0:x8}", er.uiDotNetErr);
            Console.WriteLine(" - IntrErr  :0x{0:x8}", er.uiIntrErr);
            Console.WriteLine("\n( InnerExp info )\n" + er.expDotNet.ToString());
            Console.WriteLine("program end.");
        }
    }

}