Beckhoff#TF6281でB2G78-EP1 Ethernet/IP Gatewayと接続しよう

今回の記事ではB2G78-EP1のAnywire Ethernet/IP Gatewayを使用し、Ethernet/IPネットワーク経由でBeckhoff TwinCAT3 のTF6281とデータ交換します。

さ、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

https://x.com/3threes2

技術はひとりじゃもったいない。

Reference Link

http://soup01.com/ja/category/beckhoff/twincat3/tfxxx/tf6281/

http://soup01.com/ja/category/protocol/anywire/

B2G78-EP1

B2G78-EP1はEtherNet/IPとAnyWireASLINKのゲートウェイユニットです。本ユニットを使用することで、EtherNet/IPネットワークにAnyWireASLINKシステムを接続できます。

コネクタ端子台

DC24V 電源、AnyWireASLINK 伝送線(DP,DN)を接続するコネクタ端子台です。

端子配置を以下に示します。

システム構成

AnyWireASLINK は、ゲートウェイ、リモートユニット、その周辺機器で構成されます。

リモートユニットの種類

リモートユニットには次の種類があります。

接続台数

AnyWireASLINK システム 1 ラインに接続できるリモートユニットは最大 128 台です。

接続形態

AnyWireASLINK システムは T 分岐、マルチドロップ、ツリー分岐、スター分岐など、さまざまな接続が可能です。

Implementation

B2G78-EP1側

最初にはB2G78-EP1を設定します。

Web サーバーアクセス

B2G78-EP1は出荷のIP設定は192.168.0.36です。また、Login情報は以下になります。

  • Username:anywire
  • Password:anywire

言語

言語メニューからWeb Serverの表示言語を切り替えます。

点数

ビット点数設定のメニューからEthernet/IP経由で交換するビット数を定義できます。

IP設定

B2G78-EP1のIPアドレスを変更するには、本体設定→IPアドレス設定でIPアドレスをネットワークに合わせて設定しましょう。

次はB2G78-EP1を再起動します。

入出力データ設定

今度は入出力データ設定メニューをアクセスしEthernet/IP経由で交換するデータを設定します。

下図のようにすべてのInput Dataエリアにチェックを入れてください。チェックが入っていないエリアがあると、その分のメモリが詰められてしまい、プログラム上でアドレスがずれる可能性があります。

EDS Fileダウンロード

EDS FILEをDownloadします。

Done!

Beckhoff 側

次はBeckhoff TwinCAT3側を設定します。

EDSファイルをインストールする

今回記事で使用するのは4026なので、先程DownloadしたEDS FILEを下図のDirectoryに格納してください。

Ethernet/IP ドライバー追加

Etherent/IP Driverを追加するために、Devices→右クリック→Add New Itemします。

Ethernet/IP→Ethernet/IP Scannerをクリックします。

Done!Ethernet/IP Scannerが追加されました。

Ethernet Adapter設定

次はEthernet/IPを稼働するEtherent Driverを設定するために、Adapterをクリックします。

Ethernet/IP Scannerとして使用するEtherent インタフェースを設定します。

Done!

タスク設定

次はSync Task Tabを開き、Special Sync Taskを選択し→Create new I/O Taskします。

タスク名を設定します。

Done!Ethernet/IP用のタスクが追加されました。

ネットワーク設定

次はEthernet/IP Scannerのネットワーク設定を行い、Settings Tabを開きます。そして下図にあるIP AddressとNetwork Maskを設定しましょう。

Done!

B2G78-EP1追加

次は今回記事で使用するAnyWireASLINK システムEtherNet/IP Gateway B2G78-EP1を追加するために、Device1→右クリック→Add New Itemします。

EtherNet/IP Gateway B2G78-EP1を選択し、OKで進みます。

Done!EtherNet/IP Gateway B2G78-EP1が追加されました。

Change IP

次はそのEtherNet/IP Gateway B2G78-EP1のIPアドレスを変更するために、右クリック→Change IP addressをクリックします。

IPアドレスをEtherNet/IP Gateway B2G78-EP1の設定に合わせて設定します。

Done!

Connections設定

