Задача
Ведущий / клиент pymodbus может отправить запрос подчиненному / серверу. Ведомый / сервер готовит вещи для возврата и ждет, пока мастер / клиент их заберет. Несмотря на готовность сервера / ведомого, ведущий / клиент просто возвращает ошибку «Ошибка Modbus: [Ввод / вывод] Ошибка Modbus: [Неверное сообщение] Получено неполное сообщение, ожидается не менее 2 байтов (получено 0)».
Настройка
Я использую ноутбук в качестве сервера / ведомого устройства с этим адаптером: https://www.amazon.com/dp/B076WVFXN8/ref=twister_B076X1BS4H?_encoding=UTF8&psc=1
У меня 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. Те же результаты.
Я пробовал скорость передачи данных = 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. Их можно отправлять с master / Raspberry / BananaPi на ноутбук, но не наоборот.
Неправильные ли у меня настройки прав для устройств? ...
Что я делаю не так? ...
Чего мне не хватает? ...
Поскольку RS485 работает только в одном направлении, я не думаю, что проблема связана с pymodbus (?) ... (Моя логика говорит, что pymodbus строится в стандарте RS485, и если этот базовый уровень RS485 не работает, pymodbus не будет. Это предположение верно?)
Я знаю, что некоторые люди говорят о том, что Raspberry Pi имеет 3,3 В на контактах и не работает с 5V контактами. Несмотря на это, все учебники игнорируют этот факт и работают. - Или они просто притворяются, что это работает? Спецификации TTL говорят, что все выше 2,5 В будут приняты как ВЫСОКИЕ. ТАК В ТЕОРИИ 3.3В должно быть в порядке, как подсказывают учебники.
По назначению я еще не прикрепил резисторы к проводам tx / rx для подъема / опускания. Учебники не предлагают их.
Я протестировал адаптер RS85 на ноутбуке с датчиком температуры и влажности Modbus. Кажется, это работает безупречно. Таким образом, этот факт указывает на то, что BananaPi / Raspberry Pi и комбинация адаптера RS485 + программное обеспечение + настройки должны быть каким-то образом ошибочными.