Подключение новых модулей к Wiren Board 4/5

Добрый день!
Мои коллеги готовят прошивку для модулей с интерфейсом RS-485 и протоколом modbus, а я готовлюсь подключать их к WB4. Поэтому прошу ответить на несколько вопросов, касающихся подключения новых типов модулей к контроллеру.

Вопросы:

  1. Для подключения нового типа модулей нужно:

    • добавить файл описания типа в новом файле config-wb-тип.json в каталог /usr/share/wb-homa-modbus/templates;
    • включить в файл /etc/wb-homa-modbus.conf описание устройства.
      Этого достаточно? Как составлять имя файла для новых модулей: config-wb-тип.json или это не принципиально?

    При этом, позволено описывать тип (описание каналов) в файле wb-homa-modbus.conf. Что происходит, если описание одного и того же типа есть и в шаблонах и в конфиге? Мне представляется, что описание каналов приоритетно из etc/.conf, а на самом деле?

  2. В config-wb-тип.json нет указания на номера функций, используемых для каналов. Вероятно, функция определяется типом регистра (coil, holding register и т.д.). Какие функции обязательно должны быть реализованы в модуле, чтобы без проблем можно подключить его к WB4?

Я спрашиваю потому, что наши модули, например, не стали работать с Spider 2 (http://www.insyte.ru/catalog/detail/tsentralnyy-kontroller-landrive-spider2/) из-за того, что коллеги реализовали не весь набор функций по протоколу modbus. При этом имеющихся функций для меня хватает, чтобы работать с модулем через преобразователь интерфейса Moxa NPort. Я понимаю, что WB4 использует функции libmodbus, в которых нет явного указания на коды функций. Но, может быть, есть таблица соответствия reg_type с номерами функций? Хотелось бы получить эту информацию.

  1. Для устройств uniel есть замечательная конструкция adress вида “0x0100WWRR”. Можно ли использовать ее для любых устройств, поддерживающих протокол modbus rtu?

  2. Правила описания типа предполагает, что канал (секция channels) связан с одним регистром. Исключение - rgb. Как добавить новые интегральные типы, используя конструкцию “consists_of”? Ну, очень хорошая конструкция;)

К примеру, в модуле http://www.insyte.ru/catalog/detail/releynyy-modul-ld2-r1000d/ для одного счетчика используется 2 регистра. Конечно, я всегда могу обработать пару-тройку регистров и выдать пользователю нужные данные. Но это неэффективно - опрос трех регистров идет последовательно. Я предпочел бы, например, чтобы была возможность прочесть одновременно десяток смежных регистров, чтобы потом полученные данные разделить на каналы.
Мне известно, что в драйвере modbus такая возможность заложена. Может быть, я мог бы воспользоваться этой возможностью? Не могли бы вы подсказать, в каких модулях это реализовано?

Как изменения внедрить в ПО WB4? Скопировать исходники в home, останавить wb-homa-modbus, потом make, make install? Подскажите, пожалуйста последовательность команд.

Информацию о версии прошивки WB4 дать не могу - не знаю как это получить, и не нашел в описании. Ничего не менял, купили в июне этого года. Нужно обновиться (вроде все, что я использую, работает. Но я за то, чтобы работать на самом новом софте)?

С уважением, Сергей.

Добрый день!

Во-первых, документация есть тут:
http://contactless.ru/wiki/index.php/Драйвер_wb-homa-modbus
https://github.com/contactless/wb-homa-drivers/blob/master/wb-homa-modbus/README.md

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

да

не принципиально, поиск идёт по значению поля “device_type” в темплейте.

В wb-homa-modbus.conf вы описываете не тип, а конкретное устройство. Вы можете для него указать тип и, дополнительно, описать какие-то дополнительные каналы, которых нет в темплейте.

Номера функций определяются стандартом Modbus.

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

Если вы хотите сделать нестандартные устройства и поддержать только определённые функции, только чтобы обеспечить совместимость с нашим драйвером, то можно не реализовывать WriteMultipleCoils. Также, драйвер использует WriteSingleRegister для записи одного регистра и WriteMultipleRegisters для записи нескольких.
Это поведение мы естественно можем поменять в любой момент.

Это всё очень неконкретно, дайте пожалуйста больше информации.

Вы неправильно понимаете. Ещё раз, “коды функций” определяются стандартом Modbus, Методы libmodbus однозначно соответствуют опредённому коду запроса Modbus.

