Ошибка Modbus: [Недействительное сообщение] Получено неполное сообщение, ожидается не менее 2 байтов (получено 0)

Проблема

Мастер / клиент 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 + программное обеспечение + настройки каким-то образом ошибочна.


person Andreas    schedule 07.07.2019    source источник


Ответы (2)


Во-первых, позвольте мне сказать, что мне приятно ответить на такой хорошо сформулированный вопрос. Не все тратят столько усилий на объяснение того, что они сделали и как они это сделали. Ваш вопрос - плюс один сразу после того, как вы закончите его читать.

Теперь о твоей проблеме. Вы пропустили один очень важный шаг в руководстве, которому вы следовали. Как вы говорите, Modbus полудуплексный 1, у вас только два провода, и только одно устройство может разговаривать по шине, поэтому вам нужен способ взять под контроль шину, так сказать . В вашем кабеле USB-RS485 / 422 это делается автоматически для вас аппаратным обеспечением кабеля (в частности, ваш кабель использует широко распространенный чип FTDI с сигналом TXEN -TX enable-, см. здесь для получения более подробной информации), поэтому вы заметили, что кабель работает хорошо. С другой стороны, ваш крошечный трансивер за 3 доллара - бедный брат, и у него даже нет UART, это просто несимметричный преобразователь в дифференциальный. Вот почему вам нужно предоставить сигнал DE / ~ RE (Drive Enable / Not Read Enable), чтобы бедняга знал, когда ему разрешено взять под контроль шину.

Это предупреждение, которое вы не взяли из учебника:

ВАЖНО: перед записью значений в модуль RS-485 контакты DE и RE должны быть ВЫСОКИМИ.

Это кажется достаточно простым, но если подумать, как работает Modbus ... на самом деле это не так просто. Эта строка кода:

rr = client.read_input_registers(1, 2, unit=3)

должен делать много вещей, если вы хотите успешно взаимодействовать с полудуплексом RS485: взять под контроль шину (в ваших настройках установить высокий уровень сигнала RE / ~ DE), отправить кадр запроса Modbus с запросом двух регистров на UNIT ID 3, сразу после окончания записи запроса (по прошествии 3,5 символов) отпустите управление шиной (теперь устанавливая RE / ~ DE low) и считайте ответ от ведомого.

Как я объясняю в ссылке, о которой я уже упоминал выше, есть несколько решений этой проблемы. Я предпочитаю (я больше разбираюсь в оборудовании) передает сигнал управления направлением шины аппаратно (лучший способ - иметь трансивер, в котором эта функция реализована аппаратно, например this one, но по ссылке вы также найдете решение DIY с использованием таймера 555). Теперь, если вы предпочитаете делать это программным способом, у вас есть несколько вариантов. Вы можете настроить pymodbus для переключения строки управления в соответствии с потребностями Modbus (в цитированном мной ответе есть несколько ссылок) или, если вы предпочитаете более нестандартное решение используйте libmodbus.

Если вы выберете этот последний вариант, вы можете найти все подробности о том, как собрать и установить lidmodbus с полудуплексной поддержкой, используя контакты GPIO на Rpi, и если вы хотите остаться на Python, установите wrapper и протестируйте базовый пример. Также есть несколько снимков экрана осциллографа, чтобы увидеть разницу между переключением линии с помощью программного обеспечения и оборудования. Для большинства домашних целей или любителей вы должны иметь возможность использовать переключение программного обеспечения, но я бы не стал доверять ему для промышленных или более важных приложений.

В завершение, думаю, стоит ответить на все ваши вопросы по очереди:

Поскольку RS485 работает только одним способом, я не думаю, что pymodbus является проблемой (?) ... (Моя логика говорит, что pymodbus строится в стандарте RS485, и если этот базовый уровень RS485 не работает, pymodbus не будет . Это предположение верно?)

Ну и да, и нет, и возможно ... Как вы читали выше, проблема не в pymodbus. Это просто ожидает, что вы или ваше оборудование позаботитесь о не столь незначительных деталях управления доступом к шине. Я думаю, что большинство людей используют такую ​​библиотеку для Modbus TCP, поэтому для большинства пользователей это никогда не проблема. В общем сценарии Modbus, когда у вас есть ПЛК, который общается с другим устройством через Modbus RTU по каналу RS485, проблема решается с помощью оборудования, поэтому вам также не придется беспокоиться об этом.

