Описание модуля для протокола ECPP

Протокол ECPP используется для обмена данными между основным и подчиненными модулями контроллера. Обмен выполняется небольшими пакетами (не более 16 байт), каждый из которых имеет фиксированный числовой идентификатор. Данные передаются только при их изменении. Координатором передачи выступает основной модуль.

Чтобы основной модуль мог опрашивать подчиненные модули, ему необходимо описание внутренней структуры объектов, реализованных в подчиненных модулях. Это описание оформляется в JSON-файле в формате, описанном ниже.

Общие параметры

Общие параметры модуля

Параметр

Тип

Описание

type

string

Строковый тип контроллера, для которого предназначен модуль. Например "M245A"

version

number

Версия формата описания, пока всегда 1

moduleID

number

Числовой идентификатор модуля, например 2561 (0xA01)

moduleVer

number

Числовая версия модуля

pubName

string

Пользовательское имя модуля

shortName

string

Краткое пользовательское имя. Если параметр отсутствует, то используется moduleID в HEX формате, например A01

floor

number

Позиция модуля в многослойной конструкции. Нумерация идет сверху вниз. Обычно базовый модуль сверху и нумеруется 0, средний - 1, нижний - 2

package

number

Идентификатор пакета плат для проверки совместимости. Для всех плат одного пакета он должен иметь одинаковое значение

Массив interface

Массив interface описывает различные интерфейсы, которые могут быть реализованы в модулях. Пока используется только для определения количества портов, которые физически проброшены с основной платы в модуль.

Параметры объекта интерфейса:

Параметры интерфейса

Параметр

Тип

Описание

name

string

Имя порта

id

string

Идентификатор порта (обычно это порядковый номер интерфейса начиная с 0)

mode

string

Режим порта, пока не используется

type

string

Тип порта, пока не используется

Пример:

"interface": [
    {
        "name": "COM0",
        "id": "0",
        "mode": "connector",
        "type": "uart"
    },
    {
        "name": "COM1",
        "id": "1",
        "mode": "connector",
        "type": "uart"
    }
]

Массив rxobjects

Массив rxobjects содержит объекты протокола ECPP для чтения.

Параметры объекта:

Параметры rxobjects

Параметр

Тип

Описание

ecppID

number

Числовой идентификатор объекта

size

number

Размер объекта в байтах, не может быть больше 16

comment

string (опционально)

Комментарий к объекту с описанием его структуры

Пример:

"rxobjects": [
    { "ecppID": 32, "size": 4 },                    // Показания АЦП AIN1:ADC и AIN2:ADC
    { "ecppID": 56, "size": 16, "comment": "AIN1:Напряжение, AIN2:Напряжение, AIN1:Сопротивление, AIN2:Сопротивление" }
]

Массив txobjects

Массив txobjects содержит объекты протокола ECPP для записи. Аналогичен rxobjects.

Пример:

"txobjects": [
    { "ecppID": 40, "size": 2 }    // Значения AIN1:Mode и AIN2:Mode
]

Массив groups - группы переменных

Массив groups объединяет переменные в логические группы для отображения в визуальном интерфейсе. Каждый объект в этом массиве описывает одну группу и содержит массив vars.

Параметры группы:

Параметры группы

Параметр

Тип

Описание

intName

string

Внутреннее имя группы (только латиница и цифры)

pubName

string

Пользовательское имя группы для отображения в интерфейсе

vars

array

Массив переменных, входящих в группу

Секция описания переменных vars

Массив vars описывает переменные для входов/выходов.

Параметры переменной:

Параметры переменной

Параметр

Тип

Описание

datatype

string

Тип данных ("UInt16", "Bool", "Float32" и т.д.)

vdef

number

Значение по умолчанию (если отсутствует, то 0)

pubname

string

Пользовательское название переменной

intname

string

Внутреннее имя переменной (только латинские буквы и цифры). Используется как идентификатор

shortname

string (опционально)

Краткое наименование, отображаемое на блоке. Если не указано, используется intname с добавлением адреса модуля

description

string

Описание переменной для пользователя

ecppID

number

Идентификатор объекта ECPP, в котором находится значение. Должен быть описан в txobjects или rxobjects

ecppOffsetAddr

number

Смещение от начала объекта в байтах (или в битах для булевых значений)

groupID

string

Имя группы для объединения переменных в универсальные каналы

groupMode

number

Режим работы универсальной переменной (см. таблицу режимов)

writable

boolean

Доступность для записи (размещена в объекте tx)

readable

boolean

Доступность для чтения (размещена в объекте rx)

Важно

В параметре intname допускается использовать только латинские буквы и цифры. Никаких знаков препинания и служебных символов добавлять нельзя!