Ну здравый смысл вам в помощь. Если тип называется “input”, то мы пользуемся функцией (0x04) Read Input Registers. Тут по-моему очень мало вариантов.

Ещё можно почитать исходники, там ответ на ваш вопрос находится очень просто.

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

Никак. Сейчас compound register в драйвере - это N числел, разделённые точкой с запятой.
consists_of выглядит хорошей конструкцией, пока не начинаешь задумываться о том, как должны данные обрабатываться в MQTT и как они должны конвертироваться обратно. Опять же, примеров, где это бы понадобилось, мне пока не известно.

Если я правильно вас понял, то вы говорите про типы данных вида 32- и 64- битных чисел, которые используют несколько последовательных регистров. Это есть стандарт, и это поддерживается нашим драйвером. Смотрите в документации, поиск по словам “формат канала”. Примеры использования: наше устройство WB-MCM16, счётчик PD561Z.

К сожалению на этот вопрос я могу ответить только в рамках платной тех. поддержки (обращаться на support@). К тому же скорее всего никакие изменения в wb-homa-modbus вам делать не нужно.

Информацию об обновлении вы можете найти в новостях на нашем сайте и здесь, на форуме.

Спасибо.

Так какие именно функции у вас железка не поддерживает?
Дублирование есть только у read coil / read multiple coils и read holding register / read multiple registers

Спасибо, решим проблемы другим способом.

Коллеги, подскажите, как описать регистры типа holding register, используемые в модуле в качестве счетчиков входа, чтобы была возможность изменять значение счетчиков. Сейчас я сделал так:
{
“name” : “Input 2 counter”,
“reg_type” : “holding”,
“address” : 2,
“type” : “value”
}

Но остаются две проблемы:

  • нет возможности в веб-интерфейсе редактировать значение (ну, хотя бы сбросить):

  • счетчик занимает 2 регистра (32 бита) с таким вот порядком следования:

    Регистры, функции (чтение 3, запись 16) Holding Registers
    1 - чтение/запись Счетчик входа 1 младшие 16 бит
    2 - чтение/запись Счетчик входа 1 старшие 16 бит
    3 - чтение/запись Счетчик входа 2 младшие 16 бит
    4 - чтение/запись Счетчик входа 2 старшие 16 бит

Наверное, есть возможность объединить эти ячейки, но пока не хватает опыта. Как поступить?
Для таких случаев было бы удобно использование контролов типа spin box. Не планируете?
Если интересно, модуль - Insyte LD2-R1000D.

Как можно масштабировать величину? Например, температура по значению регистра определяется как (val-32767)/100.

этого нет. По-идее можете поставить type=range, только так.
Упирается в веб-интерфейс.

Смотрите в документации на гитхабе 64-битные форматы. Искать по слову format.

А вы точно читали документацию? Есть же поле scale.
Вычитать оно правда не умеет.

Напоминаю, что всё, чего не хватает, можно сделать в рамках платной техподдержки.

Посмотрю, спасибо. Правда, не понимаю, как для 32-битной величины поможет 64-битный формат.

Ну раз не умеет, то и не поможет.

Логично, ну тогда смотрите 32-битные форматы. Суть та же - несколько регистров подряд для одной величины.

И ваши 32-битные форматы не подходят;) Половина счетчика с порядком следования big-endian, а половинки соединяются в порядке little-endian. Если считать 16 бит машинным словом, то это middle-endian.
Да ладно, сам обработаю.

Значит надо новый формат в код добавить.
Это несложно (час работы), если вдруг сделаете - то нам пожалуйста pull request.

Я так обрабатываю эту ситуацию:

// для двоного слова учитывается порядок следования слов (byteOrder)
Uint32Values CUnit::toUint32(int byteOrder){
    QByteArray data = getData(registerStartNumber,registerCount);
    QDataStream in(&data,QIODevice::ReadOnly);
    quint32 val32;
    quint16 little;
    quint16 big;

    Uint32Values values;
    while(!in.atEnd()){
        in >> little;
        in >> big;
        if(byteOrder == LITTLE_ENDIAN_ORDERING){ // прямой порядок
            val32 = big;
            val32 = (val32<<16)+little;
        }else{                          // обратный порядок
            val32 = little;
            val32 = (val32<<16)+big;
        }
        values << val32;
    }

    return values;
}