TSM#CET5をEXOR XA5 CodesysとCAN BUSで接続しよう

今回の記事では、TSM社のCET5センサをEXOR社の車載HMI XA5に接続し、CODESYS Runtime上でCANopen通信を行います。

さらに、JMobileの画面から取得データを確認できるようにします。

さあ、FAを楽しもう。

CET?

CET5は、CANopen出力を備えた堅牢・高性能なワイヤ式変位センサであり、産業用途に求められる高い品質と耐久性を備えています。優れた繰り返し精度、高いIP保護等級、耐衝撃性・耐振動性、および電磁ノイズ耐性により、農業用車両、土木機械、建設機械、多関節アームクレーン、高所作業車などのモバイル油圧機器に適しています。

CET5シリーズの注文コードは、測定範囲、電源電圧範囲、出力方式、接続仕様、センサ構成、カスタマイズ有無、および認証仕様を組み合わせて構成されます。各コードを指定することで、用途に応じた製品仕様を選定できます。例えば、測定範囲、CANopen通信、Deutschコネクタ、冗長センサ構成、SIL2/PLd対応などの仕様を注文コード上で明確に指定することができます。

動作原理

ワイヤ式変位センサは、軸受で支持されたドラムを内部に備えており、このドラムにワイヤロープが巻き付けられています。

ワイヤロープが引き出されると、その動きに連動してドラムが回転します。ワイヤロープの直線方向の移動量は、ドラムの回転角度に変換されます。

このドラムの回転角度を検出することで、ワイヤの引き出し量、すなわち直線変位量を測定します。

注意するのは、ワイヤの最大引き出し長さを超えて使用すると、ワイヤおよび内部機構を損傷するおそれがあります。使用時は、必ず仕様で定められた測定範囲内で使用してください。

端子台

CANOPEN

CANopenは、Controller Area Network(CAN)のアプリケーション層であるCAL(CAN Application Layer)を基盤とした、オープンかつ非独占的な標準通信プロトコルです。ISO/OSI参照モデルの第7層に位置づけられる通信規格であり、CAN in Automation(CiA)ユーザー団体によって開発・国際標準化され、現在も維持管理されています。

CETセンサは、CANopenデバイスとして、CiA DS301に基づくデバイス仕様の要求事項を満たしています。また、エンコーダ用デバイスプロファイルであるCiA DS406、および傾斜計用デバイスプロファイルであるCiA DS410にも部分的に対応しています。

通信オブジェクト

CANopenの通信は、CANメッセージによって行われます。CANメッセージとは、デバイスへ送信される、またはデバイスから送信されるコマンドであり、CANバス上ではネットワークパケットの形式でやり取りされます。

各CANメッセージは、以下の要素で構成されます。

  • 識別子(CANメッセージID)
  • 制御ビット
  • 0~8バイトのデータ

CANメッセージは、Communication Object、または略して COB と呼ばれることがあります。また、CANメッセージIDは COB-ID と呼ばれます。

すべての数値データ型は、データフィールド内にリトルエンディアン形式で格納されます。そのため、LSB(最下位バイト)は最も低いデータインデックスに配置され、MSB(最上位バイト)は最も高いデータインデックスに配置されます。配置例を以下の表に示します。

11ビットの識別子(COB-ID)は、4ビットのファンクションコードと7ビットのNode IDで構成されます。ファンクションコードは通信オブジェクトの種類および優先度を示し、Node IDは同一ネットワーク上に存在するCANopenデバイスを識別するために使用されます。この仕組みにより、CANopenネットワーク内で各通信オブジェクトを適切に識別し、管理することができます。

この仕組みにより、1台のCANopenマスタデバイスと、最大127台のNMTスレーブCANopenデバイス間で、ピアツーピア通信を行うことができます。CETは、以下の各章で詳しく説明する通信オブジェクトに対応しています。

  • ネットワークマネジメントオブジェクト(NMT)
  • 同期オブジェクト(SYNC)
  • エマージェンシーオブジェクト(EMCY)
  • プロセスデータオブジェクト(PDO)
  • サービスデータオブジェクト(SDO)
  • Node Guarding / Heartbeat

PDO

プロセスデータオブジェクト(PDO)は、アプリケーションオブジェクトを送信するために、最大8バイトのデータフィールドを使用して、1つのCANフレームにマッピングされます。

PDOによる転送は、プロトコル上の追加的なオーバーヘッドなしでリアルタイムに行われます。各PDOには固有の識別子が割り当てられており、1つのノードからのみ送信されます。ただし、そのPDOは複数のノードで受信することができます。これは、プロデューサ/コンシューマ通信と呼ばれます。

PDOは、通信パラメータとマッピングパラメータによって定義されます。通信パラメータは、PDOの通信機能や通信条件を示し、マッピングパラメータは、そのPDOに含まれるデータ内容を示します。

