Modbusデバイス
回路図エディタの Modbus デバイス コンポーネントの説明。
Modbusプロトコルの概要
Modbusは、長年使用されている産業用シリアル通信プロトコル規格です。このプロトコルは、主にシングルポイント(1ビット)または16ビットデータレジスタとしてデータ転送を行うための機能コードとエンコード方式を定義します。Typhoon HIL Modbusクライアントは、基本的な16ビットレジスタに加えて、32ビットと64ビットの両方のレジスタの読み書きをサポートしています。この基本データパケットは、Modbus ASCII、RTU、またはTCPのプロトコル仕様に従ってカプセル化されます。Modbus/TCPプロトコルは、Typhoon HILツールチェーンに実装されています。
Modbusはマスター/スレーブプロトコルとして定義されており、マスターとして動作するデバイスは、スレーブとして動作する1つ以上のデバイスをポーリングします。つまり、スレーブデバイスは自発的に情報を送信することができず、要求されるまで待機する必要があります。マスターはスレーブデバイスのレジスタにデータの書き込みと読み取りを行います。
Modbus/TCPでは、イーサネットがピアツーピア通信を可能にするため、マスターとスレーブの定義が曖昧になります。クライアントとサーバーの定義は、イーサネットベースのネットワークではよりよく知られています。この文脈では、スレーブがサーバー、マスターがクライアントになります。
Modbus プロトコルでは 4 種類のレジスタが定義されており、表 1にリストされています。
レジスタータイプ | アクセス | サイズ |
---|---|---|
コイル(ディスクリート出力) | 読み書き | 1ビット |
離散入力 | 読み取り専用 | 1ビット |
入力レジスタ | 読み取り専用 | 16ビット |
保有レジスター | 読み書き | 16ビット |
Modbusプロトコルは、レジスタに対して実行できる一連の関数を定義します。Typhoon HILツールチェーンでサポートされている関数は、表2に示されています。
関数型 | 関数名 | |
---|---|---|
データアクセス | 1ビットアクセス | 離散入力の読み取り |
コイルを読む | ||
シングルコイルを書く | ||
複数のコイルを書く | ||
16ビットアクセス | 入力レジスタの読み取り | |
保持レジスタの読み取り | ||
単一保持レジスタへの書き込み | ||
複数の保持レジスタへの書き込み | ||
複数のレジスタの読み取り/書き込み | ||
16~64ビットアクセス | 入力レジスタの読み取り(詳細) | |
保持レジスタの読み取り(詳細) | ||
レジスタ書き込みアドバンス |
Modbus プロトコルは、Typhoon HIL デバイス ( HIL402、HIL101、HIL404、HIL602+、HIL604、HIL506、HIL606)でサポートされています。
Modbusデバイスコンポーネント
「通信」タブにあるModbusデバイスコンポーネントは、Modbus TCPサーバー(スレーブ)機能を実装します。コンポーネントダイアログウィンドウでは、さまざまなプロパティを定義します。

Modbus デバイス コンポーネントのプロパティは、[全般]、 [ネットワーク設定] 、 [詳細設定] 、 [障害タブ]の 4 つのセクション (タブ) に分かれています。
一般タブ
Modbus設定プロパティを通じて、プロトコルのあらゆる側面を定義できます。このプロパティは、通常、モデル/モデル初期化ウィンドウ内の名前空間を通じて定義されます。設定は、表3に定義されているフィールドを持つPython辞書形式で定義されます。
実行速度は信号処理の実行速度であり、回路図の残りの部分と互換性がある必要があります。
ネットワーク設定タブ
Ethernetポートプロパティは、ModbusサーバーアプリケーションがHILデバイス背面のどのEthernetポートを使用するかを定義します。第4世代デバイス(HIL101、HIL404、HIL506、HIL606)では、利用可能なポートであればどれでも通信に使用できますが、それ以前のデバイスではポート1経由の通信のみがサポートされます。
ネットワーク設定は、構成辞書、ダイアログ ウィンドウ、または SCADA を通じて定義できます。
デフォルトでは、ネットワーク設定は構成辞書から取得されます。各パラメータに対応する辞書フィールドについては、表3を参照してください。
同じレジスタマップを持ちながらIPアドレスが異なる複数のModbusサーバーがある場合、ダイアログウィンドウからネットワーク設定を定義するのが便利です。重複する設定を作成する代わりに、1つの設定を定義し、すべてのコンポーネントのネットワーク設定を個別に変更できます。この方法でネットワーク設定を定義すると、Schematic APIを使用してパラメータを変更することもできます。
SCADA経由でネットワーク設定を定義すると、ネットワーク上でどのIPアドレスが使用されているか不明な場合に便利です。設定を変更してモデルを再コンパイルする代わりに、シミュレーション開始前にSCADAでパラメータを変更できます。パラメータソースとしてSCADAを選択すると、SCADAウィンドウからアクセスできるSCADA入力コンポーネントが作成されます。これは図2に示されています。