EtherNet/IP Gateway B2G78-EP1と接続するIO Connectionを追加するために、右クリック→Append IO Connection→Exclusive ownerをクリックします。

はいで進みます。

Done!

次はConnectionの設定画面を開きます。

InputとOutputのサイズを設定します。TwinCAT3のTF6281は最大502バイトまでしか対応していないため、EDSファイル上の設定が600バイト以上になっているとInputsとOutputsのデータ長がすべて0に変わってしまいます。そのため、赤枠の箇所をクリックして手動で設定する必要があります。

502を入力し、Applyをクリックします。

このように入力データ502Bytes、出力データ332Bytesに設定しましょう。

構造体

次はB2G78-EP1の取説に合わせて構造体を作成します。

dut_B2G78EP1_001_BitInputs

ARRAY[0..31] OF WORD は 32ワード = 512ビット分の入力を格納できます。ASLINKのリモートユニットであれば、最大512点のビット入力に対応する大きさです。

TYPE dut_B2G78EP1_001_BitInputs :
STRUCT
data:ARRAY[0..31]OF WORD; //
END_STRUCT
END_TYPE

dut_B2G78EP1_002_Error

AnyWireASLINKのエラーフラグを格納するための構造体です。PLCの入力エリアから取得した1ワード(16bit)のエラー情報を、ビットごとに名前付きでアクセスできるように定義しています。

TYPE dut_B2G78EP1_002_Error ://2
STRUCT
xDpDnShortCircuit : BIT; (* b0: DP-DN短絡異常 *)
xPowerVoltageLow : BIT; (* b1: 伝送電源低下異常 *)
xDpDnDisconnect : BIT; (* b2: DP,DN断線異常 *)
bReserved3 : BIT; (* b3 予約 *)
bReserved4 : BIT; (* b4 予約 *)
bReserved5 : BIT; (* b5 予約 *)
bReserved6 : BIT; (* b6 予約 *)
bReserved7 : BIT; (* b7 予約 *)
bReserved8 : BIT; (* b8 予約 *)
bReserved9 : BIT; (* b9 予約 *)
bReserved10 : BIT; (* b10 予約 *)
bReserved11 : BIT; (* b11 予約 *)
bReserved12 : BIT; (* b12 予約 *)
bReserved13 : BIT; (* b13 予約 *)
bReserved14 : BIT; (* b14 予約 *)
bReserved15 : BIT; (* b15 予約 *)
END_STRUCT
END_TYPE

こちらは各BITの意味になります。

dut_B2G78EP1_003_ErrorID

AnyWireASLINKで発生した異常のIDを格納するための構造体です。合計34バイト(17ワード)で構成されています。

TYPE dut_B2G78EP1_003_ErrorID :
STRUCT
wErrorIDNumbers :WORD; //2
aErrorId : ARRAY[0..15] OF WORD;//32
END_STRUCT
END_TYPE

dut_B2G78EP1_004_ConnectID

AnyWireASLINKに接続されているリモートユニットのIDを格納するための構造体です。合計258バイト(129ワード)で構成されています。

TYPE dut_B2G78EP1_004_ConnectID :
STRUCT
wConnectedID :WORD; //2
aConnectId : ARRAY[0..127] OF WORD;//128
END_STRUCT
END_TYPE

dut_B2G78EP1_005_DuplicateID

AnyWireASLINKでアドレスが重複しているリモートユニットのIDを格納するための構造体です。合計24バイト(12ワード)で構成されています。

TYPE dut_B2G78EP1_005_DuplicateID :
STRUCT
aDuplicateID : ARRAY[0..11] OF WORD; //24
END_STRUCT
END_TYPE

dut_B2G78EP1_005_DuplicateID_1

dut_B2G78EP1_005_DuplicateIDと対になる構造体で、重複アドレスが検出されたリモートユニットの個数のみを格納します。合計2バイト(1ワード)で構成されています。

TYPE dut_B2G78EP1_005_DuplicateID_1 :
STRUCT
wDuplicateID : WORD; //2
END_STRUCT
END_TYPE

dut_B2G78EP1_006_CommFlag

