Проблема
Мастер / клиент pymodbus может отправить запрос подчиненному / серверу. Подчиненный / сервер готовит вещи к возврату и ждет, пока мастер / клиент их заберет. Несмотря на готовность сервера / подчиненного устройства, главный / клиент просто возвращает ошибку «Ошибка Modbus: [Вход / выход] Ошибка Modbus: [Недопустимое сообщение] Получено неполное сообщение, ожидается не менее 2 байтов (получено 0)».
Настройка
Я использую ноутбук в качестве сервера / подчиненного устройства с этим адаптером: https://rads.stackoverflow.com/amzn/click/com/B076WVFXN8
У меня Raspberry Pi 3 / BananaPi в качестве мастера / клиента с подключенным адаптером: https://www.aliexpress.com/item/32781613765.html?spm=a2g0s.9042311.0.0.1aec4c4d0EXx8M
Я следую большей части этого руководства по настройке, за исключением того, что Arduino заменяется адаптером для ноутбука: https://circuitdigest.com/microcontroller-projects/rs485-serial-communication-between-arduino-and-raspberry-pi - контакты для Raspberry как в учебнике.
У меня есть эта программа в качестве сервера / подчиненного устройства на моем ноутбуке:
#!/usr/bin/env python
from pymodbus.server.sync import StartTcpServer
from pymodbus.server.sync import StartUdpServer
from pymodbus.server.sync import StartSerialServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSparseDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.transaction import ModbusRtuFramer, ModbusBinaryFramer
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s'
' %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
def run_server():
slave_store1 = ModbusSlaveContext(co=ModbusSequentialDataBlock(0, [1]*16))
slave_store2 = ModbusSlaveContext(di=ModbusSequentialDataBlock(0, [1]*16))
slave_store3 = ModbusSlaveContext(ir=ModbusSequentialDataBlock(0, [5]*16))
slave_store4 = ModbusSlaveContext(hr=ModbusSequentialDataBlock(0, [5]*16))
slaves = {
0x01: slave_store1,
0x02: slave_store2,
0x03: slave_store3,
0x04: slave_store4,
}
context = ModbusServerContext(slaves=slaves, single=False)
identity = ModbusDeviceIdentification()
identity.VendorName = 'Pymodbus'
identity.ProductCode = 'PM'
identity.VendorUrl = 'http://github.com/riptideio/pymodbus/'
identity.ProductName = 'Pymodbus Server'
identity.ModelName = 'Pymodbus Server'
identity.MajorMinorRevision = '2.2.0'
# RTU:
StartSerialServer(context, framer=ModbusRtuFramer, identity=identity, port='/dev/ttyUSB0', timeout=4, baudrate=115200, stopbits=1, bytesize=8, parity='N')
if __name__ == "__main__":
run_server()
Версия python на сервере / подчиненном:
$ python3 --version
Python 3.5.2
И я запускаю это с этой команды:
$ python3 pymodbus_sync_serv_example_2019.07.05-1316.py
У меня в качестве мастера / клиента на Raspberry Pi 3 / BananaPi есть следующее:
#!/usr/bin/env python
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s '
'%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
UNIT = 0x1
def run_sync_client():
client = ModbusClient(method='rtu', port='/dev/ttyS2', timeout=4, baudrate=115200, stopbits=1, bytesize=8, parity='N')
print(client)
client.connect()
log.debug("===================================")
log.debug("Read input registers")
log.debug("")
rr = client.read_input_registers(1, 2, unit=3)
print(rr)
client.close()
if __name__ == "__main__":
#for _ in range(10):
run_sync_client()
Тестируйте и анализируйте
Я пробовал Raspberry Pi 3, а также BananaPi. Те же результаты.
Я пробовал baudrate = 9600, 38400, а теперь 115200.
время ожидания уже велико, как вы можете видеть в коде.
Журналы для сервера / подчиненного:
2019-07-07 13:35:00,333 MainThread DEBUG sync :45 Client Connected [/dev/ttyUSB0:/dev/ttyUSB0]
2019-07-07 13:35:00,333 MainThread DEBUG sync :522 Started thread to serve client
2019-07-07 13:35:08,341 MainThread DEBUG rtu_framer :180 Getting Frame - 0x4 0x0 0x1 0x0 0x2
2019-07-07 13:35:08,341 MainThread DEBUG factory :137 Factory Request[ReadInputRegistersRequest: 4]
2019-07-07 13:35:08,341 MainThread DEBUG rtu_framer :115 Frame advanced, resetting header!!
2019-07-07 13:35:08,342 MainThread DEBUG context :64 validate: fc-[4] address-2: count-2
2019-07-07 13:35:08,342 MainThread DEBUG context :78 getValues fc-[4] address-2: count-2
2019-07-07 13:35:08,342 MainThread DEBUG sync :143 send: [ReadRegisterResponse (2)]- b'030404000500050846'
Вышеупомянутый сервер / подчиненный просто ждет с мигающим курсором после этой последней строки журнала ...
Журналы для мастера / клиента:
ModbusSerialClient(rtu baud[115200])
2019-07-07 13:35:04,428 MainThread DEBUG pymodbus_sync_client_example_2019.07.05-1319:165 ===================================
2019-07-07 13:35:04,429 MainThread DEBUG pymodbus_sync_client_example_2019.07.05-1319:166 Read input registers
2019-07-07 13:35:04,430 MainThread DEBUG pymodbus_sync_client_example_2019.07.05-1319:167
2019-07-07 13:35:04,430 MainThread DEBUG transaction :111 Current transaction state - IDLE
2019-07-07 13:35:04,430 MainThread DEBUG transaction :116 Running transaction 1
2019-07-07 13:35:04,431 MainThread DEBUG transaction :215 SEND: 0x3 0x4 0x0 0x1 0x0 0x2 0x21 0xe9
2019-07-07 13:35:04,431 MainThread DEBUG sync :73 New Transaction state 'SENDING'
2019-07-07 13:35:04,432 MainThread DEBUG transaction :224 Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
2019-07-07 13:35:08,439 MainThread DEBUG transaction :234 Transaction failed. (Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received))
2019-07-07 13:35:08,440 MainThread DEBUG rtu_framer :235 Frame - [b''] not ready
2019-07-07 13:35:08,441 MainThread DEBUG transaction :390 Getting transaction 3
2019-07-07 13:35:08,442 MainThread DEBUG transaction :189 Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
Modbus Error: [Input/Output] Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received)
Версия python для мастера / клиента:
$ python3 --version
Python 3.5.2
И я запускаю это с этой команды:
$ python3 pymodbus_sync_client_example_2019.07.05-1319.py
Права на / dev на Raspberry / BananaPi:
$ ls -l /dev/ttyS*
crw--w---- 1 root tty 249, 0 Jul 7 11:21 /dev/ttyS0
crw-rw---- 1 root dialout 249, 1 Jul 7 11:22 /dev/ttyS1
crw-rw---- 1 root dialout 249, 2 Jul 7 13:35 /dev/ttyS2
crw-rw---- 1 root dialout 249, 3 Jul 7 11:20 /dev/ttyS3
И на сервере / слейве на ноуте:
$ ls -l /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 0 Jul 7 13:35 /dev/ttyUSB0
Я пробовал отправлять простые числа по протоколу RS485. Их можно отправить с мастера / Raspberry / BananaPi на ноутбук, но не наоборот.
У меня неправильные настройки прав для устройств? ...
Что я делаю неправильно?...
Что мне не хватает? ...
Поскольку RS485 работает только одним способом, я не думаю, что pymodbus является проблемой (?) ... (Моя логика говорит, что pymodbus строится в стандарте RS485, и если этот базовый уровень RS485 не работает, pymodbus не будет . Это предположение верно?)
Я знаю, что некоторые люди говорят о том, что Raspberry Pi имеет 3,3 В на контактах и не работает с 5-вольтовыми контактами. Несмотря на это, похоже, что все учебники игнорируют этот факт и работают. - Или они просто притворяются, что это работает? В спецификациях TTL указано, что все выше 2,5 В будет считаться ВЫСОКИМ. Итак, в ТЕОРИИ 3,3 В должно быть в порядке, как и предполагают учебники.
Я намеренно еще не подключил резисторы к проводам tx / rx для повышения / понижения. Учебники их не предлагают.
Я протестировал адаптер RS85 на ноутбуке с датчиком температуры-влажности Modbus. Кажется, это работает безупречно. Таким образом, этот факт указывает на то, что комбинация BananaPi / Raspberry Pi и адаптера RS485 + программное обеспечение + настройки каким-то образом ошибочна.