三菱電機#MXF-EtherCAT_PART04_SDOメッセージを送信しよう

こちらは新しい記事のシリーズで、三菱電機のMXF-EtherCATバージョンのCPUで様々な検証を行います。第4話ではMXF-EtherCATからSDOメッセージを使用しWAGOの新しいEtherCATカプラー7553-8000にパラメータを読み書きします。

さ、FAを楽しもう!

Reference Link

https://soup01.com/ja/category/mitsubishi-jp/mxr/

SDO Communications (Communications using Service Data Objects)

SDO(Service Data Object:サービスデータオブジェクト)は、EtherCATマスタから必要に応じて、指定したスレーブのデータを読み書きするための通信方式で、登録されたデータへのアクセスや、デバイスパラメータの送受信に使用されます。

主な用途として、スレーブの設定情報の読み取りや、各種動作パラメータの書き込みなどが挙げられます。

SDOによるデータ通信は非周期的に実行されます。例えば、デバイスの起動時に一度だけ設定パラメータを送信するような用途に使用されます。

このように、SDOは周期的なプロセスデータ交換とは異なり、必要なタイミングで実行される通信であるため、通信の優先度は比較的低く設定されています。

MX_ECのモジュールラベル一覧

こちらは今回記事でSDOメッセージ経由でCOE読み書きのために使用するMX_ECラベルです。

モジュールラベル
(MX_EC.以下)

バッファメモリ

データ型

説明

uSet_SDOControlCommand_D

U40\G90112

WORD

SDO通信実行コマンド

uSet_SDOTransmitNodeAddress_D

U40\G90113

WORD

送信先Slaveのノードアドレス

uSet_SDOTransmitIndexNumber_D

U40\G90114

WORD

アクセス先CoE Index

uSet_SDOTransmitSubIndexNumber_D

U40\G90115

WORD

アクセス先SubIndex

udSet_SDOTransmitDataSize_D

U40\G90116~90117

DWORD

書込みデータ長。単位Byte

unSet_SDOTransmitData_D

U40\G90118~90517

WORD配列

SDO書込みデータ

uSts_SDOExecutedControlCommand_D

U40\G90518

WORD

SDO実行完了状態

udSts_SDOReceiveDataSize_D

U40\G90522~90523

DWORD

受信データ長。単位Byte

unSts_SDOReceiveData_D

U40\G90524~90923

WORD配列

SDO読出し結果

uSts_SDOErrorCode_D

U40\G90924

WORD

SDO通信エラーコード

udSts_SDODetailErrorCode_D

U40\G90926~90927

DWORD

SDO通信詳細エラー

SDO制御コマンド

完了判定は、要求コマンドと実行済みコマンドが一致することです。実行完了後でも、エラーコードを確認する必要があります。

SDO要求を0へ戻すと、MX-Fの受信データやエラー情報がクリアされるため、プログラムでは結果をローカル変数へ保存してから要求を解除します。

指令値

説明

動作

0

No Command

待機・要求解除

1

SDO Communication UPLOAD

CoE Objectの読出し

2

SDO Communication DOWNLOAD

CoE Objectの書込み

WAGO側のCoE Object Dictionary

こちらは今回記事でアクセスするCoEです。

Index

SubIndex

Object

Access

今回の用途

0x1000

0x00

Device Type

RO

デバイス種別を確認

0x10F3

0x05

Diagnosis History – Flags

RW

診断記録とEMCY通知を設定

0x1000:00 — Device Type

  • データ型:UNSIGNED32(4 Byte)
  • アクセス:Read Only
  • 仕様書記載値:0x00001389
  • 今回の実機では、SDO Readにより下位16bitとしてH1389を取得しました。上位16bitも0であれば、32bit値は0x00001389です。

0x10F3:05 — Diagnosis History Flags

これは、WAGOの診断情報の記録やEtherCAT Emergency Message(EMCY)の送信を制御するオブジェクトです。

Bit

マスク

WAGO資料の説明

1の場合

0

0x0001

Enable EMCY sending

EMCY送信を有効

1

0x0002

Ignore infos