AnyWireASLINKの通信状態を示すフラグを格納するための構造体です。1ワード(16bit)をBIT型で展開しており、各ビットに意味のある名前でアクセスできます。

TYPE dut_B2G78EP1_006_CommFlag ://2
STRUCT
xRemoteUnitAlarm : BIT; (* b0 A: リモートユニットアラーム信号 *)
xSystemReserved : BIT; (* b1 B: システム予約(電源ON固定) *)
xRemoteUnitAccessError : BIT; (* b2 C: リモートユニットアクセス異常フラグ *)
xAutoAddressDetecting : BIT; (* b3 D: アドレス自動認識フラグ *)
bReserved4 : BIT; (* b4 予約 *)
bReserved5 : BIT; (* b5 予約 *)
bReserved6 : BIT; (* b6 予約 *)
bReserved7 : BIT; (* b7 予約 *)
bReserved8 : BIT; (* b8 予約 *)
bReserved9 : BIT; (* b9 予約 *)
bReserved10 : BIT; (* b10 予約 *)
bReserved11 : BIT; (* b11 予約 *)
bReserved12 : BIT; (* b12 予約 *)
bReserved13 : BIT; (* b13 予約 *)
xUnitSwapping : BIT; (* b14 E: リモートユニット交換中フラグ *)
xUnitSwapComplete : BIT; (* b15 F: リモートユニット交換完了フラグ *)
END_STRUCT
END_TYPE

こちらは各BITの意味になります。

dut_B2G78EP1_007_Status

AnyWireASLINKマスタモジュールの総合ステータスを格納するための構造体です。3ワード(6バイト)で構成され、Word0のステータスフラグ16bitとWord1のエラー情報16bitをまとめて管理します。

TYPE dut_B2G78EP1_007_Status : //3
STRUCT
(* Word0: ステータスフラグ b0〜b15 *)
xUnitReady : BIT; (* b0 A: ユニットREADY *)
xDpDnShortCircuit : BIT; (* b1 B: DP-DN短絡異常 *)
xPowerVoltageLow : BIT; (* b2 C: 伝送電源低下異常 *)
xDpDnDisconnect : BIT; (* b3 D: DP,DN断線異常 *)
x1024PointUnsupported : BIT; (* b4 E: 1024点非対応リモートユニット接続 *)
xRemoteUnitAlarm : BIT; (* b5 F: リモートユニットアラーム信号 *)
xAddressDuplicateCheck : BIT; (* b6 G: アドレス重複検査フラグ *)
xRemoteUnitAccessError : BIT; (* b7 H: リモートユニットアクセス異常フラグ *)
xParameterWriting : BIT; (* b8 I: パラメータライト中フラグ *)
xAutoAddressDetecting : BIT; (* b9 J: アドレス自動認識フラグ *)
xUnitSwapping : BIT; (* b10 K: リモートユニット交換中フラグ *)
xUnitSwapComplete : BIT; (* b11 L: リモートユニット交換完了フラグ *)
xAdjustModeActive : BIT; (* b12 M: 調整モード中フラグ *)
bReserved13 : BIT; (* b13 予約 *)
bReserved14 : BIT; (* b14 予約 *)
bReserved15 : BIT; (* b15 予約 *)
(* Word1: エラー情報 *)
nLatestErrorCode : WORD; (* b0〜b7: 最新エラーコード *)
nLatestErrorId : WORD; (* b8〜b15: 最新エラー発生ID *)
END_STRUCT
END_TYPE

こちらは各BITの意味になります。

dut_B2G78EP1_008_RemoteUnitStatus

AnyWireASLINKに接続された最大64台のリモートユニットのステータスをまとめて格納するための構造体です。合計256バイト(128ワード)で構成されています。

TYPE dut_B2G78EP1_008_RemoteUnitStatus : //256
STRUCT
aRemoteUnitStatus :ARRAY[1..64]OF dut_B2G78EP1_008_RemoteUnitStatus_Sub;
END_STRUCT
END_TYPE

dut_B2G78EP1_008_RemoteUnitStatus_Sub

