Connecting Third Party Devices to Wiren Board: различия между версиями

Материал из Wiren Board
(добавил информацию про обнаружение устройств)
(не показано 46 промежуточных версий 3 участников)
Строка 1: Строка 1:
{{DISPLAYTITLE: Как писать шаблоны для сторонних Modbus-устройств}}
{{DISPLAYTITLE: Как подключить Modbus RTU-устройство стороннего производителя к контроллеру Wirenboard?}}
== Введение ==
== Введение ==
Рекомендуем сперва поискать ваше устройств в [[Supported_devices | Таблице поддерживаемых устройств]] — вдруг оно уже там есть. Если устройства в списке нет, но оно поддерживает протокол [[Modbus|Modbus]], то его можно подключить к контроллеру Wiren Board.
Modbus RTU — один из распространенных протоколов для связи устройств. Если устройство стороннего производителя поддерживает протокол Modbus RTU, то его можно подключить к контроллеру Wirenboard.


Существует два вида протокола Modbus:
Список всех поддерживаемых контроллером протоколов можно найти в [[Supported_devices | Таблице поддерживаемых устройств]].  
# Modbus RTU — устройства соединяются по шине RS-485.
# Modbus TCP — устройства соединяются по локальной сети через Wi-Fi или Ethernet.
 
Независимо от вида протокола, алгоритм добавления поддержки устройства в наш контроллер будет такой:
# Ищете документацию на ваше устройство с описанием его modbus-регистров.
# Составляете шаблон для нашего драйвера [[wb-mqtt-serial]].
# Копируете созданный шаблон на контроллер в папку
# Выбираете в веб-интерфейсе контроллера свой шаблон и указываете адрес.


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


== Подготовка ==
== Подключите устройство ==
Устройство с Modbus RTU:
Для подключения стороннего устройства по протоколу Modbus RTU:
# Откройте документацию на устройство и найдите описание modbus-регистров и параметров подключения (Baud rate, Data bits, Parity, Stop bits, Slave ID).
# Откройте документацию на устройство и убедитесь, что оно имеет интерфейс RS-485 и поддерживает протокол Modbus RTU.
# Проверьте, нет ли вашего устройства в [[Supported_devices | Таблице поддерживаемых устройств]]. Если устройство там есть — используйте указанные в таблице рекомендации по подключению.
# Определите, какая информация вам нужна и в каких регистрах она находится.
# Подключите устройство к контроллеру по [[RS-485 | шине RS-485]].
# Подключите устройство к контроллеру по [[RS-485 | шине RS-485]].
# Узнайте в документации на устройство параметры подключения: скорость (Baud rate), Количество битов данных (Data bits), Бит чётности (Parity), Количество стоповых битов (Stop bits), Modbus-адрес устройства.
# Проверьте связь с устройством и правильность подключения:
# Проверьте связь с устройством и правильность подключения:
#* {{Wbincludes:Stop wb-mqtt-serial}}
#* {{Wbincludes:Stop wb-mqtt-serial}}
#* Подключитесь к устройству с помощью утилиты [[modbus_client]] и считайте данные из любого известного вам регистра.  
#* Подключитесь к устройству с помощью утилиты [[modbus_client]] и считайте данные из любого известного вам регистра.  
Если чтение данных пройдёт успешно — вы верно подключили устройство и настроили параметры соединения.


Устройство Modbus TCP:
== Поиск подключенных устройств на шине ==
# Откройте документацию на устройство и найдите описание modbus-регистров и настроек подключения (адрес, порт).
После физического подключения устройства не всегда получается сразу установить с ним связь: параметры обмена могут быть неизвестны или забыты. Для этого можно воспользоваться утилитой [[Wb-mb-explorer | '''wb-mb-explorer''']]. Она позволяет просканировать шину на наличие устройств: проверить наличие подключенных устройств с указанными параметрами обмена, подобрать параметры обмена для устройства с указанным адресом, провести полный перебор все возможных комбинаций параметров обмена. Если будет обнаружено устройство Wirenboard, то для него будет выведена информация о модели устройства, его серийном номере, версии прошивки и параметрах обмена. Для стороннего modbus-устройства будут выведены только параметры обмена.
# Утилита ''modbus_client'' в релизах до 2304 содержит ошибку, из-за которой она не может работать по протоколу Modbus TCP. Если успользуете устаревший релиз, то подключите устройство к компьютеру через Ethernet.
# Попробуйте [[Working_with_WB_devices_without_a_controller |считать из устройства]] значение одного известного вам регистра.
 