重要な点として、パラメータはシミュレーション中にいつでも変更できますが、変更した値はシミュレーション開始時にのみ適用されます。シミュレーション中にパラメータを変更しても、現在のシミュレーションには影響しません。いつでも変更できるパラメータはスレーブIDのみです。
このようにネットワーク設定を定義すると、HIL API を使用してパラメータを変更することも可能になります。
詳細タブ
「パイプラインを有効にする」プロパティが選択されている場合、Modbusサーバーは、前のリクエストをまだ処理していない場合でも、複数のクライアントリクエストを受信できます。パイプラインが無効になっている場合、Modbusサーバーは現在のリクエストが処理された後にのみ、新しいリクエストをリッスンします。
「IPアドレスポートを表示」プロパティを選択すると、Modbus IPアドレスがシミュレーションに渡されるコンポーネントにip_addrという新しいポートが表示されます。これは、設定で動的IP割り当てオプションが有効になっている場合にModbusサーバーのIPアドレスを表示したり、Modbusサーバーが起動しているかどうかを確認したりするのに便利です。値は長さ4のベクトルで、IPアドレス「192.168.0.150」の場合、[192, 168, 0, 150]の形式となります。
ip_addrポートは、Modbus サーバーが起動して実行されていることを確認するためにも使用できます。
「要求カウンタポートの表示」プロパティは、クライアントからのさまざまな要求を追跡するのに役立ちます。 「読み取りカウンタポート」 、 「読み取りカウンタポート(個別)」 、 「書き込みカウンタポート」、 「書き込みカウンタポート(個別)」 、 「両方のカウンタポート」 、 「両方のカウンタポート(個別)」 、または「関数コードカウンタポート」を選択すると、コンポーネントにread_cnt 、 write_cnt 、またはfnc_code_cntという追加ポートが作成されます。これらのポートを使用することで、サーバーがクライアントから受信した読み取り/書き込み要求の数を確認できます。これは、シミュレーションで通信リンクがアクティブかどうかを確認する必要がある場合に役立ちます。
読み取りカウンタ ポートと読み取りカウンタ ポート (個別)の違いは、読み取り要求のカウント方法です。 どちらのプロパティ値でもread_cntが作成されますが、そのポートの次元はプロパティ値によって異なります。読み取りカウンタ ポートが選択されている場合、ポートの次元は 1 になり、すべての読み取り要求が一緒にカウントされます。つまり、カウンタ値は読み取り要求を受信するたびに 1 ずつ増加します。読み取りカウンタ ポート (個別)が選択されている場合、 read_cntポートの次元は 4 になり、各レジスタ タイプの読み取り要求が個別にカウントされます。 read_cnt[0]はコイル読み取り要求をカウントし、 read_cnt[1]はディスクリート読み取り要求をカウントし、 read_cnt[2]は Holding を読み取り、 read_cnt[3]は入力レジスタ要求を読み取ります。 同じことが、書き込みカウンタ ポートと書き込みカウンタ ポート (個別) のプロパティ値にも当てはまります。唯一の違いは、 write_cntが書き込みカウンタポート(個別)に対して次元2を持つことであり、 write_cnt[0]はコイルレジスタへの書き込みをカウントし、 write_cnt[1]は保持レジスタへの書き込みをカウントします。
- fnc_code_cnt[0] - 0x01 コイル読み取り
- fnc_code_cnt[1] - 0x02 ディスクリート入力の読み取り
- fnc_code_cnt[2] - 0x03 保持レジスタの読み取り
- fnc_code_cnt[3] - 0x04 入力レジスタの読み取り
- fnc_code_cnt[4] - 0x05 シングルコイル書き込み
- fnc_code_cnt[5] - 0x06 単一レジスタ書き込み
- fnc_code_cnt[6] - 0x0F 複数コイル書き込み
- fnc_code_cnt[7] - 0x10 複数のレジスタへの書き込み
- fnc_code_cnt[8] - 0x17 複数のレジスタの読み取り/書き込み
障害タブ
Modbus サーバー コンポーネントでは、2 種類の通信障害をシミュレートできます。
メッセージ遅延障害は、サーバーからクライアントへの応答に遅延を挿入します。サーバーはリクエストを受信すると、指定された時間待機してから応答を送信します。メッセージ遅延プロパティの値は、 ModelまたはSCADA のいずれかです。 Modelを選択した場合は、コンポーネントに新しいターミナルmsg_delayが作成され、外部信号を接続できるようになります。 SCADA値を選択した場合は、 Message delayという名前の SCADA 入力コンポーネントがサーバーコンポーネント内に作成され、シミュレーションの実行中に SCADA ウィンドウからこの値を変更できます。遅延値は 1 マイクロ秒単位で指定します。有効な範囲は 0 ~ 1800 秒です。
接続損失障害が発生している場合は、サーバーへのすべての接続が閉じられ、障害が発生している間は新しいリクエストは受け入れられません。障害が解消されると、サーバーは新しい接続を受け入れることができます。接続損失プロパティの値は、 ModelまたはSCADA のいずれかです。 Modelを選択した場合は、外部信号を接続できるように、コンポーネント上に新しい端末conn_lossが作成されます。 SCADA値を選択した場合は、 Connection lossという名前の SCADA 入力コンポーネントがサーバーコンポーネント内に作成され、シミュレーションの実行中に SCADA ウィンドウからこの値を変更できます。有効な値は、障害なしの場合は 0、アクティブな障害の場合は 1 です。
Modbus構成
Modbusデバイス設定は、定義済みフィールドを持つPython辞書として定義されます。この辞書は通常、モデル初期化スクリプトまたはコンポーネントマスクを通じて名前空間内で定義されます。
- ネットワークパラメータ- これらのフィールドを通じて、IPアドレス、ネットマスク、ポート、ゲートウェイなどの値が定義されます。
- レジスタマップ- これらのフィールドを通して、レジスタのアドレス、型、値などが定義されます。レジスタマップには2つのバージョンがあります。バージョン1は機能が少ないシンプルなバージョンですが、バージョン2では、各レジスタの最小値、最大値、スケール値などの機能を定義できます。これらのバージョンについては、「レジスタマップ バージョン1」および「レジスタマップ バージョン2」で説明します。
- 追加パラメータ- 追加の設定を定義するために使用されます
各パラメータの詳細については表3に記載されています。
グループ(場所) | パラメータ | M/O* | 説明 |
---|---|---|---|
ネットワークパラメータ(ネットワーク設定タブ) | IPアドレス | M |
デバイスのIPアドレス(ネットワークによって異なります)。IPアドレスは静的(例:「192.168.0.50」)または動的(例:「dynamic:50」)として定義できます。IPアドレスが動的に定義されている場合、Modbusアプリケーションはネットワーク上で最初に空いているIPアドレスを探し、そのアドレスを使用しようとします。これは、応答がなくなるまでネットワーク上でpingを実行することで実行されます。「dynamic:50」の数字50は、pingが192.168.0.50アドレス(より正確にはxxx.xxx.xxx.50。IPアドレスの最初の3つのセグメントはネットワークドメインを示します)から開始されることを意味します。 |
ポート | M | 通信ポート番号(Modbusプロトコルのデフォルトは502) | |
ネットマスク | M | サブネットマスク(ネットワークに依存) | |
スレーブID | M | スレーブ識別番号 | |
ゲートウェイ | お |
ネットワークゲートウェイを指定します。 ゲートウェイは、a) xxx.xxx.xxx.xxx 形式、または b) Linuxルートシステムコマンドの 2 つの方法で定義できます。a) のオプションを使用する場合、ルートコマンドは次の形式で自動的に生成されます。 route add -net <specified IP in the form xxx.xxx.xxx.0> netmask <specified netmask> gw <specified gateway> たとえば、IP が 192.168.0.210、ネットマスクが 255.255.255.0、ゲートウェイが 192.168.0.100 の場合、 routeコマンドは次のようになります。 ルート追加 -net 192.168.0.0 ネットマスク 255.255.255.0 ゲートウェイ 192.168.0.100 b) オプションを使用すると、上記の例のようにrouteコマンドを明示的に記述できます。a) オプションを使用する場合、IP アドレスを動的に定義することはできません。 |
|
レジスタマップ V1 (モデル初期化パネル) | コイル入力アドレス | M | コイル入力アドレスのリスト |
コイル出力アドレス | M | コイル出力アドレスのリスト | |
離散入力アドレス | M | 離散入力アドレスのリスト | |
保持レジスタ入力アドレス | M | 保持レジスタの入力アドレスのリスト | |
保持レジスタ出力アドレス | M | 保持レジスタの出力アドレスのリスト | |
入力レジスタアドレス | M | 入力レジスタアドレスのリスト | |
コイル出力初期化 | お | コイル出力レジスタの初期値リスト | |
保持レジスタ出力初期化 | お | 出力レジスタを保持するための初期値のリスト | |
レジスタマップ V2 (モデル初期化パネル) | コイルレジスタ | M | コイルレジスタの定義 |
離散レジスタ | M | 個別レジスタ定義 | |
保有レジスタ | M | 保持レジスタの定義 | |
入力レジスタ | M | 入力レジスタの定義 | |
追加パラメータ(モデル初期化パネル) | スレーブIDエコー | お | Trueの場合、エコーバックするスレーブID値を設定します。それ以外の場合、スレーブIDはslave_idで定義されます(デフォルト値はTrue)。 |
コイル_書き込み_任意の値 | お | False の場合、0xFF00 の値のみが論理 1 として表されます。True の場合、すべての非ゼロ値は論理 1 として表されます (デフォルト値は False) | |
デフォルトデバイス | お | スレーブIDを使用してメッセージをフィルタリングする設定で使用します。受信したスレーブIDがモデル内のどのデバイスとも一致しない場合、「default_device」の値がクライアントに返されます。値はTrue/Falseです。詳細は、スレーブID値を使用したModbusメッセージのフィルタリングをご覧ください。 | |
実装されていないレジスタ例外 | お | 値がTrueに設定されている場合、Modbusサーバーは未実装のレジスタにアクセスする際に例外を返します。値がFalseの場合、サーバーは未実装の1ビットレジスタに対して0を、未実装の16ビットレジスタに対して-1(65535)を返します。デフォルト値はFalseです。 |
レジスタマップバージョン1
レジスタマップ バージョン1は、レジスタマップを定義する古い方法を指します。この方法では、レジスタは文字列形式で定義され、ユーザーはレジスタのアドレスとタイプを定義します。
また、この方法では、コイルレジスタと保持レジスタは入力と出力の2つの部分に分割されます。クライアントからレジスタ値を読み取ると、Modbusデバイスコンポーネントの入力に接続された信号がサンプリングされ、その値がレジスタに書き込まれると、コンポーネントの出力が更新されます。つまり、入力レジスタと出力レジスタは同じレジスタアドレスを持つことはできません。入力値の変化によって出力値が自動的に変化し、望ましくない結果が生じるためです。
コイルおよびディスクリートレジスタのアドレスの定義
コイル レジスタとディスクリート レジスタは、以下に示すように、アドレス値 (0 ~ 65535) のリストによって単純に定義されます。
「コイル入力アドレス」 : 「0, 1, 2, 3, 4」 「コイル出力アドレス」 : 「100, 101, 102, 103, 104」 「離散入力レジスタ」 : 「0, 1, 2, 3, 4」
保持レジスタと入力レジスタのアドレスの定義
入力レジスタと保持レジスタはModbusプロトコルの定義に従って16ビット長ですが、複数のレジスタをグループ化して、異なるタイプの32ビットおよび64ビットレジスタを表すことができます。レジスタは表4に示すように定義できます。
グループに登録する | レジスタータイプ | アドレス値 |
---|---|---|
1(16ビット) |
符号なし整数 整数 |
任意の正の整数値(0~65535) |
2 (32ビット) |
符号なし整数 整数 浮動小数点 |
連続する2つの整数値の配列(0~65535) |
4(64ビット) |
符号なし整数 整数 浮動小数点 |
連続する4つの整数値の配列(0~65535) |
Typhoon HIL コントロール センターでこれがどのように見えるかを示すために、入力レジスタのさまざまな構成を以下に示します。
- すべてのレジスタは、さまざまなタイプの 16 ビット幅です。
"入力レジスタアドレス" : '0, 1, 2i, 3u, 4i, 5, 6, 7u'
- すべてのレジスタは、さまざまなタイプの 32 ビット幅です。
"入力レジスタアドレス" : '[0,1]u, [2,3], [4,5]f, [6,7]i, [8,9]i, [10,11]f' '
- すべてのレジスタは、さまざまなタイプの 64 ビット幅です。
"入力レジスタアドレス" : '[0,1,2,3]f, [4,5,6,7]u, [8,9,10,11]i, [12,13,14,15]'
- レジスタにはさまざまな長さとタイプがあります。
"入力レジスタアドレス" : '[0,1]f, 2u, 3i, [4,5,6,7]f, 8, [9,10]i, [11,12,13,14]u'
レジスタの長さを指定するには、適切な数のアドレスを角括弧で囲むだけです。
レジスタの型を指定するには、アドレス値の後にu(符号なし整数)、i(整数)、またはf(浮動小数点数)を記述します。型が明示的に指定されていない場合、レジスタは符号なし整数として定義されます。レジスタが16ビットまたは32ビットの場合、閉じ括弧の後に型を指定する必要があります。
16 ビット長のレジスタは浮動小数点として定義できません。
レジスタのエンディアンの定義
デバイスによってレジスタのエンディアンが異なります。リトルエンディアンでは最下位ワードがメモリに最初に格納され、ビッグエンディアンは最上位ワードがメモリに最初に格納されます。例えば、32ビットの符号なしレジスタを[0,1]uと定義し、そのレジスタに0xBBBB AAAAという値を書き込むと、値は次のように格納されます。
リトルエンディアン: 0 → 0xAAAA; 1 → 0xBBBB
ビッグエンディアン: 0 → 0xBBBB; 1 → 0xAAAA
デフォルトでは、Typhoon HIL ではレジスタはビッグ エンディアンとして定義されます。
レジスタをリトルエンディアンで定義するには、アドレス順序を[0,1]uではなく[1,0]uに並べ替えます。これにより、最上位ワードがアドレス3に格納され、最下位ワードがアドレス0に格納されるため、リトルエンディアン構成が実現されます。64ビットレジスタにも同様に適用されます。
レジスタの初期値の定義
コイルおよび保持出力レジスタの初期値は、値のリストとして指定できます。初期値が指定されていない場合、レジスタは0で初期化されます。
コイル出力レジスタの値は、整数値またはTrue/False値で指定できます。0以外の整数値はON状態、0はOFF状態を表します。例えば、コイル出力が「0, 1, 2, 3, 4, 5」というアドレスで定義されている場合、初期値は[0, True, 0, 1, -56, 65]と定義でき、これは[OFF, ON, OFF, ON, ON, ON, ON]状態に対応します。
コイル出力レジスタの初期値の数は、指定されたアドレスの数と一致する必要があります。
出力レジスタに保持される値は、レジスタ定義で定義された範囲の値として指定できます。例えば、レジスタが32ビット符号なしレジスタ ([0,1]u) として定義されている場合、指定する値は 0 - 2 32 -1 の範囲でなければなりません。
アドレス「0i, [1,2]u, [3,4,5,6]f」に対する出力レジスタの初期化を保持する例として、[-65, 1244, -0.235]が挙げられます。初期化値の数はアドレスグループの数と同じであり、アドレスの数と同じではないことを強調しておくことが重要です。
レジスタマップバージョン1の例
5 つのCoils_in 、5 つのCoils_out、 5 つのDiscrete Inputs 、8 つのHolding_in、 8 つのHolding_out 、および 8 つの入力レジスタを備えた Modbus デバイス構成の例を以下に示します。
「コイル入力アドレス」 : 「0, 1, 2, 3, 4」 , 「コイル出力アドレス」 : 「100, 101, 102, 103, 104」 , 「離散入力アドレス」 : 「0, 1, 2, 3, 4」 , 「保持レジスタ入力アドレス」 : 「0u, 1i, \ [ 2 , 3 ]u, [ 4 , 5 ]i, [ 6 , 7 ]f, \ [ 8 , 9 , 10 , 11 ]u, [ 12 , 13 , 14 , 15 ]i, [ 16 , 17 , 18 , 19 ]f 」 「保持レジスタ出力アドレス」 : 「100u, 101i, \ [ 102 , 103 ]u, [ 104 , 105 ]i, [ 106 , 107 ]f, \ [ 108 , 109 , 110 , 111 ]u, [ 112 , 113 , 114 , 115 ]i, [ 116 , 117 , 118 , 119 ]f ", "入力レジスタアドレス" : "0u, 1i, \ [ 2 , 3 ]u, [ 4 , 5 ]i, [ 6 , 7 ]f, \ [ 8 , 9 , 10 , 11 ]u, [ 12 , 13 , 14 , 15 ]i, [ 16 , 17 , 18 , 19 ]f ", "coil_output_init" : [ 1 , 0 , 234 , - 121 , False], "holding_register_output_init" : [ 11 , - 12 , 13 , - 6554 , 121.98 , 456696 , 9998424 , - 564.112 ]
レジスタマップバージョン2
レジスタマップ バージョン 2 は、レジスタマップを定義する新しい手法です。この手法では、レジスタは Python リストで定義され、各レジスタは辞書として定義されます。
バージョン 1 と比較して、このバージョンでは、レジスタに対してより多くのパラメータを定義し、入力レジスタと出力レジスタに同じアドレス値を持たせることができるようになりました。
レジスタ マップの例を以下に示します。
"coil_registers": [ {"addr": 0, "io_type": "in", "val_spec": "scada", "init_val": False}, {"addr": 1}, {"addr": 2, "io_type": "inout", "init_val": True} ]
レジスタの種類によって定義できるフィールドは異なりますが、 addrフィールドのみが必須です。以下の表に、各レジスタの種類のすべてのパラメータを示します。各フィールドの説明は表5に定義されています。
レジスタータイプ | フィールド名 | M/O | 許容値 | デフォルト値 |
---|---|---|---|---|
コイルレジスタ | 住所 | M | 0から65535までの整数 | |
名前 | お | ASCII文字列 | 「コイルX」 | |
io_type | お | 「イン」、「アウト」、「インアウト」 | "で" | |
val_spec | お | 「モデル」、「SCADA」、「定数」 | "モデル" | |
初期値 | お | ブール型に変換できる任意の値 | 間違い | |
離散レジスタ | 住所 | M | 0から65535までの整数 | / |
名前 | お | ASCII文字列 | 「離散X | |
io_type | お | "で" | "で" | |
val_spec | お | 「モデル」、「SCADA」、「定数」 | "モデル" | |
初期値 | お | ブール型に変換できる任意の値 | 間違い | |
保有レジスター | 住所 | M | 0から65535までの整数または数値のリスト | |
名前 | お | ASCII文字列 | 「Xを保持」 | |
長さ | お | 1, 2, 4 | 1 | |
データ型 | お | 「int」、「uint」、「float」 | 「int」 | |
語順 | お | 「BE」、「LE」 | "なれ" | |
io_type | お | 「イン」、「アウト」、「インアウト」 | "で" | |
val_spec | お | 「モデル」、「SCADA」、「定数」 | "モデル" | |
初期値 | お | int、uint、またはfloat値 | 間違い | |
分 | お | int、uint、またはfloat値 | なし | |
最大 | お | int、uint、またはfloat値 | なし | |
規模 | お | int、uint、またはfloat値 | 1 | |
入力レジスタ | 住所 | M | 0から65535までの整数または数値のリスト | |
名前 | お | ASCII文字列 | 「Xを保持」 | |
長さ | お | 1, 2, 4 | 1 | |
データ型 | お | 「int」、「uint」、「float」 | 「int」 | |
語順 | お | 「BE」、「LE」 | "なれ" | |
io_type | お | "で" | "で" | |
val_spec | お | 「モデル」、「SCADA」、「定数」 | "モデル" | |
初期値 | お | int、uint、またはfloat値 | 間違い | |
分 | お | int、uint、またはfloat値 | なし | |
最大 | お | int、uint、またはfloat値 | なし | |
規模 | お | int、uint、またはfloat値 | 1 |
- 住所 - 登録住所
- コイルとディスクリートレジスタ- アドレスは整数値として定義されます
- 保持レジスタと入力レジスタ- アドレスは整数値または値のリストとして定義できます。値が整数の場合、レジスタの長さは長さパラメータによって定義されます。値がリストの場合、リスト内の要素数によってレジスタの長さが定義されます(例:[0, 1, 2, 3]は64ビットレジスタを定義します)。
- name - レジスタ名。この名前は、 val_specがscadaとして定義されている場合にのみ実用的です。この場合、この値はSCADAウィンドウに表示される名前を定義します。
- 長さ - レジスタの長さ
- 保持レジスタと入力レジスタ- この値 1、2、または 4 は、レジスタがそれぞれ 16 ビット、32 ビット、または 64 ビットになるかどうかを定義します。
- データ型 - レジスタデータ型
- 保持レジスタと入力レジスタ- このパラメータは、レジスタが整数、符号なし整数、または浮動小数点値を格納するかどうかを定義します。
- 語順 - 語順を覚える
- 保持レジスタと入力レジスタ - このパラメータは、値がリトルエンディアン形式で保存されるか、ビッグエンディアン形式で保存されるかを定義します。
リトルエンディアンでは、最下位ワードがメモリの先頭に格納され、ビッグエンディアンは最上位ワードがメモリの先頭に格納されることを定義します。例えば、ユーザーが32ビットの符号なしレジスタを[0,1]uと定義し、そのレジスタに0xBBBB AAAAという値を書き込んだ場合、値は次のように格納されます。
リトルエンディアン: 0 → 0xAAAA; 1 → 0xBBBB
ビッグエンディアン: 0 → 0xBBBB; 1 → 0xAAAA
- 保持レジスタと入力レジスタ - このパラメータは、値がリトルエンディアン形式で保存されるか、ビッグエンディアン形式で保存されるかを定義します。
- io_type - レジスタの入出力タイプ。
- ディスクリートレジスタと入力レジスタ- これらのレジスタは入力レジスタとしてのみ定義できます。つまり、モデルからの信号をModbusデバイスコンポーネントの入力端子に接続して、レジスタの値を制御することができます。
- コイルおよび保持レジスタ- これらのレジスタは、入力、出力、または入出力レジスタとして定義できます。入力は、入力信号がレジスタ値を制御することを定義し、出力は、レジスタ値がコンポーネントの出力端子で利用可能であることを意味します。レジスタが入出力として定義されている場合、入力に接続されたモデルからの信号を使用して値を制御できるだけでなく、Modbusクライアントを使用して値を変更することもできます。このコンセプトが機能するために、レジスタ値はイベント発生時、つまり入力信号の値が変化した場合、またはクライアント要求を受信したときに更新されます。入力として定義されたレジスタの場合、値は継続的に更新されます。
- val_spec - このパラメータは、レジスタ値の指定方法を定義します。modelは、モデルからの信号を使用して値を制御することを定義します。この値は、コンポーネントに入力、出力、またはその両方を追加します( io_typeによって異なります)。scadaは、SCADA入力コンポーネントを使用して値を制御することを定義します。このコンポーネントは自動的に作成され、その値はSCADAウィンドウから制御できます。constは、レジスタが定数値を持ち、シミュレーションから変更できないことを定義します。
- init_val - レジスタの初期値。レジスタがinまたはin/outとして定義されている場合、またはSCADA制御または定数として定義されている場合に、初期値を定義できます。
- min - レジスタ値の制限。レジスタ値の下限は、 minパラメータを使用して定義できます。この制限は、Modbusコンポーネントとの間で送受信される信号に適用されます。つまり、制限が-1に設定され、クライアントが-5を書き込んだ場合、レジスタの値は-5になりますが、コンポーネントの出力は-1に制限されます。
- max - レジスタ値の制限。レジスタ値の上限は、 maxパラメータを使用して定義できます。この制限は、Modbusコンポーネントとの間で送受信される信号に適用されます。つまり、制限が5に設定され、クライアントが10を書き込んだ場合、レジスタの値は10になりますが、コンポーネントの出力は5に制限されます。
- scale - レジスタ値のスケーリング。スケーリング値は入力レジスタと出力レジスタで異なる方法で適用されます。入力レジスタの場合、入力信号はスケール値で乗算され、レジスタ値に書き込まれます。出力レジスタの場合、レジスタ値はスケール値で除算され、コンポーネントの出力に送られます。
レジスタマップバージョン2の例
10 個のコイル、5 個のディスクリート入力、16 個の保持、および 8 個の入力レジスタを備えた Modbus デバイス構成の例を以下に示します。
"coil_registers": [ {"addr": 0, "io_type": "in"}, {"addr": 1, "io_type": "in"}, {"addr": 2, "io_type": "in"}, {"addr": 3, "io_type": "in"}, {"addr": 4, "io_type": "in"}, {"addr": 100, "io_type": "out", "init_val": 1}, {"addr": 101, "io_type": "out", "init_val": 0}, {"addr": 102, "io_type": "out", "init_val": 234}, {"addr": 103, "io_type": "out", "init_val": -121}, {"addr": 104, "io_type": "out", "init_val": False}, ], "discrete_registers": [ {"addr": 0}, {"addr": 1}, {"addr": 2}, {"addr": 3}, {"addr": 4}, ] "holding_registers": [ {"addr": 0, "length": 1, "data_type": "uint", "io_type": "in"}, {"addr": 1, "length": 1, "data_type": "int", "io_type": "in"}, {"addr": 2, "length": 2, "data_type": "uint", "io_type": "in"}, {"addr": 4, "length": 2, "data_type": "int", "io_type": "in"}, {"addr": 6, "length": 2, "data_type": "float", "io_type": "in"}, {"addr": 8, "length": 4, "data_type": "uint", "io_type": "in"}, {"addr": 12, "length": 4, "data_type": "int", "io_type": "in"}, {"addr": 16, "length": 4, "data_type": "float", "io_type": "in"}, {"addr": 100, "length": 1, "data_type": "uint", "io_type": "out", "init_val": 11}, {"addr": 101, "length": 1, "data_type": "int", "io_type": "out", "init_val": -12}, {"addr": 102, "length": 2, "data_type": "uint", "io_type": "out", "init_val": 13}, {"addr": 104, "length": 2, "data_type": "int", "io_type": "out", "init_val": -6554}, {"addr": 106, "length": 2, "data_type": "float", "io_type": "out", "init_val": 121.98}, {"addr": 108, "length": 4, "data_type": "uint", "io_type": "out", "init_val": 456696}, {"addr": 112, "length": 4, "data_type": "int", "io_type": "out", "init_val": 9998424}, {"addr": 116, "length": 4, "data_type": "float", "io_type": "out", "init_val": -564.112}, ] "input_registers": [ {"addr": 0, "length": 1, "data_type": "uint"}, {"addr": 1, "length": 1, "data_type": "int"}, {"addr": 2, "length": 2, "data_type": "uint"}, {"addr": 4, "length": 2, "data_type": "int"}, {"addr": 6, "length": 2, "data_type": "float"}, {"addr": 8, "length": 4, "data_type": "uint"}, {"addr": 12, "length": 4, "data_type": "int"}, {"addr": 16, "length": 4, "data_type": "float"}, ]
下位互換性
レジスタマップ バージョン2は、必要に応じてバージョン1の設定もサポートできます。以下のコードはこれを示しています。
"coil_registers": { "coil_input_addresses": "0, 1, 2, 3, 4", "coil_output_addresses": "100, 101, 102, 103, 104", "coil_output_init": [1, 0, 234, -121, False] } "discrete_registers": { "discrete_input_addresses": "0, 1, 2, 3, 4" } "holding_registers": { "holding_register_input_addresses": "0u, 1i, \ [2,3]u, [4,5]i, [6,7]f, \ [8,9,10,11]u, [12,13,14,15]i, [16,17,18,19]f", "holding_register_output_addresses": "100u, 101i, \ [102,103]u, [104,105]i, [106,107]f, \ [108,109,110,111]u, [112,113,114,115]i, [116,117,118,119]f", "holding_register_output_init": [11, -12, 13, -6554, 121.98, 456696, 9998424, -564.112] } "input_registers": { "input_register_addresses": "0u, 1i, \ [2,3]u, [4,5]i, [6,7]f, \ [8,9,10,11]u, [12,13,14,15]i, [16,17,18,19]f", }
Modbus構成例
レジスタ マップ バージョン 1 を使用した完全な Modbus 構成の例を以下に示します。
configuration = { "ip_addr": "192.168.0.100", "netmask": "255.255.255.0", "port": 502, "slave_id": 17, "slave_id_echo": False, "unimplemented_register_exception": True, "coil_input_addresses": "0", "coil_output_addresses": "100", "discrete_input_addresses": "0", "holding_register_input_addresses": "0", "holding_register_output_addresses": "100", "input_register_addresses": "0" }
レジスタ マップ バージョン 2 を使用した完全な Modbus 構成の例を以下に示します。
configuration = { "ip_addr": "192.168.0.100", "netmask": "255.255.255.0", "port": 502, "slave_id": 17, "slave_id_echo": False, "unimplemented_register_exception": True, "coil_registers": [ {"addr": 0}, {"addr": 100, "io_type": "out"} ], "discrete_registers": [ {"addr": 0} ], "holding_registers": [ {"addr": 0}, {"addr": 100, "io_type": "out"} ], "input_registers": [ {"addr": 0} ] }
Modbusデバイスの内部
Modbus デバイス コンポーネントと、構成がコンポーネント構造にどのように影響するかをより深く理解するために、次のレジスタ マップを検討します。
"coil_registers": [], "discrete_registers": [], "holding_registers": [ {"addr": 0, "name": "holding0", io_type: "in", "val_spec": "model", "min": 1, "max": 100, "scale": 1}, {"addr": 1, "name": "holding1", io_type: "out", "val_spec": "model", "min": 2, "max": 200, "scale": 2}, {"addr": 2, "name": "holding2", io_type: "inout", "val_spec": "model", "min": 3, "max": 300, "scale": 3}, {"addr": 3, "name": "holding3", io_type: "in", "val_spec": "scada", "min": None, "max": None, "scale": 1}, {"addr": 4, "name": "holding4", "val_spec": "const"}, ], "input_registers" []
Modbusコンポーネントの内部を図3に示します。