dut_B2G78EP1_008_RemoteUnitStatusの配列要素として使用される、1台のリモートユニット分のステータスを格納するサブ構造体です。4バイト(2ワード)で構成されています。

TYPE dut_B2G78EP1_008_RemoteUnitStatus_Sub :
STRUCT
wStatusDetail : WORD; (* ステータス詳細 b0〜b15 *)
wParameter : WORD; (* パラメータ値 b0〜b15 *)
END_STRUCT
END_TYPE

こちらは各WORDの意味になります。

こちらは各BITの意味になります。

dut_B2G78EP1_010_BitOutputs

AnyWireASLINKのビット出力データを格納するための構造体で、64バイト(32ワード)で構成されています。

TYPE dut_B2G78EP1_010_BitOutputs :
STRUCT
data:ARRAY[0..31]OF WORD;
END_STRUCT
END_TYPE

dut_B2G78EP1_011_RemoteCommandsOutputs

AnyWireASLINKマスタへのコマンド出力を格納するための構造体です。8バイト(4ワード)で構成され、各種指令フラグとパラメータライト用のデータをまとめて管理します。

TYPE dut_B2G78EP1_011_RemoteCommandsOutputs :
STRUCT
(* Word0: コマンドフラグ b0〜b15 *)
xErrorFlagClear : BIT; (* b0 N: 異常フラグクリア ※1 *)
xAutoAddressDetect : BIT; (* b1 O: アドレス自動認識指令 *)
xAddressDuplicateCheck : BIT; (* b2 P: アドレス重複検査指令 *)
bReserved3 : BIT; (* b4 予約 *)
bReserved4 : BIT; (* b4 予約 *)
bReserved5 : BIT; (* b5 予約 *)
bReserved6 : BIT; (* b6 予約 *)
bReserved7 : BIT; (* b7 予約 *)
bReserved8 : BIT; (* b8 予約 *)
xParameterWrite : BIT; (* b9 Q: パラメータライト指令 *)
bReserved10 : BIT; (* b10 予約 *)
bReserved11 : BIT; (* b11 予約 *)
bReserved12 : BIT; (* b12 予約 *)
bReserved13 : BIT; (* b13 予約 *)
bReserved14 : BIT; (* b14 予約 *)
bReserved15 : BIT; (* b15 予約 *)
(* Word1: 書き込み対象ID(異常IDと同フォーマット) *)
nTargetId : WORD; (* b0〜b8: アドレス / b9〜b10: 入出力種別 *)
(* Word2: 書き込みパラメータ番号 *)
nParameterNo : WORD; (* 1〜18、アドレス変更時は35 *)
(* Word3: 書き込み値 *)
nWriteValue : WORD; (* パラメータ値 / アドレス変更時はID値 *)
END_STRUCT
END_TYPE

dut_B2G78EP1_012_RemoteUnitCommands

AnyWireASLINKに接続された最大64台のリモートユニットへのコマンドをまとめて格納するための構造体です。

TYPE dut_B2G78EP1_012_RemoteUnitCommands :
STRUCT
aRemoteUnitStatus :ARRAY[1..64]OF dut_B2G78EP1_012_RemoteUnitCommands_Sub;
END_STRUCT
END_TYPE

こちらは各WORDの意味になります。

こちらはS/Rの意味になります。

dut_B2G78EP1_012_RemoteUnitCommands_Sub

dut_B2G78EP1_012_RemoteUnitCommandsの配列要素として使用される、1台のリモートユニット分のコマンドを格納するサブ構造体です。

TYPE dut_B2G78EP1_012_RemoteUnitCommands_Sub :
STRUCT
wStatusDetail : WORD; (* 詳細 b0〜b15 *)
wParameter : WORD; (* パラメータ値 b0〜b15 *)
END_STRUCT
END_TYPE

dut_B2G78EP1_INs

AnyWireASLINKマスタモジュールの全入力データをひとつにまとめたトップレベル構造体です。個別の入力構造体をすべてメンバとして持ち、この1つの変数を宣言するだけでASLINKの全入力データにアクセスできます。