情報メッセージの記録を無視

2

0x0004

Ignore warnings

警告メッセージの記録を無視

3

0x0008

Ignore errors

エラーメッセージの記録を無視

4

0x0010

Acknowledge mode

承認モードの状態

5

0x0020

Message buffer full

診断バッファ満杯の状態

7557-0441 Status bytes

ステータスバイトは、すべてのチャネルで同一の方法で実装されています。

ステータスバイト構成

BIT

名称

値:0の状態

値:1の状態

Bit 7

Reserved(予約)

—

—

Bit 6

General Error(総合エラー)

エラーなし。Bit 0、1、4、5のエラーフラグが設定されていない状態です。

エラーあり。Bit 0、1、4、5のいずれかのエラーフラグが設定されている状態です。

Bit 5

Wire Break(断線)

センサケーブルに断線が発生していない状態です。

センサケーブルに断線が発生している状態です。

Bit 4

Overload(過負荷)

過負荷が発生していない状態です。

センサケーブルに過負荷が発生している状態です。

Bit 3

User Overrange(ユーザー設定上限超過)

フィールド側の入力電圧または入力電流が、ユーザー設定の上限値を下回っている状態です。

フィールド側の入力電圧または入力電流が、ユーザー設定の上限値を超えている状態です。

Bit 2

User Underrange(ユーザー設定下限未満)

フィールド側の入力電圧または入力電流が、ユーザー設定の下限値を上回っている状態です。

フィールド側の入力電圧または入力電流が、ユーザー設定の下限値を下回っている状態です。

Bit 1

Overrange(測定範囲上限超過)

フィールド側の入力電圧または入力電流が、測定範囲の上限値を下回っている状態です。

フィールド側の入力電圧または入力電流が、測定範囲の上限値を超えている状態です。

Bit 0

Underrange(測定範囲下限未満)

フィールド側の入力電圧または入力電流が、測定範囲の下限値を上回っている状態です。

フィールド側の入力電圧または入力電流が、測定範囲の下限値を下回っている状態です。

プロセスイメージ(Standard)

バイト位置

入力プロセスデータ

Byte 0

プロセス値 CH1_D0

Byte 1

プロセス値 CH1_D1

Byte 2

プロセス値 CH2_D0

Byte 3

プロセス値 CH2_D1

Byte 4

プロセス値 CH3_D0

Byte 5

プロセス値 CH3_D1

Byte 6

プロセス値 CH4_D0

Byte 7

プロセス値 CH4_D1

プロセスイメージ(Advanced)

バイト位置

入力プロセスデータ

Byte 0

プロセス値 CH1_D0

Byte 1

プロセス値 CH1_D1

Byte 2

プロセス値 CH2_D0

Byte 3

プロセス値 CH2_D1

Byte 4

プロセス値 CH3_D0

Byte 5

プロセス値 CH3_D1

Byte 6

プロセス値 CH4_D0

Byte 7

プロセス値 CH4_D1

Byte 8

ステータスバイト CH1_S0

Byte 9

ステータスバイト CH2_S1

Byte 10

ステータスバイト CH3_S2

Byte 11

ステータスバイト CH4_S3

7557-0461 Status bytes

ステータスバイトは、すべてのチャネルで同一の方法で実装されています。

ステータスバイト構成

BIT

名称

値:0の状態

値:1の状態

Bit 7

Reserved(予約)

予約ビット

—

Bit 6

General Error(総合エラー)

エラーなし。Bit 3(短絡)およびBit 4(断線)のエラーフラグが設定されていない状態です。

総合エラーあり。Bit 3(短絡)またはBit 4(断線)のエラーフラグが設定されている状態です。

Bit 5

Reserved(予約)

予約ビット(0固定)

—

Bit 4

Wire Break(断線)

断線が発生していない状態です。

アナログ出力端子(+AO1、−AO1)が開放状態または異常に高いインピーダンス状態にある、もしくは出力端子に外部電圧が印加されている状態です。

Bit 3

Short Circuit(短絡)

短絡が発生していない状態です。