コイル、ディスクリート、入力レジスタが定義されていないため、これらのレジスタには何も生成されません。入力信号と出力信号の次元は0です。
保持レジスタには、適切なSCADA入力、ゲイン、およびリミットコンポーネントが生成されます。SCADA入力コンポーネントは、 scada val specパラメータで定義されたすべてのレジスタ(この場合はholding3レジスタ)に対して生成されます。すべての入力レジスタと入出力レジスタに対して、入力スケーリングとリミットが実行されます。出力レジスタと入出力レジスタについても同様ですが、スケール値がそれに応じて変更される点のみが異なります。
constとして定義されたレジスタは、Modbus デバイス コンポーネントの構造を変更することはありません。
複数のModbusデバイス定義
Typhoon HIL Control Centerでは、モデル内に複数のModbusデバイスインスタンスを配置できます。各インスタンスは異なるデバイスとして表現され、それぞれに独自の設定を定義する必要があります。設定の定義は、単一のModbusデバイスの場合と同じです。
Modbusデバイスのインスタンスを複数使用する場合、すべてのデバイスに異なるIPアドレスを割り当てる必要があります(図4 )。IPアドレスの値は、一意であり、同じネットワークに属している限り任意に設定できます(最初の3バイトはネットワークによって定義され、最後のバイトのみ変更できます)。

