今回の記事ではTc2_EtherCATライブラリを使用し、EtherCATマスターやSlaveの状態取得・もしくはSDOメッセージの送信について説明します。また、プログラムにはLD2ラダー言語で書いています。
さ、FAを楽しもう。

前書き
いつも私の技術ブログとYouTubeチャンネルをご覧いただき、心より感謝申し上げます。また、いまFullさん(full@桜 八重 (@fulhause) / X)と共に毎週水曜日の夜にお届けしている「高橋クリス」ラジオ番組を運営しています。
技術は独り占めせず、届けるもの
私たちは工場の生産技術や制御に関する技術情報を、ブログや動画などで無料公開しています。「知識は誰でもアクセスできるべき」という信念のもと、現場で役立つ具体的なノウハウやトラブル事例などを発信してきました。すべて無料で続けているのは、「知らなかったせいで困る人」を少しでも減らしたいからです。
また、もしあなたの現場で…
- 「このPLCとデバイスの組み合わせ、ちゃんと動くのかな?」
- 「EtherCAT通信でうまくいかない部分を検証してほしい」
- 「新しいリモートI/Oを試したいけど社内に検証環境がない」
など、困っている構成や試してみたいアイデアがあれば、ぜひお知らせください。機器の貸出や構成の共有が可能であれば、検証し、記事や動画で発信します(ご希望に応じて匿名対応も可能です)。
支援のかたち
現在、私達の活動はほぼ無償で続けており、記事や動画の制作には、時間と検証環境の整備が必要です。この活動を継続的にコンテンツを提供するためには、皆様の温かいご支援が大変重要です。
メンバーシップ(ラジオの応援)
Fullさんとのラジオをより充実させるための支援プランです。
https://note.com/fulhause/membership/join
Amazonギフトリスト
コンテンツ制作に必要な機材・書籍をリストにしています。
https://www.amazon.co.jp/hz/wishlist/ls/H7W3RRD7C5QG?ref_=wl_share
Patreon(ブログ・動画活動への応援)
月額での小さなご支援が、記事の執筆・検証環境の充実につながります。
https://www.patreon.com/user?u=84249391
Paypal
小さな支援が大きな力になります。
https://paypal.me/soup01threes?country.x=JP&locale.x=ja_JP
知ってたら助かること、届けたいだけです
あなたの応援が、知識の共有をもっと自由で持続可能なものにしてくれます。これからもどうぞよろしくお願いします。
soup01threes*gmail.com
技術はひとりじゃもったいない。
Tc2_ethercat?
PLCライブラリTc2_EtherCATにはEtherCATマスタデバイスやスレーブデバイス上でサービスや機能を実行するためのファンクションブロックが含まれています。

ST_EcSlaveState
ST_EcSlaveState構造体はEtherCATスレーブデバイスのEtherCAT状態とリンク状態を保持します。
TYPE ST_EcSlaveState: STRUCT deviceState :BYTE; linkState :BYTE; END_STRUCT END_TYPE |
変数名 | タイプ | 説明 |
deviceState | BYTE | スレーブのEtherCAT状態 |
linkState | BYTE | EtherCATスレーブのリンク状態 |
Link State
EtherCATスレーブのリンク状態。リンク状態は以下のビットのORで構成されます:
変数名 | 値 | 説明 |
EC_LINK_STATE_OK | 0x00 | 初期状態 |
EC_LINK_STATE_NOT_PRESENT | 0x01 | EtherCATスレーブとのEtherCAT通信ができない |
EC_LINK_STATE_LINK_WITHOUT_COMM | 0x02 | ポートX(EC_LINK_STATE_PORT_A/B/C/Dで指定)のエラー。ポートにはリンクがあるが、このポートを介した通信はできない。 |
EC_LINK_STATE_MISSING_LINK | 0x04 | ポートX(EC_LINK_STATE_PORT_A/B/C/Dで指定)にはリンクがない。 |
EC_LINK_STATE_ADDITIONAL_LINK | 0x08 | ポートXの追加リンク(EC_LINK_STATE_PORT_A/B/C/Dで指定)。 |
EC_LINK_STATE_PORT_A | 0x10 | |
EC_LINK_STATE_PORT_B | 0x20 | |
EC_LINK_STATE_PORT_C | 0x40 | |
EC_LINK_STATE_PORT_D | 0x80 |
deviceState
変数名 | 値 | 説明 |
EC_DEVICE_STATE_INIT | 0x01 | 初期状態 |
EC_DEVICE_STATE_PREOP | 0x02 | Pre-operational 状態 |
EC_DEVICE_STATE_BOOTSTRAP | 0x03 | Bootstrap 状態 |
EC_DEVICE_STATE_SAFEOP | 0x04 | Safe-operational 状態 |
EC_DEVICE_STATE_OP | 0x05 | Operational 状態 |
EC_DEVICE_STATE_ERROR | 0x10 | EtherCATスレーブのステートマシンエラー |
EC_DEVICE_STATE_INVALID_VPRS | 0x20 | 無効なベンダーID、製品コード、リビジョン番号、シリアル番号 |
EC_DEVICE_STATE_INITCMD_ERROR | 0x40 | 初期化コマンド送信中のエラー。 |
EC_DEVICE_STATE_DISABLED | 0x80 | スレーブが無効 |
FB_EcGetSlaveCount
ファンクション・ブロック FB_EcGetSlaveCount を使用して、マスタに接続されているスレーブの数を取得できます。