アナログ出力端子(+AO1、−AO1)間で短絡が発生している状態です。

Bit 2

Reserved(予約)

予約ビット(0固定)

—

Bit 1

Reserved(予約)

予約ビット(0固定)

—

Bit 0

Reserved(予約)

予約ビット(0固定)

—

プロセスイメージ

出力バイト位置

出力プロセスデータ

入力バイト位置

入力プロセスデータ

Byte 0

プロセス値 CH1_D0

Byte 0

ステータスバイト CH1_S0

Byte 1

プロセス値 CH1_D1

Byte 1

ステータスバイト CH2_S1

Byte 2

プロセス値 CH2_D0

Byte 2

ステータスバイト CH3_S2

Byte 3

プロセス値 CH2_D1

Byte 3

ステータスバイト CH4_S3

Byte 4

プロセス値 CH3_D0

―

―

Byte 5

プロセス値 CH3_D1

―

―

Byte 6

プロセス値 CH4_D0

―

―

Byte 7

プロセス値 CH4_D1

―

―

Implementation

WAGO 7553-8000側

最初はWAGO 7553-8000側から設定します。

DIP スイッチ

今回の記事ではWAGO EtherCATカプラーをID=7️に設定しますので、本体にあるDIPスイッチのスイッチ1,2,3をON側にしてください。

MXF-EtherCAT側

次はMXF-EtherCAT側を構築します。

EtherCATネットワーク構築

EtherCATネットワークを構築するにはModule Parameters→Module Extended Parametersをクリックします。

モジュール設定

前回PART3で追加した7557-0441 Standardと7557-0461 Standardをモジュール構成から消します。

下図にある”X”ボタンをクリックします。

YESで進みます。

次は右側から7557-0441 Advancedと7557-0461 Advancedをモジュール構成に追加します。

Done!

7557-0441のPDO MappingにはStatus Wordが追加されました。

7557-0461のPDO MappingにはStatus Wordが追加されました。

設定保存

Close with Reflecting the Settingをクリックしネットワーク設定を保存します。

Yesをクリックします。

ラベル生成

今度はラベルを生成します。Labeling Targetを選択し→Label Nameを入力→Create Labelで構造体ラベルを生成しましょう。

Yesで進みます。

Done!

プログラム

構造体

最初は構造体を作成します。

dut_wago7553_8000_DiagStatusWord

WAGO 7553-8000 EtherCATカプラーのStatus Wordを分解するための構造体を作成します。

dut_wago7557_0461_StatusWord

WAGO 7553-0461 アナログ出力のStatus Wordを分解するための構造体を作成します。

dut_wago7557_0441_StatusWord

WAGO 7553-0441 アナログ入力のStatus Wordを分解するための構造体を作成します。

FUN

Functionを追加するために、FB/FUN→右クリック→Add New Dataし新しいFCを追加します。

fc_wago7553_8000_DiagStatusWord

fc_wago7553_8000_DiagStatusWord関数はWAGO 7553-8000 EtherCATカプラーにインストールされた診断ワードからカプラーの状態を判断します。

fc_wago7553_8000_DiagStatusWord.CHNUM.0:=iwData.0;
fc_wago7553_8000_DiagStatusWord.CHNUM.1:=iwData.1;
fc_wago7553_8000_DiagStatusWord.CHNUM.2:=iwData.2;
fc_wago7553_8000_DiagStatusWord.CHNUM.3:=iwData.3;
fc_wago7553_8000_DiagStatusWord.CHNUM.4:=iwData.4;
fc_wago7553_8000_DiagStatusWord.CHNUM.5:=iwData.5;
fc_wago7553_8000_DiagStatusWord.CHNUM.6:=iwData.6;
fc_wago7553_8000_DiagStatusWord.CHNUM.7:=iwData.7;

fc_wago7553_8000_DiagStatusWord.CHNUM.0:=iwData.8;
fc_wago7553_8000_DiagStatusWord.CHNUM.1:=iwData.9;
fc_wago7553_8000_DiagStatusWord.CHNUM.2:=iwData.A;