CANopenデバイスの動作を決定する通信パラメータおよびアプリケーションパラメータは、オブジェクトディクショナリ(Object Dictionary) と呼ばれる標準化された一覧で管理されます。

オブジェクトディクショナリでは、CANopenプロトコルスタックなどの通信部と、デバイスのアプリケーションソフトウェア部との間で交換されるすべてのデータに対して、固有の24ビットアドレスが割り当てられます。

この24ビットアドレスは、以下の2つで構成されます。

  • 16ビットのIndex
  • 8ビットのSubIndex

CANopenのオブジェクトディクショナリ内に存在する各エントリは、CANopen通信サービスを使用して読み出すことができます。

TPDO1 – Linear sensors output

デバイスのバージョンによって、TPDO1には異なる静的マッピングが用意されています。具体的には、CET5モデル用のマッピングと、CET7、CET12、CET20モデル用のマッピングがそれぞれ用意されています。

TSM16のマッピング:CET5で有効:

TSM32のマッピング:CET7、CET12、CET20で有効:

Position 1 および Position 2 は、2つのリニアセンサによって取得される長さ測定値を示します。データ形式は、マッピング方式によって異なります。

  • TSM16 マッピング:INT16
  • TSM32 マッピング:INT32

エンディアン形式は リトルエンディアン で、分解能は 0.1 mm です。

  • Position 1 は、直接値として表されます(0〜 FS)。
  • Position 2 は、補数側の値として表されます(0 ~ -FS)。

TSM16 マッピングの場合、長さ測定値が 1000.0 mm の場合:

D0 = 0x10, D1 = 0x27
→ Position 1 = 0x2710 = 10000d

分解能が 0.1 mm のため、

10000 × 0.1 mm = 1000.0 mm

一方、Position 2 は補数側の値として以下のように表されます。

D2 = 0xF0, D3 = 0xD8

→ Position 2 = 0xD8F0 = -10000d

つまり、-10000 × 0.1 mm = -1000.0 mm

TPDO2 – Inclinometers output

このマッピング機能は、傾斜センサーを内蔵したすべてのCETモデルで利用可能です。

Angle 1 および Angle 2 は、2つの傾斜センサによって取得される角度測定値を示し、データ形式は INT16 で、エンディアン形式は リトルエンディアン です。分解能は 0.1° です。

Angle 1 は、時計回り方向の角度として表されます(0 ~ 3599)。
Angle 2 は、反時計回り方向の角度として表されます(3599 ~ 0)。

ここで、値は 0.1° 単位で表されるため、たとえば 900 は 90.0° を意味します。

角度測定値が 90.0° の場合:

D0 = 0x84, D1 = 0x03
→ Angle 1 = 0x0384 = 900d

分解能が 0.1° のため、
900 × 0.1° = 90.0°となります。

一方、Angle 2 は反時計回り方向の値として以下のように表されます。

D2 = 0x8C, D3 = 0x0A
→ Angle 2 = 0x0A8C = 2700d

つまり、2700 × 0.1° = 270.0°となります。

SDO

サービスデータオブジェクト(SDO)は、オブジェクトディクショナリのエントリに対する読み出しおよび書き込みに使用されます。SDO転送プロトコルは任意サイズのオブジェクト転送に対応しており、必要に応じてデータを複数のセグメントに分割して送受信します。各セグメントには制御情報とユーザデータが含まれ、受信側はセグメントごと、またはセグメントブロックごとに確認応答を返します。転送に失敗した場合は、アボートメッセージが送信されます。

また、CETは、標準設定として1つのSDOサーバ機能を備えています。SDO通信では、オブジェクトディクショナリに対するデータの読み出しおよび書き込みを行うことができ、CETではエクスペダイト転送と通常転送(セグメント転送)の両方に対応しています。エクスペダイト転送は、最大4バイトまでの小容量データを1つのCANフレームで送受信する方式です。

送信

エクスペダイト転送を開始するには、マスタは以下のメッセージを送信します。

Cmd はリクエスト種別を示すコマンド指定子です。

Index および Sub-Id は、アクセス対象となるオブジェクトディクショナリのエントリのアドレスを示します。Data には、書き込みコマンドの場合に、書き込み値が格納されます。

受信

センサは、以下のメッセージで応答します。

Ans は応答種別を示すレスポンス指定子です。

Index および Sub-Id は、アクセスされたオブジェクトディクショナリのエントリのアドレスを示します。Data には、読み出しコマンドの場合、読み出された値が格納されます。

転送に失敗した場合は、Data フィールドにアボートコードが格納されます。

0x80 のアボートメッセージは、転送が正常に完了しなかったことを示します。

