Posted at
PLCDay 1

MCプロトコルのチートシート


アドベントカレンダー

夏休みの宿題を直前にやるタイプとバレてしまいました。。


送信と受信について

過去の記事でも書きましたが、TCPを使ったソケット通信です。

設定その他は、こちらの記事を参照下さい。

ここでは、送信・受信したいコマンド例文を上げていきます。

また、フォーマットは3Eフレームとします。


メモリ-レジスタの種類

PLCではデバイスとなっていますが、

PLCをプログラムするときのデバイスを一通り説明します。

以下()カッコ内はデバイスの説明

[]カッコ内はコマンドのコード値です。


  • Xレジスタ (PLCへの入力端子) [X*]

  • Yレジスタ (PLCからの出力値) [Y*]

  • 内部リレー (PLCでビット値として使用できる) [M*]

  • ラッチリレー (停電時にも保持されるビット) [L*]

  • アナンシェータ (警報用特殊リレー) [F*]

  • エッジリレー (入力の立ち上がり時のみON、その後自動OFF) [V*]

  • リンクリレー (GOTなどの外部デバイスと同期) [B*]

  • データレジスタ (16bitのデータ保存レジスタ) [D*]

  • リンクレジスタ (リレーと同じく外部デバイス同期 16bit) [W*]

  • タイマー (順に入力-出力-現在値) [TS][TC][TN]

  • 積算タイマー (順に入力-出力-現在値) [SS][SC][SN]

  • カウンタ (順に入力-出力-現在値) [CS][CC][CN]

  • インデックスレジスタ (数値オフセット用の特殊レジスタ) [Z*]

  • ファイルレジスタ (データ保存用の記憶領域) [ZR*][R*]

PLCをいじっている人なら、わかるかもしれませんが、

特殊レジスタ以外は変更・取得することが出来ます。

この為、制御中のPLCにも介入して実行できるため、

セキュリティには十分気をつける必要があります。


PLCとの通信タイミング

1スキャンが完了し、データ更新が完了した後のタイミングで行われます。

プログラム感覚的は、1ループの終わり、次回ループ前のイメージです。


  • スキャン

一般的なプログラムですと、変数への代入は1行毎に行われ・・・

例えば、


A=10

B=A

C=B


と何かの言語で1ループ行うと、ABCすべて10になります。

ですが、PLCの場合 1回のループ(=スキャン)では、まず計算結果の予約が行われ、

EOLまで進んだ後一斉に変化を行います。

つまり、

1回のループ(=スキャン)後にはA=10, B=null, C=nullの状態になり

2回目でA=10,B=A,C=null、

3回目でA=B=C=10となります。

※コマンドについてはすべてスペースなしです。

 ここでは見やすくスペースを入れることとします。


ヘッダフレームの指定


4Eフレームの場合

5400 1234 0000

5400 : 4Eフレーム送信であることを定義

1234 : 任意シリアル番号 PLC返答分に盛り込まれて、どのPLCかわかります。

0000 : 空き 0固定


3Eフレームの場合

5000

5000 : 3Eフレームを定義


アクセス範囲指定


4Eと3Eフレームの場合

00 FF 03FF 00

00 : ネットワーク番号

FF : PC番号

03FF : 要求先 I/O番号

00 : 要求先ユニット番号

PLCにEtherポートが1つの場合、上記にてOK

複数ポートにて他のPLCと繋がっている場合、

PLCの設定と同じく指定する。


送信データ長

このコマンド以降のデータ長さ(文字数)を16進で伝える

5000 00FF 03FF 00 0018 0020 1401 0000 D*00 0000 0001

上記なら

0020 0401 0000 D*00 0000 0001

24文字 = 0018


監視タイマー

命令文実行完了までのウォッチドッグ。

250msec =0.25sec単位で指定

16進数


0020 = 0.25 x 32 = 8sec



コマンド

ここの数値で書き込みか、読み込みか、連続か個別かを指定します。

前半が読み書きコマンド、

後半がサブコマンド

0401 0000 : ワード単位 16bit 一括読み出し(連続範囲指定)

0401 0001 : ビット単位 一括読み出し(連続範囲指定)

1401 0000 : ワード単位 16bit 一括書き込み(連続範囲指定)

1401 0001 : ビット単位 一括書き込み(連続範囲指定)

0403 0000 : ワード単位 読み出し ランダムアドレス指定

0403 0002 : ダブルワード単位 読み出し ランダムアドレス指定

0406 0000 : ブロック単位の読み出し ランダムアドレス指定

1406 0000 : ブロック単位の書き込み ランダムアドレス指定

ここからはコマンドに応じたコードになる。

例えば、

0401 0000 D*00 0001 0001 = D001から1ワード分を読み出し

1401 0000 ZR00 0001 0001 00c3 = ZR01に1ワード"00c3"を書き込み

0403 0000 0002 0000 D*00 0050 D*00 0076 = ランダムワード読み出し D050とD076 ダブルワードなし


受信データ

一例

D000 00 FF 03FF 00 000C 0000 1234 5678

D000 : 固定文

00 : ネットワーク番号

FF : PC番号

03FF : 要求先ユニットI/O番号

00 : 要求先ユニット 局番

000c : 以降のデータ長 "0000 1234 5678" = 12

0000 : 終了コード エラーの場合は C051となる

1234 5678 : 2ワード分のデータ

 ※1ワードかもしれないし、1ダブルワードかもしれない

  要求した本人だけがわかる。


最後に

ざっくりとした説明になってしまったが、

個人的には少量なら関数を作成し、

1ワードずつ読み書きしたほうがややこしくならないと感じます。

読み出し数が多い場合、PLC側で使用していない領域 D3000~D7000などに

コピー情報を並べておき、一括で読み出すことでオーバーヘッドの少ない通信になると考えます。

重要なのは現状の処理を邪魔しないことなので、

テスト環境で負荷試験を行うことをおすすめします。