Zum Inhalt springen

← Anwendungsstruktur | Inhaltsverzeichnis | Weiter: API-Referenz →

4. RouterController-Betriebsmodi



4.1 Modusübersicht

RouterController unterstützt 6 Betriebsmodi, die jeweils für ein bestimmtes Anwendungsszenario optimiert sind.


Modustabelle

Modus Enum Dimmer-Steuerung P_grid-Steuerung Erforderliche Sensoren Anwendung
OFF 0 0% (fest) ❌ Nein - Wartung, Abschaltung
AUTO 1 Automatisch ✅ P_grid → 0 Netzstrom Standard-Solar-Router
ECO 2 Halbautomatisch ⚠️ Nur Import Netzstrom Exportverhinderung
OFFGRID 3 Automatisch ❌ Nein Solarstrom Netzunabhängige Systeme
MANUAL 4 Fest ❌ Nein - Nachttarif, Test
BOOST 5 100% (fest) ❌ Nein - Zwangsheizung



4.2 OFF-Modus (0) – Deaktiviert


Beschreibung

Vollständige Abschaltung der Dimmer-Steuerung. Wird für Wartung, Fehlersuche oder wenn keine Laststeuerung erforderlich ist verwendet.


Algorithmus

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


Parameter

Keine konfigurierbaren Parameter.


Erforderliche Sensoren

Sensoren sind nicht erforderlich (Messungen laufen weiter, werden aber nicht verwendet).


Verhalten

  • Dimmer-Stufe: 0% (konstant)
  • P_grid: Nicht gesteuert
  • Zustand: IDLE
  • Messungen: Laufen weiter (PowerMeterADC arbeitet)
  • Web-Oberfläche: Verfügbar
  • Serielle Befehle: Funktionieren


Wann verwenden

  • ✅ Gerätewartung
  • ✅ Sensortest ohne Steuerung
  • ✅ System-Fehlersuche
  • ✅ Vorübergehende Lastabschaltung


Verwendungsbeispiel

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-Modus (1) – Automatischer Solar-Router


Beschreibung

Haupt-Solar-Router-Modus. Gleicht die Netzleistung (P_grid) automatisch auf Null aus und leitet überschüssige Solarenergie an die Last weiter, anstatt sie ins Netz einzuspeisen.


Algorithmus

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);
}


Verhalten nach P_grid-Vorzeichen

Situation P_grid Fehler Delta Aktion
Export ins Netz < 0 (negativ) > 0 (positiv) > 0 Erhöhung Dimmer → mehr Last
Import aus Netz > 0 (positiv) < 0 (negativ) < 0 Verringerung Dimmer → weniger Last
Ausgleich ≈ 0 (innerhalb der Schwelle) ≈ 0 0 Halten der aktuellen Stufe


Parameter

control_gain (Kp)

Beschreibung: Koeffizient des Proportionalreglers. Bestimmt die Reaktionsgeschwindigkeit auf P_grid-Änderungen.

Formel: delta = error / control_gain

Bereich: 10.0 - 1000.0

Standard: 200.0

Auswirkung:

  • Niedrigerer Kp (schneller):
  • ✅ Schnelle Reaktion auf Änderungen
  • ❌ Mögliche Oszillationen
  • Beispiel: Kp = 50 → schnell, aber instabil

  • Höherer Kp (langsamer):

  • ✅ Sanfte Steuerung
  • ✅ Stabilität
  • ❌ Langsame Reaktion
  • Beispiel: Kp = 500 → langsam, aber stabil

Empfehlungen:

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

Beschreibung: Ausgleichsschwelle in Watt. Wenn |P_grid| < Schwelle, gilt das System als ausgeglichen.

Bereich: 0.0 - 100.0 W

Standard: 10.0 W

Auswirkung:

  • Niedrigere Schwelle:
  • ✅ Präziserer Ausgleich (P_grid näher an 0)
  • ❌ Mehr Anpassungen (TRIAC-Verschleiß)

  • Höhere Schwelle:

  • ✅ Weniger Schaltzyklen
  • ❌ Ungenauerer Ausgleich

Empfehlungen:

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


Erforderliche Sensoren

Minimum:

  • Current Grid (erforderlich) – zur P_grid-Bestimmung
  • Voltage (empfohlen) – zur Leistungsberechnung

Optional:

  • ⚪ Current Load – zur Verbrauchsüberwachung
  • ⚪ Current Solar – zur Erzeugungsüberwachung


Betriebsbeispiele

Beispiel 1: Solarüberschuss

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 ✅

Beispiel 2: Wolke verdeckt die Sonne

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 ✅


Konfiguration über Schnittstellen

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-Modus (2) – Economy (Anti-Export)


Beschreibung

Exportverhinderungsmodus. Verhindert die Einspeisung von Strom ins Netz, erlaubt aber den Import. Wird verwendet, wenn der Export unrentabel oder verboten ist.


Algorithmus

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
    }
}


Unterschiede zu AUTO

Aspekt AUTO ECO
Export Verhindert (Dimmer steigt) Erlaubt (Dimmer steigt nicht)
Import Verhindert (Dimmer sinkt) Erlaubt (Dimmer sinkt langsam)
Reaktionsgeschwindigkeit Schnell (Kp) Langsamer (Kp × 1,5)
Ziel P_grid = 0 P_grid ≥ 0