VAR_INPUT
変数名 | タイプ | 説明 |
sNetId | T_AmsNetId | EtherCAT マスターデバイスの AMS ネットワーク ID を含む文字列。 |
linkState | BYTE | この入力が正エッジになると、ファンクション・ブロックがアクティブになる。 |
tTimeout | TIME | ファンクション・ブロックの実行に許容される最大時間。 |
VAR_OUTPUT
変数名 | タイプ | 説明 |
bBusy | BOOL | この出力は、ファンクション・ブロックがアクティブになると設定され、フィードバックを受信するまで設定されたままになります。 |
bError | BOOL | この出力は、コマンドの送信でエラーが発生した場合、bBusy出力がリセットされた後にセットされる。 |
nErrId | UDINT | bError出力が設定されている場合、直近に実行されたコマンドに関連するADSエラーコードを供給する。 |
nSlaves | UINT | マスターに接続されているスレーブの数 |
FB_EcGetMasterDevState
The function block FB_EcGetMasterDevState can be used to read the current state of the EtherCAT master.

VAR_INPUT
変数名 | タイプ | 説明 |
sNetId | T_AmsNetId | EtherCAT マスターデバイスの AMS ネットワーク ID を含む文字列。 |
bExecute | BOOL | この入力が正エッジになると、ファンクション・ブロックがアクティブになる。 |
tTimeout | TIME | ファンクション・ブロックの実行に許容される最大時間。 |
VAR_OUTPUT
変数名 | タイプ | 説明 |
bBusy | BOOL | この出力は、ファンクション・ブロックがアクティブになると設定され、フィードバックを受信するまで設定されたままになります。 |
bError | BOOL | この出力は、コマンドの送信でエラーが発生した場合、bBusy出力がリセットされた後にセットされる。 |
nErrId | UDINT | bError出力が設定されている場合、直近に実行されたコマンドに関連するADSエラーコードを供給する。 |
nDevState | WORD | マスター・デバイスの現在の状態 |
FB_EcGetSlaveState
ファンクションブロックFB_EcGetSlaveStateによって個々のEtherCATスレーブのEtherCATステータスとリンクステータスを読み出すことができます。呼び出しに成功すると、ST_EcSlaveState型の出力変数stateに要求されたステータス情報が格納されます。

VAR_INPUT
変数名 | タイプ | 説明 |
sNetId | T_AmsNetId | EtherCAT マスターデバイスの AMS ネットワーク ID を含む文字列。 |
nSlaveAddr | UINT | 状態を読み込むEtherCATスレーブの固定アドレス。 |
bExecute | BOOL | この入力が正エッジになると、ファンクション・ブロックがアクティブになる。 |
tTimeout | TIME | ファンクション・ブロックの実行に許容される最大時間。 |
VAR_OUTPUT
変数名 | タイプ | 説明 |
bBusy | BOOL | この出力は、ファンクション・ブロックがアクティブになると設定され、フィードバックを受信するまで設定されたままになります。 |
bError | BOOL | この出力は、コマンドの送信でエラーが発生した場合、bBusy出力がリセットされた後にセットされる。 |
nErrId | UDINT | bError出力が設定されている場合、直近に実行されたコマンドに関連するADSエラーコードを供給する。 |
state | ST_EcSlaveState | スレーブのEtherCATステータスとリンクステータスを含む構造体。 |
FB_EcGetAllSlaveStates
FB_EcGetAllSlaveStates ファンクションブロックは、マスターに接続されているすべてのスレーブの EtherCAT ステータスおよびリンクステータスを読み取ることを可能にします。呼び出しが成功した場合、パラメータ pStateBuf で渡されたバッファには、要求されたステータス情報が ST_EcSlaveState の配列として格納されます。