fc_wago7553_8000_DiagStatusWord.EVTCODE.0:=iwData.B;
fc_wago7553_8000_DiagStatusWord.EVTCODE.1:=iwData.C;
fc_wago7553_8000_DiagStatusWord.EVTCODE.2:=iwData.D;

fc_wago7553_8000_DiagStatusWord.CLRACK.0:=iwData.E;
fc_wago7553_8000_DiagStatusWord.EVENT.0:=iwData.F;


;

fc_wago7557_0461_StatusWord

fc_wago7557_0461_StatusWord関数はWAGO 7557_0461 アナログ出力にインストールされた診断ワードからモジュールの状態を判断します。

fc_wago7557_0461_StatusWord.Generalerror:=iwData.3;
fc_wago7557_0461_StatusWord.Generalerror:=iwData.4;
fc_wago7557_0461_StatusWord.Generalerror:=iwData.6;

;

fc_wago7557_0441_StatusWord

fc_wago7557_0441_StatusWord関数はWAGO 7557_0441 アナログ入力にインストールされた診断ワードからモジュールの状態を判断します。

fc_wago7557_0441_StatusWord.Underrange:=iwData.0;
fc_wago7557_0441_StatusWord.Overrange:=iwData.1;
fc_wago7557_0441_StatusWord.UserUnderrange:=iwData.2;
fc_wago7557_0441_StatusWord.UserOverrange:=iwData.3;
fc_wago7557_0441_StatusWord.WireBreak:=iwData.5;
fc_wago7557_0441_StatusWord.GeneralError:=iwData.6;
;

MAIN

次はメインプログラムです。

こちらは検証プログラムです。ST言語のR_TRIGとSHLを使用し、16ビットのデジタル出力を順番にONさせるプログラムを作成しました。

  • R_TRIGで100msクロック信号の立ち上がり、かつWAGOの入力モジュールに配線したボタンを押したことを検出し、SHLによって出力データを1ビットずつ左にシフトします。
  • NX-ECC202・NX-ECC203出力データが0の場合は初期値として1を設定し、最上位ビット(Bit 15)に到達すると出力データをクリアして、再びBit 0から処理を繰り返します。
  • WAGO 7557-0123出力モジュールはChannel1からChannel16までON・OFFを繰り返します。
  • 7557-0461アナログ出力チャンネル1の出力値は7557-0441アナログ入力値1そのままLoop Backします。
  • 先程作成した関数からWAGO 7553-8000 EtherCATカプラーとモジュールの状態を確認します。

//EtherCAT Ready
M10:=MX_EC.bIn_EtherCATFunction_Ready;

//Sub Devices
D100:=MX_EC.unSts_SubDeviceESMState_D[0];
D101:=MX_EC.unSts_SubDeviceESMState_D[1];
D102:=MX_EC.unSts_SubDeviceESMState_D[2];
D103:=MX_EC.unSts_SubDeviceESMState_D[3];

//
IF iCounter <0 THEN
iCounter:=0;
END_IF;


//fbR_TRIG(CLK:= MX_SQ.stSM.b10msClock);
fbR_TRIG(CLK:= MX_SQ.stSM.b100msClock AND stID07.Module17557_010516DI_3msNPNInputs_Channel1Data1 =1);


IF SubDevice_1001NX_ECC203_Module1NX_OD5256OutputDataSet1_OutputBit16bits = 0 THEN

SubDevice_1001NX_ECC203_Module1NX_OD5256OutputDataSet1_OutputBit16bits:=1;

END_IF;

IF fbR_TRIG.Q THEN

SubDevice_1001NX_ECC203_Module1NX_OD5256OutputDataSet1_OutputBit16bits:=
SHL(
SubDevice_1001NX_ECC203_Module1NX_OD5256OutputDataSet1_OutputBit16bits
,1
);

END_IF;

IF stID40.Module2NX_OD5256OutputDataSet1_OutputBit16bits =0 THEN
stID40.Module2NX_OD5256OutputDataSet1_OutputBit16bits:=1;
END_IF;

IF fbR_TRIG.Q THEN