Verhalten

  • P_grid > Schwelle (Import):
  • Dimmer langsam verringern
  • Geschwindigkeit: Kp × 1,5 (langsamer als AUTO)

  • P_grid < 0 (Export):

  • Dimmer NICHT erhöhen
  • Aktuelle Stufe halten

  • P_grid ≈ 0:

  • Aktuelle Stufe halten


Parameter

Gleich wie AUTO:

  • control_gain – beeinflusst die Verringerungsgeschwindigkeit beim Import
  • balance_threshold – Schwelle zur Ausgleichsbestimmung


Erforderliche Sensoren

  • Current Grid (erforderlich)
  • Voltage (empfohlen)


Wann verwenden

  • ✅ Kein Netz-Einspeisevertrag
  • ✅ Einspeisevergütung ist ungünstig (< Importkosten)
  • ✅ Technische Einspeisebeschränkung
  • ✅ Exportschutz bei instabilem Netz


Betriebsbeispiel

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-Modus (3) – Netzunabhängig


Beschreibung

Modus für autonome Systeme mit Solarpanelen und Batterien, ohne Netzanschluss. Nutzt überschüssige Solarenergie für die Last.


Algorithmus

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);
    }
}


Besonderheiten

  • Verwendet KEIN P_grid (Netzsensor kann fehlen)
  • Verwendet P_solar zur Bestimmung der verfügbaren Leistung
  • Konservativ: 80% der verfügbaren Leistung (Batterieschutz)
  • Priorität: Hauptlast → Batterien → Heizung


Parameter

  • control_gain – beeinflusst die Geschwindigkeit der Lasterhöhung
  • balance_threshold – minimale Solarleistung für die Aktivierung
  • Sicherheitsmarge: 0,8 (80%) – fest codiert


Erforderliche Sensoren

Minimum:

  • Current Solar (erforderlich) – zur Erzeugungsbestimmung
  • Voltage (empfohlen)

Optional:

  • ⚪ Current Load – für genauere Steuerung
  • ❌ Current Grid – NICHT erforderlich (kann fehlen)


Wann verwenden

  • ✅ Netzunabhängige Systeme
  • ✅ Solarpanele + Batterien
  • ✅ Kein Netzanschluss
  • ✅ Maximale Nutzung der Solarenergie


Betriebsbeispiel

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-Modus (4) – Manuell


Beschreibung

Feste Dimmer-Stufe, vom Benutzer eingestellt. Keine automatische Steuerung.


Algorithmus

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;
}


Parameter

  • manual_level – Dimmer-Stufe (0-100%)


Erforderliche Sensoren

Sensoren sind nicht erforderlich (Messungen laufen zur Überwachung weiter).


Wann verwenden

  • ✅ Nachttarif (100% für die Nacht einstellen)
  • ✅ Last-Tests
  • ✅ Temperaturhaltung (50% einstellen)
  • ✅ System-Fehlersuche


Verwendungsbeispiel

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}


Szenario: Nachttarif

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-Modus (5) – Zwangsheizung


Beschreibung

Dimmer fest auf 100%. Maximale Leistung an die Last.


Algorithmus

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


Parameter

Keine konfigurierbaren Parameter (immer 100%).


Erforderliche Sensoren

Nicht erforderlich.


Wann verwenden

  • ✅ Schnelle Warmwasserbereitung
  • ✅ Nutzung günstiger Tarife
  • ✅ Notfallmodus


Warnungen

⚠️ WARNUNG:

  • Hoher Netzverbrauch
  • Mögliche Überhitzung der Last
  • Temperatur manuell überwachen
  • Nicht unbeaufsichtigt lassen


Verwendungsbeispiel

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

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



4.8 Umschalten zwischen Modi


Sicheres Umschalten

Beim Moduswechsel führt RouterController folgende Schritte aus:

  1. Protokollierung des Moduswechsels
  2. Rücksetzung des internen Zustands
  3. Anwendung des neuen Algorithmus
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;
}


Empfehlungen zum Umschalten

Sichere Übergänge:

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

Vorsicht:

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


Befehlssequenzen

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 Minimale Sensorkonfigurationen


Für jeden Modus

Modus Erforderliche Sensoren Optional Hinweis
OFF - - Sensoren werden nicht verwendet
AUTO Voltage, Current Grid Current Load, Current Solar Grid benötigt für P_grid
ECO Voltage, Current Grid Current Load, Current Solar Grid benötigt für P_grid
OFFGRID Voltage, Current Solar Current Load Grid NICHT erforderlich
MANUAL - Voltage, Current Grid Nur zur Überwachung
BOOST - Voltage, Current Grid Nur zur Überwachung


Minimalkonfiguration (Solar-Router)

Für AUTO/ECO-Modi:

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

Ergebnis:

  • ✅ P_grid-Messung (für Ausgleich)
  • ✅ Dimmer-Steuerung
  • ❌ Kein Solar-/Last-Monitoring


Vollständige Konfiguration

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

Ergebnis:

  • ✅ Vollständiges Systemmonitoring
  • ✅ Alle Modi unterstützt
  • ✅ Detaillierte Analysen



4.10 Parameterkonfiguration über Schnittstellen


Per Serial-Befehle

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


Per 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}'


Per Web-Oberfläche

  1. Dashboard öffnen: http://192.168.4.1/
  2. Modus auswählen (6 Schaltflächen)
  3. Für MANUAL: Schieberegler bewegen
  4. Click "Apply"

← Anwendungsstruktur | Inhaltsverzeichnis | Weiter: API-Referenz →