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

Материал из Wiren Board
Строка 173: Строка 173:
С китайскими устройствами довольно частая ситуация, когда вы сделали шаблон, данные идут, но в логах сыпятся ошибки, а каналы устройства в веб-интерфейсе контроллера окрашивают красным.
С китайскими устройствами довольно частая ситуация, когда вы сделали шаблон, данные идут, но в логах сыпятся ошибки, а каналы устройства в веб-интерфейсе контроллера окрашивают красным.


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


Чтобы починить, попробуйте увеличить параметр <code>guard_interval_us</code> вплоть до тысяч единиц, например, 5000. Если работа стабилизируется, потихоньку уменьшайте это значение до тех пор, пока ошибки не появятся вновь. Предыдущее значение, когда всё работало хорошо и будет вашим значением в шаблоне.
Чтобы починить, попробуйте увеличить параметр <code>guard_interval_us</code> вплоть до тысяч единиц, например, 5000. Если работа стабилизируется, потихоньку уменьшайте это значение до тех пор, пока ошибки не появятся вновь. Предыдущее значение, когда всё работало хорошо и будет вашим значением в шаблоне.
Строка 179: Строка 179:
Ещё есть параметр <code>response_timeout_ms</code> — это максимальное время ответа устройств, подключенных к этому порту, в миллисекундах, по умолчанию 500 мс. С ним тоже можно аккуратно поэкспериментировать.
Ещё есть параметр <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 Диаграмме таймаутов цикла опроса].
Не выставляйте без нужны огромных значений в этих параметрах — это замедлит опрос устройств на канале, куда подключено проблемной устройство. Подробнее о том, как работают эти параметры, смотрите в [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 шаблона:
Оба параметра пишутся в секцию device шаблона:

Версия 09:59, 13 июля 2023

Введение

Рекомендуем сперва поискать ваше устройств в Таблице поддерживаемых устройств — вдруг оно уже там есть. Если устройства в списке нет, но оно поддерживает протокол Modbus, то его можно подключить к контроллеру Wiren Board.

Существует два вида протокола Modbus:

  1. Modbus RTU — устройства соединяются по шине RS-485.
  2. Modbus TCP — устройства соединяются по локальной сети через Wi-Fi или Ethernet.

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

  1. Ищете документацию на ваше устройство с описанием его modbus-регистров.
  2. Составляете шаблон для нашего драйвера wb-mqtt-serial.
  3. Копируете созданный шаблон на контроллер в папку
  4. Выбираете в веб-интерфейсе контроллера свой шаблон и указываете адрес.

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

Подготовка

Устройство с Modbus RTU:

  1. Откройте документацию на устройство и найдите описание modbus-регистров и параметров подключения (Baud rate, Data bits, Parity, Stop bits, Slave ID).
  2. Подключите устройство к контроллеру по шине RS-485.
  3. Проверьте связь с устройством и правильность подключения:
    • Остановите драйвер wb-mqtt-serial или иное ПО, которое опрашивает устройство.
    • Подключитесь к устройству с помощью утилиты modbus_client и считайте данные из любого известного вам регистра.

Устройство Modbus TCP:

  1. Откройте документацию на устройство и найдите описание modbus-регистров и настроек подключения (адрес, порт).
  2. Так как утилита modbus_client содержит ошибку, из-за которой она не может работать по протоколу Modbus TCP, то подключите устройство к компьютеру через Ethernet.
  3. Попробуйте считать из устройства значение одного известного вам регистра.

Если вы смогли получить содержимое регистра — вы всё делаете верно и можете продолжать.

Создание шаблона

Рассказать драйверу wb-mqtt-serial, который в контроллере работает с Modbus-устройствами можно двумя способами:

  1. Добавить регистры устройства прямо в веб-интерфейсе контроллера. Этот способ удобен для быстрой проверки работы.
  2. Создать шаблон, который описывает регистры устройства, их тип и другие параметры. Этот способ удобен для масштабирования: просто копируете шаблон на другой контроллер и в нём появляется поддержка вашего устройства.

Здесь мы рассмотрим создание простого шаблона. Упрощённо шаблон устройства выглядит так:

{
    "device_type": "my-relay",  // тип устройства  уникальный идентификатор
    "title": "My Relay",        // отображаемое название
    "group": "g-relay",         // группа, в которой будет отображаться шаблон. Список групп в документации
    "device": {                     
        "name": "MY-RELAY",     // имя устройства, используется в MQTT
        "id": "my-relay",
        "groups": [ ],          // группы параметров и каналов        
        "channels": [ ],        // каналы, доступно в скриптах и на вкладке Устройства
        "parameters": [ ],      // параметры, можно менять в настройках устройства
        "translations": { }     // переводы 
    }
}

Полное описание смотрите в документации драйвера wb-mqtt-serial.

Допустим, у нас есть одноканальное Modbus-реле, у которого таблица регистров, показанная ниже.

Адрес Тип Название Назначение
0 Discrete Input Input 1 Состояние входа устройства
1 Input Register Input 1 Counter Значение счётчика входов
3 Coil Relay 1 Состояние выхода и управление им
10 Holding Input Mode Выбор режима взаимодействия входов с выходами

В таком случае шаблон будет выглядеть так:

{
    "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": "Режим входа"
            }
        }
    }
}