Режимы работы groupMode

Значения groupMode

Режим

Значение

Описание

ext_none

0x00

Вход не сконфигурирован

ext_in_a

0x10

Аналоговый вход - данные в АЦП

ext_volt3_3

0x20

Аналоговый вход - данные в float 0-3.3V

ext_volt10

0x30

Аналоговый вход - данные в float 0-10V

ext_cur

0x40

Аналоговый вход - данные в float 4-20mA

ext_res

0x50

Аналоговый вход - данные в float в Омах

ext_din

0x60

Дискретный вход - есть/нет сигнала

ext_cntr

0x70

Счетный вход - количество импульсов

ext_frec

0x80

Частотный вход - частота в целых Гц

ext_out_d

0x90

Цифровой выход - реле или дискретный сигнал

ext_out_a

0xA0

Аналоговый выход - 0-10В значение от 0 до 1000

ext_out_a_5

0xA1

Аналоговый выход - 0-5В значение от 0 до 1000

ext_out_a_24

0xA2

Аналоговый выход - 0-24В значение от 0 до 1000

ext_out_v24

0x11

Дискретный выход 0-24 В

ext_out_spwm

0x13

Медленный ШИМ

ext_out_fpwm

0x14

Быстрый ШИМ

ext_ref

0xB0

Источники опорного напряжения

Пример простых переменных (без группировки в каналы)

Если переменные не требуется объединять в универсальные каналы, параметры groupID и groupMode можно оставить пустыми (или 0). Переменные при этом будут сгруппированы только визуально в интерфейсе.

"groups": [
    {
        "intName": "F00",
        "pubName": "Модуль F00",
        "vars": [
            {"datatype": "UInt16", "vdef": 500, "pubname": "Частота сигнала", "description": "Частота звука в Гц, минимальное значение 184Гц", "intname": "SpeakerFreq", "writable": true, "readable": true, "groupID": "", "groupMode": 0, "ecppID": 3584, "ecppOffsetAddr": 0},
            {"datatype": "UInt16", "vdef": 50, "pubname": "Громкость сигнала", "description": "Громкость звука от 0 до 100%", "intname": "Volume", "writable": true, "readable": true, "groupID": "", "groupMode": 0, "ecppID": 3584, "ecppOffsetAddr": 2},
            {"datatype": "UInt16", "vdef": 0, "pubname": "Включить звук", "description": "Включить звук на заданное время, мс", "intname": "Speaker", "writable": true, "readable": true, "groupID": "", "groupMode": 0, "ecppID": 3584, "ecppOffsetAddr": 4},
            {"datatype": "UInt16", "vdef": 2, "pubname": "Время фильтрации", "description": "Время фильтрации для цифровых входов на включение, мс", "intname": "TimeFilter", "writable": true, "readable": true, "groupID": "", "groupMode": 0, "ecppID": 40, "ecppOffsetAddr": 2},
            {"datatype": "UInt16", "vdef": 1000, "pubname": "Время подсчета частоты", "description": "Время подсчета частоты цифрового сигнала, мс", "intname": "TimeFreq", "writable": true, "readable": true, "groupID": "", "groupMode": 0, "ecppID": 40, "ecppOffsetAddr": 4},
            {"datatype": "UInt8", "vdef": 0, "pubname": "Код ошибки", "intname": "ErrCode", "shortname": "ErrCode", "writable": false, "readable": true, "groupID": "", "groupMode": 0, "ecppID": 208, "ecppOffsetAddr": 0}
        ]
    }
]

Принцип группировки переменных в универсальные каналы

Параметры groupID и groupMode объединяют переменные в логические группы (универсальные каналы). Это нужно, когда несколько переменных относятся к одному физическому каналу (например, АЦП, напряжение, сопротивление — всё с одного входа).

Основные правила:

  1. Один физический канал = один groupID

  2. groupMode = 0 — управляющая переменная (задает режим работы канала)

  3. Остальные groupMode — типы данных (напряжение, сопротивление, АЦП и т.д.)

  4. Программа использует ту переменную, чей groupMode совпадает со значением управляющей переменной

Пример группировки для канала AIN1:

