Перейти к содержимому

← Структура приложения | Содержание | Далее: Справочник API →

4. Режимы работы RouterController



4.1 Обзор режимов

RouterController поддерживает 6 режимов работы, каждый из которых оптимизирован для конкретного сценария использования.


Таблица режимов

Режим Enum Управление диммером Управление P_grid Необходимые датчики Применение
OFF 0 0% (фикс.) ❌ Нет Обслуживание, отключение
AUTO 1 Автоматический ✅ P_grid → 0 Ток сети Стандартный солнечный роутер
ECO 2 Полуавтоматический ⚠️ Только импорт Ток сети Защита от экспорта
OFFGRID 3 Автоматический ❌ Нет Ток солнца Автономные системы
MANUAL 4 Фиксированный ❌ Нет Ночной тариф, тестирование
BOOST 5 100% (фикс.) ❌ Нет Принудительный нагрев



4.2 Режим OFF (0) — Отключён


Описание

Полное отключение диммера. Используется при техническом обслуживании, отладке или когда управление нагрузкой не требуется.


Алгоритм

cpp
void RouterController::processOffMode() {
    // Dimmer always 0%
    if (m_status.dimmer_percent != 0) {
        applyDimmerLevel(0);
    }
    m_status.state = RouterState::IDLE;
}


Параметры

Настраиваемые параметры отсутствуют.


Необходимые датчики

Датчики не требуются (измерения продолжаются, но не используются).


Поведение

  • Уровень диммера: 0% (постоянно)
  • P_grid: не контролируется
  • Состояние: IDLE
  • Измерения: продолжаются (PowerMeterADC работает)
  • Веб-интерфейс: доступен
  • Последовательные команды: работают


Когда использовать

  • ✅ Техническое обслуживание устройства
  • ✅ Тестирование датчиков без управления
  • ✅ Отладка системы
  • ✅ Временное отключение нагрузки


Пример использования

cpp
// Via code
RouterController& router = RouterController::getInstance();
router.setMode(RouterMode::OFF);

// Via Serial
set-mode 0

// Via REST API
POST /api/mode
{"mode": 0}



4.3 Режим AUTO (1) — Автоматический солнечный роутер


Описание

Основной режим солнечного роутера. Автоматически балансирует мощность сети (P_grid) к нулю, перенаправляя избыток солнечной энергии на нагрузку вместо экспорта в сеть.


Алгоритм

cpp
void RouterController::processAutoMode(float power_grid) {
    // Goal: P_grid → 0
    // Proportional control with configurable gain

    float error = -power_grid;  // Invert: export = positive error

    // Check if within balance threshold
    if (fabs(power_grid) <= balance_threshold) {
        // Within threshold - hold current level
        return;
    }

    // Proportional control
    float delta = error / control_gain;
    m_target_level += delta;

    // Apply new level (clamped to 0-100%)
    applyDimmerLevel(m_target_level);
}


Поведение в зависимости от знака P_grid

Ситуация P_grid Ошибка Дельта Действие
Экспорт в сеть < 0 (отрицательный) > 0 (положительная) > 0 Увеличить диммер → больше нагрузка
Импорт из сети > 0 (положительная) < 0 (отрицательный) < 0 Уменьшить диммер → меньше нагрузка
Баланс ≈ 0 (в пределах порога) ≈ 0 0 Удерживать текущий уровень


Параметры

control_gain (Kp)

Описание: коэффициент пропорционального регулятора. Определяет скорость реакции на изменения P_grid.

Формула: delta = error / control_gain

Диапазон: 10.0 — 1000.0

По умолчанию: 200.0

Влияние:

  • Меньший Kp (быстрее):
  • ✅ Быстрая реакция на изменения
  • ❌ Возможны колебания
  • Пример: Kp = 50 → быстро, но нестабильно

  • Больший Kp (медленнее):

  • ✅ Плавное управление
  • ✅ Стабильность
  • ❌ Медленная реакция
  • Пример: Kp = 500 → медленно, но стабильно

Рекомендации:

python
System Type              | Recommended Kp | Comment
-------------------------|----------------|------------------------
Stable grid              | 150 - 250      | Optimal
Unstable grid            | 300 - 500      | Increase for stability
Fast clouds              | 100 - 150      | Decrease for responsiveness
High inertia heater      | 200 - 400      | Medium values

balance_threshold

Описание: порог баланса в Ваттах. Если |P_grid| < threshold, система считается сбалансированной.

Диапазон: 0.0 — 100.0 Вт

По умолчанию: 10.0 Вт

Влияние:

  • Меньший порог:
  • ✅ Более точный баланс (P_grid ближе к 0)
  • ❌ Больше регулировок (износ TRIAC)

  • Больший порог:

  • ✅ Меньше коммутаций
  • ❌ Менее точный баланс

