Files
2026-10-11 01:27:15 +03:00

21 KiB
Raw Permalink Blame History

LightHub и шина CAN

Источник: авторский документ «Lighthub и шина CAN» (docx, 2026-10-02), сверен с кодом lighthub/candriver.cpp/h. CAN-поддержка в прошивке появилась в v4.4.0.

Что такое CAN шина

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

В прошивке LightHub используется фиксированная скорость 50 kbit/s (candriver.cpp: STMCan.setBaudRate(50000) / CAN.begin(50000) / Can0.begin(CAN_BPS_50K)), что обеспечивает длину шины до нескольких сотен метров — достаточно для большинства домовладений.

Поддержка CAN встроена во многие современные (и не очень) микроконтроллеры. Из тех микроконтроллеров, на которых работает прошивка LightHub, встроенная поддержка используется в следующих чипах:

  • ARM SAM3E (Arduino DUE) — библиотека due_can
  • ESP32 — библиотека arduino-CAN (пины: GPIO 35 — RX, GPIO 5 — TX)
  • STM32 — библиотека STM32_CAN

Подключение внешнего CAN-контроллера по SPI для чипов без встроенной поддержки не реализовано в текущем коде (candriver.cpp использует только встроенные контроллеры).

Какие возможности появляются у LightHub

Теперь нет необходимости организовывать подключение локальной сети (или WiFi) к каждому устройству. Необходим минимум один контроллер (лучше пара), который подключен одновременно и к локальной сети, и к шине CAN. Он будет выполнять роль шлюза и держателя настроек периферийных контроллеров.

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

При всем прочем, даже такие упрощенные устройства умеют почти то же самое, что их «старшие братья»:

  • тот же формат JSON-файла настройки позволяет организовывать как локальное, так и удаленное управление устройством;
  • малое устройство может иметь на борту термостаты, возможность подключения термодатчиков и прочих сенсоров, PID-регуляторы, UART для управления кондиционером или для Modbus;
  • к таким устройствам можно подключать элементы управления: кнопки, переключатели, энкодеры (элемент с вращающейся ручкой), герконы дверей и датчики движения/присутствия;
  • они также поддерживают все возможности по определению одинарных-двойных-тройных-длительных нажатий кнопок, как и все LightHub.

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

Кроме того, CAN-шина позволяет таким простым устройствам напрямую общаться между собой, например:

  • для реализации сценариев переключения сцен освещения, проходных выключателей;
  • для передачи измерений сенсоров на удаленные контроллеры (например, измерения влажности помещений на контроллер форсуночного увлажнения, значения CO2 в помещениях на систему вентиляции).

Причем такое взаимодействие теперь может происходить без посредничества локальной сети и MQTT-брокера, что еще более увеличивает надежность и живучесть системы в целом.

Примеры применения контроллеров, подключенных только по шине CAN (далее — lightspot)

  • Автономный управляемый термостат теплого пола
  • Автономное, управляемое локальным выключателем реле или диммер света (AC или RGB)
  • Датчик движения, локально и удаленно управляющий светом, с сенсорами температуры, влажности, CO2 на борту
  • Многоклавишный многофункциональный выключатель с сенсорами температуры-влажности, энкодером
  • Удаленные счетчики воды-газа-электричества
  • Управляемые клапаны вентиляции
  • Удаленные ультразвуковые датчики приближения для управления подсветкой ступеней

Как организована передача данных по шине CAN

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

Формат идентификатора кадра

Идентификатор кадра (до 32 бит, canid_t в candriver.h):