その原因は、8.3節のアボートコード表に記載されているいずれかの理由に該当します。

Node ID(ノードID)

CANopenネットワーク上の各デバイスは、固有のNode-IDによって一意に識別されます。Node-IDは1~127の範囲で設定され、同一ネットワーク内で重複しないように設定する必要があります。Node-IDを変更する場合は、以下に示すSDOコマンドを送信します。

(Default ID=4)

Store parameters(パラメータの保存)

オブジェクトディクショナリ内のすべてのパラメータは、内部の不揮発性メモリ内に設けられた専用領域へ保存することができます。この保存領域は、チェックサム計算およびミラーリングされたバックアップによって保護されています。これにより、保存処理中に予期しない電源断が発生した場合でも、データ損失を防止できるようになっています。

ただし、マイクロコントローラの内部構造上、パラメータの書き込み回数には制限があり、最大 10,000回 までとなります。

Store default parameters(デフォルトパラメータを保存する)

このSDOを使用することで、不揮発性メモリに保存されているオブジェクトディクショナリ内のすべてのパラメータを、工場出荷時のデフォルト値へ復元することができます。なお、復元処理を完了させるには、デバイスのリセットが必要です。

set/reset customer INCLINOMETER ZERO point (Preset value) カスタマ用傾斜ゼロ点の設定/リセット

本コマンドにより、角度測定値を任意のプリセット値へ補正することができます。プリセット値に 0 を設定した場合、現在のセンサ位置を傾斜角度のゼロ点として登録できます。冗長センサ構成の場合、本設定は2つの角度出力の両方に適用されます。

  • 形式:UINT16
  • 解像度:別コマンドで設定される分解能。
  • 範囲:0 ~ 65535

PRESET値

動作

0

ゼロ点を設定

0以外

プリセット点を設定

FB

次は今回記事で使用したFBを紹介します。

SDO_WRITE_DATA (FB)

このファンクションブロックは、デバイスのオブジェクトディクショナリ内にある特定のオブジェクトへデータを書き込むために使用します。データがエラーなく書き込まれた場合、CONFIRM が TRUE になります。

DATA は、リトルエンディアンのバイト順で指定する必要があります。エラーが発生した場合、ERROR は 0 以外の値になります。

SDOアボートが発生した場合、ERROR には CANOPEN_KERNEL_ERROR.CANOPEN_KERNEL_OTHER_ERROR が設定され、ERRORINFO には、CiA 301で定義されている該当するアボートコードが リトルエンディアン形式で格納されます。

VAR_INPUT

名称

説明

NETWORK

USINT

ファンクションブロックを動作させるCANネットワーク番号を指定します。CANbusコンフィグレータ上のネットワーク番号とは異なります。CiA405のNETWORKはNETID + 1で計算されます。例:1 = CAN0、2 = CAN1、3 = CAN2

ENABLE

BOOL

立ち上がりエッジでファンクションブロックを有効化します。立ち下がりエッジで処理を中断します。

TIMEOUT

UDINT

タイムアウト時間をms単位で指定します。0の場合、タイムアウトなしを意味します。

DEVICE

DEVICE

書き込み先デバイスのNode-IDを指定します。0の場合はローカルデバイス、つまりCANopen Managerを意味します。

CHANNEL

USINT

使用するSDOチャネルを指定します。0は空いている任意のチャネルを使用し、1..nは特定のチャネルを指定します。

INDEX

WORD

書き込み対象となるオブジェクトのIndexを指定します。

SUBINDEX

BYTE

書き込み対象となるオブジェクトのSubIndexを指定します。

MODE

SDO_MODE

使用するSDOモードを指定します。通常はSDO_MODE.AUTOを使用します。

DATA

POINTER TO BYTE

書き込むデータへのポインタを指定します。データはリトルエンディアンのバイト順で指定する必要があります。

DATALENGTH

UDINT

書き込むデータの長さをバイト単位で指定します。

CONFIRM

BOOL

TRUEになると、ファンクションブロックがエラーなく正常に完了したことを示します。

ERROR

CANOPEN_KERNEL_ERROR

処理中に発生したエラー内容を示します。詳細はCANOPEN_KERNEL_ERRORを参照します。

VAR_OUTPUT

名称

説明

CONFIRM

BOOL

TRUEになると、SDO書き込み処理がエラーなく正常に完了したことを示します。

ERROR

CANOPEN_KERNEL_ERROR

処理中に発生したエラーコードを示します。詳細は CANOPEN_KERNEL_ERROR を参照します。

ERRORINFO

SDO_ERROR

SDOアボート発生時の詳細情報を示します。ERROR が CANOPEN_KERNEL_ERROR.CANOPEN_KERNEL_OTHER_ERROR の場合、CiA 301で定義されたアボートコードがリトルエンディアン形式で格納されます。