Если вы смогли получить содержимое регистра — вы всё делаете верно и можете продолжать.
 
== Создание шаблона ==
Рассказать драйверу wb-mqtt-serial, который в контроллере работает с Modbus-устройствами можно двумя способами:
# [[RS-485:Configuration_via_Web_Interface#without-template|Добавить регистры]] устройства прямо в веб-интерфейсе контроллера. Этот способ удобен для быстрой проверки работы.
# Создать шаблон, который описывает регистры устройства, их тип и другие параметры. Этот способ удобен для масштабирования: просто копируете шаблон на другой контроллер и в нём появляется поддержка вашего устройства.
 
Здесь мы рассмотрим создание простого шаблона. Упрощённо шаблон устройства выглядит так:
<syntaxhighlight lang="json">
{
    "device_type": "my-relay", // тип устройства — уникальный идентификатор
    "title": "My Relay",       // отображаемое название
    "group": "g-relay",         // группа, в которой будет отображаться шаблон. Список групп в документации
    "device": {                   
        "name": "MY-RELAY",    // имя устройства, используется в MQTT
        "id": "my-relay",
        "groups": [ ],          // группы параметров и каналов       
        "channels": [ ],        // каналы, доступно в скриптах и на вкладке Устройства
        "parameters": [ ],      // параметры, можно менять в настройках устройства
        "translations": { }    // переводы
    }
}
</syntaxhighlight>
'''Полное описание смотрите в [https://github.com/wirenboard/wb-mqtt-serial документации драйвера wb-mqtt-serial на Github].'''
 
Допустим, у нас есть одноканальное Modbus-реле, у которого таблица регистров, показанная ниже.
{|  border="1" class="wikitable"
! Адрес || Тип || Название || Назначение
|-
| 0 || Discrete Input || Input 1 ||  Состояние входа устройства
|-
| 1 || Input Register || Input 1 Counter ||  Значение счётчика входов
|-
| 3 || Coil || Relay 1 ||  Состояние выхода и управление им
|-
| 10 || Holding || Input Mode ||  Выбор режима взаимодействия входов с выходами
|-
|}
 
В таком случае шаблон будет выглядеть так:
<syntaxhighlight lang="json">
{
    "device_type": "my-relay",
    "title": "My Relay",
    "group": "g-relay",
    "device": {
        "name": "MY-RELAY",
        "id": "my-relay",
        "groups": [
            {
                "title": "Channels",
                "id": "channels",
                "order": 0
            },
            {
                "title": "Settings",
                "id": "settings",
                "order": 1
            }
        ],
        "channels": [
            {
                "name": "Input 1",
                "reg_type": "discrete",
                "address": 1,
                "type": "switch",
                "group": "channels"
            },
            {
                "name": "Input 1 Counter",
                "reg_type": "input",
                "address": 2,
                "type": "value",
                "group": "channels"
            },
            {
                "name": "Relay 1",
                "reg_type": "coil",
                "address": 3,
                "type": "switch",
                "group": "channels"
            }
        ],
        "parameters": [
            {
                "id": "input1",
                "title": "Input Mode",
                "reg_type": "input",
                "address": 10,
                "format": "s8",
                "enum": [
                    1,
                    2
                ],
                "enum_titles": [
                    "Switch Relay",
                    "Not used"
                ],
                "default": 1
            }
        ],
        "translations": {
            "ru": {
                "Channels": "Каналы",
                "Settings": "Настройки",
                "Input 1": "Вход 1",
                "Input 1 Counter": "Вход 1 счетчик",
                "Relay 1": "Реле 1",
                "Input Mode": "Режим входа"
            }
        }
    }
}
</syntaxhighlight>


