mirror of
https://github.com/anklimov/lighthub
synced 2026-10-28 11:15:00 +00:00
- Introduced multivent ventilation configuration for managing multiple zones. - Added PID heating batteries configuration for temperature control. - Created relay GPIO switch configuration for controlling relays. - Implemented RGBW LED strip configuration for lighting control. - Added Modbus CO2 sensor configuration for environmental monitoring. - Introduced Sonoff S26 humidity controller example for humidity management. - Created sprinkler irrigation configuration for garden management. - Added thermostat on/off relay configuration for heating and cooling control. - Implemented ventilation fan monitoring configuration for performance tracking. - Added core concepts documentation for LightHub, detailing items, commands, and execution objects.
729 lines
37 KiB
Markdown
729 lines
37 KiB
Markdown
# LightHub: Модуль многоканального кондиционера и вентиляции (out\_Multivent)
|
||
|
||
> Документ описывает назначение, архитектуру и конфигурирование модуля управления многозональными системами кондиционирования и вентиляции LightHub.
|
||
> Предназначен для инженеров HVAC-систем, интеграторов и разработчиков.
|
||
> Верифицирован по исходному коду `lighthub/modules/out_multivent.cpp` и
|
||
> рабочим конфигурациям.
|
||
|
||
---
|
||
|
||
## 1. Назначение модуля
|
||
|
||
### 1.1 Область применения
|
||
|
||
Модуль `out_Multivent` предназначен для управления системами кондиционирования и вентиляции с **центральной установкой** и **множеством независимых зон/комнат**.
|
||
|
||
### 1.2 Типовые сценарии
|
||
|
||
#### Сценарий 1: Многозональный кондиционер
|
||
- Центральная сплит-система или компактная установка (1 компрессор, 1 вентилятор)
|
||
- Несколько помещений с электромоторными задвижками (воздушными затворами)
|
||
- Каждое помещение требует своего микроклимата
|
||
|
||
#### Сценарий 2: Многозональная приточная вентиляция
|
||
- Центральная приточная установка с одним вентилятором
|
||
- Несколько независимых воздуховодов с регулируемыми задвижками
|
||
- Распределение воздушного потока в зависимости от потребностей зон
|
||
|
||
#### Сценарий 3: Комбинированная система (климат + вентиляция)
|
||
- Центральный кондиционер + приточная вентиляция
|
||
- Управление как охлаждением/нагревом, так и циркуляцией воздуха
|
||
|
||
### 1.3 Ключевые возможности
|
||
|
||
- **Балансировка воздушного потока** — автоматическое распределение производительности между зонами
|
||
- **PID-регулирование температуры** — независимая стабилизация для каждой зоны
|
||
- **Интеллектуальное переключение режимов** — автоматическое определение HEAT/COOL по температуре воздуха в канале центральной установки
|
||
- **Агрегация команд** — управление центральной установкой на основе суммарного спроса от зон (boost)
|
||
- **Каскадирование** — передача состояний зон и центральной установки на внешние системы (панели, MQTT)
|
||
- **Отслеживание ручного управления центральной установкой** — если режим/уставка центрального кондиционера изменены с пульта, модуль принимает это как инструкцию: выключение установки останавливает все зоны (чтобы исключить немедленный автореверс), повторное включение восстанавливает их состояние
|
||
|
||
---
|
||
|
||
## 2. Архитектура и принцип работы
|
||
|
||
### 2.1 Компоненты системы
|
||
|
||
```
|
||
┌────────────────────────────────────────────┐
|
||
│ Центральная установка (AC-узел, "") │
|
||
│ (компрессор, вентилятор, датчик temp) │
|
||
│ Управляется по S_MODE / S_FAN / S_SET │
|
||
└──────────────┬─────────────────────────────┘
|
||
│
|
||
┌─────┴─────┐
|
||
│ │
|
||
┌────▼─────┐ ┌─▼─────────┐
|
||
│ Зона 1 │ │ Зона N │
|
||
│ Задвижка1│ │ ЗадвижкаN │
|
||
│ PID, V │ │ PID, V │
|
||
└──────────┘ └───────────┘
|
||
```
|
||
|
||
### 2.2 Логика работы (Poll)
|
||
|
||
#### Фаза 1: Определение режима центральной установки
|
||
Модуль определяет режим AC по температуре воздуха в канале (`""/val`):
|
||
- `val < 15 °C` → COOL
|
||
- `15 °C ≤ val ≤ 30 °C` → FAN
|
||
- `val > 30 °C` → HEAT
|
||
|
||
Если температура не поступала более 60 секунд, значение инвалидируется,
|
||
и режим берётся из последнего известного режима AC (`""/mode`).
|
||
|
||
#### Фаза 2: PID-расчёты по зонам
|
||
Для зон в режиме HEAT/COOL с активным PID:
|
||
- Вход PID: текущая температура зоны (`val`)
|
||
- Установка: требуемая температура зоны (`set`)
|
||
- Выход PID: `po` (0…255)
|
||
|
||
Направление PID задаётся автоматически по режиму AC: HEAT → DIRECT,
|
||
COOL → REVERSE. Знак коэффициента `kP` в конфигурации задаёт направление
|
||
по умолчанию (положительный — DIRECT, отрицательный — REVERSE).
|
||
|
||
В режимах FAN/AUTO ("слабые" режимы) и в пассивном режиме PID
|
||
принудительно включается, как только AC переходит в HEAT/COOL. Пока AC
|
||
вентилятирует, PID переводится в MANUAL, и запросы воздуха в зоны
|
||
берутся из последнего внешнего значения `/fan` зоны (`fan_in`).
|
||
|
||
#### Фаза 3: Балансировка (только для зон с активным PID в HEAT/COOL)
|
||
```
|
||
balance = Σ(po_zone) для зон в HEAT
|
||
balance -= Σ(po_zone) для зон в COOL
|
||
```
|
||
|
||
#### Фаза 4: Boost центральной установки
|
||
- `balance > boost` (по умолчанию 230) → уставка AC принудительно
|
||
поднимается до 30 °C (HEAT) / опускается до 17 °C (COOL), прежняя
|
||
уставка запоминается в `@preset`
|
||
- `|balance| < 10` (deadband) → активный PID-запрос считается
|
||
отсутствующим, boost сбрасывается
|
||
|
||
#### Фаза 5: Выбор команды центральной установки
|
||
- Если активных PID-запросов нет (`pidActive == false`): boost
|
||
сбрасывается; если хотя бы одна зона в AUTO (`autoRequested`) или
|
||
FAN (`ventRequested`) и вентилятор уже ненулевой (`lastACfan > 0`),
|
||
на AC уходит соответствующая команда. Если запросов нет — на AC
|
||
команда не отправляется вовсе (экономия)
|
||
- Итоговый уровень вентилятора (`lastACfan` от PID зон) отправляется
|
||
на AC
|
||
|
||
#### Фаза 6: Распределение производительности по задвижкам
|
||
Для каждой зоны пересчитывается выходной сигнал задвижки:
|
||
|
||
$$out = \frac{(V\_{zone} \times fan\_{zone}) \times 255}{V\_{zone}} \times \frac{V\_{max}}{V\_{max} \times fan\_{max}} = fan\_{zone} \times \frac{V\_{max}}{fan\_{max} \times V\_{zone}} \times 255$$
|
||
|
||
практически: относительный запрос зоны нормируется на самую требующую
|
||
зону, итоговый `out` в диапазоне 0…255 отправляется в item задвижки
|
||
(поле `item` зоны или каскад). Если суммарный запрос равен нулю, задвижки
|
||
не трогаются (остаются в текущем положении).
|
||
|
||
---
|
||
|
||
## 3. Структура JSON-конфигурации
|
||
|
||
### 3.1 Формат item типа VENTS (18)
|
||
|
||
```json
|
||
"item_name": [
|
||
18,
|
||
{
|
||
"zone_1": { ... },
|
||
"zone_2": { ... },
|
||
"": { ... }
|
||
}
|
||
]
|
||
```
|
||
|
||
Объект маршрутизации содержит **именованные зоны** + **пустую строку** `""`
|
||
для центральной установки.
|
||
|
||
ВАЖНО: поля `fan`, `cmd`, `out` зоны и центральной установки — это
|
||
**числовые** ячейки внутреннего состояния, а не маршрутизация. Если вместо
|
||
числа записать объект `{"emit": ...}`, зона будет **проигнорирована
|
||
целиком** (драйвер проверяет `fan` и `cmd` на целочисленность). Маршрутизация
|
||
значений наружу делается полями `item` и `cas` (см. ниже).
|
||
|
||
### 3.2 Структура зоны
|
||
|
||
```json
|
||
"zone_name": {
|
||
"V": 60,
|
||
"pid": [-1.0, 0.1, 0.05, 5.0],
|
||
"set": 21.0,
|
||
"val": 21.0,
|
||
"fan": -1,
|
||
"cmd": 1,
|
||
"out": -1,
|
||
"item": "damper_zal1/set",
|
||
"cas": {
|
||
"fan": {"emit": "house/f_room1/fan"},
|
||
"cmd": {"can": [15, 331, "cmd"]},
|
||
"set": {"item": "panel1/settemp"}
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Поля зоны:
|
||
|
||
| Поле | Тип | Назначение |
|
||
|------|-----|-----------|
|
||
| `fan` | int (0-255, инициализируется -1) | Текущий запрос воздуха зоны. Управляется суффиксом `/fan` зоны или встроенным PID (в активных режимах). Значение хранится в конфиге и переживает перезагрузку |
|
||
| `cmd` | int (код CMD\_*) | Текущий режим зоны (ON/OFF/HEAT/COOL/FAN/AUTO/HEATCOOL/DRY). Инициализируется CMD\_OFF (2) |
|
||
| `out` | int (0-255, инициализируется -1) | Финальный выходной сигнал задвижки после балансировки |
|
||
| `V` | int | Номинальный объём воздуха зоны (в относительных единицах), по умолчанию 60 |
|
||
| `pid` | объект или массив ≥3 | ПИД-регулятор: `[kP, kI, kD, dT(сек, по умолчанию 5)]` либо `{"kP":..,"kI":..,"kD":..,"dT":..}`. Знак kP задаёт направление: `>0` — DIRECT (нагрев), `<0` — REVERSE (охлаждение). При наличии `pid` создаются числовые ячейки `set` (по умолчанию 20.0), `val` (NaN), `po` (-2.0) |
|
||
| `set` | float | Уставка температуры зоны (вход PID) |
|
||
| `val` | float | Текущая температура зоны (вход PID, суффикс `/val`) |
|
||
| `AlarmTime` | сек | Время устаревания данных PID (по умолчанию 120 с) |
|
||
| `AlarmValue` | float | Порог аварии PID (по умолчанию 0.0) |
|
||
| `item` | строка | Item-цель по умолчанию для выходного сигнала задвижки (`out`). При изменении `out` в item отправляется значение 0-255 |
|
||
| `cas` | объект | Каскадирование изменений зоны на внешние объекты. Под-объекты `fan`, `cmd`, `set` — обычные EXEC-объекты (`item`/`emit`/`can`/`map`), исполняются при изменении соответствующего свойства зоны |
|
||
|
||
### 3.3 Центральная установка (пустая зона `""`)
|
||
|
||
```json
|
||
"": {
|
||
"item": "ac_2",
|
||
"turnbyfan": 15,
|
||
"boost": 200,
|
||
"supress": 7,
|
||
"overridecmd": 1,
|
||
"onextcmd": {"emit": "house/vent/extcmd"}
|
||
}
|
||
```
|
||
|
||
#### Поля:
|
||
|
||
| Поле | Назначение |
|
||
|------|-----------|
|
||
|`item`| Item центральной установки (обычно MBUS-канал кондиционера/вентустановки). Команды AC (mode/fan/set) отправляются в него |
|
||
|`turnbyfan`| Команда (код CMD\_), генерируемая при подаче ненулевого `/fan` в зону, если зона в CMD\_OFF; при `/fan=0` зона автоматически переводится в CMD\_OFF. 0 — отключено |
|
||
|`boost`| Порог \|balance\| (по умолчанию 230). При превышении модуль принудительно поднимает/опускает уставку AC (set) до 30/17 °C |
|
||
|`supress`| Битмаска подавления повторной отправки на AC: 1=FAN, 2=SET, 4=CMD (по умолчанию 0xF — всё). **В коде ключ пишется «supress» (одна s)** |
|
||
|`overridecmd`| Подмена команды, уходящей на AC, любой другой, кроме CMD\_OFF |
|
||
|`onextcmd`| EXEC-объект (с опциональной `map`), исполняемый при **ручном** изменении режима или уставки AC на пульте/извне |
|
||
| `val` | Температура воздуха в канале AC (вход `/val` центрального item; определяет HEAT/COOL/FAN) |
|
||
| `mode` | Текущий режим AC (вход `/cmd` или `/mode` центрального item) |
|
||
| `set` | Уставка температуры AC (сохраняется при получении `/set`) |
|
||
| `@lastCmd`, `@lastFan`, `@lastSet`, `@preCmd`, `@preset` | Служебные: последнее отправленное состояние, состояние до останова вентилятора, уставка до boost |
|
||
|
||
---
|
||
|
||
## 4. Детальная конфигурация компонентов
|
||
|
||
### 4.1 PID-контроллер
|
||
|
||
#### Формат
|
||
|
||
```json
|
||
"pid": [1.0, 0.05, 0.02, 5.0]
|
||
```
|
||
|
||
или объектом:
|
||
|
||
```json
|
||
"pid": {"kP": -1.0, "kI": 0.05, "kD": 0.02, "dT": 50},
|
||
"AlarmTime": 240,
|
||
"AlarmValue": 128
|
||
```
|
||
|
||
- **kP** (пропорциональный коэффициент): 0.5—2.0. Знак задаёт направление
|
||
регулятора: положительный — DIRECT (растёт при set > val, нагрев),
|
||
отрицательный — REVERSE (растёт при set < val, охлаждение)
|
||
- **kI** (интегральный): 0.0—0.2 — устраняет постоянное отклонение
|
||
- **kD** (дифференциальный): 0.01—0.1 — снижает колебания
|
||
- **dT** (период сэмплирования, сек): по умолчанию 5
|
||
|
||
`AlarmTime` и `AlarmValue` — поля зоны, а не `pid`.
|
||
|
||
### 4.2 Объём воздуха (V)
|
||
|
||
Указывается в **относительных единицах** (не обязательно м³/ч), по
|
||
умолчанию 60. Используется для пропорционального распределения между
|
||
зонами.
|
||
|
||
### 4.3 Каскадные команды (`cas`)
|
||
|
||
`cas` — обычный EXEC-объект с тремя под-объектами: `fan`, `cmd`, `set`.
|
||
Каждый исполняется (с полным синтаксисом `item`/`emit`/`can`/`map`) при
|
||
изменении соответственно вентилятора, режима или уставки зоны. Полезен
|
||
для дублирования состояния зоны на климатическую панель, другой
|
||
контроллер по CAN или в MQTT-топик для Home Assistant.
|
||
|
||
```json
|
||
"cas": {
|
||
"fan": {"emit": "house/f_room1/fan", "map": {"cmd": "fan"}},
|
||
"cmd": {"item": "panel1/mode"},
|
||
"set": {"item": "panel1/settemp"}
|
||
}
|
||
```
|
||
|
||
Без `cas` изменения зоны всё равно публикуются в статусные топики item'а
|
||
(`/cmd`, `/fan`, `/set` зоны) — каскад нужен именно для внешних адресатов.
|
||
|
||
---
|
||
|
||
## 5. Режимы работы модуля
|
||
|
||
### 5.1 Команды зон
|
||
|
||
Команды задаются в `/cmd` зоны (или через `/fan`):
|
||
|
||
| Команда | Код | Поведение |
|
||
|-----|-----|-----------|
|
||
| `ON` | 1 | Включить зону с последним режимом (из `@precmd`, по умолчанию FAN) и последним уровнем вентилятора |
|
||
| `OFF` | 2 | Выключить зону (PID в MANUAL, вентилятор 0); предыдущий режим сохраняется в `@precmd` |
|
||
| `HEAT` | 0x14 | Нагрев: PID в DIRECT, вентилятор минимум 30 % |
|
||
| `COOL` | 0x15 | Охлаждение: PID в REVERSE, вентилятор минимум 30 % |
|
||
| `HEATCOOL` | 0x13 | Автовыбор HEAT/COOL по уставке и текущей температуре с гистерезисом 1 °C |
|
||
| `FAN` (FAN\_ONLY) | 0xF | Только вентиляция с текущим уровнем `/fan` |
|
||
| `AUTO` | 0xE | Пассивный режим: запрос воздуха берётся из внешних значений `/fan` (например, от CO2-PID) |
|
||
| `DRY` | 0x16 | Осушение (PID в REVERSE, как COOL) |
|
||
| `FREEZE` | 0xD | Заморозка зоны: блокирует `/fan`, ON и OFF |
|
||
| `UNFREEZE` | 0xC | Разморозка зоны |
|
||
|
||
Уровни вентилятора через `/fan` зоны: `HIGH` → 255, `MEDIUM` → 128,
|
||
`LOW` → 64; либо число 0-255; `OFF` → 0.
|
||
|
||
### 5.2 Определение режима центральной установки
|
||
|
||
```
|
||
AC temp < 15°C → CMD_COOL
|
||
15°C ≤ AC temp ≤ 30°C → CMD_FAN
|
||
AC temp > 30°C → CMD_HEAT
|
||
```
|
||
|
||
Температура подаётся на `/val` корневого item (без subitem). Если данные
|
||
от AC не поступали более 60 секунд, режим берётся из `""/mode`.
|
||
|
||
При обнаружении тепла или холода PID регуляторы зон автоматически
|
||
активируются, их выходы направляются в балансировщик, а прямое управление
|
||
`/fan` зон блокируется (последнее внешнее значение запоминается в
|
||
`fan_in`). При переходе установки обратно в режим вентиляции используется
|
||
последнее значение `fan_in` каждой зоны, и система возвращается в режим
|
||
распределения воздуха по внешним запросам `/fan`.
|
||
|
||
### 5.3 Поведение в режимах зон
|
||
|
||
- **HEAT/COOL (активный режим)**: вентилятор зоны задаётся выходом PID.
|
||
Если при этом фактический режим воздуха противоположный (AC дует
|
||
холодом, а зона просит HEAT), задвижка зоны закрывается (`fan = 0`).
|
||
- **FAN/AUTO (пассивный режим)**: PID работает только когда AC реально
|
||
греет/охладит; в остальное время уровень зоны берётся из `fan_in`.
|
||
Пассивный режим включается командой `/fan AUTO` (статус публикуется
|
||
как `AUTO`), снимается любой явной командой или `/fan <уровень>`.
|
||
|
||
---
|
||
|
||
## 6. Примеры конфигурации
|
||
|
||
### 6.1 Минимальный рабочий пример: приточная вентиляция на 2 зоны
|
||
|
||
Центральная установка — Modbus-вентустановка (`vent`), зоны открываются
|
||
PWM-каналами. Запросы воздуха в зоны приходят по MQTT (`/fan`).
|
||
|
||
```json
|
||
{
|
||
"mqtt": ["lh1", "192.168.1.10"],
|
||
"topics": {"root": "house"},
|
||
|
||
"items": {
|
||
"ac_multizone": [
|
||
[18, 5],
|
||
{
|
||
"bedroom": {
|
||
"V": 40,
|
||
"pid": [1.0, 0.05, 0.02, 5.0],
|
||
"set": 21.0,
|
||
"cmd": 15,
|
||
"fan": -1,
|
||
"out": -1,
|
||
"item": "damper_bedroom/set",
|
||
"cas": { "fan": {"emit": "house/climate/bedroom/fan"} }
|
||
},
|
||
"living_room": {
|
||
"V": 80,
|
||
"pid": [1.0, 0.05, 0.02, 5.0],
|
||
"set": 22.0,
|
||
"cmd": 15,
|
||
"fan": -1,
|
||
"out": -1,
|
||
"item": "damper_living/set",
|
||
"cas": { "fan": {"emit": "house/climate/living/fan"} }
|
||
},
|
||
"": {
|
||
"item": "vent",
|
||
"turnbyfan": 15,
|
||
"val": -1,
|
||
"mode": 2
|
||
}
|
||
}
|
||
],
|
||
|
||
"damper_bedroom": [3, 5, null, null],
|
||
"damper_living": [3, 6, null, null],
|
||
|
||
"vent": [14, [4, "airset", {
|
||
"tset": {"emit": "house/vent/set", "@V": null},
|
||
"pmode": {"emit": "house/vent/cmd", "@V": null},
|
||
"fanspeed": {"emit": "house/vent/fan", "@V": null},
|
||
"on": {"emit": "house/vent/oncmd", "@V": null},
|
||
"$temp": {"item": "ac_multizone/val", "@S": null}
|
||
}], null]
|
||
}
|
||
}
|
||
```
|
||
|
||
Здесь `cmd: 15` (FAN\_ONLY) — зоны стартуют в режиме вентиляции;
|
||
`turnbyfan: 15` — подача ненулевого `/fan` в выключенную зону сама
|
||
переводит её в FAN\_ONLY. Температура воздуха в канале (`$temp` из Modbus)
|
||
заводится на `/val` корневого item — модуль по ней определяет HEAT/COOL.
|
||
|
||
### 6.2 Многозональный кондиционер Haier + CO2-вентиляция (рабочая схема)
|
||
|
||
Полный пример рабочей системы: центральный кондиционер Haier по Modbus,
|
||
зоны с задвижками на мотор-приводах, температуры зон — по 1-Wire,
|
||
запросы воздуха — от PID-регуляторов CO2.
|
||
|
||
```json
|
||
{
|
||
"mqtt": ["lh2", "192.168.1.4"],
|
||
"topics": {"root": "house"},
|
||
|
||
"ow": {
|
||
"283A3F81E3503CC8": {"emit": "t_ac2", "item": "vac"},
|
||
"286C3381E3823CBC": {"emit": "t_zal", "item": "vac/zal"},
|
||
"28B41581E3563CDE": {"emit": "t_bedr21", "item": "vac/bedr21"},
|
||
"28C1A581E3563C2D": {"emit": "t_bedr22", "item": "vac/bedr22"}
|
||
},
|
||
|
||
"modbus": {
|
||
"haier": {
|
||
"baud": 9600,
|
||
"serial": "8N1",
|
||
"poll": {
|
||
"regs": [[0, 3]],
|
||
"irs": [[0, 1]],
|
||
"coils": [0],
|
||
"delay": 10000
|
||
},
|
||
"par": {
|
||
"pwr": {
|
||
"coil": 0,
|
||
"map": {"cmd": [1, ["OFF", 0]], "def": 40001},
|
||
"id": 1
|
||
},
|
||
"acmode": {
|
||
"reg": 1,
|
||
"map": {
|
||
"cmd": [
|
||
["FAN_ONLY", 4],
|
||
["HEAT", 2],
|
||
["COOL", 1],
|
||
["DRY", 3],
|
||
["AUTO", 5]
|
||
],
|
||
"val": null
|
||
},
|
||
"id": 1
|
||
},
|
||
"$temp": {"ir": 0},
|
||
"set": {"reg": 0, "id": 2},
|
||
"fan": {
|
||
"reg": 2,
|
||
"id": 7,
|
||
"map": {
|
||
"cmd": [
|
||
["LOW", 1],
|
||
["HIGH", 3],
|
||
["MEDIUM", 2],
|
||
["AUTO", 4]
|
||
],
|
||
"val": [1, 255, 1, 3]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
"items": {
|
||
"ac_2": [
|
||
14,
|
||
[
|
||
"haier",
|
||
{
|
||
"pwr": {"emit": "house/ac/cmd", "item": "vac/mode", "@V": null},
|
||
"$temp": {"emit": "house/ac/temp", "item": "vac/temp", "@S": null},
|
||
"set": {"emit": "house/ac/setpoint", "item": "vac/set"},
|
||
"acmode":{"emit": "house/ac/mode", "@V": null},
|
||
"fan": {"emit": "house/ac/fan", "@V": null}
|
||
}
|
||
]
|
||
],
|
||
|
||
"vac": [
|
||
[18, 5],
|
||
{
|
||
"": {"item": "ac_2"},
|
||
"zal": {
|
||
"pid": {"kP": 490, "kI": 100, "kD": 9879, "dT": 40},
|
||
"set": 21.0,
|
||
"fan": 0,
|
||
"cmd": 14,
|
||
"item": "acgzal/set"
|
||
},
|
||
"bedr21": {
|
||
"pid": {"kP": 490, "kI": 100, "kD": 9879, "dT": 40},
|
||
"set": 21.0,
|
||
"fan": 0,
|
||
"cmd": 14,
|
||
"item": "acgbedr21/set"
|
||
},
|
||
"bedr22": {
|
||
"pid": {"kP": 490, "kI": 100, "kD": 9879, "dT": 40},
|
||
"set": 21.0,
|
||
"fan": 0,
|
||
"cmd": 14,
|
||
"item": "acgbedr22/set"
|
||
}
|
||
}
|
||
],
|
||
|
||
"acgzal": [7, ["ig2", "og1"]],
|
||
"acgbedr21": [7, ["ig4", "og3"]],
|
||
"acgbedr22": [7, ["ig1", "og2"]],
|
||
|
||
"og1": [12, [4, 33, 58, 629, 289, 5000]],
|
||
"og2": [12, [5, 32, 59, 631, 296, 5000]],
|
||
"og3": [12, [6, 31, 60, 627, 289, 5000]],
|
||
|
||
"ig1": [12, [8, 29, 62, 623, 286, 5000]],
|
||
"ig2": [12, [7, 30, 63, 634, 296, 5000]],
|
||
"ig4": [12, [11, 27, 65, 620, 289, 5000]]
|
||
}
|
||
}
|
||
```
|
||
|
||
**Как это работает:**
|
||
|
||
- **`ac_2`** (тип MBUS): кондиционер Haier. Опрос 10 сек. Параметр `pwr`
|
||
(coil 0) — питание: `map.cmd` по умолчанию (первый элемент) означает
|
||
«команда OFF → значение 0», запись 1 включает; `def` подставляет
|
||
значение регистра `acmode` при записи питания
|
||
питания. `acmode` и `fan` маппят текстовые команды HA в коды регистров.
|
||
- **`vac`** (тип VENTS): модуль мультизоны. Корневой AC-узел `""`
|
||
связан с `ac_2` (`"item": "ac_2"`): температура из `$temp` идёт на
|
||
`/val` (определение HEAT/COOL), команды режима/вентилятора/уставки
|
||
уходят обратно в `ac_2`.
|
||
- **Зоны**: `cmd: 14` (HEATCOOL) — автопереключение нагрев/охлаждение.
|
||
Температура зоны — 1-Wire в `/val` зоны (через item `vac/zal` и т.п.),
|
||
уставка `/set` зоны. Выход PID идёт в `fan` зоны, а итоговый `out`
|
||
отправляется в item группы (`acgzal` — группа задвижки-вход этой зоны).
|
||
- **Задвижки**: тип MOTOR (12) с припасовкой (позиция по резистору
|
||
обратной связи), группы `acg*` объединяют мотор задвижки и мотор
|
||
привода заслонки.
|
||
|
||
### 6.3 Каскадирование состояния зоны на панель и CAN (фрагмент)
|
||
|
||
```json
|
||
"zal3": {
|
||
"V": 200,
|
||
"can": [13, 41, "set"],
|
||
"cas": {
|
||
"fan": { "can": [13, 31, "fan"] },
|
||
"cmd": { "can": [13, 31, "cmd"] }
|
||
},
|
||
"cmd": 1,
|
||
"fan": -1,
|
||
"out": -1
|
||
}
|
||
```
|
||
|
||
- `"can": [13, 41, "set"]` в теле зоны — target по умолчанию: сигнал
|
||
`out` (0-255, положение задвижки) уходит на CAN-устройство 13, item 41,
|
||
суффикс `set` (аналогично работает поле `item` для локальных items).
|
||
- `cas.fan` / `cas.cmd` — дублирование режима и уровня вентилятора зоны
|
||
на другой item/устройство (например, на климатическую панель на
|
||
контроллере 13).
|
||
|
||
---
|
||
|
||
## 7. Протокол управления через MQTT
|
||
|
||
Топики статусов: `<root>/s_out/<item>/...`. Команды: `<root>/<controller>/<item>/...`
|
||
(контроллер здесь — имя MQTT-подключения, см. конфигурацию `mqtt`).
|
||
|
||
### 7.1 Отправка команд
|
||
|
||
```
|
||
# Команда зоны
|
||
house/lh2/vac/zal/cmd <- HEAT | COOL | FAN_ONLY | AUTO | ON | OFF
|
||
|
||
# Уровень вентилятора зоны (число 0-255 или HIGH/MEDIUM/LOW)
|
||
house/lh2/vac/zal/fan <- 128
|
||
|
||
# Уставка температуры зоны
|
||
house/lh2/vac/zal/set <- 22.5
|
||
|
||
# Текущая температура зоны (вход PID)
|
||
house/lh2/vac/zal/val <- 21.8
|
||
```
|
||
|
||
### 7.2 Получение статусов
|
||
|
||
```
|
||
house/s_out/vac/zal/cmd <- HEAT / COOL / FAN_ONLY / OFF
|
||
house/s_out/vac/zal/fan <- 0-255 (текущий запрос зоны)
|
||
house/s_out/vac/zal/out <- 0-255 (положение задвижки)
|
||
house/s_out/vac/zal/set <- уставка зоны
|
||
house/s_out/ac_2/cmd <- режим центральной установки
|
||
house/s_out/ac_2/fan <- вентилятор центральной установки
|
||
house/s_out/ac_2/temp <- температура в канале AC
|
||
```
|
||
|
||
Фактические значения в статусных топиках зависят от `map` шаблона
|
||
Modbus-устройства (в примере §6.2: HEAT=2, COOL=1, FAN\_ONLY=4, DRY=3, AUTO=5).
|
||
|
||
---
|
||
|
||
## 8. Алгоритм балансировки воздушного потока
|
||
|
||
### 8.1 Принцип
|
||
|
||
Модуль распределяет воздух пропорционально запросам зон, нормируя на
|
||
самую требующую зону.
|
||
|
||
### 8.2 Пример расчёта
|
||
|
||
Исходные данные (fan в диапазоне 0…255):
|
||
- Зона 1: V=40, fan=200 → запрос = 40 × 200 = 8000
|
||
- Зона 2: V=80, fan=180 → запрос = 80 × 180 = 14400 (максимальная)
|
||
|
||
Расчёт выходов:
|
||
- Зона 1: `out = (8000 × 255 / 40) × 80 / 14400 ≈ 283 → 255 (кап)`
|
||
- Зона 2: `out = (14400 × 255 / 80) × 80 / 14400 = 255`
|
||
|
||
Результат: обе задвижки полностью открыты, поскольку суммарная
|
||
производительность не избыточна. Если бы запросы были меньше (например,
|
||
fan=50 и fan=60), вторая зона получила бы 255, а первая пропорционально
|
||
меньшую долю — так достигается баланс.
|
||
|
||
---
|
||
|
||
## 9. Служебные поля (в конфиг-дереве)
|
||
|
||
```json
|
||
"@lastCmd": -1, // Последняя отправленная AC команда
|
||
"@lastFan": -1, // Последнее отправленное значение вентилятора AC
|
||
"@lastSet": -1, // Последняя отправленная уставка AC
|
||
"@preCmd": 15, // Режим AC до останова вентилятора, восстанавливается при повторном запуске
|
||
"@preset": 21, // Уставка AC, сохранённая перед boost
|
||
"@precmd": 15, // Режим зоны до OFF, восстанавливается при ON
|
||
"@preHaltcmd": 0, // Команда зоны до глобального останова (stopAllzones)
|
||
"@pasv": 0, // Флаг пассивного режима зоны
|
||
"fan_in": 0, // Последнее внешнее значение /fan зоны
|
||
"po": -2.0 // Выход PID (внутреннее)
|
||
```
|
||
|
||
## 10. Интеграция с внешними системами
|
||
|
||
### 10.1 Задвижки
|
||
|
||
Выход `out` зоны направляется через `item` зоны (или `can`/`cas`) в
|
||
PWM-канал, мотор-привод или группу:
|
||
|
||
```json
|
||
"damper": [3, 5, null, null] // PWM-выход
|
||
"damper": [12, [4, 33, 58, 629, 289, 5000]] // мотор-привод с обратной связью
|
||
```
|
||
|
||
### 10.2 Датчики температуры
|
||
|
||
Текущая температура зоны подаётся на `/val` зоны (1-Wire, Modbus, MQTT):
|
||
|
||
```json
|
||
"ow": {
|
||
"283A3F81E3503CC8": {"emit": "t_ac2", "item": "vac"} // корневой item - на AC-узел
|
||
}
|
||
```
|
||
|
||
### 10.3 Центральная установка через Modbus
|
||
|
||
AC-узел `""` связывается с Modbus-каналом через `item` и получает
|
||
телеметрию через параметры шаблона (`item`/`emit` в описании параметров):
|
||
`$temp` → `/val` корневого item, `acmode` → `/mode`, `fan` → `/fan`,
|
||
`set` → `/set`.
|
||
|
||
---
|
||
|
||
## 11. Рекомендации по эксплуатации
|
||
|
||
### 11.1 Настройка PID
|
||
|
||
1. Начальные значения: kP=1.0, kI=0.05, kD=0.02, dT=5 с
|
||
2. Постепенно увеличивайте kP до появления колебаний, затем снижайте
|
||
3. Добавьте kI для устранения постоянного отклонения
|
||
4. Добавьте kD для демпфирования
|
||
5. В рабочих конфигурациях LightHub используются короткие импульсные
|
||
исполнительные механизмы, поэтому встречаются сильно форсированные
|
||
коэффициенты (например, kP в сотни единиц) с большой dT — не
|
||
копируйте их в другую систему без настройки
|
||
|
||
### 11.2 Распределение объёмов (V)
|
||
|
||
- Сумма V должна соответствовать производительности центральной установки
|
||
- Для равномерного распределения: V ≈ площадь помещения
|
||
- Для приоритизации: увеличьте V критичным зонам
|
||
|
||
### 11.3 Мониторинг
|
||
|
||
- Следите за `balance` в логах (`VENT: Chan balance=`) — в установившемся
|
||
режиме должен быть близок к нулю
|
||
- Проверяйте `out` зон — не должны постоянно висеть на 0 или 255
|
||
- Контролируйте переходы HEAT↔COOL — они не должны быть частыми
|
||
|
||
### 11.4 Диагностика проблем
|
||
|
||
| Проблема | Причина | Решение |
|
||
|----------|---------|---------|
|
||
| Зона игнорируется целиком (нет в статусах) | `fan` или `cmd` зоны заданы объектом вместо числа | Поля `fan`/`cmd`/`out` — только числовые; маршрутизация через `item`/`cas` |
|
||
| Задвижка не реагирует | `out` зоны = 0 | Зона в OFF или фактический режим AC противоположен запросу зоны — проверьте `/cmd` зоны и режим AC |
|
||
| Вентилятор AC не включается от запроса зоны | Вентилятор уже был 0 и нет активного PID | Подайте ненулевой `/fan` или настройте `turnbyfan` |
|
||
| Колебания температуры | PID слишком агрессивен | Снизьте kP |
|
||
| Не достигается setpoint | PID недостаточен | Увеличьте kI |
|
||
| AC часто переключается | balance скачет | Увеличьте dT в PID |
|
||
|
||
---
|
||
|
||
## 12. Ограничения и известные особенности
|
||
|
||
1. **Автономный dT**: у каждого PID-регулятора зон свой период
|
||
сэмплирования dT, задаётся отдельно для каждой зоны
|
||
2. **Порядок обработки**: сначала зоны, потом центральная установка
|
||
3. **Гистерезис режимов**: автоматическое переключение AC может быть
|
||
медленным (до 60 сек при отсутствии данных о температуре канала)
|
||
4. **Состояние хранится в конфиге**: значения `fan`/`cmd`/`out` зон
|
||
сохраняются в JSON-конфиге и переживают перезагрузку (в отличие от
|
||
истории команд)
|
||
5. **Поля-числа**: `fan`, `cmd`, `out` зон и AC-узла — числовые ячейки;
|
||
объектная запись в них ломает обработку зоны
|
||
|
||
---
|
||
|
||
## 13. Заключение
|
||
|
||
Модуль `out_Multivent` предоставляет полнофункциональное решение для
|
||
управления многозональными системами климатизации:
|
||
|
||
- Автоматическая балансировка воздушного потока
|
||
- Независимое PID-регулирование для каждой зоны
|
||
- Автоматическая агрегация команд (boost)
|
||
- Каскадирование состояния на внешние системы
|
||
|
||
---
|
||
|
||
**Версия документа:** 2.0
|
||
**Дата:** 2026-10-11
|
||
**Статус:** Верифицировано по исходному коду
|