SDO_READ

SDO_READ ファンクションブロックは、CANopenデバイスのオブジェクトディクショナリ内にある指定オブジェクトからデータを読み出すために使用されます。読み出しが正常に完了すると、CONFIRM が TRUE となり、DATA には読み出しデータがリトルエンディアンのバイト順で格納されます。エラー発生時には ERROR が0以外となります。SDOアボートが発生した場合、ERROR には CANOPEN_KERNEL_ERROR.CANOPEN_KERNEL_OTHER_ERROR が設定され、ERRORINFO にはCiA 301で定義されたアボートコードがリトルエンディアン形式で格納されます。

VAR_INPUT

名称

説明

NETWORK

USINT

ファンクションブロックを動作させるCANネットワーク番号を指定します。CANbusコンフィグレータ上のネットワーク番号とは異なります。CiA405のNETWORKはNETID + 1で計算されます。例:1 = CAN0、2 = CAN1、3 = CAN2

ENABLE

BOOL

立ち上がりエッジでファンクションブロックを有効化します。立ち下がりエッジで処理を中断します。

TIMEOUT

UDINT

タイムアウト時間をms単位で指定します。0の場合、タイムアウトなしを意味します。

DEVICE

DEVICE

読み出し先デバイスのNode-IDを指定します。0の場合はローカルデバイス、つまりCANopen Managerを意味します。

CHANNEL

USINT

使用するSDOチャネルを指定します。0は空いている任意のチャネルを使用し、1..nは特定のチャネルを指定します。

INDEX

WORD

読み出し対象となるオブジェクトのIndexを指定します。

SUBINDEX

BYTE

読み出し対象となるオブジェクトのSubIndexを指定します。

MODE

SDO_MODE

使用するSDOモードを指定します。通常はSDO_MODE.AUTOを使用します。

DATA

POINTER TO BYTE

読み出したデータを書き込むメモリ領域へのポインタを指定します。データはCANopenのバイト順、つまりリトルエンディアン形式で格納されます。

Implementation

それから実際にプロジェクトを作成しましょう。

Codesys側

最初にEXOR XA5のCodesys側から構築します。

CANマスターを追加する

CodesysプロジェクトからDeviceを選択し→右クリック→Add Deviceします。

Fieldbus→CANBusを追加します。

これでCANBusが追加されました。

CANマネージャーを追加する

次はCANOpen Managerを追加するため、先程追加したCANBus→右クリック→Add Deviceします。

CANopen→CANopen Manager→CANopen Maganerを追加しましょう。

これでCANOPEN マスターが追加されました。

EDSファイルのインストール

次は今回記事で使用するTSM CET5センサーのEDS FILEをインストールするため、Tools→Device Repositoryをクリックします。

Installボタンをクリックします。

CET5のEDS FILEを選択します。

これでCET5のEDS FILEが登録できました。

CET5を追加

今度はTSM CET5 センサーをCAN OPENネットワークに追加するために、CANopen Manager→右クリック→Add Deviceします。

今回記事で使用するTSM CET5センサー(SI)を選択し追加しましょう。

それでTSM CET5センサーがCAN OPENネットワーク内に追加されました。

CANOPEN I/O Mapping Tabで”Address”から、このSesnorが占有した絶対アドレスは%IB100からだとわかります。そのアドレスはのちほどのGVLで変数定義するときに使用します。

CANバスの設定

次はCANbusの通信設定などを設定します。

Genral→Networkを0に設定します。今回XA5のCAN BUS1を使用しますので、もしCAN BUS2を使用するなら、Network番号=1に設定してください。またBaud Rateにもアプリケーションに合わせて設定しましょう。

CAN Open マネージャーの設定

今度はCAN Open Mangerを設定します。

General→Node-IDさえ設定すればOkです。

CET5センサーの設定

最後はCET5の設定になります。

General→Node-IDでCETセンサーのNode-IDを設定しましょう。今回はセンサーのDefault値4を使用します。

また、下図のReset Node Checkboxを外してください。

GVL

gHMI

こちらのGVLはHMIの読み書き用のGVLで、SDO通信などで取得・設定する値を格納するためのグローバル変数を定義しています。REAL型、BOOL型、INT型の読み出し用および書き込み用配列を用意し、各種パラメータの一時保存領域として使用します。また、デバイス名、ハードウェアバージョン、ファームウェアバージョンを格納する文字列変数も定義しています。

{attribute ‘qualified_only’}
VAR_GLOBAL
arrr32,arrwr32 :ARRAY[0..99]OF REAL;
arrrx,arrwx :ARRAY[0..99]OF BOOL;
arrri,arrwi :ARRAY[0..99]OF INT;
TSM_4_strDeviceName :STRING;
TSM_4_strHardwareVersion :STRING;
TSM_4_strFirmwareVersion :STRING;
END_VAR