Рекомендации:

python
Load Power               | Recommended Threshold
-------------------------|----------------------
< 500 W                  | 5 - 10 W
500 - 1500 W             | 10 - 20 W
> 1500 W                 | 20 - 50 W


Необходимые датчики

Минимум:

  • Ток сети (обязательно) — для определения P_grid
  • Напряжение (рекомендуется) — для расчёта мощности

Опционально:

  • ⚪ Ток нагрузки — для мониторинга потребления
  • ⚪ Ток солнца — для мониторинга генерации


Примеры работы

Пример 1: Избыток солнечной энергии

python
Initial state:
  P_solar = 3000 W
  P_house = 800 W
  P_grid = -2200 W (export!)
  Dimmer = 0%

After 10 seconds (Kp=200):
  error = -(-2200) = +2200
  delta = 2200 / 200 = +11% per iteration
  → Dimmer gradually increases

After 30 seconds:
  Dimmer ≈ 70% (~1400 W to heater)
  P_grid ≈ -800 W (still exporting)
  → Continues to increase

After 60 seconds (stabilization):
  Dimmer = 95% (~1900 W)
  P_grid ≈ -5 W (within 10W threshold)
  → Balance achieved ✅

Пример 2: Тучи закрыли солнце

python
Stable state:
  P_solar = 2500 W
  P_grid = 0 W (balance)
  Dimmer = 80% (~1600 W)

Cloud:
  P_solar = 500 W (sharp drop)
  P_grid = +1100 W (import!)

  error = -1100
  delta = -1100 / 200 = -5.5%
  → Dimmer decreases by 5.5%

After 5 seconds:
  Dimmer ≈ 50% (~1000 W)
  P_grid ≈ +100 W (close to balance)

After 10 seconds:
  Dimmer = 30% (~600 W)
  P_grid ≈ +5 W (within threshold)
  → New balance achieved ✅


Настройка через интерфейсы

cpp
// Via code
router.setMode(RouterMode::AUTO);
router.setControlGain(200.0f);
router.setBalanceThreshold(10.0f);

// Via Serial
set-mode 1
set-kp 200
set-threshold 10

// Via REST API
POST /api/mode
{"mode": 1}

POST /api/config
{"control_gain": 200.0, "balance_threshold": 10.0}



4.4 Режим ECO (2) — Экономный (защита от экспорта)


Описание

Режим защиты от экспорта. Не допускает подачи электроэнергии в сеть, но разрешает импорт. Используется, когда экспорт невыгоден или запрещён.


Алгоритм

cpp
void RouterController::processEcoMode(float power_grid) {
    // Goal: P_grid >= 0 (avoid export, allow import)

    if (power_grid > balance_threshold) {
        // IMPORTING from grid - reduce load
        float error = -power_grid;

        // Slower response: increase gain by 1.5x
        float delta = error / (control_gain * 1.5f);
        m_target_level += delta;

        applyDimmerLevel(m_target_level);
    } else {
        // EXPORTING or BALANCED - hold current level
        // Do not increase load aggressively
    }
}


Отличия от режима AUTO

Аспект AUTO ECO
Экспорт Предотвращается (диммер растёт) Допускается (диммер не растёт)
Импорт Предотвращается (диммер снижается) Допускается (диммер медленно снижается)
Скорость реакции Быстрая (Kp) Медленнее (Kp × 1.5)
Цель P_grid = 0 P_grid ≥ 0


Поведение

  • P_grid > threshold (импорт):
  • Медленно снижать диммер
  • Скорость: Kp × 1.5 (медленнее, чем AUTO)

  • P_grid < 0 (экспорт):

  • НЕ увеличивать диммер
  • Удерживать текущий уровень

  • P_grid ≈ 0:

  • Удерживать текущий уровень


Параметры

Аналогичны режиму AUTO:

  • control_gain — влияет на скорость снижения при импорте
  • balance_threshold — порог для определения баланса


Необходимые датчики

  • Ток сети (обязательно)
  • Напряжение (рекомендуется)


Когда использовать

  • ✅ Нет договора на экспорт в сеть
  • ✅ Тариф на экспорт невыгоден (< стоимости импорта)
  • ✅ Технические ограничения на экспорт
  • ✅ Защита от экспорта при нестабильной сети


Пример работы

python
Initial state:
  P_solar = 2000 W
  P_house = 1000 W
  P_grid = -1000 W (export 1 kW)
  Dimmer = 0%

In ECO mode:
  → Dimmer does NOT increase
  → P_grid remains -1000 W (export continues)

  Result: Excess goes to grid (acceptable in ECO)

After 1 hour (cloud):
  P_solar = 500 W
  P_house = 1000 W
  P_grid = +500 W (import!)

  → Dimmer slowly decreases (if it was enabled)
  → After some time P_grid ≈ 0



