Inter-frame delay и inter-character time-out

Добрый день!

Пробую написать реализацию modbus rtu для самодельного устройства для работы в связке с вашим контроллером. В свзяи с этим возник вопрос:

Согласно спецификации modbus, пауза между символами составляет 1.5 времени передачи одного символа на выбраной скорости, а пауза между кадрами 3.5 символа соответственно. При этом в той же спецификации есть рекомендация на скоростях выше 19200 не рассчитывать длительность пауз исходя из 1.5 и 3.5 символа, а использовать константные значения 750μs и 1.750ms для детектирования межсимвольных и межкадровых пауз соответственно. Собственно сам вопрос - ваши контроллеры используют именно такие таймиги на скоростях выше 19200? И что произойдёт если я всё таки буду использовать тайминги в 1.5 и 3.5 символа на высоких скоростях?

Добрый день!

Данные параметры настраиваются в конфиге драйвера wb-mqtt-serial.
Описание находится по этой ссылке: GitHub - wirenboard/wb-mqtt-serial: Wiren Board MQTT serial protocol driver · GitHub.

Сопоставил в своей тестовой аппаратной конфигурации (WB 8.4 + WB-MSW v.4) wb-mqtt-serial.conf и config-wb-msw_v4.json с описанием на GitHub. Есть некоторе количество непонятных моментов. А именно:

  1. Не нашел ничего про inter-character time-out
  2. Параметр min_request_interval в моих файлах ни где не фигурирует, а на GutHub не описано значение по умолчанию для этого параметра
  3. Значение параметра frame_timeout_ms в моём config-wb-msw_v4.json равно 0. Не ясно каким образом устройство определяет границы посылки?
  4. В комментариях к параметрам не однократно используется фраза “помечены как отключенные”, но кто (или что), при каких условиях, как и где их “помечает” не совсем ясно.
  5. В разделе “Особенности работы драйвера - Таймауты и количество неудачных циклов” не однозначно изложено использование типов таймаутов. По фразе “Можно использовать только один тип таймаута” сложилось не верное представление, что “два типа одновременно использовать нельзя”, однако это не так - пришлось “продираться” сквозь текст.

Добрый день!

На часть вопросов я не смогу ответить сразу: некоторые моменты нужно уточнить с коллегами. Для этого важно понять, какую именно задачу вы решаете.

В чем возникла необходимость в особой реализации Modbus RTU? То есть чем не устраивает исходная?
Wiren Board не отступает от классической версии протокола Modbus и полностью с ним совместим.

Отдельного параметра с таким названием в описании нет. Ближе всего по смыслу здесь frame_timeout_ms: он описан как минимально необходимая задержка между посылками, которая в некоторых протоколах используется для определения границ посылок. Для Modbus отдельно указан флаг force_frame_timeout: если он выключен, драйвер после получения ожидаемого числа байт ответа не ждёт дополнительный таймаут, а сразу переходит к следующему запросу. Также рядом описан guard_interval_us – дополнительная задержка перед записью в порт; для сторонних устройств рекомендуют ставить не меньше 3.5 символа на выбранной скорости.

Это необязательный параметр. В общей схеме конфигурации для него указано значение по умолчанию 0. При этом в примерах конфигурации могут встречаться и другие значения.

В общей схеме конфигурации для frame_timeout_ms по умолчанию указано 20 мс, однако в конкретных шаблонах устройств это значение может быть переопределено. Для наших устройств с Быстрым Modbus в шаблоне используется значение 0.

Драйвер помечает их сам. Устройство помечается отключённым, если в течение device_timeout_ms и более чем device_max_fail_cycles подряд циклов ни один из его регистров не был успешно прочитан.
Хорошо иллюстрирует работу цикла опроса эта диаграмма:

Имеется в виду, что можно использовать один из критериев отдельно или оба вместе. При совместном использовании срабатывание происходит при выполнении обоих условий. Чтобы оставить только один критерий, для второго нужно задать 0.

О особой реализации я ничего не писал. Моя задача - реализовать классический modbus “как минимум” и возможно позднее добавить к нему некоторые опции поддерживаемые вашими контроллерами. Например такими как ответ от слейва без предусмотренной спецификацией modbus паузы в 3.5 символа. Насколько я понимаю контроллер WB может принимать ответы в таком режиме. Главный вопрос касался как раз времени “тишины” между запросами от мастера и ответами от слейва. Как я написал в первом сообщении - спецификация подразумевает расчет этого “времени тишины” на основе установленной скорости порта по определенной формуле. Но этот расчет предлагается производить до скоростей порта 19200. В случае более высоких скоростей стандартом рекомендуется использовать фиксированые значения вне зависимости от установленной скорости передачи. Поскольку это всего лишь “рекомендация”, то я хотел выяснить следуете ли вы ей или нет в вашей реализации драйвера.

Нет, этот параметр не соответствует по смыслу inter-character time-out.

Inter-character time-out это максимальное время между передачей отдельных байтов посылки (фрейма). Использовать его можно для определения конца посылки либо для того что бы отвергнуть весь фрейм как “не полный”. То есть: если в течение inter-character time-out новый байт не поступил - значит фрейм закончен и можно приступать к его разбору. А указаный Вами frame_timeout_ms - это видимо то, что в спецификации называется inter-frame delay, то есть время, которое слейв должен выждать перед тем как начать овечать мастеру.

Если я правильно понял - это значение “в ручную” фиксируется в шаблонах устройств и не изменяется автоматически при изменении скорости порта? Тогда для меня становится совсем не ясно как это соотносится со спецификацией modbus.

Да, это я уже понял. Я просто хотел обратить ваше внимание на формулировку, допускающую не однозначную трактовку.

PS: Возможно я в той или иной мере заблуждаюсь в своих выводах или задаю “не правильные” вопросы. Но всё же надеюсь разобраться с вашей помощью.

Именно он.
Если включить force_frame_timeout GitHub - wirenboard/wb-mqtt-serial: Wiren Board MQTT serial protocol driver · GitHub

Максимальное вермя между байтами - 1,5 времени одного байта на текущей скорости.
Зависит от скорости, при измерении скорости соответственно уменьшается пропорционально, в отличии от межкадрового.
Вот тут в случае истечения счетчика переключается на межкадровый.

1 Like

То есть это всегда будет t1.5 на любой скорости? Даже на скоростях выше 19200?

А межкадровое всегда постоянно,не зависит от скорости и задано в шаблоне устройства?

PS: посмотрел код по ссылке, но честно говоря не достаточно знаком C++, пишу на ассемблере.

Да. Максимальное значение, после которого начнет тикать таймер “конец фрейма”. Наши устройства не делают задержек между байтами, она так-то не нужна.

Оно типично не задается. Даже для сторонних устройств которые начинают ответ спустя сотню миллисекунд после окончания передачи запроса - нет проблема с таймингом между байтами. Поскольку реализация как правило самой передачи - аппаратная, то есть обработчик прерывания конца передачи если в буфере что-то есть отдает в регистр передатчика следующий байт.

В шаблоне можно поменять таймаут, конечно. Но это если устройство явно затягивает ответ.