gTSM

こちらのGVLはCET5デバイスから受信した入力データをCODESYS上で参照するため、入力メモリ領域に直接割り付けた変数を定義しています。CET5_0_0 は %IB100 から始まる4バイトの入力データを USINT 配列として扱い、CET5_0_1 は %IW52 から始まる2ワードの入力データを UINT 配列として扱います。これにより、受信したPDOデータをバイト単位またはワード単位で参照できます。

{attribute ‘qualified_only’}
VAR_GLOBAL
CET5_0_0 AT %IB100 :ARRAY[0..3]OF USINT;
CET5_0_1 AT %IW52 :ARRAY[0..1]OF UINT;
END_VAR

pTSMCET5_ID004

次はプログラムを作成しましょう。

VAR

今回の記事で使用するプログラムの変数を定義します。

PROGRAM pTSMCET5_ID004
VAR
Position1,Position2:INT;
rPosition1,rPosition2:REAL;
ErrorRegister: INT;
NumbeOfErrors: INT;
arrErrroField: ARRAY[0..7] OF DINT;
i: INT;
iTestCounter: INT;
xParametersStoreOK: BOOL;
xParametersStoreError: BOOL;
xBusReset: BOOL;
iInitCounter: INT;
xDataIntited: BOOL;
END_VAR

VAR
iInitStep:INT;
xReInit :BOOL;
xInited:BOOL;
xInitError:BOOL;
xInitReset:BOOL;
INDEX:WORD;
SUBINDEX:WORD;
data:ARRAY[0..99]OF BYTE;
data2:ARRAY[0..3]OF BYTE;
uint8Baudrate :USINT;
uint8NodeID :USINT;
strDeviceName:STRING;
strHardwareVersion:STRING;
strFirmwareVersion:STRING;
setValue:DINT;
iSDOReadPollingStep:INT;
xSensorSetZero: BOOL;
xSensorSetZeroErr: BOOL;
xSensorSetZeroOK: BOOL;
fbTON1,fbTON2:Standard.TON;
END_VAR
VAR
NodeID:INT;
DeviceState:INT;
CANMasterStatus: _3SCOS.CANOPEN_KERNEL_STATE;
DATALENGTH:UDINT;
DATALENGTH2:UDINT;
ERRORINFO:CIA405.SDO_ERROR;
EERR:CIA405.SDO_ERROR;
MODE:CIA405.SDO_MODE;
DEVICE:CIA405.DEVICE:=4;
fbR_TRIG:Standard.R_TRIG;
fbR_TRIG2:Standard.R_TRIG;
fbR_TRIG3:Standard.R_TRIG;
SDO_READ_DATA :CIA405.SDO_READ_DATA;
SDO_READ_DATA2 :CIA405.SDO_READ4;
SDO_WRITE_DATA :CIA405.SDO_WRITE_DATA;
SDO_WRITE_DATA2 :CIA405.SDO_WRITE_DATA;
arrdata000 :ARRAY[0..3]OF BYTE;
xParametersStore:BOOL;

iDummy:INT;
END_VAR

a000SDOInitData

こちらのプログラムは、CET5デバイスの起動時または再初期化要求時に、SDO通信を使用してデバイス情報および通信設定値を読み出す初期化処理です。

SDO_READ_DATA ファンクションブロックにより、オブジェクトディクショナリの 1008h、1009h、100Ah、3000h、3001h を順番に読み出し、デバイス名、ハードウェアバージョン、ファームウェアバージョン、ボーレート、Node-IDを取得します。

各SDO Read処理はステップ制御により順番に実行され、正常完了時には初期化完了フラグを設定します。処理中にエラーが発生した場合は、初期化エラー状態へ遷移し、SDO通信を停止します

fbR_TRIG3(CLK:=
iInitCounter=0
);

fbR_TRIG2(CLK:=
( xReInit ) AND NOT SDO_READ_DATA.ENABLE
);
IF fbR_TRIG2.Q OR fbR_TRIG3.Q THEN
IF TRUE THEN
NodeID:=IoConfig_Globals.SI.NodeID;
iInitStep:=10;
;
END_IF
END_IF;

IF iInitStep > 0 AND TO_INT(SDO_READ_DATA.ERROR)<>0 THEN
iInitStep:=999;
END_IF

CASE iInitStep OF