4.5 Режим OFFGRID (3) — Автономный


Описание

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


Алгоритм

cpp
void RouterController::processOffgridMode(const Measurements& meas) {
    float power_solar = meas.power_active[CURRENT_SOLAR];
    float power_load = meas.power_active[CURRENT_LOAD];

    if (power_solar > balance_threshold) {
        // Solar generation available
        float available_power = power_solar * 0.8f;  // 80% safety margin

        if (available_power > power_load + balance_threshold) {
            // Can increase load
            float delta = (available_power - power_load) / (control_gain * 2.0f);
            m_target_level += delta;
        } else if (available_power < power_load - balance_threshold) {
            // Need to reduce load
            m_target_level -= 5.0f;  // Gradual decrease
        }

        applyDimmerLevel(m_target_level);
    } else {
        // No solar generation - reduce load to minimum
        m_target_level -= 10.0f;  // Faster decrease
        applyDimmerLevel(m_target_level);
    }
}


Особенности

  • Не использует P_grid (датчик сети может отсутствовать)
  • Использует P_solar для определения доступной мощности
  • Консервативный подход: 80% доступной мощности (защита аккумуляторов)
  • Приоритет: основная нагрузка → аккумуляторы → нагреватель


Параметры

  • control_gain — влияет на скорость роста нагрузки
  • balance_threshold — минимальная солнечная мощность для активации
  • Коэффициент запаса: 0.8 (80%) — зашит в код


Необходимые датчики

Минимум:

  • Ток солнца (обязательно) — для определения генерации
  • Напряжение (рекомендуется)

Опционально:

  • ⚪ Ток нагрузки — для более точного управления
  • ❌ Ток сети — не требуется (сети нет)


Когда использовать

  • ✅ Автономные системы
  • ✅ Солнечные панели + аккумуляторы
  • ✅ Нет подключения к сети
  • ✅ Максимальное использование солнечной энергии


Пример работы

python
Daytime (sunny):
  P_solar = 1500 W
  P_house = 800 W (from battery/solar)
  P_load (dimmer) = 0 W

  available_power = 1500 * 0.8 = 1200 W

  → Can turn on heater
  → Dimmer gradually increases to ~60% (1200 W)
  → Battery is not discharging (enough solar)

Evening (sunset):
  P_solar = 200 W (dropping)
  available_power = 200 * 0.8 = 160 W
  P_load = 800 W (heater was on)

  → Too little solar
  → Dimmer quickly decreases (10% per iteration)
  → After several iterations: Dimmer = 0%
  → Battery is saved for main load

Night:
  P_solar = 0 W
  → Dimmer = 0%
  → Heater is off



4.6 Режим MANUAL (4) — Ручной


Описание

Фиксированный уровень диммера, заданный пользователем. Автоматическое управление отсутствует.


Алгоритм

cpp
void RouterController::processManualMode() {
    // Fixed level set by user
    if (m_status.dimmer_percent != m_manual_level) {
        applyDimmerLevel(m_manual_level);
    }
    m_status.state = RouterState::IDLE;
}


Параметры

  • manual_level — уровень диммера (0–100%)


Необходимые датчики

Датчики не требуются (измерения продолжаются для мониторинга).


Когда использовать

  • ✅ Ночной тариф (установить 100% на ночь)
  • ✅ Тестирование нагрузки
  • ✅ Поддержание температуры (установить 50%)
  • ✅ Отладка системы


Пример использования

cpp
// Set 75%
router.setMode(RouterMode::MANUAL);
router.setManualLevel(75);

// Via Serial
set-mode 4
set-manual 75

// Via REST API
POST /api/mode
{"mode": 4}

POST /api/manual
{"level": 75}


Сценарий: ночной тариф

bash
# 23:00 - night tariff starts (cheap)
set-mode 4
set-manual 100  # Full power

# 07:00 - night tariff ends
set-mode 1      # Switch to AUTO



4.7 Режим BOOST (5) — Принудительный нагрев


Описание

Диммер зафиксирован на 100%. Максимальная мощность на нагрузку.


Алгоритм

cpp
void RouterController::processBoostMode() {
    // Always 100%
    if (m_status.dimmer_percent != 100) {
        applyDimmerLevel(100);
    }
    m_status.state = RouterState::AT_MAXIMUM;
}


Параметры

Настраиваемые параметры отсутствуют (всегда 100%).


Необходимые датчики

Не требуются.


Когда использовать

  • ✅ Быстрый нагрев водонагревателя
  • ✅ Использование дешёвого тарифа
  • ✅ Аварийный режим


Предупреждения

⚠️ ВНИМАНИЕ:

  • Высокое потребление из сети
  • Возможен перегрев нагрузки
  • Контролировать температуру вручную
  • Не оставлять без присмотра