Загрузка шаблона на контроллер

Когда шаблон готов, его надо загрузить на контроллер:

  1. Сохраните шаблон в файл, например, my-relay.json и загрузите его на контроллер в папку /etc/wb-mqtt-serial.conf.d/templates по инструкции.
  2. Проверьте шаблон на синтаксические ошибки командой:
    # wb-mqtt-serial -g
    <3>ERROR: [serial config] Failed to parse /etc/wb-mqtt-serial.conf.d/templates/my-best-template.json
    Failed to parse JSON /etc/wb-mqtt-serial.conf.d/templates/my-best-template.json:* Line 12, Column 5
      Missing ',' or '}' in object declaration
    
    в примере в шаблоне my-best-template.json в строке 12, символ 5 ожидается , or }, а находится что-то другое.
  3. Если с шаблоном всё в порядке, то перейдите в настройки драйвера и выберите ваш шаблон.

Отклонения от стандарта и что с ними делать

Оптимизация запросов драйвером

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

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

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

Нужное значение рассчитывается по формуле:

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

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

Если каналы устройства периодически мигают красным

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

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

Чтобы починить, попробуйте увеличить параметр guard_interval_us вплоть до тысяч единиц, например, 5000. Если работа стабилизируется, потихоньку уменьшайте это значение до тех пор, пока ошибки не появятся вновь. Предыдущее значение, когда всё работало хорошо и будет вашим значением в шаблоне.

Ещё есть параметр response_timeout_ms — это максимальное время ответа устройств, подключенных к этому порту, в миллисекундах, по умолчанию 500 мс. С ним тоже можно аккуратно поэкспериментировать.

Не выставляйте без нужны огромных значений в этих параметрах — это замедлит опрос устройств на канале, куда подключено проблемной устройство. Подробнее о том, как работают эти параметры, смотрите в Диаграмме таймаутов цикла опроса.

Оба параметра пишутся в секцию device шаблона:

"device": {
    "name": "BAC-6000ELNW",
    "id": "bac-6000elnw",
    "response_timeout_ms": 100,
    "guard_interval_us": 5000,
...
}

Разные регистры для чтения состояния и управления

Иногда в сторонних устройствах встречаются особенности:

  1. В некоторые регистры можно только писать информацию, но нельзя считывать.
  2. Один и тот же параметр может читаться по одному адресу, а записываться по другому.

Для того, чтобы драйвер работал с такими устройствами без ошибок, мы добавили параметр write_address.

Писать можно, читать нельзя

Допустим, в нашем устройстве есть такой регистр только для записи.

Адрес Тип Название Назначение
20 Coil Relay 1 Switch Управление выходом. Только для записи.

В этом случае канал надо описывать так:

{
    "name": "Relay 1 Switch",
    "write_address": "20",
    "reg_type": "coil",
    "type": "pushbutton",
    "format": "u16",
    "group": "channels",
    "on_value": 1 // определяет, что записывать в регистр при нажатии
}

Писать в один регистр, читать из другого

Допустим, в нашем устройстве команда записывается в один регистр, а читается из другого. Этот метод можно использовать только, если у обоих регистров один тип. Если типы разные — создавайте два разных канала: на чтение и на запись.

Адрес Тип Название Назначение
20 Coil Relay 1 Switch Управление выходом. Только для записи.
21 Coil Relay 1 State Состояние выхода. Только для чтения.

В этом случае канал надо описывать так: у нас будет один параметр в контроллере, но при обмене данными запись будет производиться один регистр, а чтение — из другого:

{
    "name": "Relay 1",
    "write_address": "20",   // адрес, куда мы записываем команды
    "address": "21",         // адрес, по которому мы читаем состояние    
    "reg_type": "coil",
    "type": "switch",
    "format": "u16",
    "group": "channels"
}

Произвольные значения в регистрах с бинарной логикой

Иногда бывает так, что по смыслу регистр должен представляться в веб-интерфейсе переключателем ВКЛ/ВЫКЛ, но допустимые значения у него не 1/0.

В этом случае вы описываете обычный канал с типом switch и указываете значения on_value и off_value, например:

{
  "name": "Status",
  "reg_type": "holding",
  "address": "0",
  "type": "switch",
  "format": "u16",
  "on_value": "0x00a5", // ВКЛ
  "off_value": "0x005a" // ВЫКЛ
}

Теперь драйвер будет автоматически при чтении конвертировать указанные значения в положение переключателя, а при изменении положения переключателя — записывать указанные значения.

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