stID40.Module2NX_OD5256OutputDataSet1_OutputBit16bits:=
SHL(
stID40.Module2NX_OD5256OutputDataSet1_OutputBit16bits
,1
);
IF iCounter = 0 THEN
stID07.Module27557_012316DO_05ANPNOutputs_Channel1Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel2Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel3Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel4Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel5Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel6Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel7Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel8Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel9Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel10Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel11Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel12Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel13Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel14Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel15Data1:=0;
stID07.Module27557_012316DO_05ANPNOutputs_Channel16Data1:=0;
iCounter:=iCounter+1;
ELSE
stID07.Module27557_012316DO_05ANPNOutputs_Channel1Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel2Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel3Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel4Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel5Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel6Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel7Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel8Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel9Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel10Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel11Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel12Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel13Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel14Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel15Data1:=1;
stID07.Module27557_012316DO_05ANPNOutputs_Channel16Data1:=1;
iCounter:=0;
END_IF;

END_IF;

stID07.Module47557_04614AO_UIStandardOutputs_Channel1Word1:=stID07.Module37557_04414AI_UIStandardInputs_Channel1Word1;

//
dutWago7553_8000_DiagsatatusWord:=fc_wago7553_8000_DiagStatusWord(
EN:=TRUE
,iwData:=stID07.Input_DiagnosticsStatusWord
);
//
dut_wago7557_0461_StatusWord[1]:=fc_wago7557_0461_StatusWord(
EN:=TRUE
,iwData:=stID07.Module47557_04614AO_UIAdvancedInputs_Channel1Status
);
dut_wago7557_0461_StatusWord[2]:=fc_wago7557_0461_StatusWord(
EN:=TRUE
,iwData:=stID07.Module47557_04614AO_UIAdvancedInputs_Channel2Status
);
dut_wago7557_0461_StatusWord[3]:=fc_wago7557_0461_StatusWord(
EN:=TRUE
,iwData:=stID07.Module47557_04614AO_UIAdvancedInputs_Channel3Status
);
dut_wago7557_0461_StatusWord[4]:=fc_wago7557_0461_StatusWord(
EN:=TRUE
,iwData:=stID07.Module47557_04614AO_UIAdvancedInputs_Channel4Status
);
//
dut_wago7557_0441_StatusWord[1]:=fc_wago7557_0441_StatusWord(
EN:=TRUE
,iwData:=stID07.Module47557_04614AO_UIAdvancedInputs_Channel1Status
);
dut_wago7557_0441_StatusWord[2]:=fc_wago7557_0441_StatusWord(
EN:=TRUE
,iwData:=stID07.Module47557_04614AO_UIAdvancedInputs_Channel2Status
);
dut_wago7557_0441_StatusWord[3]:=fc_wago7557_0441_StatusWord(
EN:=TRUE
,iwData:=stID07.Module47557_04614AO_UIAdvancedInputs_Channel3Status
);
dut_wago7557_0441_StatusWord[4]:=fc_wago7557_0441_StatusWord(
EN:=TRUE
,iwData:=stID07.Module47557_04614AO_UIAdvancedInputs_Channel4Status
);

pSDO

pSDOは、MX-F100-ECをEtherCAT MainDevice、WAGO 7553-8000をSubDeviceとして使用し、CoE(CANopen over EtherCAT)のSDO通信によって、WAGOの内部パラメータを読み書きするサンプルプログラムである。

EtherCATのPDO通信は、一定周期で入出力データを交換するために使用する。一方、SDO通信は、機器内部のObject Dictionaryにアクセスし、パラメータや診断情報を個別に読み書きするために使用する非周期通信である。

今回のプログラムでは、WAGOのDevice Typeを読み出す機能と、Diagnosis HistoryのFlagsを変更する機能を実装した。

指令・操作フラグ

Local Label

型

説明

bReadReq

BOOL

SDO Read実行要求。FALSE→TRUEで起動

bWriteReq

BOOL

SDO Write実行要求。FALSE→TRUEで起動

bWritePermit

BOOL

書込み許可。今回の解説付きコードで追加

bReadPrev

BOOL

Read要求の前回状態。立上り検出用

bWritePrev

BOOL