Пример использования

cpp
// Enable BOOST
router.setMode(RouterMode::BOOST);

// Return to AUTO after 2 hours
delay(2 * 60 * 60 * 1000);
router.setMode(RouterMode::AUTO);



4.8 Переключение режимов


Безопасное переключение

При смене режима RouterController:

  1. Записывает смену режима в журнал
  2. Сбрасывает внутреннее состояние
  3. Применяет новый алгоритм
cpp
void RouterController::setMode(RouterMode mode) {
    if (m_status.mode == mode) {
        return;  // No change
    }

    RouterMode old_mode = m_status.mode;
    m_status.mode = mode;

    ESP_LOGI(TAG, "Mode changed: %d -> %d",
             static_cast(old_mode),
             static_cast(mode));

    // Reset state for new mode
    m_status.state = RouterState::IDLE;
}


Рекомендации по переключению

Безопасные переходы:

python
OFF ↔ AUTO      ✅ Safe
OFF ↔ MANUAL    ✅ Safe
AUTO ↔ ECO      ✅ Safe (similar algorithms)
MANUAL ↔ BOOST  ✅ Safe

С осторожностью:

python
AUTO → BOOST    ⚠️ Sharp power spike
OFFGRID → AUTO  ⚠️ Different sensors


Последовательности команд

bash
# Example 1: Morning transition
set-mode 0        # OFF - pause
# ... system check ...
set-mode 1        # AUTO - start operation

# Example 2: Testing
set-mode 4        # MANUAL
set-manual 25     # 25% for test
# ... observation ...
set-manual 50     # 50%
# ... observation ...
set-mode 1        # Return to AUTO



4.9 Минимальные конфигурации датчиков


По каждому режиму

Режим Необходимые датчики Опциональные Примечание
OFF Датчики не используются
AUTO Напряжение, Ток сети Ток нагрузки, Ток солнца Сеть нужна для P_grid
ECO Напряжение, Ток сети Ток нагрузки, Ток солнца Сеть нужна для P_grid
OFFGRID Напряжение, Ток солнца Ток нагрузки Ток сети не нужен
MANUAL Напряжение, Ток сети Только для мониторинга
BOOST Напряжение, Ток сети Только для мониторинга


Минимальная конфигурация (солнечный роутер)

Для режимов AUTO/ECO:

python
ADC0: GPIO35, VOLTAGE_AC,    enabled=true   ← Required
ADC1: GPIO36, CURRENT_GRID,  enabled=true   ← Required
ADC2: -,      NONE,           enabled=false
ADC3: -,      NONE,           enabled=false

Dimmer1: GPIO19, enabled=true               ← Required
ZeroCross: GPIO18, enabled=true             ← Required

Результат:

  • ✅ Измерение P_grid (для баланса)
  • ✅ Управление диммером
  • ❌ Нет мониторинга солнца/нагрузки


Полная конфигурация

python
ADC0: GPIO35, VOLTAGE_AC,     enabled=true
ADC1: GPIO39, CURRENT_LOAD,   enabled=true
ADC2: GPIO36, CURRENT_GRID,   enabled=true
ADC3: GPIO34, CURRENT_SOLAR,  enabled=true

Dimmer1: GPIO19, enabled=true
Dimmer2: GPIO23, enabled=true (optional)
ZeroCross: GPIO18, enabled=true

Результат:

  • ✅ Полный мониторинг системы
  • ✅ Поддержка всех режимов
  • ✅ Детальная аналитика



4.10 Настройка параметров через интерфейсы


Через последовательные команды

bash
# Mode switching
set-mode 0          # OFF
set-mode 1          # AUTO
set-mode 2          # ECO
set-mode 3          # OFFGRID
set-mode 4          # MANUAL
set-mode 5          # BOOST

# AUTO/ECO parameters
set-kp 200          # Set Kp = 200
set-threshold 10    # Balance threshold 10 W

# MANUAL parameters
set-manual 75       # Set 75%

# Save
config-save         # Save to NVS


Через REST API

bash
# Set mode
curl -X POST http://192.168.4.1/api/mode \
  -H "Content-Type: application/json" \
  -d '{"mode": 1}'

# Set parameters
curl -X POST http://192.168.4.1/api/config \
  -H "Content-Type: application/json" \
  -d '{
    "control_gain": 200.0,
    "balance_threshold": 10.0
  }'

# Set MANUAL level
curl -X POST http://192.168.4.1/api/manual \
  -H "Content-Type: application/json" \
  -d '{"level": 75}'


Через веб-интерфейс

  1. Открыть панель управления: http://192.168.4.1/
  2. Выбрать режим (6 кнопок)
  3. Для MANUAL: переместить слайдер
  4. Click "Apply"

← Структура приложения | Содержание | Далее: Справочник API →