TYPE dut_B2G78EP1_INs :
STRUCT
st001BitInputs :dut_B2G78EP1_001_BitInputs;
st002Error :dut_B2G78EP1_002_Error;
st003ErroID :dut_B2G78EP1_003_ErrorID;
st004ConnectID :dut_B2G78EP1_004_ConnectID;
st006DuplicateID :dut_B2G78EP1_005_DuplicateID;
st005CommFlag :dut_B2G78EP1_006_CommFlag;
st0061DuplicateID :dut_B2G78EP1_005_DuplicateID_1;
st007Status :dut_B2G78EP1_007_Status;
st008RemoteUnitStatus :dut_B2G78EP1_008_RemoteUnitStatus;
END_STRUCT
END_TYPE

dut_B2G78EP1_Outs

AnyWireASLINKマスタモジュールの全出力データをひとつにまとめたトップレベル構造体です。

TYPE dut_B2G78EP1_Outs :
STRUCT
st001BitInputs :dut_B2G78EP1_010_BitOutputs;
st002SystemArea :WORD;
st003SystemArea :WORD;
st004Commands :ARRAY[0..3]OF WORD;
st004RemoteCommands :dut_B2G78EP1_012_RemoteUnitCommands;
END_STRUCT
END_TYPE

GVL

AnyWireASLINKマスタモジュールの入出力データをPLCのI/Oエリアにマッピングするためのグローバル変数定義です。

{attribute ‘qualified_only’}
VAR_GLOBAL
arrIn AT %I*:ARRAY[0..501]OF BYTE;
arrOut AT %Q*:ARRAY[0..331]OF BYTE;
dut_B2G78EP1_INs:dut_B2G78EP1_INs;
dut_B2G78EP1_Outs:dut_B2G78EP1_Outs;
END_VAR

MAIN

PLCハードウェアが自動更新する生バイト配列arrInの内容を、プログラムからアクセスしやすい入力構造体dut_B2G78EP1_INsにコピーします。コピーサイズはSIZEOF(arrIn)の502バイトを指定しています。

SIZEOF(dut_B2G78EP1_INs)(648バイト)ではなくSIZEOF(arrIn)(502バイト)を使っている点がポイントです。構造体の方が大きいため、SIZEOFに構造体を指定すると配列の範囲を超えた読み出しになってしまいます。SIZEOF(arrIn)を指定することで安全にコピーできます。

MEMCPY(destAddr:=ADR(gvlIO.dut_B2G78EP1_INs)
,srcAddr:=ADR(gvlIO.arrIn[0])
,n:=SIZEOF(gvlIO.arrIn)
);


MEMCPY(destAddr:=ADR(gvlIO.arrOut)
,srcAddr:=ADR(gvlIO.dut_B2G78EP1_Outs)
,n:=SIZEOF(gvlIO.arrOut)
);

入力データマッピング

先程追加した接続の入力部分を開きます。

次は右クリック→Change Linkします。

先程定義した入力変数と割り付けます。

出力データマッピング

先程追加した接続の出力部分を開きます。

次はOutputs→右クリック→Change Linkします。

先程定義した出力変数と割り付けます。

結果

まずWiresharkでキャプチャしたパケットから、CIP I/Oデータが正常に交換されていることを確認しました。

入力データからB2G78EP1がReady状態であること確認できました。

現在接続されているAnywireデバイスが3つであることが確認できました。

また、3台目に接続されているBS-H0317-1KのIDについても、正常に認識されていることを確認しました。

次にBS-H0317-1Kの計測値を取得するため、未使用のリモートコマンドエリアに以下の値を書き込みます。

  • 16#4220:ID 0x220にBit14をONする(Rフラグ、データ読み出し)
  • 0:測定値の取得

これで完了です。3台目のリモートユニットステータスエリアから、BS-H0317-1Kの現在の計測値を正常に取得することができました。

ダウンロード

こちらのLinkから記事のプロジェクトをDownloadしてください。

https://github.com/soup01Threes/TwinCAT3/blob/main/TwinCAT-TestWithAnywireGatewayB2G78-EP1.tnzip

シェアする

  • このエントリーをはてなブックマークに追加

フォローする