Write要求の前回状態。立上り検出用

bIgnoreInfo

BOOL

WAGO Bit 1をON/OFF

bIgnoreWarning

BOOL

WAGO Bit 2をON/OFF

bIgnoreError

BOOL

WAGO Bit 3をONにする要求

bPermitBit3Change

BOOL

Bit 3のON操作を個別に許可

完了・異常フラグ

Local Label

型

TRUEになる条件

bReadDone

BOOL

Device TypeのSDO Read成功

bDownloadAck

BOOL

SDO Downloadの正常応答を受信

bWriteVerified

BOOL

再読出しのBit 0~3が書込み要求と一致

bWriteDone

BOOL

Write検証まで完了

bValueChanged

BOOL

書込み前後のBit 1~3に変化があった

bSdoError

BOOL

SDO通信・サイズ判定・検証で異常

bConfigError

BOOL

書込み許可不足などの操作条件エラー

こちらはFlowです。

今回のプログラムでは、単純にSDOでデータを書き込むだけではなく、書込み前の値を取得し、必要なビットのみ変更して書き込み、最後に再読出しして検証する方式を採用している。

これにより、既存の診断設定をできる限り維持しながら、必要な設定だけを変更できる。また、SDO Downloadの成功と、書込み後に値が一致したことを個別のフラグで確認できるため、異常発生時の切り分けも容易になる。

最終的な目的は、SDO通信が成立することだけではなく、「何を書き込もうとしたか」「正常応答があったか」「書込み後に何が読み出されたか」を記録し、設定変更を検証できるようにすることである。

(*
MX-F EtherCAT SDO Read / Write / Verify

Target: WAGO
Node Address: 7

READ:
0x1000:00 Device Type

READ-MODIFY-WRITE-VERIFY:
0x10F3:05 Diagnosis History Flags

Bit 0: Preserve original value
Bit 1: bIgnoreInfo
Bit 2: bIgnoreWarning
Bit 3: bIgnoreError (permission required)
Bit 4-15: Preserve original value

SDO Read size: 1 or 2 bytes
SDO Write size: Same as Read size

bWriteDone = TRUE only after read-back match
*)

dwTransmitNodeAddress := 7;

CASE uiStep OF

// ============================================
// IDLE
// ============================================

0:
IF bReadReq AND NOT bReadPrev THEN

bReadDone := FALSE;
bSdoError := FALSE;
bConfigError := FALSE;
uiErrorStep := 0;

uiStep := 10;

ELSIF bWriteReq AND NOT bWritePrev THEN

bWriteDone := FALSE;
bWriteVerified := FALSE;
bValueChanged := FALSE;
bDownloadAck := FALSE;
bSdoError := FALSE;
bConfigError := FALSE;

uiErrorStep := 0;
wSdoError := 0;
dwSdoDetail := 0;
dwFlagsReadSize := 0;
dwVerifySize := 0;

uiStep := 20;

END_IF;


// ============================================
// READ Device Type 0x1000:00
// ============================================

10:
IF (MX_EC.uSet_SDOControlCommand_D = 0)
AND
(MX_EC.uSts_SDOExecutedControlCommand_D = 0)
THEN

MX_EC.uSet_SDOTransmitNodeAddress_D :=
dwTransmitNodeAddress;

MX_EC.uSet_SDOTransmitIndexNumber_D :=
16#1000;

MX_EC.uSet_SDOTransmitSubIndexNumber_D := 0;

MX_EC.uSet_SDOControlCommand_D := 1;

uiStep := 11;
END_IF;

11:
IF MX_EC.uSts_SDOExecutedControlCommand_D = 1 THEN

wSdoError :=
MX_EC.uSts_SDOErrorCode_D;

dwSdoDetail :=
MX_EC.udSts_SDODetailErrorCode_D;

IF (wSdoError = 0)
AND
(MX_EC.udSts_SDOReceiveDataSize_D = 4)
THEN

wDeviceTypeLo :=
MX_EC.unSts_SDOReceiveData_D[0];

wDeviceTypeHi :=
MX_EC.unSts_SDOReceiveData_D[1];

