📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
ページの作成:「== 概要 == MODBUSは1979年にModicon (現Schneider Electric) により開発された産業用通信プロトコルである。<br> 単純で堅牢な設計により、製造業、ビル管理、エネルギー管理等の様々な産業分野で使用されている。<br> <br> 通信方式として、マスター・スレーブ方式を採用しており、1台のマスター機器が複数のスレーブ機器と通信を行う。<br> マスターからの要…」 |
|||
| (同じ利用者による、間の5版が非表示) | |||
| 31行目: | 31行目: | ||
セキュリティおいては、認証機能は備えていないため、閉じたネットワーク内での使用が推奨される。<br> | セキュリティおいては、認証機能は備えていないため、閉じたネットワーク内での使用が推奨される。<br> | ||
近年では、暗号化やセキュリティ機能を追加した拡張仕様も提案されている。<br> | 近年では、暗号化やセキュリティ機能を追加した拡張仕様も提案されている。<br> | ||
<br><br> | |||
== Modbus RS-485 と Modbus RS-232C の比較 == | |||
<center> | |||
{| class="wikitable" | |||
|+ Modbus RS-485 と Modbus RS-232C の比較 | |||
|- | |||
! !! RS-485 !! RS-232C | |||
|- | |||
| 接続形態 || マルチドロップ (複数デバイス) || ポイント・ツー・ポイント (1対1) | |||
|- | |||
| 伝送距離 || 最大1200m程度 || 最大15m程度 | |||
|- | |||
| ノイズ耐性 || 高い (差動信号) || 低い | |||
|- | |||
| 用途 || 工場の自動化、ビル管理 || 近距離の機器接続 | |||
|} | |||
</center> | |||
<br><br> | |||
== Modbus RTU / Modbus ASCII == | |||
* Modbus RTU | |||
*: RS-485またはRS-232Cで使用 | |||
*: バイナリ形式でデータを送信 (効率的) | |||
*: RS-485では最大32台 (または拡張で247台) のデバイスをマルチドロップ接続可能 | |||
*: <br> | |||
* Modbus ASCII | |||
*: RS-485またはRS-232Cで使用 | |||
*: ASCII文字形式でデータを送信 | |||
*: デバッグが容易だが、RTUより速度が遅い | |||
<br><br> | |||
== Modbus RTU メッセージ構造 == | |||
Modbus RTUでは、全てのデータがバイナリ形式で送信される。<br> | |||
<br> | |||
メッセージは、デバイスアドレス、ファンクションコード、データ、CRCチェックサムで構成される。<br> | |||
CRCは下位バイトが先に送信されるリトルエンディアン形式である。<br> | |||
<br> | |||
[[ファイル:Modbus RTU Message 1.png|フレームなし|中央|600px]] | |||
<br><br> | |||
== 通信シーケンス == | |||
==== Modbus RTU 基本通信シーケンス ==== | |||
Modbus RTU通信では、マスターがリクエストフレームを送信し、スレーブが応答する。<br> | |||
RS-485のHalf Duplex方式では、送信開始時にDE-ONでドライバを有効化して、送信完了後はDE-OFFで受信モードに切り替える。<br> | |||
<br> | |||
スレーブは、T3.5 (フレーム間無通信時間) を経過後にリクエストを受信したと判断して、CRCチェックとデータ処理を行った後、応答フレームを返信する。<br> | |||
正常応答を受信できない場合、マスターはタイムアウト処理を実行する。<br> | |||
<br> | |||
[[ファイル:Modbus RTU Message 2.png|フレームなし|中央|600px]] | |||
<br> | |||
==== Modbus ASCII 基本通信シーケンス ==== | |||
Modbus ASCII通信では、各バイトが16進数のASCII文字として送信される。<br> | |||
メッセージは開始文字 (:) で始まり、スレーブアドレス、ファンクションコード、データ、LRCチェックサム、終了文字 (CR LF) で構成される。<br> | |||
<br> | |||
ASCII形式は人間が読みやすく、デバッグ作業が容易であるというメリットがある。<br> | |||
<br> | |||
通信シーケンスはRTUと同様に、マスターからのリクエストに対してスレーブが応答する形式である。<br> | |||
<br> | |||
[[ファイル:Modbus ASCII Message 3.png|フレームなし|中央|600px]] | |||
<br> | |||
==== マルチドロップ接続時の通信フロー ==== | |||
RS-485のマルチドロップ接続では、1台のマスターが複数のスレーブと通信を行う。<br> | |||
<br> | |||
各スレーブには固有のアドレスが割り当てられ、マスターはリクエスト時に対象スレーブのアドレスを指定する。<br> | |||
バス上の全てのスレーブがメッセージを受信するが、指定されたアドレスのスレーブのみが応答を返す。<br> | |||
他のスレーブは受信したメッセージを無視して、待機状態を維持する。<br> | |||
<br> | |||
この方式により、単一のバスで多数のデバイスを効率的に制御できる。<br> | |||
<br> | |||
[[ファイル:Modbus Multiple Slave 4.png|フレームなし|中央|600px]] | |||
<br><br> | |||
== マスター・スレーブ状態遷移 == | |||
==== マスター側状態遷移 ==== | |||
マスター側は、アイドル状態からポーリングを開始して、リクエスト生成、フレーム生成、送信中、応答待ちの順に遷移する。<br> | |||
<br> | |||
応答を受信した場合、CRCまたはLRCチェックを行い、正常であれば検証状態に進む。<br> | |||
応答がない場合はタイムアウトとなり、再送判定を行う。<br> | |||
<br> | |||
エラーが確定した場合は、アイドル状態に戻る。<br> | |||
<br> | |||
この状態遷移により、通信の信頼性が確保される。<br> | |||
<br> | |||
==== スレーブ側状態遷移 ==== | |||
スレーブ側は、受信待ち状態でフレームの到着を監視する。<br> | |||
フレームを受信すると、受信中状態に遷移して、アドレスを確認する。<br> | |||
自身のアドレスと一致すれば、アドレス判定、検証、処理中、応答生成、応答送信の順に進む。<br> | |||
<br> | |||
アドレスが不一致の場合やCRCまたはLRCエラーが検出された場合は、受信待ち状態に戻る。<br> | |||
<br> | |||
この動作により、マルチドロップ環境で適切なスレーブのみが応答を返す仕組みが実現される。<br> | |||
<br> | |||
[[ファイル:Modbus Master Slave StateMachine 5.jpg|フレームなし|中央|600px]] | |||
<br><br> | |||
== 通信エラーと対策 == | |||
==== アドレス衝突とバス競合 ==== | |||
マルチドロップ環境で設計ミスやアドレス重複が発生すると、複数のスレーブが同時に応答を送信して、バス競合 (データ衝突) が発生する。<br> | |||
この場合、マスターは破損したデータを受信して、CRCエラーが発生する。<br> | |||
マスターは、タイムアウトまたはCRCエラーを検出すると、再送処理またはエラー処理を実行する。<br> | |||
<br> | |||
システム設計時には、各スレーブに重複しない固有のアドレスを割り当てることが必須である。<br> | |||
<br> | |||
また、定期的なアドレス確認と衝突検出機能の実装が推奨される。<br> | |||
<br> | |||
[[ファイル:Modbus Collision 6.png|フレームなし|中央|600px]] | |||
<br> | |||
==== 通信エラーと対策 ==== | |||
Modbus通信における代表的なエラーとして、タイムアウト、CRCまたはLRCエラー、フレーミングエラー、アドレス不一致が挙げられる。<br> | |||
タイムアウトは、スレーブの応答遅延やケーブル断線、ノイズによる応答消失が原因である。<br> | |||
<br> | |||
対策として、適切なタイムアウト時間の設定と再送処理の実装が必要である。<br> | |||
* CRCまたはLRCエラー | |||
*: ノイズやケーブル劣化、インピーダンス不整合により発生する。 | |||
*: シールドケーブルの使用、適切な終端抵抗の配置、ケーブル長の遵守が有効である。 | |||
*: <br> | |||
* フレーミングエラー | |||
*: ボーレート設定の相違やパリティ設定の不一致が原因であり、通信パラメータの統一が必要である。 | |||
*: アドレス不一致は、設定ミスや重複により発生するため、システム構築時のアドレス管理が重要である。 | |||
<br><br> | |||
== MODBUSのデータ型 == | |||
Modbusには、4種類の主要なデータ型がある。<br> | |||
<br> | |||
==== コイル ==== | |||
1ビットのデジタル出力 (読み書き可能) が可能である。<br> | |||
<br> | |||
* アドレス範囲 | |||
*: 00001 - 09999 | |||
<br> | |||
* ファンクションコード | |||
** 01 | |||
**: Read Coils | |||
** 05 | |||
**: Write Single Coil | |||
** 15 | |||
**: Write Multiple Coils | |||
<br> | |||
用途例を以下に示す。<br> | |||
* ON / OFF制御 | |||
*: バルブの開閉状態, モータの起動 / 停止, ランプの点灯 / 消灯 | |||
<br> | |||
==== ディスクリート入力 ==== | |||
1ビットのデジタル入力 (読み取り専用) が可能である。<br> | |||
<br> | |||
* アドレス範囲 | |||
*: 10001 - 19999 | |||
<br> | |||
* ファンクションコード | |||
** 02 | |||
**: Read Discrete Inputs | |||
<br> | |||
用途例を以下に示す。<br> | |||
* リミットスイッチの状態 | |||
* センサのON / OFF信号 | |||
* アラーム信号 | |||
<br> | |||
==== 入力レジスタ ==== | |||
16ビットのデータレジスタ (読み取り専用) である。<br> | |||
<br> | |||
* アドレス範囲 | |||
*: 30001 - 39999 | |||
<br> | |||
* ファンクションコード | |||
** 04 | |||
**: Read Input Registers | |||
<br> | |||
用途例を以下に示す。<br> | |||
* アナログ入力値 | |||
* 測定値 (温度、圧力等) | |||
* カウンタ値 | |||
<br> | |||
==== 保持レジスタ ==== | |||
16ビットのデータレジスタ (読み書き可能) である。<br> | |||
<br> | |||
* アドレス範囲 | |||
*: 40001 - 49999 | |||
<br> | |||
* ファンクションコード | |||
** 03 | |||
**: Read Holding Registers | |||
** 06 | |||
**: Write Single Register | |||
** 16 | |||
**: Write Multiple Registers | |||
<br> | |||
用途例を以下に示す。<br> | |||
* 設定値 | |||
*: 温度、速度、時間等 | |||
* 制御パラメータ | |||
* 出力値の調整 | |||
* アナログ出力の制御 | |||
<br> | |||
==== 実装上の注意点 ==== | |||
* アドレッシング | |||
*: プログラム内でのアドレス指定は通常0ベースである。 | |||
*: 例 : コイル00001は、実際にはアドレス0として指定する。 | |||
<br> | |||
* データ形式 | |||
*: 保持レジスタは、16ビット整数値を扱う。 | |||
*: 浮動小数点数を扱う場合は、2つのレジスタを組み合わせて使用する。 | |||
*: ビッグエンディアン / リトルエンディアンを考慮する必要がある。 | |||
<br> | |||
* アクセス制御 | |||
*: 読み取り専用、あるいは、読み書き可能かを判断する必要がある。 | |||
<br> | |||
* エラーハンドリング | |||
*: 不正なアドレスへのアクセス | |||
*: 範囲外の値の書き込み | |||
*: 通信エラー | |||
<br> | |||
==== 使用例 ==== | |||
以下の例では、コイルと保持レジスタを使用している。<br> | |||
<br> | |||
コイルはデジタル制御 (ON / OFF)、保持レジスタはアナログ値や設定値の制御に使用する。<br> | |||
<br> | |||
<syntaxhighlight lang="c#"> | |||
// コイルの制御 | |||
public async Task ControlValveExample(IModbusMaster master) | |||
{ | |||
// バルブの開閉制御 | |||
await master.WriteSingleCoilAsync( | |||
slaveId: 1, | |||
coilAddress: 0, // コイル00001 | |||
value: true // バルブを開く | |||
); | |||
// 複数のコイルの状態を一度に読み取る | |||
bool[] valveStates = await master.ReadCoilsAsync( | |||
slaveId: 1, | |||
startAddress: 0, // コイル00001から | |||
numberOfPoints: 4 // 4つのコイルの状態を読む | |||
); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c#"> | |||
// 保持レジスタの制御 | |||
public async Task ControlTemperatureExample(IModbusMaster master) | |||
{ | |||
// 温度設定値の書き込み (例 : 25.5[℃]) | |||
ushort temperatureValue = 255; // 0.1[℃]単位で設定 | |||
await master.WriteSingleRegisterAsync( | |||
slaveId: 1, | |||
registerAddress: 0, // レジスタ40001 | |||
value: temperatureValue | |||
); | |||
// 現在の設定値を読み取る | |||
ushort[] settings = await master.ReadHoldingRegistersAsync( | |||
slaveId: 1, | |||
startAddress: 0, // レジスタ40001から | |||
numberOfPoints: 1 // 1つのレジスタを読む | |||
); | |||
decimal actualTemperature = settings[0] / 10.0m; // 実際の温度値に変換 | |||
} | |||
</syntaxhighlight> | |||
<br><br> | <br><br> | ||