Files
lighthub/documentation/core/rotary_encoder.md
T
2026-10-11 01:27:15 +03:00

120 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Rotary Encoder
> Источник: авторский документ «Rotary Encoder» (docx, 2026-10-02), сверен с кодом `lighthub/inputs.cpp`.
Появилась возможность подключить к контроллеру орган управления, который называется Rotary encoder (далее — энкодер).
Энкодер упрощает управление такими устройствами, как диммируемое и светодиодное освещение, позволяя выбор яркости/цвета/насыщенности/цветовой температуры делать тактильно, вращением рукоятки регулятора. Одним энкодером можно управлять несколькими, как локальными, так и удаленными устройствами. Освещение здесь приведено в качестве самого применимого примера. Если хотите — данным элементом управления можно регулировать все, что поддерживает команды на увеличение и уменьшение. Например, через автоматизации Home Assistant можно управлять громкостью ресивера или колонки Алиса.
Многие энкодеры также имеют контакт нажатия, и данная возможность тоже может быть использована. Все варианты анализа одинарных-двойных-тройных-длительных нажатий могут быть использованы аналогично с настройкой дискретных входов контроллера и использоваться для любых нужд, в том числе для включения, выключения устройств, переключения профилей управления энкодера.
Все возможности доступны при настройке энкодера через JSON-конфигурацию.
Подключить энкодер можно к прошивке LightHub на всех платформах (включенных с флагом `ROTARYENCODER`, см. «Доступность» ниже). Особенно хочется подчеркнуть возможность подключить такой элемент (наряду с дополнительными кнопками и датчиками) к контроллеру LightSpot на базе STM32 или ESP32 — минималистической системе, которая может быть смонтирована в каждом выключателе и которая может общаться с основным контроллером LightHub по двухпроводной шине CAN (см. [CAN и lightspot](../integrations/can_lightspot.md)). Также можно собрать универсальный выключатель с кнопками и рукояткой энкодера на базе ESP32 или ESP8266, взаимодействующий с остальными системами дома через WiFi (как с контроллерами LightHub, так и с другими устройствами, управляемыми через MQTT), хотя вариант проводного подключения, конечно, предпочтителен.
## Настройка
Рассмотрим настройку энкодера на примерах.
В данном примере энкодер подключен к следующим PIN-ам контроллера:
- 14 — контакт нажатия;
- 4 и 5 — контакты A и B энкодера, соответственно.
Четвертый (опциональный) параметр массива `#` может задавать режим подключения энкодера. Имеет смысл пробовать менять значение в интервале 1-3, если значение по умолчанию (2) не работает корректно для какого-то отдельно взятого энкодера.
Параметр `T` соответствует значению **32** — это тип входа «rotary encoder».
Параметр `"+-"` определяет обработчик, вызываемый при вращении рукоятки энкодера по или против часовой стрелки. Обработчик аналогичен описанному в разделе «диммирование с использованием кнопок» ([button\_presses.md](button_presses.md)). Но там пары параметров `icmd`/`irev` и `ecmd`/`erev` используются поочередно, а в случае энкодера первый параметр используется в случае вращения по часовой стрелке, а второй — против часовой.
Настройка в примере ниже переключает локальное устройство `dimmer` между состояниями ON и OFF (команда `toggle`) по однократному клику на энкодер (параметр `click`), а при вращении рукоятки по и против часовой стрелки увеличивает или уменьшает яркость локального устройства `dimmer` соответственно (команды `%+1` и `%-1`):
```json
{
"T": 32, "#": [14, 4, 5, 2],
"+-": { "item": "dimmer/set", "icmd": "%+1", "irev": "%-1" },
"click": { "item": "dimmer/cmd", "icmd": "toggle" }
}
```
Поворот по часовой и против часовой стрелки можно разнести на два отдельных обработчика, если вдруг это будет необходимо, чтобы управлять разными устройствами при вращении в разных направлениях. Следующее описание эквивалентно предыдущему:
```json
{
"T": 32, "#": [14, 4, 5],
"+": { "item": "dimmer/set", "icmd": "%+1" },
"-": { "item": "dimmer/set", "icmd": "%-1" },
"click": { "item": "dimmer/cmd", "icmd": "toggle" }
}
```
Теперь попробуем управлять удаленным устройством `dimmer2`, подключенным к контроллеру с именем `light` через MQTT:
```json
{
"T": 32, "#": [14, 4, 5],
"+-": { "emit": "myhome/light/dimmer2/set", "ecmd": "%+1", "erev": "%-1" },
"click": { "emit": "myhome/light/dimmer2/cmd", "ecmd": "toggle" }
}
```
И пример по управлению удаленным устройством с itemid = 31, настроенным на контроллере с адресом 13 по CAN-шине (см. [CAN и lightspot](../integrations/can_lightspot.md)):
```json
{
"T": 32, "#": [14, 4, 5],
"+-": { "can": [13, 31, "set"], "icmd": "%+1", "irev": "%-1" },
"click": { "can": [13, 31, "cmd"], "icmd": "toggle" }
}
```
### Профили (act)
Усложним задачу. Теперь попробуем управлять одним энкодером яркостью, цветом и насыщенностью светодиодной ленты. Для этого понадобится создать несколько профилей энкодера.
Профили можно задать в виде JSON-массива или JSON-объекта в параметре `act`. Массив и объект аналогичны: в первом случае для активации нужного профиля будет использоваться целое число, определяющее порядковый номер элемента в массиве, содержащего нужный профиль (начиная с 1, так как значение 0 зарезервировано для активации «корневого профиля», который может быть описан непосредственно в объекте входа, на одном уровне с параметрами `#`, `T` — аналогично предыдущим примерам). Во втором случае для активации можно пользоваться именем объекта (пустая строка активирует корневой профиль). Это, конечно, делает конфиг более читаемым, но чуть более ресурсоемко.
В примере ниже изначально активен корневой профиль, в котором осуществляется управление яркостью светодиодной ленты. Однократный клик (команда `activate` в обработчике события `click`) активирует профиль номер 1 — в котором управляется насыщенность цвета. Однократный клик из профиля 1 переводит энкодер в профиль 2, в котором можно настроить оттенок цвета. Ну и, соответственно, клик из профиля 2 активирует корневой профиль (0). В каждом профиле длительное нажатие включает или выключает `led`.
```json
{
"T": 32, "#": [14, 4, 5],
"+-": { "item": "led/set", "icmd": "%+1", "irev": "%-1" },
"lcmd": { "item": "led/cmd", "icmd": "toggle" },
"click": { "activate": 1 },
"act": [
{
"+-": { "item": "led/hue", "icmd": "%+1", "irev": "%-1" },
"lcmd": { "item": "led/cmd", "icmd": "toggle" },
"click": { "activate": 2 }
},
{
"+-": { "item": "led/sat", "icmd": "%+1", "irev": "%-1" },
"lcmd": { "item": "led/cmd", "icmd": "toggle" },
"click": { "activate": 0 }
}
]
}
```
NB: `activate` можно использовать в описании других входов контроллера — таким образом, например, нажатием других кнопок можно выбирать режим действия энкодера.
## Доступность (сверка с кодом, 2026-10-02)
- Тип входа `T:32` (`IN_RE`) работает при компиляции с флагом `ROTARYENCODER` (`inputs.cpp`).
- Флаг включен по умолчанию: **due, esp32-wifi, esp32c3-wifi, esp8266-wifi, lighthub21, nrf52840, stm32, stm32-noip** (`build-flags/*`).
- Массив `#`: `[контакт_нажатия, A, B, режим]`; режим по умолчанию — 2 (`inputs.cpp`, `setupRotaryEncoder`).
- `activate` поддерживает число (индекс профиля, 0 — корневой), строку (имя профиля) и массив `["имя_входа", <значение>]` — активация профиля во внешнем входе (`inputs.cpp`, `checkInstructions`).
## Не реализовано
Черновик из исходного документа, **не реализованный** в текущем коде:
- вход `T:99` с профилями и обработчиками `goto`/`onenter` (переходы между профилями по событиям, «сценарный» энкодер).
## Связанные документы
- [Нажатия кнопок](button_presses.md)
- [CAN и lightspot](../integrations/can_lightspot.md)
- [Справочник суффиксов](suffixes_reference.md)