bReadDone := TRUE;
uiStep := 12;

ELSE

bSdoError := TRUE;
uiErrorStep := 11;
uiStep := 90;

END_IF;

MX_EC.uSet_SDOControlCommand_D := 0;

END_IF;

12:
IF MX_EC.uSts_SDOExecutedControlCommand_D = 0 THEN
uiStep := 0;
END_IF;


// ============================================
// STEP 20: Read Flags Before Write
// ============================================

20:
IF (MX_EC.uSet_SDOControlCommand_D = 0)
AND
(MX_EC.uSts_SDOExecutedControlCommand_D = 0)
THEN

MX_EC.uSet_SDOTransmitNodeAddress_D :=
dwTransmitNodeAddress;

MX_EC.uSet_SDOTransmitIndexNumber_D :=
16#10F3;

MX_EC.uSet_SDOTransmitSubIndexNumber_D := 5;

MX_EC.uSet_SDOControlCommand_D := 1;

uiStep := 21;

END_IF;


// ============================================
// STEP 21: Create Write Data
// ============================================

21:
IF MX_EC.uSts_SDOExecutedControlCommand_D = 1 THEN

wSdoError :=
MX_EC.uSts_SDOErrorCode_D;

dwSdoDetail :=
MX_EC.udSts_SDODetailErrorCode_D;

dwFlagsReadSize :=
MX_EC.udSts_SDOReceiveDataSize_D;

IF (wSdoError = 0)
AND
((dwFlagsReadSize = 1)
OR (dwFlagsReadSize = 2))
THEN

wFlagsBefore :=
MX_EC.unSts_SDOReceiveData_D[0];

// Clear Bit 1, 2, 3 only
// Preserve all other bits
wFlagsWrite :=
wFlagsBefore AND 16#FFF1;

// Bit 1 – Ignore Information
IF bIgnoreInfo THEN
wFlagsWrite :=
wFlagsWrite OR 16#0002;
END_IF;

// Bit 2 – Ignore Warning
IF bIgnoreWarning THEN
wFlagsWrite :=
wFlagsWrite OR 16#0004;
END_IF;

// Bit 3 – Ignore Error
IF bIgnoreError THEN
wFlagsWrite :=
wFlagsWrite OR 16#0008;
END_IF;

// For 1-byte SDO, limit to 8 bits
IF dwFlagsReadSize = 1 THEN
wFlagsWrite :=
wFlagsWrite AND 16#00FF;
END_IF;

