Pymodbus 基本示例
Pymodbus Basic Example
我有一个简单的 modbus 设备 (Ebyte MA02-XACX0440),我正在尝试学习如何使用它。使用称为串行端口监视器 (www.serial-port-monitor.org) 的第三方 GUI,我能够或多或少地“偶然发现”打开和关闭离散输出所需的正确十六进制输入。我不明白这些单位、地址、线圈、寄存器等术语,以及它们与十六进制方面的关系。打破我认为我到目前为止所知道的(下面是将第一个离散输出'ON'转换的十六进制字符串):
0x20 0x05 0x00 0x00 0xFF 0x00 0x8A 0x8B
我知道 0x20 是十六进制的设备地址。 Ebyte设备的文档规定默认硬件地址是'31',第一个软件地址是'1'。如果我理解正确,那意味着我线上的第一个物理 modbus 设备的地址为“32”,如果我将其他 modbus 设备放在线上(RS485 或 TCP(?)),下一个设备将是'33'等等。
我知道下一个字节0x05是'write coil'.
我不知道'0x00'和'0x00'接下来的两个字节指的是什么。
接下来的两个字节基本上是 on/off,'0xFF00' 是 'ON' 和 0x0000 是 'OFF'。
最后两个字节只是 CRC 校验和。
到目前为止,我可以让我的 DO(离散输出)打开、打开并点亮 LED,作为一个简单的概念证明。现在,当我采用这种方法来使用 pymodbus 库(我的最终目标)时,事情似乎并不一致。
我可以使用 pymodbus REPL 连接到我的设备
pymodbus.console serial --baudrate 9600 --bytesize 8 --parity N --stopbits 1 --port /dev/cu.usbserial-AH01F4EN
我可以确认设备已连接:
----------------------------------------------------------------------------
__________ _____ .___ __________ .__
\______ \___.__. / \ ____ __| _/ \______ \ ____ ______ | |
| ___< | |/ \ / \ / _ \ / __ | | _// __ \____ \| |
| | \___ / Y ( <_> ) /_/ | | | \ ___/| |_> > |__
|____| / ____\____|__ /\____/\____ | /\ |____|_ /\___ > __/|____/
\/ \/ \/ \/ \/ \/|__|
v1.3.0 - [pymodbus, version 2.5.3]
----------------------------------------------------------------------------
> client.connect
true
然而,当我尝试 运行 之前使用串行监视器执行的相同命令时,我很难将十六进制值映射到 pymodbus 中的 'client.write_coil' 命令所期望的整数:
> client.write_coil address=32 value=255 unit=1
{
"original_function_code": "5 (0x5)",
"error": "[Input/Output] No Response received from the remote unit/Unable to decode response"
}
地址是什么意思?这是 coil/register 地址还是设备地址?对于 'value',我输入了“255”,因为这会将所有位翻转为“1”,认为这会被视为 'ON',而值“0”将被关闭。我还尝试了“65280”,这是十进制的 0xFF00。单位是什么意思?我之前确定的值是“32”以针对线路上的特定设备吗?或者地址可能是'31'(这是硬件地址)然后单元地址是'1',使得整体'address' 32?
编辑:这显示在 client.write_coil 命令的 'help' 中,但仍然无法帮助我弄清楚如何将正确的部分放在正确的位置。我不知道 'coil offset' 是什么以及它与离散输出的关系。我没有看到任何映射到将被视为 'coil offset' 的十六进制字符串的内容。这是为那些可能知道如何正确形成请求的人提供的上下文。
我有时也会遇到这个错误,而且不一致。如果这是一个权限问题,人们会认为您每次都会得到它吗?我不认为改变指定文件的权限或 运行 具有根权限的 pymodbus 服务器是没有意义的。
Unhandled exception in event loop:
File "/usr/local/Cellar/python@3.9/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/events.py", line 80, in _run
self._context.run(self._callback, *self._args)
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/input/vt100.py", line 170, in callback_wrapper
callback()
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 708, in read_from_input
self.key_processor.process_keys()
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_processor.py", line 271, in process_keys
self._process_coroutine.send(key_press)
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_processor.py", line 186, in _process
self._call_handler(matches[-1], key_sequence=buffer[:])
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_processor.py", line 321, in _call_handler
handler.call(event)
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_bindings.py", line 124, in call
result = self.handler(event)
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/shortcuts/prompt.py", line 798, in _accept_input
self.default_buffer.validate_and_handle()
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/buffer.py", line 1877, in validate_and_handle
self.append_to_history()
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/buffer.py", line 1385, in append_to_history
self.history.append_string(self.text)
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/history.py", line 74, in append_string
self.store_string(string)
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/history.py", line 295, in store_string
with open(self.filename, "ab") as f:
Exception [Errno 13] Permission denied: '../.pymodhis'
{ress ENTER to continue...
Modbus specs describe the protocol and are worth a look. I use this online Modbus parser当我想快速解析一个命令时;您提供的字节串 (20 05 00 00 FF 00 8A 8B
) 的输出是:
Part of Data Package
Description
Value
20
Slave address
0x20 (32)
05
Function code
0x05 (5) - Write Single Coil
00 00
Output address
Physical: 0x0000 (0) Logical: 0x0001 (1)
FF 00
Output value
On
8A 8B
CRC
0x8A8B (35467)
从属地址表示您希望与总线上的哪个设备通信。这是在设备上设置的(您不能只添加设备并期望一切正常)。用于设置从属 ID 的方法因设备而异(有些有实用程序来执行此操作,有些使用开关或通过自己的用户界面进行设置,有些对此进行了硬编码)。您的设备 (Ebyte MA02-XACX0440) 默认为 32,但这可以使用设备上的 DIP 开关更改(这在手册中有介绍)。
您正在使用功能代码 5 - 'Write Single Coil'。线圈是比特,所以可以打开或关闭。
'output address' 表示您要写入设备上的哪个线圈。这个地址的含义因设备而异(一般文档中会有一个table解释这个)。对于您的设备,这在手册的 table 7.1(“寄存器列表”)中。
值就是写什么。对于 'write single coil' 函数,这必须是两个值之一:
value
meaning
0x0000
Off
0xFF00
On
所有其他值均无效。然而,许多库(包括 pymodbus)会为你处理这个细节,允许你传递 True
/False
.
把这些放在一起你需要这样的东西:
client.write_coil(0, True, unit=32)
注意:您问了很多问题,因此本文可能无法完全回答这些问题,但希望能为您指明正确的方向(太多信息无法放入评论!)。
我有一个简单的 modbus 设备 (Ebyte MA02-XACX0440),我正在尝试学习如何使用它。使用称为串行端口监视器 (www.serial-port-monitor.org) 的第三方 GUI,我能够或多或少地“偶然发现”打开和关闭离散输出所需的正确十六进制输入。我不明白这些单位、地址、线圈、寄存器等术语,以及它们与十六进制方面的关系。打破我认为我到目前为止所知道的(下面是将第一个离散输出'ON'转换的十六进制字符串):
0x20 0x05 0x00 0x00 0xFF 0x00 0x8A 0x8B
我知道 0x20 是十六进制的设备地址。 Ebyte设备的文档规定默认硬件地址是'31',第一个软件地址是'1'。如果我理解正确,那意味着我线上的第一个物理 modbus 设备的地址为“32”,如果我将其他 modbus 设备放在线上(RS485 或 TCP(?)),下一个设备将是'33'等等。
我知道下一个字节0x05是'write coil'.
我不知道'0x00'和'0x00'接下来的两个字节指的是什么。
接下来的两个字节基本上是 on/off,'0xFF00' 是 'ON' 和 0x0000 是 'OFF'。
最后两个字节只是 CRC 校验和。
到目前为止,我可以让我的 DO(离散输出)打开、打开并点亮 LED,作为一个简单的概念证明。现在,当我采用这种方法来使用 pymodbus 库(我的最终目标)时,事情似乎并不一致。
我可以使用 pymodbus REPL 连接到我的设备
pymodbus.console serial --baudrate 9600 --bytesize 8 --parity N --stopbits 1 --port /dev/cu.usbserial-AH01F4EN
我可以确认设备已连接:
----------------------------------------------------------------------------
__________ _____ .___ __________ .__
\______ \___.__. / \ ____ __| _/ \______ \ ____ ______ | |
| ___< | |/ \ / \ / _ \ / __ | | _// __ \____ \| |
| | \___ / Y ( <_> ) /_/ | | | \ ___/| |_> > |__
|____| / ____\____|__ /\____/\____ | /\ |____|_ /\___ > __/|____/
\/ \/ \/ \/ \/ \/|__|
v1.3.0 - [pymodbus, version 2.5.3]
----------------------------------------------------------------------------
> client.connect
true
然而,当我尝试 运行 之前使用串行监视器执行的相同命令时,我很难将十六进制值映射到 pymodbus 中的 'client.write_coil' 命令所期望的整数:
> client.write_coil address=32 value=255 unit=1
{
"original_function_code": "5 (0x5)",
"error": "[Input/Output] No Response received from the remote unit/Unable to decode response"
}
地址是什么意思?这是 coil/register 地址还是设备地址?对于 'value',我输入了“255”,因为这会将所有位翻转为“1”,认为这会被视为 'ON',而值“0”将被关闭。我还尝试了“65280”,这是十进制的 0xFF00。单位是什么意思?我之前确定的值是“32”以针对线路上的特定设备吗?或者地址可能是'31'(这是硬件地址)然后单元地址是'1',使得整体'address' 32?
编辑:这显示在 client.write_coil 命令的 'help' 中,但仍然无法帮助我弄清楚如何将正确的部分放在正确的位置。我不知道 'coil offset' 是什么以及它与离散输出的关系。我没有看到任何映射到将被视为 'coil offset' 的十六进制字符串的内容。这是为那些可能知道如何正确形成请求的人提供的上下文。
我有时也会遇到这个错误,而且不一致。如果这是一个权限问题,人们会认为您每次都会得到它吗?我不认为改变指定文件的权限或 运行 具有根权限的 pymodbus 服务器是没有意义的。
Unhandled exception in event loop:
File "/usr/local/Cellar/python@3.9/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/events.py", line 80, in _run
self._context.run(self._callback, *self._args)
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/input/vt100.py", line 170, in callback_wrapper
callback()
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 708, in read_from_input
self.key_processor.process_keys()
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_processor.py", line 271, in process_keys
self._process_coroutine.send(key_press)
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_processor.py", line 186, in _process
self._call_handler(matches[-1], key_sequence=buffer[:])
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_processor.py", line 321, in _call_handler
handler.call(event)
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_bindings.py", line 124, in call
result = self.handler(event)
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/shortcuts/prompt.py", line 798, in _accept_input
self.default_buffer.validate_and_handle()
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/buffer.py", line 1877, in validate_and_handle
self.append_to_history()
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/buffer.py", line 1385, in append_to_history
self.history.append_string(self.text)
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/history.py", line 74, in append_string
self.store_string(string)
File "/usr/local/lib/python3.9/site-packages/prompt_toolkit/history.py", line 295, in store_string
with open(self.filename, "ab") as f:
Exception [Errno 13] Permission denied: '../.pymodhis'
{ress ENTER to continue...
Modbus specs describe the protocol and are worth a look. I use this online Modbus parser当我想快速解析一个命令时;您提供的字节串 (20 05 00 00 FF 00 8A 8B
) 的输出是:
Part of Data Package | Description | Value |
---|---|---|
20 | Slave address | 0x20 (32) |
05 | Function code | 0x05 (5) - Write Single Coil |
00 00 | Output address | Physical: 0x0000 (0) Logical: 0x0001 (1) |
FF 00 | Output value | On |
8A 8B | CRC | 0x8A8B (35467) |
从属地址表示您希望与总线上的哪个设备通信。这是在设备上设置的(您不能只添加设备并期望一切正常)。用于设置从属 ID 的方法因设备而异(有些有实用程序来执行此操作,有些使用开关或通过自己的用户界面进行设置,有些对此进行了硬编码)。您的设备 (Ebyte MA02-XACX0440) 默认为 32,但这可以使用设备上的 DIP 开关更改(这在手册中有介绍)。
您正在使用功能代码 5 - 'Write Single Coil'。线圈是比特,所以可以打开或关闭。
'output address' 表示您要写入设备上的哪个线圈。这个地址的含义因设备而异(一般文档中会有一个table解释这个)。对于您的设备,这在手册的 table 7.1(“寄存器列表”)中。
值就是写什么。对于 'write single coil' 函数,这必须是两个值之一:
value | meaning |
---|---|
0x0000 | Off |
0xFF00 | On |
所有其他值均无效。然而,许多库(包括 pymodbus)会为你处理这个细节,允许你传递 True
/False
.
把这些放在一起你需要这样的东西:
client.write_coil(0, True, unit=32)
注意:您问了很多问题,因此本文可能无法完全回答这些问题,但希望能为您指明正确的方向(太多信息无法放入评论!)。