開発環境
■ 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®のサイクリック通信を開始します。
- ③ 制御対象スレーブの検索
-
EtherCAT®スレーブには不揮発なID(VenderIDとProductID)が書き込まれています。
これをキーにして制御対象のスレーブの存在と位置を検索取得します。
- ④ マスターサイクル周期待ち
-
マスターサイクルを迎えるまで待機します。
- ⑤ 入出力制御
-
RSW-ECATによって、EtherCAT®スレーブのI/O情報は連続する仮想のアドレス空間(VIOS)に再配置されています。
I/Oアドレス空間を扱うようにEtherCAT®スレーブ機器に対する入出力を制御し、I/Oスレーブからモーションスレーブまで様々なEtherCAT®スレーブ機器を制御します。
■ 開発環境
Visual Studio |
対応バージョン |
: |
2008,2010,2012,2013,2015,2017,2019 |
対応開発言語 |
: |
C/C++,C#/VB(.Net Framework4.5以上) |
|
■ 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 |
指定スレーブの指定インデックスへデータを書き込みます。 |
■ サンプルプログラム
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();
}
}
}
}
※EtherCAT® は、Beckhoff Automation GmbH, Germanyの登録商標です。