// Bit 3 change protection
IF (((wFlagsBefore XOR wFlagsWrite)
AND 16#0008) <> 0)
AND NOT bPermitBit3Change
THEN

bConfigError := TRUE;
uiErrorStep := 25;
uiStep := 90;

ELSE

uiStep := 22;

END_IF;

ELSE

bSdoError := TRUE;
uiErrorStep := 21;
uiStep := 90;

END_IF;

MX_EC.uSet_SDOControlCommand_D := 0;

END_IF;


// ============================================
// STEP 22: Wait Read Reset
// ============================================

22:
IF MX_EC.uSts_SDOExecutedControlCommand_D = 0 THEN
uiStep := 30;
END_IF;


// ============================================
// STEP 30: SDO Download
// ============================================

30:
IF (MX_EC.uSet_SDOControlCommand_D = 0)
AND
(MX_EC.uSts_SDOExecutedControlCommand_D = 0)
THEN

MX_EC.uSet_SDOTransmitNodeAddress_D :=
dwTransmitNodeAddress;

MX_EC.uSet_SDOTransmitIndexNumber_D :=
16#10F3;

MX_EC.uSet_SDOTransmitSubIndexNumber_D := 5;

// Match actual received object size
MX_EC.udSet_SDOTransmitDataSize_D :=
dwFlagsReadSize;

MX_EC.unSet_SDOTransmitData_D[0] :=
wFlagsWrite;

// SDO Download
MX_EC.uSet_SDOControlCommand_D := 2;

uiStep := 31;

END_IF;


// ============================================
// STEP 31: Check Download ACK
// ============================================

31:
IF MX_EC.uSts_SDOExecutedControlCommand_D = 2 THEN

wSdoError :=
MX_EC.uSts_SDOErrorCode_D;

dwSdoDetail :=
MX_EC.udSts_SDODetailErrorCode_D;

IF wSdoError = 0 THEN

bDownloadAck := TRUE;
uiStep := 32;

ELSE

bSdoError := TRUE;
uiErrorStep := 31;
uiStep := 90;

END_IF;

MX_EC.uSet_SDOControlCommand_D := 0;

END_IF;


// ============================================
// STEP 32: Wait Download Reset
// ============================================

32:
IF MX_EC.uSts_SDOExecutedControlCommand_D = 0 THEN
uiStep := 40;
END_IF;


// ============================================
// STEP 40: Read Back 0x10F3:05
// ============================================

40:
IF (MX_EC.uSet_SDOControlCommand_D = 0)
AND
(MX_EC.uSts_SDOExecutedControlCommand_D = 0)
THEN

MX_EC.uSet_SDOTransmitNodeAddress_D :=
dwTransmitNodeAddress;

MX_EC.uSet_SDOTransmitIndexNumber_D :=
16#10F3;

MX_EC.uSet_SDOTransmitSubIndexNumber_D := 5;

MX_EC.uSet_SDOControlCommand_D := 1;

uiStep := 41;

END_IF;


// ============================================
// STEP 41: Verify Read Back
// ============================================

41:
IF MX_EC.uSts_SDOExecutedControlCommand_D = 1 THEN

wSdoError :=
MX_EC.uSts_SDOErrorCode_D;

dwSdoDetail :=
MX_EC.udSts_SDODetailErrorCode_D;

dwVerifySize :=
MX_EC.udSts_SDOReceiveDataSize_D;

IF (wSdoError = 0)
AND
(dwVerifySize = dwFlagsReadSize)
THEN

wFlagsAfter :=
MX_EC.unSts_SDOReceiveData_D[0];

// Verify Bit 0 to 3
// Bit 4 and 5 may be read-only/status
IF ((wFlagsAfter XOR wFlagsWrite)
AND 16#000F) = 0
THEN

bWriteVerified := TRUE;
bWriteDone := TRUE;

// Detect actual change of Bit 1 to 3
bValueChanged :=
((wFlagsBefore XOR wFlagsAfter)
AND 16#000E) <> 0;

ELSE

bSdoError := TRUE;
uiErrorStep := 41;

END_IF;

ELSE

bSdoError := TRUE;
uiErrorStep := 41;

END_IF;

MX_EC.uSet_SDOControlCommand_D := 0;
uiStep := 42;

END_IF;


// ============================================
// STEP 42: Wait Verify Reset
// ============================================

42:
IF MX_EC.uSts_SDOExecutedControlCommand_D = 0 THEN
uiStep := 0;
END_IF;


// ============================================
// STEP 90: Error Recovery
// ============================================

90:
MX_EC.uSet_SDOControlCommand_D := 0;

IF MX_EC.uSts_SDOExecutedControlCommand_D = 0 THEN
uiStep := 0;
END_IF;

END_CASE;


// ============================================
// Rising Edge Detection
// ============================================

bReadPrev := bReadReq;
bWritePrev := bWriteReq;

CPUと接続する

最後はPCとMXF-EtherCATをUSB-Cで接続します。

ダウンロード

プロジェクトをCPUにダウンロードし、電源を入れ直します。

結果

WAGO 7553-8000 EtherCAT Coupler本体にあるRUNとI/O LED両方も緑点灯になっています。

オムロンのECC203はエラーなく、RUN・TS両方とも緑点灯になっています。

4つのEtherCAT Slaveもステータス=8、つまりOP状態になっています。

次はbReadReqをTRUEにし、SDOメッセージを送信します。

Done!WAGO 7553-8000 EtherCATカプラーからデバイスIDが取得しました。

最後はbWriteReqをTRUEにし、SDOメッセージを送信し、IgnoreInfo FlagをTrueにします。

シェアする

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

フォローする