通信プロトコルModbus RTU(スレーブエミュレーター)

テンプレート説明

TC-3000がModbus RTUスレーブとして動作し、デバイスモデル(レジスタ/コイルマップ)に基づいてマスター機器からの要求に応答します。自局アドレス宛かつCRC一致の要求のみ処理し、未対応ファンクションコードや範囲外アドレスには例外応答を返します。

 

  • 1 要求フレーム受信
    シリアル回線上のマスター機器からの要求フレームを待機します。スレーブID・ファンクションコードからフレーム全長を判定して1件受信し、CRCを検証します。
  • 2 デバイスモデル参照・応答
    自局宛の要求をデバイスモデルで処理し、応答PDUを組み立てて返送します。マップに存在しないアドレスや未対応FCには例外応答を返します。他局宛の要求は無視します。
  • 3 テスト停止まで継続
    上記①②をテスト停止まで繰り返します。応答方針は build_response() を編集することで、読取専用レジスタや意図的な異常応答などDUT固有の挙動を自由に再現できます。
初期ユニット配置
 ・スロット1:DIFユニット(TC-IFDIF) ※1
  RS-485(半二重2線)/19200bps/8bit/偶数パリティ/ストップ1bit
ユニットの選択肢

 ・RS-422/RS-485通信:DIFユニット(TC-IFDIF)を使用します。※2

 ・RS-232C(1対1)通信:COMユニット(TC-IFCOM)でも利用できます。※2

※1 ユニットを別スロットへ変更する場合、ユニット設定のスロット割り付け変更を行うことで、設定値などを引き継ぎ可能です。
※2 スロットにユニットを取り付け・配線し、スクリプトの SLOTCH 設定を変更してください。

接続図

TC-3000(DIFユニット)のRS-485端子(A/B)とマスター機器のRS-485端子(A/B)を接続します。TC-3000はデバイスモデルを参照して要求に応答します。

 

マスター機器 Modbus マスター 要求 → 応答受信 RS-485 A / B 終端抵抗(バス終端) RS-485 バス A / B(2線・半二重) ①要求フレーム送信 ④応答フレーム受信 TC-3000(Modbus RTU スレーブ) DIFユニット(TC-IFDIF) Modbus RTU スレーブ 自局ID = 1 RS-485 A / B(UART1) 終端抵抗(ユニット設定) ②解析 ③応答 Luaスクリプト(device) device model 参照・応答生成 マップ / アドレス holding [0x0000] 0x0012 holding [0x0001] 0x0034 input [0x0000] 0x00FF coils [0x0000] 1 coils [0x0001] 0 discrete [0x0000] 1 未定義アドレス 例外0x02 未対応FC 例外0x01

※ 必ずIGNDを接続してください。

※ RS-485バスの両端には終端抵抗が必要です。TC-3000側の終端抵抗はユニット設定で有効にできます。
※ 受信エラー(CRC不一致・未対応FC等)の際は t3.5(フレーム間無音)相当の残留バイトを読み捨てて次フレーム境界へ再同期します。この無音時間は MODBUS_RTU_BAUDRATEMODBUS_RTU_BITS_PER_CHAR から自動算出されます。

設定変数

全設定変数を記載しています。実機の仕様に合わせて変更してください。

変数名

内容

初期値

MODBUS_RTU_BAUDRATE

ボーレート (bps)。t3.5(フレーム間無音)の算出に使用。ユニット設定のボーレートと一致させる。この変数は全てのテストスクリプトから共通で参照されます。

19200

MODBUS_RTU_BITS_PER_CHAR

1文字あたりのビット数。Modbus RTUは通常11(1start+8data+1parity+1stop)。この変数は全てのテストスクリプトから共通で参照されます。

11

SLOT

使用するDIFユニットのスロット番号。使用するユニットに応じて変更。

DIF1

CH

DIFユニットのUARTチャンネル番号

UART1

OWN_ID

自局スレーブアドレス (ID)。この宛先の要求のみ応答する。1〜247

1

RECEIVE_TIMEOUT

要求受信タイムアウト (ms)。この時間受信が無ければ再度受信待機に入る。

5000

device

スレーブが保持するデバイスモデル(メモリマップ)。マスターからのアクセスはこのマップを参照して処理します。各マップに存在しないアドレスへのアクセスには例外応答(0x02)を返します。

マップ 用途
holding_registers 保持レジスタ [アドレス]=16bit値。FC 0x03読出/0x06・0x10書込
input_registers 入力レジスタ(読取専用) [アドレス]=16bit値。FC 0x04読出
coils コイル [アドレス]=0/1。FC 0x01読出/0x05・0x0F書込
discrete_inputs 離散入力(読取専用) [アドレス]=0/1。FC 0x02読出

サンプル有
使用例は接続図参照

グローバル変数の設定

以下の変数はグローバル変数に定義され、全テストスクリプトから共通で参照されます。

変数名

内容

初期値

MODBUS_TIMEOUT_MS

受信・応答関数でタイムアウト引数を省略した場合に使用する既定のタイムアウト (ms)。本テンプレートでは要求受信で RECEIVE_TIMEOUT を明示指定するため、通常この値は使用されません。

1000

MODBUS_RTU_BAUDRATEMODBUS_RTU_BITS_PER_CHAR もグローバル変数に定義されていますが、本テンプレートではテストスクリプト冒頭で値を設定するため「設定変数」の項に記載しています。グローバル変数側の初期値は 0(未設定)で、未設定のまま実行するとエラーになります。

対応ファンクションコード

初期の build_response() が処理するファンクションコード(FC)です。未対応FCには例外応答(0x01 ILLEGAL FUNCTION)、範囲外アドレスには例外応答(0x02 ILLEGAL DATA ADDRESS)を返します。

FC

内容

対象マップ

0x01

コイル読出し

coils

0x02

離散入力(入力ステータス)読出し

discrete_inputs

0x03

保持レジスタ読出し

holding_registers

0x04

入力レジスタ読出し

input_registers

0x05

コイル1点書込み(0xFF00=ON/0x0000=OFF)

coils

0x06

保持レジスタ1点書込み

holding_registers

0x0F

コイル複数書込み

coils

0x10

保持レジスタ複数書込み

holding_registers

※ 本テンプレートはテスト実行ボタンで開始し、テスト停止ボタンで終了します。
※ 要求受信・解析・応答PDU組立・CRC・送信の共通処理はグローバル関数(スクリプト)に定義されています。「どう応答するか」の方針のみ本スクリプトの build_response() で実装します。

他のプロジェクトでModbusを扱う方法

本テンプレートは、Modbusプロトコルの処理をグローバル関数に実装しています。

・要求フレームの受信・解析、応答PDUの組立、CRC-16(Modbus)計算、応答送信など、Modbusプロトコルの実装はすべてグローバル関数(スクリプト)に含まれます
・別のプロジェクトでModbusプロトコルを扱いたい場合は、このテンプレートのグローバル関数(スクリプト)の内容を、対象のプロジェクトのグローバル関数(スクリプト)にコピーすることで、同じModbus関数群(ModbusRtu*ModbusTcp* など)をそのまま利用できます。
・Modbus関数は MODBUS_TIMEOUT_MSMODBUS_RTU_BAUDRATEMODBUS_RTU_BITS_PER_CHAR などのグローバル変数を参照します。あわせて、これらのグローバル変数も対象プロジェクトのグローバル変数に設定してください(「グローバル変数の設定」の項を参照)。
・同ライブラリはModbus RTU(RS-485/RS-422)とModbus TCP(LAN)の両方に対応しています。