pythonでModbus機器と通信する(2) レスポンスの受信

前回の記事でpythonでModbus/TCPに対してリクエスト(コマンド)を送信しましたので、返ってきたレスポンスを受信してみます。

対象機器のレジスタマップを確認する

例えば、とあるIT機器の例ですが、Inletの入力電圧を読みたい場合、

ファンクションコードとレジスタの定義をその機器の取説や仕様書から読み取ります。

Holding Register MapにInletがマップされています。
Inlet1は Register 0x3000-0x303f です。

詳細な割り当てを参照すると最初の16レジスタは以下の様に割り当てられています。

各レジスタは2byte(=32bit)です。これも仕様書で確認しておきます。が、パラメータ毎にBit Mask型であったり、Word型であったり、Float型(4byte)の半分であったりします。

とにかくまとめてアドレス0x3000から16レジスタ分をreadしてみます。

Function Code 0x03 (Read Holding Registers)でUnit ID 0x01のユニットのレジスタ0x3000fから16レジスタをreadする

Modbus データ
リクエスト ‘000000000006010330000010’

レスポンス ‘00000000002301032009e30001000200640078000c0000000042cbe1473d5d2f1b0000000000000000’

区切ってみます。
TX:
Transaction, Protocol, length, Id, FC, Address, Num
0000 0000 0006 01 03 3000 0010

RX:
Transaction, Protocol, length, Id, FC, size, Registar data
0000 0000 0023 01 03 20 09e3 0001 0002 0064 0078 000c 0000 0000 42cb e147 3d5d 2f1b 0000 0000 0000 0000

16レジスタ分つまり0x20(=32)バイトのデータがレスポンスされました。

単純に2byteのHexで各レジスタ値を表示すると

REGISTER VALUES
0x3000 : 0x9e3
0x3001 : 0x1
0x3002 : 0x2
0x3003 : 0x64
0x3004 : 0x78
0x3005 : 0xc
0x3006 : 0x0
0x3007 : 0x0
0x3008 : 0x42cb
0x3009 : 0xe147
0x300a : 0x3d5d
0x300b : 0x2f1b
0x300c : 0x0
0x300d : 0x0
0x300e : 0x0
0x300f : 0x0

オフセット 0x03 Word Minimum voltage rating in V が 0x64 = 100[v] であることが解ります。

オフセット 0x00 Bit maskが 0x9e3 なので Bit0,1はOnです。RMS Voltage, RMS Currentすなわち電圧センサと電流センサがサポートされています。

現在の電圧は

オフセット 0x08-0x09 の4byteのfloatです。0x42cb e147 float型を10進に変換すると

0x42cbe147 = 101.9399…[v]

それらしい値をreadできました。

Hex Float -> 10進表示


$python
Python 3.6.4
>>> import struct, binascii
>>> s="42cbe147"
>>> print(struct.unpack('>f', binascii.unhexlify(s))[0])
101.93999481201172

気を付けること

このようにModbusの場合は各機器ごとにレジスタマップを確認して正しく受信データを切り出す必要があります。

関連記事

2019-03-29: pythonでModbus機器と通信する(3) レジスタ読取り用ツール

コメントを残す

メールアドレスが公開されることはありません。

16 + 19 =