Modbus-tk получает ошибку Modbus: код исключения = 3
Я пытаюсь использовать modbus-tk
для последовательной связи с устройством через Modbus RTU по сети RS-485.
Чтобы понять, как использовать modbus-tk
, Я пытаюсь запросить:
- Регистр ввода:
Year of Manufacture
- Адрес регистрации:
0x7543 = 30019
- Устройство:
1
- Тип данных: 16-битное целое число
- Значение =
2019
(проверено с помощью бесплатного главного симулятора Modbus).
Вот код, который я использую, в основном на основе rtumaster_example.py. Вход:
#!/usr/bin/env python3
import time
from collections import namedtuple
from logging import Logger
from serial import Serial
from modbus_tk import modbus_rtu
import modbus_tk.defines as cst # cst = constants
from modbus_tk.utils import create_logger
PORT = "COM3"
SLAVE_NUM = 1
MODBUS_MASTER_TIMEOUT_SEC = 5.0
ModbusReg = namedtuple("ModbusInputRegister", ["name", "block_type", "address"])
year_of_manuf = ModbusReg(
"year of manufacture", cst.HOLDING_REGISTERS, 18
) # 0x7543 = 30019
logger = create_logger(name="console") # type: Logger
serial_ = Serial(PORT)
modbus_master = modbus_rtu.RtuMaster(serial_)
modbus_master.set_timeout(MODBUS_MASTER_TIMEOUT_SEC)
modbus_master.set_verbose(True)
time.sleep(2) # Per https://github.com/ljean/modbus-tk/issues/73#issuecomment-284800980
logger.info(
modbus_master.execute(
slave=SLAVE_NUM,
function_code=cst.READ_INPUT_REGISTERS,
starting_address=year_of_manuf.address,
)
)
Выход:
2020-01-21 10:38:09,031 INFO modbus_rtu.__init__ MainThread RtuMaster COM3 is opened
2020-01-21 10:38:11,048 DEBUG modbus.execute MainThread -> 1-4-0-18-0-0-80-15
2020-01-21 10:38:11,077 DEBUG modbus.execute MainThread <- 1-132-3-3-1
---------------------------------------------------------------------------
ModbusError Traceback (most recent call last)
<ipython-input-2-9afaebcf3a35> in <module>
7 slave=SLAVE_NUM,
8 function_code=cst.READ_INPUT_REGISTERS,
----> 9 starting_address=year_of_manuf.address,
10 )
c:\path\to\venv\lib\site-packages\modbus_tk\utils.py in new(*args, **kwargs)
37 ret = fcn(*args, **kwargs)
38 except Exception as excpt:
---> 39 raise excpt
40 finally:
41 if threadsafe:
c:\path\to\venv\lib\site-packages\modbus_tk\utils.py in new(*args, **kwargs)
35 lock.acquire()
36 try:
---> 37 ret = fcn(*args, **kwargs)
38 except Exception as excpt:
39 raise excpt
c:\path\to\venv\lib\site-packages\modbus_tk\modbus.py in execute(self, slave, function_code, starting_address, quantity_of_x, output_value, data_format, expected_length)
312 # the slave has returned an error
313 exception_code = byte_2
--> 314 raise ModbusError(exception_code)
315 else:
316 if is_read_function:
ModbusError: Modbus Error: Exception code = 3
Похоже, это исключение для случая, если the slave has returned an error
Как вы думаете, что я делаю не так? Я новичок в этой библиотеке.
Что я прочитал
- Не могу подключиться к ведомому устройству с помощью Python modbus_tk, я использую
pyserial >= 3.1
- И все остальные вопросы под
modbus-tk
тег, некоторые сообщения в группах Google и примеры репо +README.md
Особенности устройства
- Устройство: SST Sensing's OXY-LC-485
- Modbus RTU, 9600/8-N-1
- Руководство пользователя (раздел 7.1.2.1 содержит набор входных регистров)
- Устройство подключено к машине Windows, на которой я запускаю этот скрипт Python
Пакеты
Я использую Python 3.6 в Windows 10.
pyserial==3.4
modbus-tk==1.1.0
** ИЗМЕНИТЬ 1**
Согласно комментарию @Brits, я обновил адреса своего реестра, чтобы они соответствовали кодам функций и адресам фреймов данных.
** РЕДАКТИРОВАТЬ 2**
Обновленный вопрос, поскольку после более правильного использования библиотеки я получаю другую ошибку.
1 ответ
Моя проблема заключалась в непонимании Master.execute
метод. Я не понимал, чтоquantity_of_x
параметр нужно было сделать ненулевым. Особая благодарность @Brits за помощь в выявлении нескольких ключевых проблем, которые у меня возникли с исходным кодом.
Когда аргумент function_code == defines.READ_INPUT_REGISTERS
, quantity_of_x
означает количество H
(Тип C, беззнаковое короткое, длина = 2 байта = 16 бит, исходный код) для чтения (исходный кодmodbus.py
, строка 138).
Поскольку тип данных устройства для year_of_manuf
регистр - это 16-битное целое число без знака, правильным изменением было добавление quantity_of_x=1
как аргумент.
Функциональный ввод:
logger.info(
modbus_master.execute(
slave=SLAVE_NUM,
function_code=cst.READ_INPUT_REGISTERS,
starting_address=year_of_manuf.address,
quantity_of_x=1,
)
)
Выход:
2020-01-21 18:42:05,520 DEBUG modbus.execute MainThread -> 1-4-0-18-0-1-145-207
2020-01-21 18:42:05,560 DEBUG modbus.execute MainThread <- 1-4-2-7-227-250-137
2020-01-21 18:42:05,562 INFO <ipython-input-1-2d4d0280e33d>.<module> MainThread (2019,)