Я знаю, что некоторые люди говорят о том, что Raspberry Pi имеет 3,3 В на контактах и ​​не работает с 5-вольтовыми контактами. Несмотря на это, похоже, что все учебники игнорируют этот факт и работают. - Или они просто притворяются, что это работает? В спецификациях TTL указано, что все выше 2,5 В будет считаться ВЫСОКИМ. Итак, в ТЕОРИИ 3,3 В должно быть в порядке, как и предполагают учебники.

Правильно, MAX485 datahseet указывает пороговые значения для VIH и VOL, и если вы используйте 5 В для питания ваших трансиверов, разные логические уровни не будут проблемой (в этом конкретном случае обратите внимание, что это не общее утверждение, другие устройства могут выйти из строя или в конечном итоге выйти из строя, если вы смешаете логические уровни).

Я намеренно еще не подключил резисторы к проводам tx / rx для повышения / понижения. Учебники их не предлагают.

Скорее всего, вам не потребуется подключать к шине согласующие резисторы для собственного проекта. Для длинных автобусов (на заводе или предприятии, где устройства могут находиться на расстоянии сотен метров друг от друга) вы, вероятно, будете беспокоиться об этой проблеме. В вашем крошечном трансивере уже есть согласующие резисторы, поэтому лучше не добавлять сопротивление. Для вашего кабеля у меня не хватило терпения найти руководство (не знаю, есть ли оно; у меня есть аналогичный кабель, и единственный способ быть уверенным - снять крышку и заглянуть под его колпак).

Как только вы все настроите и запустите, обратите внимание, что на вашем клиенте:

print(rr)

Должно быть:

print(rr.registers)

Если вы хотите, это показать прочитанные вами значения.

person Marcos G.    schedule 07.07.2019
comment
Замечательный ответ. В отделе объяснения и серьезные и хорошие предложения по решению. - Я пока выбираю программное решение, модифицируя pymodbus. Просто чтобы получить быстрые результаты. Оно работает. Обязательно рассмотрю ваши предложения по оборудованию. - person Andreas; 07.07.2019
comment
Вы говорите, что Modbus - это полудуплексный протокол ... Но, НАСКОЛЬКО, это не часть протокола, не так ли? AFAIK Modbus - это последовательный протокол, если он работает на RS-232, RS-485, полудуплексном или полнодуплексном, не имеет значения, поскольку он просто определяет, как пакеты данных будут нести информацию и проверку. - person Michel Feinstein; 31.10.2019
comment
Да, вы правы, утверждение Modbus является полудуплексным может показаться слишком сложным для понимания. Modbus на самом деле не заботится о том, как режим передачи используется на шине, но если вы строите сеть Modbus на полнодуплексном канале, он всегда будет использоваться в полудуплексном режиме. Как я уже упоминал где-то еще, заменив двухпроводной RS485 (на самом деле это три провода: A, B и GND) на RS232 (трехпроводной, RX, TX и GND) был бы способом решить проблему отсутствия сигнала управления направлением шины, с которой мы хорошо знакомы (где это возможно: короткие шины) - person Marcos G.; 31.10.2019

Как и предполагал Маркос Г. выше, я модифицировал pymodbus для управления выбранным GPIO.

Я выбрал программное решение, так как мне просто нужно немного быстро работать, не заказывая новое оборудование, и ждать этого. Позже я найду подходящее / лучшее оборудование.

программное решение, изменяющее pymodbus

Найдите файл «sync.py» в папке «client», чтобы изменить клиентскую / главную сторону вашей установки.

Я модифицирую клиент / мастер здесь, так как на этой стороне у меня «плохое» оборудование RS485. Если у вас есть две из этих «плохих» аппаратных вещей, вам может потребоваться изменить и серверную часть.

Файл sync.py, вероятно, можно найти в

~ / .local / lib / python3.5 / сайт-пакеты / pymodbus / клиент

Это может варьироваться в зависимости от используемой версии Python. У меня сейчас 3,5. Часть «~ /» означает, что он находится в вашей домашней папке. Точка перед "local" делает файл стандартным скрытым. В терминале вы также можете использовать команду «ls -al» для отображения скрытых файлов. Графический пользовательский интерфейс вашего дистрибутива Linux наверняка также сможет каким-то образом отображать скрытые файлы.