Поле Биты Назначение
reserve 3 Должно быть 0
status 1 1 — статус, 0 — запрос
payloadType 4 Тип передаваемых данных
deviceId 8 devID устройства (1..255)
itemId 10 0..1023 (или sequence # для длинных кадров)
subItemId 6 0..62 (63 — субайтем не задан)

Типы полезной нагрузки (payloadType)

Значение Имя Назначение
1 itemCommand Команда или статус для/от того или иного item
2 lookupMAC Запрос devID по MAC-адресу устройства (в ответе передается devID)
3 configFrame Кадр передачи конфигурации (JSON, частями)
4 OTAFrame Кадр передачи прошивки по CAN
5 auth Аутентификация
6 metric Метрики (см. metricType)
7 sysCmd Системные команды (см. commandType)
8 rawPinCtrl Прямое управление пинами

Формат данных (datagram_t)

enum metricType { MAC=1, IP=2, NetMask=3, GW=4, DNS=5, UpTime=6, Salt=7 };

typedef union {
  uint8_t data[8];
  char payload[8];
  struct {
    itemCmdStore cmd;        // команда
    itemArgStore param;      // аргумент команды
  };
  struct {
    macAddress mac;          // MAC-адрес
    uint16_t currentConfCRC; // CRC текущей конфигурации
  };
  struct {
    uint8_t sysCmd;
    uint8_t sysCmdData[7];
  };
  struct {
    uint32_t metric1;
    uint32_t metric2;
  };
} datagram_t;

Системные команды (sysCmd, commandType):

Значение Команда
1 reboot — перезагрузка контроллера
2 get — получить информацию
3 save — сохранить конфигурацию
4 load — загрузить конфигурацию

Процедура инициализации устройства и загрузки конфигурации

  1. Вычисление MAC-адреса. Этот адрес является уникальным идентификатором устройства, даже если у него отсутствует сетевой интерфейс и имеется в наличии только CAN. MAC-адрес вычисляется из уникального серийного номера чипа для ARM-базированных устройств, для AVR считывается из EEPROM, для ESP используется MAC-адрес интерфейса WiFi.

  2. Устройство отправляет запрос в CAN-шину, установив payloadType = lookupMAC (2) в пакете и передав 6 байт MAC-адреса.

  3. Мастер-контроллер, содержащий конфигурацию устройства внутри своего файла настроек, формирует ответный пакет нулевой длины с установленным битом status в id и заполненным полем deviceId. С этого момента устройство знает свой devID.

  4. Устройство отправляет запрос в CAN-шину, установив payloadType = configFrame (3) и полученный на предыдущем этапе devID. В качестве sequence # для первого пакета используется значение 0xFFFF (-1), запрос каждого последующего пакета осуществляется с увеличением sequence # на единицу. В ответ на каждый запрос устройство получает кадр данных; последовательность данных содержит JSON-конфигурацию.

Пример конфигурации CAN внутри конфига мастер-устройства

"can": {
  "addr": 14,
  "conf": {
    "DE:54:71:48:17:2E": {
      "can": { "addr": 21, "name": "olmexino" },
      "items": {
        "relay1": [[6, 1], 1],
        "relay2": [[6, 2], 5],
        "relays": [["GROUP", 3], ["relay1", "relay2"]]
      },
      "in": {
        "41": { "T": 2, "item": "relays", "can": [10, 2], "scmd": "TOGGLE", "rcmd": "" }
      }
    },
    "DE:48:4E:03:B3:DF": {
      "can": { "addr": 22, "name": "sonar" },
      "items": {
        "relay1": [[6, 1], 1]
      },
      "in": [
        {
          "T": 7, "#": [14, 15],
          "act": [
            { "map": [0, 100], "scmd": { "can": [13, 32], "icmd": "XON 10000" } },
            { "map": [0, 200], "scmd": { "can": [13, 31], "icmd": "XON 15000" } }
          ]
        }
      ]
    }
  }
}

can.addr — devID этого контроллера. can.conf — объект «MAC-адрес → конфигурация периферийного контроллера»; каждая периферия содержит собственный can (devID и имя) и обычные секции items/in.

Способ настройки взаимодействия контроллеров с использованием шины CAN

В процессе работы контроллеры имеют возможность отправки на один или несколько других контроллеров, подключенных по шине CAN, следующего набора пакетов:

Тип управляющего воздействия Числовое значение суффикса Суффикс (символьное значение)
Команды для управления удаленными устройствами 1 cmd
Уставки для удаленного устройства 2 set
Текущие значения сенсоров 3 val
Отложенная команда 4 del
Цвет в нотации HSV 5 hsv
Цвет в нотации RGB 6 rgb
Интенсивность вентиляции 7 fan
Режим работы климатической установки 8 mode
Вспомогательная команда (FREEZE / UNFREEZE / ENABLE / DISABLE) 9 ctrl
Цвет (hue) 10 hue
Насыщенность цвета 11 sat
Цветовая температура 12 temp

Адресация объекта назначения (item)

Для адресации объекта назначения (item), который обработает соответствующую команду в сети CAN, используется следующая нотация:

[ <DevID>, <ItemID>, <suffix> <subitem> ]
  • DevID — адрес устройства, определяется на этапе конфигурирования (см. выше). DevID = 0 адресует сообщение всем устройствам сети.
  • ItemID — числовой идентификатор объекта (item). Задается при настройке удаленного объекта в JSON-конфигурации того контроллера, к которому объект подключен: первый элемент массива настройки item должен быть массивом, в котором первый объект определяет тип объекта, а второй — требуемый ItemID. Пример:
"items": {
  "relay1": [[6, 1], 1],
  "relay2": [[6, 2], 5],
  "relays": [["GROUP", 3], ["relay1", "relay2"]]
}

В примере выше для объекта relay1 определяется itemID = 1, для объекта relay2 — itemID = 2, а для группы relays — itemID = 3.

В том случае, если ItemID пересекаются между контроллерами и пакет отправлен на широковещательный адрес 0, пакет будет выполнен сразу всеми контроллерами, в которых определен объект с данным ID.

  • Suffix — числовое или символьное значение, определяющее тип управляющего воздействия согласно таблице выше. Допустимо определять дополнительные числовые суффиксы, например, для управления теми регистрами устройства Modbus, которые не укладываются в таблицу выше. В этом случае при описании устройства Modbus можно задать параметр "id": <значение>, где значение — число в интервале 13-31, и этот параметр можно будет адресовать, задавая данное число в массиве can на третьей позиции.
  • Subitem — опциональный параметр, который может использоваться двояко:
    • если указана цифра — адресация суб-объекта, входящего в удаленный управляемый объект. Примеры объектов, которые имеют внутри перечень суб-объектов: MULTIVENT (многоканальная вентиляция/кондиционирование), HUM (многоканальный форсуночный увлажнитель), адресная светодиодная лента. Для адресации соответствующего суб-объекта используется порядковый номер, согласно которому данный суб-объект описан в JSON-конфигурации контроллера назначения;
    • если указана строка — делается попытка преобразовать данную строку в команду, и это значение передается удаленному устройству. Удаленное устройство исполнит пакет только в том случае, если текущее состояние устройства эквивалентно данной команде. Данная функция особо полезна для удаленных групп устройств: например, можно адресовать команды управления яркостью группе светильников, а исполнят их только светильники, находящиеся в состоянии «ON».

Функция шлюза

Мастер-контроллер, который хранит конфигурацию периферийного, также выполняет функцию шлюза между шиной CAN и интерфейсами MQTT и HTTP.

Так как мастер-контроллер знает имя периферийного, при подключении к MQTT-брокеру он дополнительно подписывается на командный топик периферийного. Это позволяет управлять устройствами, подключенными через шину CAN, абсолютно прозрачно, с использованием стандартной нотации командных топиков root/name/item/[subitem/]suffix, например, через myhome/sonar/relay1/cmd для примера конфига выше.

Когда удаленный периферийный контроллер выполнит команду (либо вследствие изменения внутреннего состояния устройства) — изменение его статуса транслируется в шину CAN. Мастер-контроллер, который владеет конфигом периферийного, транслирует такое изменение статуса в свой стандартный статусный топик, например, в myhome/s_out/relay1/cmd.

Доступность в сборках (сверка с кодом, 2026-10-02)

  • Флаг CANDRV включен по умолчанию: esp32-wifi, lighthub21, stm32-noip; в esp32c3-wifi закомментирован (build-flags/*).
  • Скорость: 50 kbit/s, фиксированная (candriver.cpp).
  • ESP32: CAN на GPIO 35 (RX) / GPIO 5 (TX) (candriver.cpp).
  • Поддержка SPI-кан-контроллеров для чипов без встроенной CAN — не реализована (см. выше).

Не реализовано

Черновики из исходного документа, допущенные до релиза, но не реализованные в текущем коде:

  • вход T:99 с профилями, обработчиками goto/onenter и сценарным переходом между профилями;
  • подключение CAN через внешний SPI-контроллер для чипов без встроенной поддержки.

Связанные документы