3Eフレームの電文構造を1バイトずつ読む(バイナリ/ASCII)
MCプロトコル(SLMP)の 3E フレームで、要求電文と応答電文が何バイト目に何を持つのかを三菱電機マニュアルの実例をもとに1バイトずつ読み解きます。リトルエンディアンの落とし穴、ASCII との違い、iQ-R 向けのサブコマンドも扱います。
更新
3E フレームの要求電文は、大きく3つの部分に分かれます。どの PLC に送るか(あて先)、この後に何バイト続くか(長さ)、何をしてほしいか(コマンドとデータ)です。この記事では、マニュアルに載っている「M100〜M131 をワード単位で読む」例を使って、バイナリの電文を先頭から順に読んでいきます。
要求電文の中身
バイナリの 3E フレームの要求電文は、次の順に並びます。値は、接続した PLC 自身にアクセスする場合のものです。
| 項目 | バイト数 | 値 | 電文上のバイト |
|---|---|---|---|
| サブヘッダ | 2 | 3E フレームの要求 | 50 00 |
| ネットワーク番号 | 1 | 自局 | 00 |
| PC 番号(要求先局番) | 1 | 自局 | FF |
| 要求先ユニット I/O 番号 | 2 | 03FF(自局の CPU) | FF 03 |
| 要求先ユニット局番号 | 1 | マルチドロップなし | 00 |
| 要求データ長 | 2 | 監視タイマから最後までのバイト数 | 例 0C 00 |
| 監視タイマ | 2 | 250 ms 単位 | 例 10 00(4 秒) |
| コマンド | 2 | 一括読出しは 0401 | 01 04 |
| サブコマンド | 2 | ワード単位は 0000 | 00 00 |
| 要求データ | 可変 | コマンドごとに決まる |
あて先の4項目(ネットワーク番号から要求先ユニット局番号まで)は、自局にアクセスするなら 00 FF FF 03 00 で固定です。マルチ CPU システムの2号機に送る場合は I/O 番号が 03E1 になる、といった違いはありますが、最初はこの値を覚えておけば足ります。
監視タイマは、PLC が処理を終えるまで待つ上限時間です。0000 にすると処理が終わるまで無限に待ちます。マニュアルは、自局へのアクセスなら 0001〜0028(0.25〜10 秒)を推奨しています。
実際の電文を読む
マニュアルの設定例では、M100〜M131 の32点をワード単位で2ワード分読み出しています。要求電文は次の21バイトです。
50 00 サブヘッダ 3E 要求00 ネットワーク番号 自局FF PC 番号 自局FF 03 I/O 番号 03FF00 局番号 0C 00 要求データ長 = 12 バイト10 00 監視タイマ 16 × 250 ms = 4 秒01 04 コマンド 0401 一括読出し00 00 サブコマンド ワード単位64 00 00 先頭デバイス 10090 デバイスコード M02 00 点数 2 ワード後半の要求データ(64 00 00 90 02 00)が、一括読出しコマンドの中身です。
64 00 00:先頭デバイス番号。100 を16進にした64を3バイトで表す90:デバイスコード。M は9002 00:点数。2ワード
要求データ長の 0C 00 は 12 バイトです。監視タイマ(2)+コマンド(2)+サブコマンド(2)+要求データ(6)=12 になります。
バイナリは下位バイトが先に来る
一番つまずきやすいのは、バイトの並び順です。バイナリの電文では、2バイト以上の数値を下位バイトから先に送ります(リトルエンディアン)。
- コマンド
0401は01 04と送る - I/O 番号
03FFはFF 03と送る - デバイス番号 100(16進で
000064)は64 00 00と送る
応答電文
PLC からの応答は次のようになります。
D0 00 サブヘッダ 3E 応答00 ネットワーク番号 自局FF PC 番号 自局FF 03 I/O 番号 03FF00 局番号 06 00 応答データ長 = 6 バイト00 00 終了コード 正常終了34 12 M100〜M115 1234H02 00 M116〜M131 0002H応答のサブヘッダは D0 00 です。あて先の4項目は要求と同じ値が返ってきます。
応答データ長の 06 00 は、終了コードから最後までのバイト数です。終了コード(2)+データ(4)=6 になります。
終了コードの 00 00 は正常終了を表します。0 以外のときはエラーで、その読み方はエラーコードの記事で扱います。
読み出したデータ 34 12 02 00 も、ワードごとに下位バイトが先です。M100〜M115 が 1234、M116〜M131 が 0002 になります。
ASCII コードの場合
同じ読み出しを ASCII コードで送ると、各項目を16進の文字列にして、上位の桁から並べます。
5000 サブヘッダ 00 ネットワーク番号 FF PC 番号 03FF I/O 番号 00 局番号 0018 要求データ長 = 24 文字0010 監視タイマ 0401 コマンド 0000 サブコマンド M* デバイスコード 000100 先頭デバイス 10 進のまま0002 点数 D000 サブヘッダ 00 ネットワーク番号 FF PC 番号 03FF I/O 番号 00 局番号 000C 応答データ長 = 12 文字0000 終了コード 1234 M100〜M115 0002 M116〜M131 違いは3つです。
- 並び順が逆になる。コマンドは
0401の文字列そのまま - 桁数が倍になる。1バイトの項目は2文字、2バイトの項目は4文字で表す
- デバイスの書き方が変わる。デバイスコードは
M*のように記号の2文字、デバイス番号は000100のように6桁で表す。バイナリと違い、M や D のような10進のデバイスは10進のまま書く
要求データ長も文字数で数えます。監視タイマ(4文字)+それ以降(20文字)=24 なので 0018 です。
ASCII は電文を目で読みやすい反面、データ量がバイナリの約2倍になります。
デバイスコードとサブコマンド
デバイスコードは、デバイスの種類を表す番号です。よく使うものを挙げます。
| デバイス | コード | デバイス | コード |
|---|---|---|---|
| X(入力) | 9C | D(データレジスタ) | A8 |
| Y(出力) | 9D | W(リンクレジスタ) | B4 |
| M(内部リレー) | 90 | R(ファイルレジスタ) | AF |
| L(ラッチリレー) | 92 | ZR(ファイルレジスタ) | B0 |
| B(リンクリレー) | A0 | TN(タイマ現在値) | C2 |
| SM(特殊リレー) | 91 | SD(特殊レジスタ) | A9 |
MELSEC iQ-R にアクセスする場合は、サブコマンドを 0002(ワード単位)や 0003(ビット単位)にした形式も使えます。この形式では、デバイス番号が4バイト、デバイスコードが2バイトになります(D なら A8 00)。Q/L シリーズ向けの 0000/0001 も iQ-R で互換用に使えます。ただし、ロングタイマなど iQ-R で増えたデバイスは 0002/0003 でしか指定できません。
一度に読める点数には上限がある
一括読出し(0401)で1回に読める点数は、ワード単位で 960 点までです。ビット単位ならバイナリで 7168 点、ASCII で 3584 点までです。これより多く読みたい場合は、要求を分けて送ります。
4E フレームは、先頭にシリアル番号が付くだけ
4E フレームは、3E フレームのサブヘッダの部分が6バイトに増えたものです。
54 00 サブヘッダ 4E 要求34 12 シリアル番号 1234H(任意)00 00 固定値 … ここから先は 3E と同じ 要求に付けたシリアル番号は、応答にもそのまま付いて返ってきます。複数の要求を送ったときに、どの応答がどの要求への返事かを照合できます。応答のサブヘッダは D4 00 です。
次の記事では、終了コードが 0 以外のとき、つまりエラーが返ってきたときの読み方を扱います。
出典
- MELSECコミュニケーションプロトコルリファレンスマニュアル(SH-080003)p.39〜44, 付7 p.471〜474
- SLMPリファレンスマニュアル(SH-080931)p.17〜28, 34〜38, 44