なぜこの記事を読むべきか。
Stack Overflow、control.com、CSDNでは、“どのオープンソースのModbusライブラリを使えばいいのか?”という質問が何千回も聞かれました。それぞれの答えは断片的で、誰もシステムを比較していません。検索された投稿の半分は10年前のNModbus4のコードで、NModbusのメインリポジトリが3.0.xに移行したことさえ知らなかった。
7つのスタックのリポジトリを3日間かけて調べ、それぞれの最小の例を実行し、メンテナンス状態を確認しました。以下は結果です。急いでいる場合は、“初心者推奨パス”セクションに直接ジャンプし、プラットフォームに対応するライブラリを選択して開始します。
概要比較表
| プロトコルスタック | 言語は | ライセンス | 星の数 | メンテナンス状態 | メイン駅。 | 駅から。 | RTU | TCP | 誰にふさわしい? |
|---|---|---|---|---|---|---|---|---|---|
| FreeModbus | C | BSD | ~1.5k | 低活動。 | 支払いは | ✅ | ✅ | ✅ | STM32ベアメタル/RTOS |
| libmodbus | C | LGPL v2.1+ | ~3.5k | アクティブな活動 | ✅ | ✅ | ✅ | ✅ | Linux産業用コンピュータ/ゲートウェイ |
| pymodbus | Python | BSD | ~2.2k | 非常にアクティブ。 | ✅ | ✅ | ✅ | ✅ | 上位コンピュータ/テストスクリプト |
| NModbus | C# | MIT | ~700 | アクティブな活動 | ✅ | ✅ | ✅ | ✅ | . NET/WinFormホスト |
| jamod | Java | Apache 2.0 | ~300 | 停滞した | ✅ | ✅ | ✅ | ✅ | Javaレガシーシステム |
| modbus-tk | Python | LGPL | ~500 | 低活動。 | ✅ | ✅ | ✅ | ✅ | ラピッドプロトタイピング |
| QtModbus | C++ | LGPL/GPL | Qtの内部 | アクティブな活動 | ✅ | ✅ | ❌ | ✅ | Qtクロスプラットフォームアプリケーション |
Starの数は2026 year 6 月に私が捕まえたもので、おおよそのオーダーで、具体的な数はGitHubに行って一目でわかります。
Free Modbus-組み込みベアメタルの標準的な答え
GitHub: https://github.com/cwalter-at/freemodbus
Free Modbusはオーストリアの組込みエンジニアChristian Walterによって書かれた。STM 32のサークルでは、Linuxカーネルのext 4と同等のものです。他には何もできませんが、それを使用するには最悪です。
** コードサイズ **:起動した関数コードと転送モードに応じて、約6-12KBのROMがコンパイルされます。RAMは数百バイト、主にデータバッファとイベントキューの一部をオーバーヘッドします。基本的にはCortex-M 0が動作します。
** ファンクションコードは、0 3(リードホールドレジスタ)、0 4(リード入力レジスタ)、0 6(単一レジスタへの書き込み)、16(複数レジスタへの書き込み)、0 1(リードコイル)、0 2(ディスクリート入力の読み取り)、0 5(単一コイルへの書き込み)、15(複数コイルへの書き込み)をサポートしています。また17(ステーションIDから報告)。22(マスク書き込みレジスタ)と23(複数のレジスタを読み書き)はなく、必要に応じて追加する必要があります。
** トランスポートモード **:RTU、ASCI I、TCPをサポートし、マクロスイッチをコンパイルします。
** マスター/スレーブ **:これはFree Modbusで最も誤解されている場所です。公式リポジトリはスレーブコードのみをオープンソースで、マスターステーションは有料です。GitHubにはマスター機能を追加したコミュニティ魔法のバージョンがたくさんあります。例えば、arminkのFree Modbus_Slave-Master-RTT-STM 32はオープンソースで品質は良いが、公式のメンテナンスではない。これらのサードパーティ製バージョンを使用する場合は、タイムアウト処理と再試行ロジックが粗く実装されており、直接生産しないでください。
** コード例 **-STM 32でRTUスレーブを初期化し、アドレス1、ボーレート96 00、チェックなし:
#include "mb.h"
int main(void) {
eMBInit(MB_RTU, 0x01, 0, 9600, MB_PAR_NONE);
eMBEnable();
while (1) {
eMBPoll();
}
}この3行だけです♪eMBPoll `ではプロトコルスタック全体のステートマシンを実行し,ノンブロッキングで,タイマ割込みで3.5Tのタイムアウト信号を供給する必要がある.この3.5 TタイマはFree Modbus移植のNo.1のピットであり、以下で詳しく説明します。
** 既知の問題 **: - 公式リポジトリの更新は非常に遅く、v 1.6の最後のメジャーバージョンは何年も動いていない、バグ修正は運命を修正しない - 単一シリアルポートのみをサポートし、プロトコルスタックインスタンスは1つのUARTのみをバインドでき、マルチシリアルポートシナリオはコードを変更する必要があります。 - TCPモードはソケットではなくlwIP raw APIを使用します。つまり、Free RTOS +LWIP環境では動作しますが、Linuxでは動作しません。 - 浮動小数点数処理補助関数なし、大小変換は自分で書く
** ドキュメント **:HTML形式のAPIドキュメントは1つだけで、十分ですが、十分ではありません。中国語のコミュニティチュートリアルはたくさんあり、CSNはたくさん検索します。
libmodbus:Linux産業用コンピュータのための完璧な選択
GitHub: https://github.com/stephane/libmodbus
ステファン·ランボー-フランス人。libmodbusはC言語で書かれた最も成熟したModbusライブラリの一つです。3.5 K星は悪くない。
Free Modbusとは設計が大きく異なります。Free Modbusはリソースに制約のあるMCU用に設計されており、コールバック関数とステートマシンを備えている。libmodbusはPOSIXスタイルで、APIをブロックし、`modbus_read_registers`呼び出しはデータが戻るかタイムアウトするまで待ちます。産業用コンピュータプログラムを書く人は、ステートマシンを気にしないシンプルで直接的なスタイルが好きです。
** ほとんどすべて。0 1/0 2/0 3/0 4/0 5/0 6/0 7/0F/10/11/16/17、22(マスク書き込み)と23(複数の読み書き)もサポートしています。`mod_set_float` / `mod_get_float`があり、EE754に准拠して小数点数を直接でき、ABCD/BA/BADC/CDABの4のエンディアンをサポートする。
** 転送モード **:RTU + TCPをフルサポート。同じAPIセットで、`modbus_new_rtu`はシリアルポートコンテキストを作成し、`modbus_new_tcp`はTCPコンテキストを作成し、それ以降の読み書きインタフェースはまったく同じです。
** マスター/スレーブ ***:どちらもサポートされています。TCPスレーブは`modbus_tcp_listen` + `modbus_tcp_accept`とLinuxソケットサーバを書くためのルーチンである。
** コード例 **--スレーブステーション1の保持レジスタ0 x 0000を読み取り、1つの16ビット値を返します。
#include <modbus.h>
#include <stdio.h>
int main() {
modbus_t *ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);
modbus_set_slave(ctx, 1);
modbus_connect(ctx);
uint16_t val;
modbus_read_registers(ctx, 0, 1, &val);
printf("Register 0 = %dn", val);
modbus_close(ctx);
modbus_free(ctx);
}** 既知の問題 **: - `modbus_connect`のセマンティクスはピットを踏みやすい。RTUモードでは`open`シリアルポートを開き,TCPモードでは`connect`接続サーバを下げる. TCPスレーブモードでは`modbus_connect`を必要とせず、`modbus_tcp_listen`を使用します。混乱していて、なぜかわからない。 - `mod_free`以降、ポインタは的に空にならない。ループ内で再接続すると、手動で`ctx = NULL`を行わずにfree and newを再接続すると、ランダムなクラッシュやクレイジーな再接続として現れることがあります。私はこれを食べた。 - スレッドは安全でない。modbus_t *`コンテキストは2つのスレッドで同時にOperationすることはできず、独自にロックする必要があります。 - Windowsでのシリアル名は`\.\ COM10`このフォーマットは、Linuxは`/dev/ttyUSB0`で、クロスプラットフォームコンパイルは注意する必要があります。
** ドキュメント **:ウェブサイトlibmodbus.orgには、マニュアルページスタイルのドキュメントとオンラインmkdocsがあります。明確ですが、サンプルプロジェクトはありません。`tests/`ディレクトリにあります。
pymodbus:Pythonエコシステムのデファクトスタンダード
GitHub: https://github.com/pymodbus-dev/pymodbus
pymodbusは現在最も活発にメンテナンスされているModbusライブラリの一つです。pymodbus-dev組織が引き継いだ後、3.xは非同期アーキテクチャを書き直し、asyncioをサポートし、リリースを続けた。2024年末までの最新安定版はv 3.6.xです。
** 完全サポート。0 1/0 2/0 3/0 4/0 5/0 6/15/16/22/23、43(読み取りデバイス識別)もあります。
** 転送モード **:RTU + TCP + TLS。TLSサポートはpymodbus 3.xで新たに追加され、`modbus+tls//`を直接実行できます。ASCIIモードもサポートされているが、3.xで非推奨とマークされた。
** マスター/スレーブ **:両方をサポートし、同期APIと非同期APIの両方をサポートします。スレーブステーションは完全なシミュレータを実行できます--`pymodbus.simulator`はJSON設定ファイルから複数のレジスタを持つ仮想デバイスを起動でき、ホストコンピュータの開発とデバッグに非常に便利です。
** コード例 **--同期モードはホールドレジスタを読み取ります:
from pymodbus.client import ModbusSerialClient
client = ModbusSerialClient(port="/dev/ttyUSB0", baudrate=9600)
client.connect()
rr = client.read_holding_registers(address=0, count=1, slave=1)
print(rr.registers[0])
client.close()非同期版は少し多く行,使用`async with`コンテキストマネージャ,協調asyncio実行。
** 既知の問題 **: - 2.xから3.xまでのAPIの変化は大きい.` pymodbus.client.sync.ModbusSerialClient `が` pymodbus.client.ModbusSerialClient `になり,` read_holding_registers `戻り値が`ReadHoldingRegistersResponse`から`ModbusResponse`になる.インターネットで`from pymodbus.client.sync import ...`のサンプルコードを見つけた場合、2.xだからコピーしないで - 同期モードと非同期モードは混在できません。同じプロセスでasyncioイベントループが実行されると、同期クライアントはイベントループをブロックしてタイムアウトします。 - RTUモードではシリアルタイムアウト設定が敏感です。低速デバイス(4800bps)ではデフォルトの3 秒のタイムアウトでは不十分な場合があり、5-10 秒に設定する必要があります。 - pipインストール時`pip install pymodbus`,`pymodbus3`または`pymodbus2`ではない,インストールを間違えないでください。
** ドキュメント **:readthedocsに完全なドキュメントがあり、`examples/`ディレクトリには数十のサンプルスクリプトがあります。中国語のファイルはありませんが、英語はクリアです。
NModbus:. NETプラットフォームの唯一の深刻な選択肢
GitHub: https://github.com/NModbus/NModbus
NModbusの歴史は複雑です。最初のNModbusはGoogle Code(そう、Google Code)上のプロジェクトでしたが、GitHubに移行してNModbus4になり、その後NModbus4は廃止されました。現在のNModbus/NModbusはNModbus4の後継であり、メンテナはrquackenbush、活発に開発中であり、nugetパッケージ名 `NModbus`、最新版は3.0.x、. NET 6+をサポートしている。
** コード **:01/02/03/04/05/06/15/16 全サポート。22と23はカスタム機能コード処理が必要です。
** 転送モード **:RTU、ASCII、TCP、UDPをフルサポート。シリアルポートは`NModbus.Serial`パッケージでWindows/Linuxに対応している。
** マスター/スレーブ ***:どちらもサポートされています。スレーブステーションはカスタムデータストレージをサポートし、レジスタをメモリ、データベース、さらにはPLCにマッピングできます。
** コード例 **-TCPマスターがレジスタを読み取ります:
using NModbus;
var client = new TcpClient("192.168.1.100", 502);
var factory = new ModbusFactory();
var master = factory.CreateMaster(client);
ushort[] result = master.ReadHoldingRegisters(1, 0, 1);
Console.WriteLine(result[0]);** 既知の問題 **: - シリアルポートサポートは`System.IO.Ports`に依存します。Linux 上では追加の構成権限が必要です。 - `SlaveDataStore`マルチスレッド下ではスレッドセーフではなく、高い同時読み書き時には自分でロックする - 非同期API `ReadHoldingRegistersAsync`は`Task`を返すが、基盤となるI/Oは実際には同期されており、真のasync I/Oはexistenceしない
** ドキュメント ** READMEで十分です。`Samples/`ディレクトリにはいくつかの例があります。主にStack Overflowの古い投稿に依存しています。
Jamod-Javaエコシステムの“前身”ですが、使用しないでください。
SourceForge: https://sourceforge.net/projects/jamod/ GitHub (openHAB fork): https://github.com/openhab/jamod
Jamodは2002 yearにDieter Wimbergerによって書かれましたこの部屋にいる多くのエンジニアよりも長く働いています最後の実質的な更新は2010 yearであり、それ以降はほとんどexistenceしない。open HABコミュニティはいくつかのバグを修正したバージョンをフォークしましたが、そのフォークは受動的なメンテナンスです。
Modbusを実行する新しいJavaプロジェクトを開始する場合は、jamodをスキップしてj 2 mod(GitHub:steveohara/j 2 mod)を見てください。J 2 modは、Jamod、Apache 2.0ライセンス、Java 8+、まだ更新中(2024 year 7 月に最後にコミットされた)、RTU + TCPのフルサポート、マスタースレーブの両方のバージョンです。
しかし、この記事はJamodをカバーしているので、私はそれを書きます。Jamodがサポートする機能コード:0 1/0 2/0 3/0 4/0 5/0 6/15/16。トランスポートモードRTU + ASCII + TCP.シリアルCommunicationは`javax.comm`(巨大古いAPI,JDKには付属していない)に依存しており,代替案はRXTX あるいはjSerialCommである.
コード例:
import net.wimpi.modbus.Modbus;
import net.wimpi.modbus.io.ModbusTCPTransaction;
import net.wimpi.modbus.msg.ReadInputRegistersRequest;
import net.wimpi.modbus.msg.ReadInputRegistersResponse;
import net.wimpi.modbus.net.TCPMasterConnection;
import java.net.InetAddress;
TCPMasterConnection conn = new TCPMasterConnection(
InetAddress.getByName("192.168.1.100"));
conn.connect();
ReadInputRegistersRequest req = new ReadInputRegistersRequest(0, 1);
ModbusTCPTransaction trans = new ModbusTCPTransaction(conn);
trans.setRequest(req);
trans.execute();
ReadInputRegistersResponse res = (ReadInputRegistersResponse) trans.getResponse();
System.out.println(res.getRegisterValue(0));
conn.close();“既知の問題”という言葉は、Jamodにとっては軽すぎます。それ自体が問題です。しかし、2012 yearの古いシステムを維持していて、それを使用する必要がある場合は、open HABのフォークはオリジナルよりも信頼性が高いです。
modbus-tk-ラピッドプロトタイピングのための素晴らしいヘルパー
GitHub: https://github.com/ljean/modbus-tk
フランス人のLuc Jeanが書いた、名前のtkはTest Kitの略で、明確に定義されています:テストツール。本番環境ではない。しかし、実際には多くの人がそれを生産するのは簡単だからです。
** コード ** 01/02/03/04/05/06/15/16。22/23はサポートされない。
** 送信モード **:RTU + TCP。ASCIIはサポートされません。
** マスター/スレーブ ***:どちらもサポートされています。ステーションからは、簡単に`add_slave` + `add_block`でエミュレートされたデバイスを作成できます。読み書きリクエストを受信したときにカスタムロジックを挿入するフック関数メカニズムが組み込まれています。この設計はスマートで、テストスクリプトを書くときにフックに直接障害シナリオを挿入できます。
** コード例 **-RTUマスター·リード·レジスタ:
import serial
import modbus_tk.defines as cst
from modbus_tk import modbus_rtu
master = modbus_rtu.RtuMaster(
serial.Serial(port="/dev/ttyUSB0", baudrate=9600))
val = master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 1)
print(val[0])** 既知の問題 **: - 最後のアップデートは2020年頃で、バグ修正はコミュニティPRに基づいています。Python 3.12互換性に問題がある - 非同期のサポートがなく、すべてのOperationが同期ブロックされます。 - 浮動小数点数には組み込み補助がないので、自分で`struct.pack/unpack` - マスターステーション`execute` 方法のタイムアウトはあまり制御できず、下位レベルはpyserialのタイムアウトに依存し、応答のないスレーブステーションに遭遇して長い時間がかかる可能性がある
** ドキュメント **:`examples/`ディレクトリにあるいくつかの例がドキュメント全体です。コードサイズが小さくて、10分で読めます。
QtModbus:Qt開発者向けのネイティブソリューション
これは“ライブラリ”ではなく、Qtの公式`qtserialbus`モジュールの一部です。Qt 5.8が導入され、Qt 6の標準モジュールとなった。
Qt公式なので、API設計は完全にQtスタイルです:シグナルスロット、イベントループ、QModbusReply。クロスプラットフォームの自然なサポート-同じコードセットがWindows、Linux、macOS、Embedded Linux(Boot2Qt)で実行されます。
** 関数コード **`QModbusDataUnit RegisterType`列挙ですべての標準型Coils、DiscreteInputs、InputRegisters、HoldingRegistersをサポートします。下部はカスタム機能コードを送信できます。
** 転送モード ** TCPのみ`QModbusTcpClient` / `QModbusTcpServer`。** RTUはなし。これは重要な制限です。QtにはModbus RTUサポートが組み込まれていません。QSerialPortを使用してアプリケーション層でRTUフレームParseを書くか、サードパーティ製の実装を見つける必要があります。一部の開発者は`QModbusRtu SerialMaster`(コミュニティプロジェクト)でこのギャップを埋めています。
** マスター/スレーブ ***:どちらもサポートされています。TCPスレーブは`QModbusTcpServer`によって実現でき、カスタムデータは`QModbusServer`のレジストリにマッピングされます。
** コード例 **-TCPクライアントはレジスタを読み取ります:
#include <QModbusTcpClient>
#include <QModbusDataUnit>
auto client = new QModbusTcpClient(this);
client->setConnectionParameter(
QModbusDevice::NetworkAddressParameter, "192.168.1.100");
client->setConnectionParameter(
QModbusDevice::NetworkPortParameter, 502);
client->connectDevice();
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 0, 1);
auto *reply = client->sendReadRequest(unit, 1);
connect(reply, &QModbusReply::finished, this, [reply]() {
qDebug() << reply->result().values().at(0);
});非同期、結果を信号スロットで接続します。注意 `sendReadRequest`から返される`QModbusReply*`ライフサイクルはQtで管理されますので、手動で削除しないでください。
** 既知の問題 **: - RTUがなければ、これが最大です。Qtの公式ModbusモジュールにRTUはありません - 接続切断后再连,你要在 `stateChanged` 信号里自己书き再连 - `QModbusTcpServer`のTCPコネクション数には上限があり、デフォルトでは1です。`setMaxClients`を使用して変更する - ライセンス問題:QtはLGPL/GPLデュアルライセンスであり、商用クローズドソースプロジェクトはQt Commercial Licenseを購入する必要がある。
** ドキュメント **:Qtの公式ドキュメントは素晴らしいです。サンプルプロジェクトはQt Creatorのウェルカムページにあります。
新規推奨ルート
あなたの技術に基づいて選択してください:
- ** STM 32ベアメタル/Free RTOS ** → Free Modbus選択の余地はありません。それが標準的な答えです。移植は半日かかり、3.5Tタイマーを調整して半日を追加し、その後は気にしない - **Linux Industrial Computer/Gateway(C)** → libmodbus。Raspberry PiがDebianをModbusゲートウェイとして実行している場合、libmodbus + MQTTブリッジが古典的なソリューションです。libmod `,`mosquitto` 上云 - **Pythonホスト/テストスクリプト ** → pymodbus。pymodbus.simulatorシミュレーション+ pymodbusクライアントの読み書き、1つのスクリプトでデバイスのデバッグを行います。PytestでModbus自動テストを実行 - ** C#Win Form/ WPF 上位コンピュータ ** → NModbus。NuGetがインストールされ、3行のコードがレジスタの読み取りを開始する。工場で最も一般的なテクノロジースタックの組み合わせであるScottPlotでリアルタイムカーブを作成 - **Qtクロスプラットフォームデスクトップアプリケーション ** → QtModbus。アプリケーションがすでにQtを使用している場合は、追加のCライブラリ依存関係を導入せず、Qt公式を使用します。 - **Java Enterprise Systems(新規プロジェクト)** → jamodを使用しないでください。j 2 mod(GitHub:steveohara/j 2 mod)では、Jamodのモダンな書き直しで、APIがはるかに明確になりました。 - ** 迅速にアイデアを検証 ** → modbus-tk。3分でスレーブシミュレータを起動し、レジスタマップが正しいことを確認し、pymodbusに切り替えて正式にします。
クラシック·コンビネーション·スキーム
**“Free Modbusスレーブ+ pymodbusホストテスト”**:組み込み機器はFree Modbusをスレーブとして実行し、Pythonでpymodbusスクリプトを書き、機能検証のためにレジスタを読み書きする。Modbus Pollよりも柔軟性があります。データ検証、境界テスト、ストレステストをスクリプトに追加できます。その後、真の上位マシン(C#またはQt)に切り替えます。
**“libmodbus Gateway + pymodbus設定ツール”**:産業用コンピュータはlibmodbusを実行し、数十台のModbus RTUデバイスに接続し、データを収集してMQTTに転送します。Webバックエンドはデバイスパラメータの読み書きにpymodbusを使用しています。リアルタイム性は必要ありません。Python開発効率はすべてを圧倒します。
**“QtModbusはインターフェースを行い、libmodbusは低レベルを行う”**:QtはクロスプラットフォームデスクトップSCADAを書き、ヒューマンマシンインタラクションとチャートはQtチャートを使用しますが、Modbus CommunicationはQt Modbusを直接使用せず(RTUがないため)、libmodbus C APIを介して低レベルの取得を行い、Qtは表示のみを担当します。この組み合わせは、プラント監視システムでは一般的です。
避難所の一覧
** 最初のピット:Free Modbusの3.5 Tタイマー **
Modbus RTUプロトコルは、フレーム間の少なくとも3.5文字の間隔を指定します。ボーレート9600での1文字は約1ms、3.5 T ≈ 3.5 msである。多くの人が移植時にタイマーを3.5 ms周期割込みに直接設定する。間違っている。Free Modbusの3.5 Tタイマの使用法は、受信するバイトごとにタイマをリセットし、タイマがオーバーフローした場合(3.5 Tに新しいバイトがないことを示す)フレームが終了すると仮定する。したがって、タイマーは周期モードではなくシングルモードに設定する。バイトを受信した割込みで`vMBPortTimersEnable`タイマを再起動します。
ボーレートが異なる場合、3.5 Tに対応する時間は異なります:9600bps → 〜 3.65 ms、19200bps → 〜 1.83 ms、115200bps → 〜 304μs。115200では3.5 Tは約300マイクロ秒です。タイマの最小粒度が1msの場合、キャリブレーションはそれほど細かくなく、フレーム間隔検出はエラーになります。この場合、ボーレートを38400に下げるか、ハードウェアタイマのHigh Precisionモードを使用します。
#2:libmodbusのconnect vs new_tcp vs listenセマンティクス
`mod_new_t"192.168.1.100 "502`コンテキストを作成しましたが、接続されていない。 `modbus_connect ctx` RTUモードではシリアルポートを開き、TCPマスターモードではサーバに接続します。 TCPスレーブモードでは、`mod_`ではなく、`mod_t_listen ctx 1` + `mod_t_ctx s`をします。
最も一般的なエラー:TCPスレーブを書くときに習慣的に`modbus_connect`をチューニングして、マスターからのリクエストを受信できないことがわかります。因为`connect` 是去连他人,不是待他人来连你。
もう1つのピット:`mod_free ctx`の后に`ctx`ポインタがまだある.ループ内で再接続したい場合(例えば、ネットワークが切断されて復元された場合)は、最初に`ctx = NULL`と`modbus_new_tcp`が必要です。さもなければ、解放されたメモリにアクセスする可能性があります。WiresharkはTCP SYNが何万回も再送信されるのを見ます-それは'modbus_connect `のアクセス野ポインタです。
** 3番目のピット:pymodbus同期と非同期モードの混在 **
pymodbus 3.xには2つのクライアントAPIがある:同期的 `ModbusSerialClient` / `ModbusTClient`,非同期的 `AsyncModbusSerialClient` / `AsyncModbusTClient`である.
すでにasyncioイベントループを持つプロセスで同期クライアントを使用すると、基盤となるソケットI/Oがイベントループをブロックし、すべての非同期タスクが一時停止します。逆に,純粋な同期スクリプトで非同期クライアントを使用すると,`await`構文がエラーとなります。
ルールは単純です:完全に同期または完全に非同期です。テストスクリプトは通常同期で十分です。本番環境では、プロセスが数十台のデバイスを同時に接続する場合、非同期モードを使用する必要があります。さもなければ、1つのデバイスがタイムアウトして他の49台をドラッグします。
** 4番目のピット:バイト順序の問題-ライブラリのポットではなく、毎回ピットです。
Modbusプロトコル自体は16ビットレジスタの転送フォーマット(ビッグエンディアン)のみを定義しており、上位バイトを先頭にしている。しかし、2つのレジスタで32ビット浮動小数点数を渡すとき、誰が前に誰が後に来るかはプロトコルには関係ありません。メーカーによって処理方法が異なります。
- Schneider PLC 用ビッグエンディアン·ダブルワード(ABCD):レジスタNは上位16ビット、N+1は下位16ビットを格納 - Siemens S 7 -1200バイト交換形式(CDABまたはBADC) - 一部の国産計器用純小端DCBA
libmodbusは`modbus_set_float`と4種類のエンディアン定数を提供しており,pymodbusは`BinaryPayloadDecoder`がエンディアンを指定できるが,FreeModbusは何も持たない― ―自分で`union` あるいは`memcpy`と綴る.
血の教訓:2日間調整した後、温度測定値は天文学的で、最終的にバイトオーダーが逆になりました。まず、相手のデバイスのマニュアルにFloatの格納フォーマットが書かれているか確認してください。書かれていない場合は、2つのレジスタを読んで自分で綴り、4つの配列のうちの1つが正しいです。
** Pit 5:Pit of Broadcast Address 0 **
Modbusはアドレス0がブロードキャストアドレスであり、マスターはブロードキャストフレームを送信し、すべてのスレーブは実行するが応答しない。しかし、実際には、多くのスレーブデバイスはブロードキャストをサポートしておらず、アドレス0は過去に直接反応しません。ブロードキャストをサポートするデバイスもありますが、完全にはサポートしていません。0 6(単一レジスタへの書き込み)ブロードキャストは実行でき、16(複数レジスタへの書き込み)ブロードキャストは無視されます。
`libmodbus_set_slave ctx 0`で放送している場合は、応答を期待しないでください。mod_read_registers `ブロードキャストモードでのは未です。
選択決定の迅速化
何千もの単語を読みたくない場合は、ここに決定木があります:
1.対象プラットフォームはMCUベアメタル→ Free Modbus 2.ターゲットプラットフォーム:Linux → libmodbus 3. Pythonでpymodbusを使用 4. C#/. NET → NModbus 5. Qt → QtModbus(TCPシナリオ)またはlibmodbus(RTUシナリオ)を使用します。 6. Javaで新しいプロジェクトを実行する→ Jamodを使用しない 7. modbus-tkを使ってpymodbusを確認してください。
すべてのライブラリに最小実行可能なサンプルを投稿しましたが、コピー &ペーストしてデバイスアドレスを変更するだけで実行できます。Communicationがうまくいかない場合は、まずModbus Pollまたはpymodbusを使用して純粋なソフトウェアループバックを行い、ハードウェアリンクが問題ないことを確認し、プロトコルスタックのバグを疑います。
質問はmodbus.cnフォーラムに行きます。
Leave a Reply