1
правка
(адреса в примере и коде json-файла отличаются) |
|||
(не показано 17 промежуточных версий 3 участников) | |||
Строка 1: | Строка 1: | ||
{{DISPLAYTITLE: | {{DISPLAYTITLE: Как писать шаблоны для сторонних Modbus-устройств}} | ||
== Введение == | == Введение == | ||
Рекомендуем сперва поискать ваше устройств в [[Supported_devices | Таблице поддерживаемых устройств]] — вдруг оно уже там есть. Если устройства в списке нет, но оно поддерживает протокол [[Modbus|Modbus]], то его можно подключить к контроллеру Wiren Board. | Рекомендуем сперва поискать ваше устройств в [[Supported_devices | Таблице поддерживаемых устройств]] — вдруг оно уже там есть. Если устройства в списке нет, но оно поддерживает протокол [[Modbus|Modbus]], то его можно подключить к контроллеру Wiren Board. | ||
Строка 25: | Строка 25: | ||
Устройство Modbus TCP: | Устройство Modbus TCP: | ||
# Откройте документацию на устройство и найдите описание modbus-регистров и настроек подключения (адрес, порт). | # Откройте документацию на устройство и найдите описание modbus-регистров и настроек подключения (адрес, порт). | ||
# | # Утилита ''modbus_client'' в релизах до 2304 содержит ошибку, из-за которой она не может работать по протоколу Modbus TCP. Если успользуете устаревший релиз, то подключите устройство к компьютеру через Ethernet. | ||
# Попробуйте считать из устройства значение одного известного вам регистра | # Попробуйте [[Working_with_WB_devices_without_a_controller |считать из устройства]] значение одного известного вам регистра. | ||
Если вы смогли получить содержимое регистра — вы всё делаете верно и можете продолжать. | Если вы смогли получить содержимое регистра — вы всё делаете верно и можете продолжать. | ||
Строка 32: | Строка 32: | ||
== Создание шаблона == | == Создание шаблона == | ||
Рассказать драйверу wb-mqtt-serial, который в контроллере работает с Modbus-устройствами можно двумя способами: | Рассказать драйверу wb-mqtt-serial, который в контроллере работает с Modbus-устройствами можно двумя способами: | ||
# | # [[RS-485:Configuration_via_Web_Interface#without-template|Добавить регистры]] устройства прямо в веб-интерфейсе контроллера. Этот способ удобен для быстрой проверки работы. | ||
# Создать шаблон, который описывает регистры устройства, их тип и другие параметры. Этот способ удобен для масштабирования: просто копируете шаблон на другой контроллер и в нём появляется поддержка вашего устройства. | # Создать шаблон, который описывает регистры устройства, их тип и другие параметры. Этот способ удобен для масштабирования: просто копируете шаблон на другой контроллер и в нём появляется поддержка вашего устройства. | ||
Строка 51: | Строка 51: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Полное описание смотрите в [https://github.com/wirenboard/wb-mqtt-serial документации драйвера wb-mqtt-serial]. | '''Полное описание смотрите в [https://github.com/wirenboard/wb-mqtt-serial документации драйвера wb-mqtt-serial на Github].''' | ||
Допустим, у нас есть одноканальное Modbus-реле, у которого таблица регистров, показанная ниже. | Допустим, у нас есть одноканальное Modbus-реле, у которого таблица регистров, показанная ниже. | ||
Строка 92: | Строка 92: | ||
"name": "Input 1", | "name": "Input 1", | ||
"reg_type": "discrete", | "reg_type": "discrete", | ||
"address": | "address": 0, | ||
"type": "switch", | "type": "switch", | ||
"group": "channels" | "group": "channels" | ||
Строка 99: | Строка 99: | ||
"name": "Input 1 Counter", | "name": "Input 1 Counter", | ||
"reg_type": "input", | "reg_type": "input", | ||
"address": | "address": 1, | ||
"type": "value", | "type": "value", | ||
"group": "channels" | "group": "channels" | ||
Строка 154: | Строка 154: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
#: в примере в шаблоне ''my-best-template.json'' в строке 12, символ 5 ожидается <code>,</code> or <code>}</code>, а находится что-то другое. | #: в примере в шаблоне ''my-best-template.json'' в строке 12, символ 5 ожидается <code>,</code> or <code>}</code>, а находится что-то другое. | ||
# Если с шаблоном всё в порядке, то перейдите в настройки драйвера и | # Если с шаблоном всё в порядке, то перейдите в настройки драйвера и [[RS-485:Configuration_via_Web_Interface|выберите ваш шаблон]]. | ||
== Отклонения от стандарта и что с ними делать == | == Отклонения от стандарта и что с ними делать == | ||
=== Оптимизация запросов драйвером === | === Оптимизация запросов драйвером === | ||
Стандартом Modbus RTU предусмотрен обязательный интервал тишины в 3.5 символа между фреймами данных (под символом подразумевается посылка, состоящая из стартового бита, битов данных, бита четности и стоп-битов). | Стандартом Modbus RTU предусмотрен обязательный интервал тишины в 3.5 символа между фреймами данных (под символом подразумевается посылка, состоящая из стартового бита, битов данных, бита четности и стоп-битов). | ||
Строка 168: | Строка 166: | ||
Нужное значение рассчитывается по формуле: | Нужное значение рассчитывается по формуле: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
guard_interval_us = (3.5*11* | guard_interval_us = (3.5*11*10^6)/(скорость в бит/с). | ||
</syntaxhighlight> | |||
Например, для скорости 9600 бит/с <code>guard_interval_us = (3.5*11*10^6)/9600 = 4000 мкс</code>. При проблемах с подключением стороннего устройства для теста это значение можно увеличить (например до 100000 мкс), так как сторонние устройства иногда работают не совсем корректно. | |||
=== Если каналы устройства периодически мигают красным === | |||
Со сторонними устройствами довольно частая ситуация, когда вы сделали шаблон, данные идут, но в логах сыпятся ошибки, а каналы устройства в веб-интерфейсе контроллера окрашивают красным. | |||
Основная причина этому — устройство слишком медленно обрабатывает запросы нашего драйвера. Для начала мы рекомендуем подключить такие устройства на отдельную шину, чтобы они не тормозили работу нормальных устройств, а потом использовать рекомендации ниже. | |||
Чтобы починить, попробуйте увеличить параметр <code>guard_interval_us</code> вплоть до тысяч единиц, например, 5000. Если работа стабилизируется, потихоньку уменьшайте это значение до тех пор, пока ошибки не появятся вновь. Предыдущее значение, когда всё работало хорошо и будет вашим значением в шаблоне. | |||
Ещё есть параметр <code>response_timeout_ms</code> — это максимальное время ответа устройства в миллисекундах, по умолчанию 500 мс. С ним тоже можно аккуратно поэкспериментировать. | |||
Не выставляйте без нужды огромных значений в этих параметрах — это замедлит опрос устройств на порту, куда подключено проблемное устройство. Подробнее о том, как работают эти параметры, смотрите в [https://github.com/wirenboard/wb-mqtt-serial#%D0%94%D0%B8%D0%B0%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0-%D1%82%D0%B0%D0%B9%D0%BC%D0%B0%D1%83%D1%82%D0%BE%D0%B2-%D1%86%D0%B8%D0%BA%D0%BB%D0%B0-%D0%BE%D0%BF%D1%80%D0%BE%D1%81%D0%B0 Диаграмме таймаутов цикла опроса]. | |||
Оба параметра пишутся в секцию device шаблона: | |||
<syntaxhighlight lang="json"> | |||
"device": { | |||
"name": "BAC-6000ELNW", | |||
"id": "bac-6000elnw", | |||
"response_timeout_ms": 100, | |||
"guard_interval_us": 5000, | |||
... | |||
} | |||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Разные регистры для чтения состояния и управления === | === Разные регистры для чтения состояния и управления === | ||
Строка 203: | Строка 223: | ||
==== Писать в один регистр, читать из другого==== | ==== Писать в один регистр, читать из другого==== | ||
Допустим, в нашем устройстве команда записывается в один регистр, а читается из другого. Этот метод можно использовать только, если у обоих регистров один тип. Если типы разные — создавайте два разных | Допустим, в нашем устройстве команда записывается в один регистр, а читается из другого. Этот метод можно использовать только, если у обоих регистров один тип. Если типы разные — создавайте два разных канала: на чтение и на запись. | ||
{| border="1" class="wikitable" | {| border="1" class="wikitable" | ||
Строка 214: | Строка 234: | ||
|} | |} | ||
В этом случае канал надо описывать так | В этом случае канал надо описывать так: у нас будет один параметр в контроллере, но при обмене данными запись будет производиться один регистр, а чтение — из другого: | ||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
{ | { | ||
Строка 239: | Строка 259: | ||
"type": "switch", | "type": "switch", | ||
"format": "u16", | "format": "u16", | ||
"on_value": "0x00a5", | "on_value": "0x00a5", // ВКЛ | ||
"off_value": "0x005a" | "off_value": "0x005a" // ВЫКЛ | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Теперь драйвер будет автоматически при чтении конвертировать указанные значения в положение переключателя, а при изменении положения переключателя — записывать указанные значения. | |||
== Полезные ссылки == | == Полезные ссылки == |
правка