0:
SDO_READ_DATA.ENABLE:=FALSE;
;
10:
xInited:=FALSE;
xDataIntited:=FALSE;
xInitError:=FALSE;
strDeviceName:=”;
SDO_READ_DATA.INDEX:=16#1008;
SDO_READ_DATA.SUBINDEX:=16#00;
MEM.MemFill(ADR(data),SIZEOF(data),0);
DATALENGTH:=100;
SDO_READ_DATA.ENABLE:=TRUE;
iInitStep:=15;
15:
IF SDO_READ_DATA.CONFIRM THEN
MEM.MemMove(
ADR(data),ADR(strDeviceName)
,uiNumberOfBytes:=TO_UINT(DATALENGTH)
);
SDO_READ_DATA.ENABLE:=FALSE;
iInitStep:=20;
END_IF;
;
20:
strHardwareVersion:=”;
SDO_READ_DATA.INDEX:=16#1009;
SDO_READ_DATA.SUBINDEX:=16#00;
MEM.MemFill(ADR(data),SIZEOF(data),0);
DATALENGTH:=100;
SDO_READ_DATA.ENABLE:=TRUE;
iInitStep:=25;
25:
IF SDO_READ_DATA.CONFIRM THEN
MEM.MemMove(
ADR(data)
,ADR(strHardwareVersion)
,uiNumberOfBytes:=TO_UINT(DATALENGTH)
);
SDO_READ_DATA.ENABLE:=FALSE;
iInitStep:=30;
END_IF;
;
30:
strFirmwareVersion:=”;
SDO_READ_DATA.INDEX:=16#100A;
SDO_READ_DATA.SUBINDEX:=16#00;
MEM.MemFill(ADR(data),SIZEOF(data),0);
DATALENGTH:=100;
SDO_READ_DATA.ENABLE:=TRUE;
iInitStep:=35;
35:
IF SDO_READ_DATA.CONFIRM THEN
MEM.MemMove(
ADR(data)
,ADR(strFirmwareVersion)
,uiNumberOfBytes:=TO_UINT(DATALENGTH)
);
SDO_READ_DATA.ENABLE:=FALSE;
iInitStep:=40;
END_IF;
40:
uint8Baudrate:=0;
SDO_READ_DATA.INDEX:=16#3000;
SDO_READ_DATA.SUBINDEX:=16#00;
MEM.MemFill(ADR(data),SIZEOF(data),0);
DATALENGTH:=100;
SDO_READ_DATA.ENABLE:=TRUE;
iInitStep:=45;
45:
IF SDO_READ_DATA.CONFIRM THEN
MEM.MemMove(
ADR(data)
,ADR(uint8Baudrate)
,uiNumberOfBytes:=TO_UINT(DATALENGTH)
);
SDO_READ_DATA.ENABLE:=FALSE;
iInitStep:=50;
END_IF;
50:
uint8NodeID:=0;
SDO_READ_DATA.INDEX:=16#3001;
SDO_READ_DATA.SUBINDEX:=16#00;
MEM.MemFill(ADR(data),SIZEOF(data),0);
DATALENGTH:=100;
SDO_READ_DATA.ENABLE:=TRUE;
iInitStep:=55;
55:
IF SDO_READ_DATA.CONFIRM THEN
MEM.MemMove(
ADR(data)
,ADR(uint8NodeID)
,uiNumberOfBytes:=TO_UINT(DATALENGTH)
);
SDO_READ_DATA.ENABLE:=FALSE;
iInitStep:=60;
END_IF;
60:
iInitStep:=899;

899:
iInitStep:=900;
900:
xInited:=TRUE;
iTestCounter:=iTestCounter+1;
xDataIntited:=TRUE;
iInitCounter:=iInitCounter+1;

999:
xInitError:=TRUE;
SDO_READ_DATA.ENABLE:=FALSE;
IF xInitReset THEN
xInitError:=FALSE;
iInitStep:=0;
END_IF
;


END_CASE

a100CANBusStatus

こちらのプログラムは、CANopen Managerおよび対象デバイスの通信状態を取得し、必要に応じてCANバスアラームをリセットします。また、CET5からPDOで受信した4バイトの位置データを、2つのINT16値として Position1 および Position2 に展開します。CET5の位置データ分解能は0.1 mmであるため、取得した整数値を10で除算し、mm単位の実位置データ rPosition1、rPosition2 として扱います。

CANMasterStatus:=IoConfig_Globals.CANopen_Manager.KernelState;
DeviceState:=TO_INT(IoConfig_Globals.SI.CANopenState);

IF xBusReset THEN
IoConfig_Globals.CANbus.ResetBusAlarm();
END_IF

a200PDO

MEM.MemMove(ADR(gTSM.CET5_0_0),ADR(Position1),SIZEOF(Position1));
MEM.MemMove(ADR(gTSM.CET5_0_0[2]),ADR(Position2),SIZEOF(Position2));
rPosition1:=TO_REAL(Position1)/10.0;
rPosition2:=TO_REAL(Position2)/10.0;