VAR_INPUT
変数名 | タイプ | 説明 |
sNetId | T_AmsNetId | EtherCAT マスターデバイスの AMS ネットワーク ID を含む文字列。 |
pStateBuf | POINTER TO ARRAY[0..EC_MAX_SLAVES] OF ST_EcSlaveState | スレーブ状態を書き込むST_EcSlaveStatesの配列のアドレス。 |
cbBufLen | UDINT | 読み込むデータに対して利用可能な最大バッファサイズ(バイト単位) |
bExecute | BOOL | この入力が正エッジになると、ファンクション・ブロックがアクティブになる。 |
tTimeout | TIME | ファンクション・ブロックの実行に許容される最大時間。 |
VAR_OUTPUT
変数名 | タイプ | 説明 |
bBusy | BOOL | この出力は、ファンクション・ブロックがアクティブになると設定され、フィードバックを受信するまで設定されたままになります。 |
bError | BOOL | この出力は、コマンドの送信でエラーが発生した場合、bBusy出力がリセットされた後にセットされる。 |
nErrId | UDINT | bError出力が設定されている場合、直近に実行されたコマンドに関連するADSエラーコードを供給する。 |
nSlaves | UINT | スレーブのEtherCATステータスとリンクステータスを含む構造体。 |
FB_EcCoeSdoRead
ファンクションブロックFB_EcCoeSdoReadはSDO (Service Data Object) アクセスでEtherCATスレーブのオブジェクトディレクトリからデータを読み込むことができます。このためにはスレーブがメールボックスを持ち、”CANopen over EtherCAT” (CoE) プロトコルをサポートしている必要があります。
nSubIndex と nIndex パラメータにより、読み込むオブジェクトを選択することができる。サブエレメントを含む完全なパラメータにアクセスするには、FB_EcCoeSdoReadEx 関数ブロックを使用する必要があります。

VAR_INPUT
変数名 | タイプ | 説明 |
sNetId | T_AmsNetId | EtherCAT マスターデバイスの AMS ネットワーク ID を含む文字列。 |
nSlaveAddr | UINT | SDOアップロードコマンドを送信するEtherCATスレーブの固定アドレス。 |
pStateBuf | POINTER TO ARRAY[0..EC_MAX_SLAVES] OF ST_EcSlaveState | スレーブ状態を書き込むST_EcSlaveStatesの配列のアドレス。 |
nSubIndex | BYTE | 読み込まれるオブジェクトのサブインデックス。 |
nIndex | WORD | 読み込まれるオブジェクトのインデックス。 |
pDstBuf | PVOID | 受信バッファへのアドレス(ポインタ)。 |
cbBufLen | UDINT | 読み込むデータに対して利用可能な最大バッファサイズ(バイト単位) |
bExecute | BOOL | この入力が正エッジになると、ファンクション・ブロックがアクティブになる。 |
tTimeout | TIME | ファンクション・ブロックの実行に許容される最大時間。 |
VAR_OUTPUT
変数名 | タイプ | 説明 |
bBusy | BOOL | この出力は、ファンクション・ブロックがアクティブになると設定され、フィードバックを受信するまで設定されたままになります。 |
bError | BOOL | この出力は、コマンドの送信でエラーが発生した場合、bBusy出力がリセットされた後にセットされる。 |
nErrId | UDINT | bError出力が設定されている場合、直近に実行されたコマンドに関連するADSエラーコードを供給する。 |
cbRead | UDINT | 正常に読み取られたデータ・バイト数 |
Implementation
LD2プログラムの追加
今回の記事ではLD2ラダー言語でプログラムを作成します。LD2プログラムを追加するには、TwinCAT→右クリック>POUをクリックします。

Implementation LanguageをLD2に選択し→OKで決定します。

ライブラリーの追加
Tc2_EtherCATライブラリを追加します。Referencesをクリックし→Add Libraryをクリックします。

Tc2_EtherCATを検索し、ライブラリを追加しましょう。

Done!

