mirror of
https://github.com/anklimov/lighthub
synced 2026-10-28 11:15:00 +00:00
120 lines
12 KiB
Markdown
120 lines
12 KiB
Markdown
# 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)
|