== Загрузка шаблона на контроллер ==
== Создайте шаблон ==
Когда шаблон готов, его надо загрузить на контроллер:
Для удобства использования устройства [https://github.com/wirenboard/wb-mqtt-serial#%D0%A4%D0%B0%D0%B9%D0%BB-%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D0%B8-%D0%B8-%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D1%8B создайте шаблон для драйвера wb-mqtt-serial] в шаблоне укажите:
# Сохраните шаблон в файл, например, <code>my-relay.json</code> и загрузите его на контроллер в папку <code>/etc/wb-mqtt-serial.conf.d/templates</code> по [[View_controller_files_from_your_computer|инструкции]].
* регистры, в которых хранятся нужные вам данные;
# Проверьте шаблон на синтаксические ошибки командой:
* параметры инициализации, если они необходимы;
#:<syntaxhighlight lang="bash">
* обязательно в шаблоне задайте параметр <code>guard_interval_us</code> (задержка перед записью каждого запроса в порт), значение которого должно быть не менее 3.5 символа при выбранной скорости. Нужное значение рассчитывается по формуле:
# wb-mqtt-serial -g
<code>guard_interval_us = (3.5*11*10<sup>6</sup>)/(скорость в бит/с)</code>.  
<3>ERROR: [serial config] Failed to parse /etc/wb-mqtt-serial.conf.d/templates/my-best-template.json
<p>Например, для скорости 9600 бит/с <code>guard_interval_us = (3.5*11*10<sup>6</sup>)/9600 = 4000 мкс</code>. При проблемах с подключением стороннего устройства для теста это значение можно увеличить (например до 100000 мкс), так как сторонние устройства иногда работают не совсем корректно.</p>
Failed to parse JSON /etc/wb-mqtt-serial.conf.d/templates/my-best-template.json:* Line 12, Column 5
* для проверки корректности шаблона выполните на контроллере команду <code>wb-mqtt-serial -g</code>.
  Missing ',' or '}' in object declaration
Эта команда проверит на корректность файлы шаблонов в директориях <code>/usr/share/wb-mqtt-serial/templates</code> (директория предустановленных шаблонов) и <code>/etc/wb-mqtt-serial.conf.d/templates</code> (директория для пользовательских шаблонов). Если в шаблонах содержатся ошибки, то на экран будут выведены диагностические сообщения с указанием имени шаблона и ошибка.
</syntaxhighlight>
#: в примере в шаблоне ''my-best-template.json'' в строке 12, символ 5 ожидается <code>,</code> or <code>}</code>, а находится что-то другое.
# Если с шаблоном всё в порядке, то перейдите в настройки драйвера и [[RS-485:Configuration_via_Web_Interface|выберите ваш шаблон]].


== Отклонения от стандарта и что с ними делать ==
== Особенности реализации Modbus RTU в устройствах Wiren Board ==
=== Оптимизация запросов драйвером ===
Стандартом Modbus RTU предусмотрен обязательный интервал тишины в 3.5 символа между фреймами данных (под символом подразумевается посылка, состоящая из стартового бита, битов данных, бита четности и стоп-битов).
Стандартом Modbus RTU предусмотрен обязательный интервал тишины в 3.5 символа между фреймами данных (под символом подразумевается посылка, состоящая из стартового бита, битов данных, бита четности и стоп-битов).


Строка 164: Строка 39:
Поэтому, чтобы соответствовать требованиям протокола Modbus-RTU, нужно для сторонних устройств задавать параметр ''guard_interval_us''. Этот параметр задает задержку перед записью каждого запроса в порт.
Поэтому, чтобы соответствовать требованиям протокола Modbus-RTU, нужно для сторонних устройств задавать параметр ''guard_interval_us''. Этот параметр задает задержку перед записью каждого запроса в порт.


Нужное значение рассчитывается по формуле:
== Совместная работа модулей Wiren Board и устройств сторонних производителей на одной шине==
<syntaxhighlight lang="bash">
При работе модулей Wirenboard и устройств сторонних производителей на одной шине RS-485 параметр <code>guard_interval_us</code> следует задавать целиком для порта, также следует изменить параметр '''RS-485 Response Delay (ms)''' (Задержка перед ответом по RS-485) у модулей Wirenboard (если такой параметр имеется), например установив значение 8 мс. Это необходимо, так как несоблюдение интервалов тишины при обращении к модулям Wirenboard приводит к сбою в работе некоторых устройств сторонних производителей.
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>
 
=== Разные регистры для чтения состояния и управления ===
Иногда в сторонних устройствах встречаются особенности:
# В некоторые регистры можно только писать информацию, но нельзя считывать.
# Один и тот же параметр может читаться по одному адресу, а записываться по другому.
 
Для того, чтобы драйвер работал с такими устройствами без ошибок, мы добавили параметр '''write_address'''.
 
==== Писать можно, читать нельзя ====
Допустим, в нашем устройстве есть такой регистр только для записи.
 
{|  border="1" class="wikitable"
! Адрес || Тип || Название || Назначение
|-
| 20 || Coil || Relay 1 Switch ||  Управление выходом. Только для записи.
|-
|}
 
В этом случае канал надо описывать так:
<syntaxhighlight lang="json">
{
    "name": "Relay 1 Switch",
    "write_address": "20",
    "reg_type": "coil",
    "type": "pushbutton",
    "format": "u16",
    "group": "channels",
    "on_value": 1 // определяет, что записывать в регистр при нажатии
}
</syntaxhighlight>
 
==== Писать в один регистр, читать из другого====
Допустим, в нашем устройстве команда записывается в один регистр, а читается из другого. Этот метод можно использовать только, если у обоих регистров один тип. Если типы разные — создавайте два разных канала: на чтение и на запись.
 
{|  border="1" class="wikitable"
! Адрес || Тип || Название || Назначение
|-
| 20 || Coil || Relay 1 Switch||  Управление выходом. Только для записи.
|-
| 21 || Coil || Relay 1 State||  Состояние выхода. Только для чтения.
|-
|}
 
В этом случае канал надо описывать так: у нас будет один параметр в контроллере, но при обмене данными запись будет производиться один регистр, а чтение — из другого:
<syntaxhighlight lang="json">
{
    "name": "Relay 1",
    "write_address": "20",  // адрес, куда мы записываем команды
    "address": "21",         // адрес, по которому мы читаем состояние   
    "reg_type": "coil",
    "type": "switch",
    "format": "u16",
    "group": "channels"
}
</syntaxhighlight>
 
=== Произвольные значения в регистрах с бинарной логикой ===
Иногда бывает так, что по смыслу регистр должен представляться в веб-интерфейсе переключателем ВКЛ/ВЫКЛ, но допустимые значения у него не 1/0.
 
В этом случае вы описываете обычный канал с типом '''switch''' и указываете значения <code>on_value</code> и <code>off_value</code>, например:
 
<syntaxhighlight lang="json">
{
  "name": "Status",
  "reg_type": "holding",
  "address": "0",
  "type": "switch",
  "format": "u16",
  "on_value": "0x00a5", // ВКЛ
  "off_value": "0x005a" // ВЫКЛ
}
</syntaxhighlight>
Теперь драйвер будет автоматически при чтении конвертировать указанные значения в положение переключателя, а при изменении положения переключателя — записывать указанные значения.


== Полезные ссылки ==
== Полезные ссылки ==
Строка 270: Строка 47:
* [[RS-485|Описание шины RS-485]]
* [[RS-485|Описание шины RS-485]]
* [https://github.com/wirenboard/wb-mqtt-serial Документация wb-mqtt-serial]
* [https://github.com/wirenboard/wb-mqtt-serial Документация wb-mqtt-serial]
* [https://github.com/wirenboard/conventions/blob/main/README.md Описание соглашений MQTT]
* [https://github.com/wirenboard/homeui/blob/master/conventions.md Описание соглашений MQTT]
* [http://json.parser.online.fr Онлайн проверка JSON]
* [http://json.parser.online.fr Онлайн проверка JSON]
* Темы на портале:
* Темы на форуме:
** [https://support.wirenboard.com/t/oshibki-pri-chtenii-bolid-s2000-pp/8080 Ошибки при чтении Bolid С2000-ПП]
** [https://support.wirenboard.com/t/oshibki-pri-chtenii-bolid-s2000-pp/8080 Ошибки при чтении Bolid С2000-ПП]
** [https://support.wirenboard.com/t/request-timed-out/8344/17 Request timed out]
** [https://support.wirenboard.com/t/request-timed-out/8344/17 Request timed out]

Версия 09:56, 30 июня 2022

Введение

Modbus RTU — один из распространенных протоколов для связи устройств. Если устройство стороннего производителя поддерживает протокол Modbus RTU, то его можно подключить к контроллеру Wirenboard.

Список всех поддерживаемых контроллером протоколов можно найти в Таблице поддерживаемых устройств.

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

Подключите устройство

Для подключения стороннего устройства по протоколу Modbus RTU:

  1. Откройте документацию на устройство и убедитесь, что оно имеет интерфейс RS-485 и поддерживает протокол Modbus RTU.
  2. Проверьте, нет ли вашего устройства в Таблице поддерживаемых устройств. Если устройство там есть — используйте указанные в таблице рекомендации по подключению.
  3. Определите, какая информация вам нужна и в каких регистрах она находится.
  4. Подключите устройство к контроллеру по шине RS-485.
  5. Узнайте в документации на устройство параметры подключения: скорость (Baud rate), Количество битов данных (Data bits), Бит чётности (Parity), Количество стоповых битов (Stop bits), Modbus-адрес устройства.
  6. Проверьте связь с устройством и правильность подключения:
    • Остановите драйвер wb-mqtt-serial или иное ПО, которое опрашивает устройство.
    • Подключитесь к устройству с помощью утилиты modbus_client и считайте данные из любого известного вам регистра.

Если чтение данных пройдёт успешно — вы верно подключили устройство и настроили параметры соединения.

Поиск подключенных устройств на шине

После физического подключения устройства не всегда получается сразу установить с ним связь: параметры обмена могут быть неизвестны или забыты. Для этого можно воспользоваться утилитой wb-mb-explorer. Она позволяет просканировать шину на наличие устройств: проверить наличие подключенных устройств с указанными параметрами обмена, подобрать параметры обмена для устройства с указанным адресом, провести полный перебор все возможных комбинаций параметров обмена. Если будет обнаружено устройство Wirenboard, то для него будет выведена информация о модели устройства, его серийном номере, версии прошивки и параметрах обмена. Для стороннего modbus-устройства будут выведены только параметры обмена.

Создайте шаблон

Для удобства использования устройства создайте шаблон для драйвера wb-mqtt-serial в шаблоне укажите:

  • регистры, в которых хранятся нужные вам данные;
  • параметры инициализации, если они необходимы;
  • обязательно в шаблоне задайте параметр guard_interval_us (задержка перед записью каждого запроса в порт), значение которого должно быть не менее 3.5 символа при выбранной скорости. Нужное значение рассчитывается по формуле:

guard_interval_us = (3.5*11*106)/(скорость в бит/с).

Например, для скорости 9600 бит/с guard_interval_us = (3.5*11*106)/9600 = 4000 мкс. При проблемах с подключением стороннего устройства для теста это значение можно увеличить (например до 100000 мкс), так как сторонние устройства иногда работают не совсем корректно.

  • для проверки корректности шаблона выполните на контроллере команду wb-mqtt-serial -g.

Эта команда проверит на корректность файлы шаблонов в директориях /usr/share/wb-mqtt-serial/templates (директория предустановленных шаблонов) и /etc/wb-mqtt-serial.conf.d/templates (директория для пользовательских шаблонов). Если в шаблонах содержатся ошибки, то на экран будут выведены диагностические сообщения с указанием имени шаблона и ошибка.

Особенности реализации Modbus RTU в устройствах Wiren Board

Стандартом Modbus RTU предусмотрен обязательный интервал тишины в 3.5 символа между фреймами данных (под символом подразумевается посылка, состоящая из стартового бита, битов данных, бита четности и стоп-битов).

Для ускорения опроса устройств Wiren Board мы соблюдаем этот интервал только перед первым запросом к следующему в цикле опроса устройству (параметр frame_timeout_ms в шаблонах устройств).

Поэтому, чтобы соответствовать требованиям протокола Modbus-RTU, нужно для сторонних устройств задавать параметр guard_interval_us. Этот параметр задает задержку перед записью каждого запроса в порт.

Совместная работа модулей Wiren Board и устройств сторонних производителей на одной шине

При работе модулей Wirenboard и устройств сторонних производителей на одной шине RS-485 параметр guard_interval_us следует задавать целиком для порта, также следует изменить параметр RS-485 Response Delay (ms) (Задержка перед ответом по RS-485) у модулей Wirenboard (если такой параметр имеется), например установив значение 8 мс. Это необходимо, так как несоблюдение интервалов тишины при обращении к модулям Wirenboard приводит к сбою в работе некоторых устройств сторонних производителей.

Полезные ссылки