スレーブID値を使用したModbusメッセージのフィルタリング
Modbusサイトの構成によっては、複数のデバイスが同じレジスタマップとIPアドレスを持つ必要があります。この場合、スレーブIDはメッセージを適切なデバイスにルーティングするために使用されます。その一例を図5に示します。モデルには複数のデバイスが存在し、すべて同じレジスタマップを持っています。クライアントからのリクエストメッセージのスレーブID値が1、2、3、…の場合、特定のデバイスがターゲットとなり、その値がクライアントに報告されます。スレーブIDが100の場合、すべてのデバイスの集約値がサーバーに報告されます。

この構成を実現するには、図 6 に示すように、すべてのデバイスの IP アドレスが同じでありながら、slave_id 値が異なっていることを確認するために、各デバイスごとに構成を定義する必要があります (個別のデバイスとして動作するため、すべてのデバイスの集約値を含む) 。

セットアップ内のデバイスの1つを「デフォルトデバイス」として定義できます。この場合、クライアントから受信したスレーブIDが他のデバイスのいずれの値とも一致しない場合、デフォルトデバイスの値が返されます。図6では、集約デバイスがデフォルトとして定義されています。いずれのデバイスもデフォルトとして定義されていない場合は、最後にアクセスしたデバイスの値が返されます。
このような場合、デバイス設定でスレーブIDエコーを無効にすることも有効です。デフォルトではこのオプションが有効になっており、クライアントのリクエストで定義されたスレーブIDの値が返されます。無効にすると、そのデバイスのスレーブIDの実際の値が返されます。つまり、クライアントがスレーブID 5を送信したが、設定例のようにデバイスが3台しか実装されていない場合、デバイス100が値を返しているにもかかわらず、値5が返されます。スレーブIDエコーが無効になっている場合は、ID 100が返され、クライアントはどのデバイスが値を返したかを知ることができます。
Modbusデバイスコンポーネントの制限
Modbus プロトコルでは 64 ビット レジスタ操作がサポートされていますが、HIL デバイス内のすべてのレジスタは 32 ビット長であるため、受信データと送信データは 32 ビット値に変換されることに留意してください。
時間同期
時刻同期が必要な場合は、 「時刻同期」をご覧ください。
仮想HILサポート
Virtual HILは現在このプロトコルをサポートしていません。非リアルタイム環境(例:ローカルコンピュータでモデルを実行する場合)を使用する場合、このコンポーネントへの入力は破棄され、このコンポーネントからの出力はゼロになります。