a300SDOWrite

こちらはSDO経由でパラメータ書くのプログラムを呼び出します。

a310SetZero();
a399StoreParams();

a310SetZero

こちらのプログラムは、ゼロ点設定要求 xSensorSetZero の立ち上がりを検出し、SDO_WRITE_DATA ファンクションブロックによるSDO書き込みを実行します。SDO書き込みが正常に完了した場合は xSensorSetZeroOK を TRUE とし、エラーが発生した場合は xSensorSetZeroErr を TRUE とします。処理完了後またはエラー発生時には、SDO_WRITE_DATA.ENABLE を FALSE に戻し、次回の要求に備えます。

fbR_TRIG(CLK:=xSensorSetZero);

IF fbR_TRIG.Q THEN
SDO_WRITE_DATA.ENABLE:=TRUE;
END_IF

IF SDO_WRITE_DATA.CONFIRM THEN
xSensorSetZeroOK:=TRUE;
SDO_WRITE_DATA.ENABLE:=FALSE;
xSensorSetZeroErr:=FALSE;
END_IF

IF TO_INT(SDO_WRITE_DATA.ERROR) <> 0 THEN
xSensorSetZeroOK:=FALSE;
SDO_WRITE_DATA.ENABLE:=FALSE;
xSensorSetZeroErr:=TRUE;
END_IF

a399StoreParams

こちらのプログラムは、パラメータ保存コマンドに使用する文字列 “save” をバイト配列 arrdata000 に設定します。このデータを SDO_WRITE_DATA2 により 1010h:01h へ書き込むことで、センサ内部の不揮発性メモリへパラメータ保存を要求します。SDO書き込みが正常に完了した場合は xParametersStoreOK が TRUE となり、エラーが発生した場合は xParametersStoreError が TRUE となります。

arrdata000[0]:=16#73;
arrdata000[1]:=16#61;
arrdata000[2]:=16#76;
arrdata000[3]:=16#65;


xParametersStoreError:=TO_INT(SDO_WRITE_DATA2.ERROR) <>0;
xParametersStoreOK:=SDO_WRITE_DATA2.CONFIRM;

a400SDOPolling

こちらのプログラムでは、CET5デバイスの初期化完了後、SDO通信によりエラー情報を周期的に読み出します。1003h:00h からエラー履歴に登録されているエラー数を取得し、1001h:00h からError Registerの状態を取得します。

正常時は500ms周期で読み出しを繰り返し、SDO通信エラーが発生した場合は一度SDO Readを停止した後、500ms待機して再試行します。

IF iSDOReadPollingStep > 0 AND TO_INT(SDO_READ_DATA2.ERROR)<>0 THEN
iSDOReadPollingStep:=999;
END_IF

CASE iSDOReadPollingStep OF

0:
SDO_READ_DATA2.ENABLE:=FALSE;
IF xInited THEN
iSDOReadPollingStep:=10;
END_IF
;
10:
NumbeOfErrors:=0;
SDO_READ_DATA2.INDEX:=16#1003;
SDO_READ_DATA2.SUBINDEX:=16#00;
MEM.MemFill(ADR(data2),SIZEOF(data2),0);
DATALENGTH:=100;
SDO_READ_DATA2.ENABLE:=TRUE;
iSDOReadPollingStep:=15;
15:
IF SDO_READ_DATA2.CONFIRM THEN
MEM.MemMove(
ADR(data2),ADR(NumbeOfErrors)
,uiNumberOfBytes:=TO_UINT(DATALENGTH)
);
SDO_READ_DATA2.ENABLE:=FALSE;
iSDOReadPollingStep:=20;
END_IF;
;
20:
ErrorRegister:=0;
SDO_READ_DATA2.INDEX:=16#1001;
SDO_READ_DATA2.SUBINDEX:=16#00;
MEM.MemFill(ADR(data2),SIZEOF(data2),0);
DATALENGTH:=100;
SDO_READ_DATA2.ENABLE:=TRUE;
iSDOReadPollingStep:=25;
25:
IF SDO_READ_DATA2.CONFIRM THEN
MEM.MemMove(
ADR(data2),ADR(ErrorRegister)
,uiNumberOfBytes:=TO_UINT(DATALENGTH)
);
SDO_READ_DATA2.ENABLE:=FALSE;
iSDOReadPollingStep:=60;
END_IF;
;
60:
iSDOReadPollingStep:=899;