プログラム1-FB_EcGetSlaveCount
最初の実装はFB_EcGetSlaveCountを使用し、EtherCATネットワークにあるSlave数を取得します。

LD2言語でプログラムを追加するには、TwinCAT右側にあるToolboxを使用する必要があります。

ブロック追加
Ladder→BlockをネットワークにDropします。

Done!これには空きブロックが追加されました。

FB設定
こちらのブロックではFB_EcGetSlaveCountを呼び出し使用しますので、Blockの???をクリックします。

FB_EcGetSlaveCountを入力します。

これでブロックがFB_EcGetSlaveCountに変わりました。

インスタンス設定
次はFB_EcGetSlaveCountの上にある???欄をクリックします。

VARエリアで宣言したFB_EcGetSlaveCount インタンスを入力します。

Done!これでFB_EcGetSlaveCount ブロックの構築完了です。

ネットワーク挿入
ネットワーク1の前に新しいネットワークを追加したいので、該当するネットワークを選ぶ→Insert Networkします。

Done!

接点追加
次は新しいネットワークに接点を追加します。Toolbox→ContactをDropします。

コイル追加
今度はToolbox→Coilでコイルをネットワークに追加しましょう。

Done!これで基本の接点・コイル回路を追加しました。

プログラム
ネットワーク1に接点とコイルを接続する変数を定義しましょう。下図ではxEcGetSlaveCount=TRUEとき、FB_EcGetSlaveCountが実行されます。

AMSNetId
次は新しいネットワークを追加し、MOVEブロックを使用し、Local TwinCAT RuntimeのAMSNetIdをT_AMSNetIdに転送します。

FB出力用コイル追加
次はFBの出力に変数と接続したいので、コイルを接続していきます。

Done!

リセットコイルの設定
このコイルをリセットコイルとして使用したいので(つまりTRUE=変数をFALSEに)、コイルを右クリック→Resetします。

Done!

ブロック追加
次は接点とコイルの間にブロックを追加できます。Blockをネットワーク1にDropしていきましょう。

Done!下図のように、xEcGetSlaveCount=TRUEのとき、fbEcGetSlaveCount.nSlavesに0を書き込みます。

タスクの設定
プログラムのTwinCAT Runtimeを実行したいので、PlcTask→右クリック→Add→Existing Itemします。

先ほど私たち作成したpEtherCATプログラムを選び→Okします。

結果
Done!FB_EcGetSlaveCountを実行すると、nSlaves=1で、つまり現在EtherCATスレーブが1つ存在しています。

プログラム2-FB_EcGetMasterDevState
次はプログラム1と同じ操作方法で、FB_EcGetMasterDevStateを使用し、現在のEtherCATマスターの状態を確認します。


プログラム3-FB_EcGetSlaveStates
プログラム3ではFB_EcGetSlaveStatesを使用し、指定のEtherCATスレーブの状態を取得します。今回の例ではSlaveアドレス1001のEtherCATスレーブの状態を取得し、結果は8になります。


8というのは、Slaveが現在OP状態になってることを示しています。

プログラム4-FB_EcGetAllSlaveStates
プログラム4ではFB_EcGetAllSlaveStatesを使用し、EtherCATネットワーク内にあるすべてのEtherCATスレーブの状態を取得します。下図のように、xEcGetAllSlaveStatesがTRUEになると、実行結果Bufferのメモリアドレスとサイズを、ADRとSIZEOF関数を使用し、直接FBのInputに書き込みます。

Done!nSlaves=1なので、現在EtherCATネットワークには1つのEtherCATスレーブが存在しています。

そしてStateBuffには各Slaveの状態が格納されています。

プログラム5-FB_EcCoeSdoRead
最後はLD2の中にST BlockとEcCoeSdoReadを使用し、EtherCATスレーブに対してSDOメッセージを送信します。

ST Blockは普通のST Editorと同じです。

次はEtherCAT SlaveにSDOを送信するとき、必要なSubIndexなどの情報をどこから参照してるかを説明します。もちろんESI FILEから調べることも可能ですが、TwinCATから調べることもできます。

該当するEtherCAT Slaveをクリックし→CoE Onlineをクリックします。

Index=nindexで、例えば下図のように1018はnindexで、Serial Numberを調べたいときははIndexは1018:04なので、SubIndex=4になります。

注意するのはST Blockで変数の現在値を確認できないことです。

ですが、diVal値=1540で、SDOメッセージが送信成功したことがわかりました。
