概要
Modbusは1979年にModicon社(現Schneider Electric)がPLC(プログラマブルロジックコントローラ)向けに開発した産業用通信プロトコルです。現在も産業機器における事実上の標準プロトコルとして世界中で使われています。
Modbusはオープン規格として公開されており、特許もライセンス費用も不要です。マスタースレーブ(クライアント/サーバー)構成でシンプルな通信を実現し、RS-485やRS-232Cの物理層(Modbus RTU/ASCII)またはTCPネットワーク(Modbus TCP)上で動作します。
PLCと温度調節器・インバーター(周波数変換器)・電力計・センサーユニットなどのフィールド機器を接続するのに最もよく使われます。設定・計測値の読み書き、コイル(ビット)とレジスタ(16ビット整数)というシンプルなデータモデルが特徴です。
歴史・背景
Modbusは1979年にModicon社(旧Gould Electronics)が自社PLCの通信規格として開発しました。当初は独自規格でしたが、シンプルさと実用性が評価されて多くのメーカーに採用され、産業フィールドの標準として普及しました。
1996年にModbus TCP(Ethernet上のModbus)が導入され、イーサネットネットワークでの産業通信にも対応しました。2004年にはModbus-IDEというオープン規格推進団体(現Modbus Organization)が設立され、仕様が正式にオープン化されました。
現在、産業機器のほぼ全カテゴリにModbus対応製品が存在し、ビル管理・エネルギー管理・水処理・製造業など幅広い分野で使われています。
技術仕様
Modbusのバリアント
| バリアント | 物理層 | フォーマット | 特徴 |
|---|---|---|---|
| Modbus RTU | RS-485 / RS-232C | バイナリ | 最も一般的。高効率 |
| Modbus ASCII | RS-485 / RS-232C | ASCIIテキスト | 人間可読、通信効率低 |
| Modbus TCP | Ethernet / TCP/IP | バイナリ | LANで使用 |
| Modbus UDP | Ethernet / UDP | バイナリ | 低レイテンシ用途 |
データモデル
Modbusは4種類のデータオブジェクトを定義しています:
| オブジェクト | アクセス | ビット幅 | 説明 |
|---|---|---|---|
| コイル(Coil) | 読み書き | 1ビット | デジタル出力(例:リレー状態) |
| ディスクリート入力(DI) | 読み取りのみ | 1ビット | デジタル入力(例:スイッチ) |
| 保持レジスタ(HR) | 読み書き | 16ビット | アナログ出力・設定値 |
| 入力レジスタ(IR) | 読み取りのみ | 16ビット | アナログ入力・計測値 |
アドレス範囲は0〜65535(機能コードで区別)。Modbusアドレスは1始まりと0始まりで表記が異なる場合があるため注意が必要です(「400001」表記と「40000」のオフセット計算等)。
機能コード(Function Code)
よく使われる機能コード:
| コード | 機能 |
|---|---|
| 0x01 | コイル読み取り(Read Coils) |
| 0x02 | ディスクリート入力読み取り |
| 0x03 | 保持レジスタ読み取り(最多使用) |
| 0x04 | 入力レジスタ読み取り |
| 0x05 | 単一コイル書き込み |
| 0x06 | 単一レジスタ書き込み |
| 0x0F | 複数コイル書き込み |
| 0x10 | 複数レジスタ書き込み |
エラーレスポンスの場合は機能コードの最上位ビットを1にし(0x83等)、例外コードを返します。
Modbus RTUフレームフォーマット
[スレーブアドレス(1B)][機能コード(1B)][データ(N B)][CRC(2B)]
例:スレーブ1の保持レジスタ40001〜40002を読む
送信: [0x01][0x03][0x00][0x00][0x00][0x02][0xC4][0x0B]
アドレス=1, FC=03, 開始Reg=0x0000, 個数=2, CRC
応答: [0x01][0x03][0x04][0x01][0xF4][0x00][0x64][CRC2B]
アドレス=1, FC=03, バイト数=4, Reg1=500(0x01F4), Reg2=100(0x0064)
CRCはCRC-16/ANSIアルゴリズム(多項式0x8005)を使います。
Modbus TCPフレームフォーマット
Modbus TCPはTCP/IP上で動作し、CRCの代わりにMBAP(Modbus Application Protocol)ヘッダーが付加されます:
[トランザクションID(2B)][プロトコルID(2B)=0x0000][データ長(2B)][ユニットID(1B)][機能コード(1B)][データ(N B)]
デフォルトTCPポート: 502
動作原理
マスタースレーブモデル
Modbusはマスタースレーブ(Modbus TCP以降ではクライアント/サーバーとも呼ぶ)のプロトコルです:
- マスター(クライアント): リクエストを送信。PLCやSCADAシステムが担当
- スレーブ(サーバー): リクエストに応答。計測器・センサーユニット・インバーターが担当
- スレーブはマスターのリクエストがないとデータを送信しない(ポーリング方式)
// FreeModbus等のライブラリを使ったModbus RTU実装例(マスター側)
#include "mb.h" // FreeModbus
#include "mbport.h"
// Modbus RTU初期化(スレーブアドレス1、RS-485、9600bps)
eMBErrorCode err = eMBInit(MB_RTU, 1, 1, 9600, MB_PAR_NONE);
eMBEnable();
// 保持レジスタ読み取りリクエスト送信(FC03)
USHORT regs[10];
UCHAR slave_addr = 1; // スレーブアドレス
USHORT reg_start = 0; // 開始レジスタ
USHORT reg_count = 10; // レジスタ数
// FreeModbusではコールバック関数でレジスタへのアクセスを実装
eMBErrorCode eMBRegHoldingCB(UCHAR *pucRegBuffer, USHORT usAddress,
USHORT usNRegs, eMBRegisterMode eMode) {
if (eMode == MB_REG_READ) {
for (int i = 0; i < usNRegs; i++) {
*pucRegBuffer++ = (regs[i] >> 8) & 0xFF;
*pucRegBuffer++ = regs[i] & 0xFF;
}
}
return MB_ENOERR;
}
// メインループで定期的にポーリング
while (1) {
eMBPoll(); // Modbusイベント処理
HAL_Delay(1);
}
CRC-16計算
Modbus RTUのCRC計算:
uint16_t calc_modbus_crc(uint8_t *buf, uint16_t len) {
uint16_t crc = 0xFFFF;
for (uint16_t i = 0; i < len; i++) {
crc ^= buf[i];
for (int j = 0; j < 8; j++) {
if (crc & 0x0001) crc = (crc >> 1) ^ 0xA001;
else crc >>= 1;
}
}
return crc; // LSBファースト(低位バイトを先に送信)
}
用途・ユースケース
Modbusが使われる産業現場:
- PLCと計測器の接続: 温度調節器・流量計・電力計からModbus RTU(RS-485)でPLCにデータ収集
- インバーター制御: モーターインバーターの速度設定・運転/停止命令をModbusで送受信
- 太陽光発電: パワーコンディショナーとデータロガーのModbus通信で発電量モニタリング
- ビル管理: 空調機器・電力計・環境センサーのデータをBASサーバーがModbus TCPで収集
- 水処理プラント: 水質センサー・ポンプ制御盤との通信
- SCADA/HMI: SCADA(監視制御)システムがModbus TCPでフィールド機器を監視・制御
実装・開発のポイント
ライブラリの活用
Modbus実装はゼロから開発せず、実績のあるオープンソースライブラリを使います:
| ライブラリ | 言語 | 特徴 |
|---|---|---|
| FreeModbus | C | RTOS対応マイコン向け。FreeRTOS等と連携 |
| libmodbus | C | Linux/Windowsマスター実装 |
| pymodbus | Python | Pythonテスト・プロトタイピング |
| ModbusScope | - | デバッグ・解析ツール |
タイムアウトとレスポンス時間
Modbus RTUでは「3.5文字時間(T3.5)」がフレーム間のサイレント区間です。9600bpsの場合、1文字≈1ms程度なので約3.5msです。マスターはリクエスト送信後、一定時間(標準は500ms〜1秒)待ってタイムアウト処理を行います。
レジスタのデータ型変換
Modbusレジスタは16ビット整数ですが、多くの機器では32ビット浮動小数点数(IEEE 754)を2レジスタで表現します:
// 2レジスタから32ビット浮動小数点数に変換
float modbus_regs_to_float(uint16_t reg_hi, uint16_t reg_lo) {
uint32_t raw = ((uint32_t)reg_hi << 16) | reg_lo;
float val;
memcpy(&val, &raw, sizeof(float));
return val;
}
他技術との比較
Modbus vs OPC UA
| 項目 | Modbus | OPC UA |
|---|---|---|
| 制定年 | 1979年 | 2008年 |
| データモデル | シンプル(コイル/レジスタ) | 複雑・柔軟(オブジェクトモデル) |
| セキュリティ | なし | TLS・認証・暗号化 |
| 対応プロトコル | RS-485/Ethernet | Ethernet/Internet |
| 導入コスト | 低い | 高い |
OPC UAはより高機能で安全なプロトコルですが、Modbusの単純さとレガシー互換性は今も大きな価値があります。
Modbus vs CANopen
CANバス上のCANopenはリアルタイム性に優れ、モーション制御など高速応答が必要な用途に向きます。Modbusはポーリング方式で低速ですが、設定・計測値の読み書きには十分です。