899:
fbTON1(IN:=TRUE,PT:=T#500MS);
IF fbTON1.Q THEN
fbTON1(IN:=FALSE);
iSDOReadPollingStep:=10;
END_IF

999:
fbTON2(IN:=TRUE,PT:=T#500MS);
IF fbTON2.Q THEN
fbTON2(IN:=FALSE);
iSDOReadPollingStep:=10;
SDO_READ_DATA2.ENABLE:=FALSE;
END_IF
;


END_CASE


SDO_READ_DATA2.NETWORK:=1;

SDO_READ_DATA2(
NETWORK:=
,ENABLE:=
,TIMEOUT:=0
,CONFIRM=>
,ERROR=>EERR
,CHANNEL:=
,DEVICE:=IoConfig_Globals.SI.NodeID
,INDEX:=
,SUBINDEX:=
,DATA=>data2
,DATALENGTH=>DATALENGTH2
,ERRORINFO=>ERRORINFO
)
;

a990HMI

こちらのプログラムでは、CET5デバイスから取得した情報、通信状態、位置データ、エラー情報、および操作結果をHMI用グローバル変数 gHMI に転送します。

また、HMI側からの操作要求をPLC内部の制御変数へ反映します。

gHMI.TSM_4_strDeviceName:=strDeviceName;
gHMI.TSM_4_strFirmwareVersion:=strFirmwareVersion;
gHMI.TSM_4_strHardwareVersion:=strHardwareVersion;

gHMI.arrri[0]:=uint8NodeID;
gHMI.arrri[1]:=uint8Baudrate;
gHMI.arrri[2]:=iInitStep;
gHMI.arrri[3]:=DeviceState;
gHMI.arrri[4]:=TO_INT(CANMasterStatus);
gHMI.arrri[5]:=iSDOReadPollingStep;
gHMI.arrri[6]:=NumbeOfErrors;
gHMI.arrri[7]:=ErrorRegister;

gHMI.arrr32[0]:=rPosition1;
gHMI.arrr32[1]:=rPosition2;

gHMI.arrrx[0]:=xDataIntited;
gHMI.arrrx[1]:=xInitError;
gHMI.arrrx[2]:=xSensorSetZeroOK;
gHMI.arrrx[3]:=xSensorSetZeroErr;
gHMI.arrrx[4]:=xParametersStoreOK;
gHMI.arrrx[5]:=xParametersStoreError;

xReInit:=gHMI.arrwx[0];
xSensorSetZero:=gHMI.arrwx[1];
xParametersStore:=gHMI.arrwx[2];
xBusReset:=gHMI.arrwx[3];

a999BlockCall

こちらのプログラムでは、初期化用SDO読み出し、エラー情報ポーリング用SDO読み出し、ゼロ点設定用SDO書き込み、およびパラメータ保存用SDO書き込みの各ファンクションブロックを呼び出します 。

SDO_READ_DATA.NETWORK:=1;

SDO_READ_DATA(
NETWORK:=
,ENABLE:=
,TIMEOUT:=0
,CONFIRM=>
,ERROR=>EERR
,CHANNEL:=0
,DEVICE:=IoConfig_Globals.SI.NodeID
,INDEX:=
,SUBINDEX:=
,MODE:=MODE
,DATA:=ADR(data)
,DATALENGTH:=DATALENGTH
,ERRORINFO=>ERRORINFO
)
;

SDO_READ_DATA2.NETWORK:=1;

SDO_READ_DATA2(
NETWORK:=
,ENABLE:=
,TIMEOUT:=0
,CONFIRM=>
,ERROR=>EERR
,CHANNEL:=
,DEVICE:=IoConfig_Globals.SI.NodeID
,INDEX:=
,SUBINDEX:=
,DATA=>data2
,DATALENGTH=>DATALENGTH2
,ERRORINFO=>ERRORINFO
)
;

SDO_WRITE_DATA(
NETWORK:=1
,DEVICE:=4
,CHANNEL:=0
,INDEX:=16#6003
,SUBINDEX:=0
,Data:=ADR(setValue)
,DATALENGTH:=SIZEOF(setValue)
);

SDO_WRITE_DATA2(
NETWORK:=1
,ENABLE:=xParametersStore
,DEVICE:=4
,CHANNEL:=0
,INDEX:=16#1010
,SUBINDEX:=1
,Data:=ADR(arrdata000)
,DATALENGTH:=SIZEOF(arrdata000)
);

Download

最後はOnline→LoginでプロジェクトをCodesys RuntimeにDownloadしましょう。

結果

Codesys RuntimeとTSM CET5センサーが通信成立できました。

EXOR側

次はEXOR側のHMIを構築します。

画面

こちらは今回記事作成した画面です。

LED変数

今回は使用しなかったが、XA5専用のLED変数を定義しました。

結果

こちらの動画で動作確認できます。

ダウンロード

今回記事で作成したプロジェクトを下記のLinkからダウンロードできます。

https://github.com/soup01Threes/Codesys/blob/main/Demo_TSM_CET5_XA5.zip

シェアする

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

フォローする