"groups": [
    {
        "intName": "AIN",
        "pubName": "Аналоговые входы",
        "vars": [
            // Управляющая переменная
            {"datatype": "UInt8", "vdef": "48", "pubname": "AIN1", "intname": "AIN1:Mode", "writable": true, "readable": false, "groupID": "AIN1", "groupMode": 0, "ecppID": 40, "ecppOffsetAddr": 0},
            // Переменные данных
            {"datatype": "UInt16", "vdef": "0", "pubname": "AIN1:АЦП", "intname": "AIN1:ADC", "description": "Значение АЦП", "writable": false, "readable": true, "groupID": "AIN1", "groupMode": 16, "ecppID": 32, "ecppOffsetAddr": 0},
            {"datatype": "Float32", "vdef": "0", "pubname": "AIN1:Напряжение", "intname": "AIN1:Volt", "description": "Значение напряжения", "writable": false, "readable": true, "groupID": "AIN1", "groupMode": 48, "ecppID": 56, "ecppOffsetAddr": 0},
            {"datatype": "Float32", "vdef": "0", "pubname": "AIN1:Сопротивление", "intname": "AIN1:Res", "description": "Значение сопротивления", "writable": false, "readable": true, "groupID": "AIN1", "groupMode": 80, "ecppID": 56, "ecppOffsetAddr": 8}
        ]
    }
]

Как это работает:

  • Программа читает AIN1:Mode (groupMode = 0)

  • Если Mode = 48 (напряжение) → использует AIN1:Volt

  • Если Mode = 80 (сопротивление) → использует AIN1:Res

  • Если Mode = 16 (АЦП) → использует AIN1:ADC

Визуальное представление:

Группа "Аналоговые входы"
├── Канал AIN1 (режим = напряжение):
│   ├── AIN1:Mode = 48
│   └── AIN1:Volt = 5.23 V   ← активно
└── Канал AIN2 (режим = сопротивление):
    ├── AIN2:Mode = 80
    └── AIN2:Res = 1200 Ω    ← активно

Важно

В каждой группе (по groupID) должна быть только одна переменная с groupMode = 0.

Полный пример описания модуля

{
    "type": "M245A",
    "version": 1,
    "moduleID": 2561,
    "moduleVer": 1,
    "pubName": "Модуль аналоговых входов",
    "shortName": "AIN",
    "floor": 0,
    "package": 1,

    "interface": [
        {"name": "COM0", "id": "0", "mode": "connector", "type": "uart"}
    ],

    "rxobjects": [
        {"ecppID": 32, "size": 4},
        {"ecppID": 56, "size": 16}
    ],

    "txobjects": [
        {"ecppID": 40, "size": 2}
    ],

    "groups": [
        {
            "intName": "AIN",
            "pubName": "Аналоговые входы",
            "vars": [
                {"datatype": "UInt16", "vdef": "0", "pubname": "AIN1:АЦП", "intname": "AIN1:ADC", "description": "Значение АЦП", "writable": false, "readable": true, "groupID": "AIN1", "groupMode": 16, "ecppID": 32, "ecppOffsetAddr": 0},
                {"datatype": "UInt16", "vdef": "0", "pubname": "AIN2:АЦП", "intname": "AIN2:ADC", "description": "Значение АЦП", "writable": false, "readable": true, "groupID": "AIN2", "groupMode": 16, "ecppID": 32, "ecppOffsetAddr": 2},
                {"datatype": "Float32", "vdef": "0", "pubname": "AIN1:Напряжение", "intname": "AIN1:Volt", "description": "Значение напряжения", "writable": false, "readable": true, "groupID": "AIN1", "groupMode": 48, "ecppID": 56, "ecppOffsetAddr": 0},
                {"datatype": "Float32", "vdef": "0", "pubname": "AIN2:Напряжение", "intname": "AIN2:Volt", "description": "Значение напряжения", "writable": false, "readable": true, "groupID": "AIN2", "groupMode": 48, "ecppID": 56, "ecppOffsetAddr": 4},
                {"datatype": "Float32", "vdef": "0", "pubname": "AIN1:Сопротивление", "intname": "AIN1:Res", "description": "Значение сопротивления", "writable": false, "readable": true, "groupID": "AIN1", "groupMode": 80, "ecppID": 56, "ecppOffsetAddr": 8},
                {"datatype": "Float32", "vdef": "0", "pubname": "AIN2:Сопротивление", "intname": "AIN2:Res", "description": "Значение сопротивления", "writable": false, "readable": true, "groupID": "AIN2", "groupMode": 80, "ecppID": 56, "ecppOffsetAddr": 12},
                {"datatype": "UInt8", "vdef": "48", "pubname": "AIN1", "intname": "AIN1:Mode", "writable": true, "readable": false, "groupID": "AIN1", "groupMode": 0, "ecppID": 40, "ecppOffsetAddr": 0},
                {"datatype": "UInt8", "vdef": "48", "pubname": "AIN2", "intname": "AIN2:Mode", "writable": true, "readable": false, "groupID": "AIN2", "groupMode": 0, "ecppID": 40, "ecppOffsetAddr": 1}
            ]
        }
    ]
}