В начале файла "sync.py" добавьте следующий код:

import RPi.GPIO as GPIO
pin_de_re = 7
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin_de_re, GPIO.OUT, initial=GPIO.HIGH)

Это может выглядеть примерно так:

more imports ...

from pymodbus.transaction import ModbusSocketFramer, ModbusBinaryFramer
from pymodbus.transaction import ModbusAsciiFramer, ModbusRtuFramer
from pymodbus.client.common import ModbusClientMixin

import RPi.GPIO as GPIO
pin_de_re = 7
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin_de_re, GPIO.OUT, initial=GPIO.HIGH)

# --------------------------------------------------------------------------- #
# Logging
# --------------------------------------------------------------------------- #
import logging
_logger = logging.getLogger(__name__)

...more code

Установите пин-код по своему усмотрению. У меня контрольный контакт GPIO4 - это контакт 7 в Raspberry Pi / BananaPi.

Затем вы прокручиваете вниз и находите раздел под названием

# --------------------------------------------------------------------------- #
# Modbus Serial Client Transport Implementation
# --------------------------------------------------------------------------- #

Я изменяю этот раздел, так как использую Modbus RTU и, следовательно, последовательный порт для передачи данных.

В этом разделе вы должны найти определение «отправить»:

    def _send(self, request):
        """ Sends data on the underlying socket

Внутри этой функции найдите строку:

            size = self.socket.write(request)

И примите это с помощью булавки:

            _logger.debug("GPIO - Setting pin high")
            GPIO.output(pin_de_re, 1)
            time.sleep(.300)
            size = self.socket.write(request)
            time.sleep(.300)
            _logger.debug("GPIO - Setting pin low")
            GPIO.output(pin_de_re, 0)

Причина, по которой я использую строки "_logger.debug (" GPIO - Установка высокого / низкого уровня вывода ") ', заключается в том, что я затем вижу в журнале в терминале, что программа выполняет эти действия, и я могу быть уверен, что они выполненный. Если они не отображаются в журнале, я сделал это не в том месте - или что-то еще ...

Причина использования time.sleep (.300) заключается в том, чтобы дать оборудованию время для работы. .300 составляет 0,3 секунды. Большое количество в этом контексте.

Когда я использую вышеуказанное решение, я получаю следующие журналы.

Подчиненный / сервер:

2019-07-07 23:08:43,532 MainThread      DEBUG    sync           :45       Client Connected [/dev/ttyUSB0:/dev/ttyUSB0]
2019-07-07 23:08:43,533 MainThread      DEBUG    sync           :522      Started thread to serve client
2019-07-07 23:08:47,534 MainThread      DEBUG    rtu_framer     :232      Frame check failed, ignoring!!
2019-07-07 23:08:47,535 MainThread      DEBUG    rtu_framer     :128      Resetting frame - Current Frame in buffer - 0x3 0x4 0x0 0x1 0x0 0x82
2019-07-07 23:08:59,543 MainThread      DEBUG    rtu_framer     :180      Getting Frame - 0x4 0x0 0x1 0x0 0x2
2019-07-07 23:08:59,544 MainThread      DEBUG    factory        :137      Factory Request[ReadInputRegistersRequest: 4]
2019-07-07 23:08:59,544 MainThread      DEBUG    rtu_framer     :115      Frame advanced, resetting header!!
2019-07-07 23:08:59,544 MainThread      DEBUG    context        :64       validate: fc-[4] address-2: count-2
2019-07-07 23:08:59,544 MainThread      DEBUG    context        :78       getValues fc-[4] address-2: count-2
2019-07-07 23:08:59,545 MainThread      DEBUG    sync           :143      send: [ReadRegisterResponse (2)]- b'030404000500050846'

Мастер / клиент:

ModbusSerialClient(rtu baud[115200])
2019-07-07 23:08:55,839 MainThread      DEBUG    pymodbus_sync_client_example_2019.07.05-1319:165      ===================================
2019-07-07 23:08:55,840 MainThread      DEBUG    pymodbus_sync_client_example_2019.07.05-1319:166      Read input registers
2019-07-07 23:08:55,841 MainThread      DEBUG    pymodbus_sync_client_example_2019.07.05-1319:167      
2019-07-07 23:08:55,842 MainThread      DEBUG    transaction    :111      Current transaction state - IDLE
2019-07-07 23:08:55,842 MainThread      DEBUG    transaction    :116      Running transaction 1
2019-07-07 23:08:55,843 MainThread      DEBUG    transaction    :215      SEND: 0x3 0x4 0x0 0x1 0x0 0x2 0x21 0xe9
2019-07-07 23:08:55,843 MainThread      DEBUG    sync           :79       New Transaction state 'SENDING'
2019-07-07 23:08:55,844 MainThread      DEBUG    sync           :538      GPIO - Setting pin high
2019-07-07 23:08:55,845 MainThread      DEBUG    sync           :541      GPIO - Setting pin low
2019-07-07 23:08:55,845 MainThread      DEBUG    transaction    :224      Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
2019-07-07 23:08:59,516 MainThread      DEBUG    transaction    :300      Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
2019-07-07 23:08:59,518 MainThread      DEBUG    transaction    :229      RECV: 0x3 0x4 0x4 0x0 0x5 0x0 0x5 0x8 0x46
2019-07-07 23:08:59,519 MainThread      DEBUG    rtu_framer     :180      Getting Frame - 0x4 0x4 0x0 0x5 0x0 0x5
2019-07-07 23:08:59,519 MainThread      DEBUG    factory        :266      Factory Response[ReadInputRegistersResponse: 4]
2019-07-07 23:08:59,520 MainThread      DEBUG    rtu_framer     :115      Frame advanced, resetting header!!
2019-07-07 23:08:59,521 MainThread      DEBUG    transaction    :379      Adding transaction 3
2019-07-07 23:08:59,522 MainThread      DEBUG    transaction    :390      Getting transaction 3
2019-07-07 23:08:59,522 MainThread      DEBUG    transaction    :189      Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
ReadRegisterResponse (2)

Коробка передач МОЖЕТ БЫТЬ не всегда, но она точно определяет причину проблемы и, следовательно, возможные решения.

Я пока не знаю, что у меня получится. Более стабильное железо точно.

Что касается модификации pymodbus или другого программного обеспечения в связи с этой проблемой, я хотел бы процитировать из следующий пост в другой угрозе:

Любой, кто запускает Modbus в многозадачной ОС, такой как Linux или Windows, никогда не сможет удовлетворить требованиям спецификации последовательного порта, это не обсуждается, задача обычно составляет 10 мс, поэтому выполнение требований по времени 3,5 мкс просто не подходит и никогда не будет .

Аппаратное решение предпочтительнее.

Благодаря Маркосу Г.

person Andreas    schedule 07.07.2019
comment
Я рад, что вам удалось приблизиться к рабочему решению, Андреас. Возможно, вы сможете повысить надежность решения, сократив задержки. Для Modbus вам нужно подождать 3,5 символа, то есть при используемой вами скорости передачи (115,2 кбит / с) около 0,3 мс (я думаю, что 3,5 микросекунды, которые вы указали, были опечаткой в ​​исходном сообщении). Если вы уменьшите время ожидания, скажем, до 0,5 мс, все должно работать довольно надежно. По крайней мере, это то, что я получил, когда играл с pymodbus. я - person Marcos G.; 08.07.2019
comment
Возможно, вы даже сможете полностью отказаться от задержки, если заставите pyserial работать в режиме блокировки (порт не вернется, пока все данные не будут записаны на шину; это должно быть возможно на Rpi, но это не вариант для большинство USB-адаптеров, поэтому я модифицировал свой кабель FTDI для использования сигнала TXEN). Если вы посмотрите исходный пост, который я привел выше, вы можете увидеть захваты области с помощью libmodbus. Я получал задержку в 500-600 микросекунд от последнего фронта до освобождения шины. - person Marcos G.; 08.07.2019
comment
Но, как вы говорите, в этом случае аппаратное решение было бы намного надежнее. Этот программный трюк достаточно хорош для нас, чтобы играть дома, но любая профессиональная реализация Modbus справится с этим с помощью оборудования. Или, может быть, с ОС реального времени. - person Marcos G.; 08.07.2019