Passa al contenuto

← Struttura dell'applicazione | Indice | Avanti: Riferimento API →

4. Modalità operative del RouterController



4.1 Panoramica delle modalità

RouterController supporta 6 modalità operative, ciascuna ottimizzata per uno specifico scenario di utilizzo.


Tabella delle modalità

Modalità Enum Controllo dimmer Controllo P_grid Sensori richiesti Applicazione
OFF 0 0% (fisso) ❌ No - Manutenzione, spegnimento
AUTO 1 Automatico ✅ P_grid → 0 Corrente di rete Router solare standard
ECO 2 Semi-automatico ⚠️ Solo importazione Corrente di rete Prevenzione esportazione
OFFGRID 3 Automatico ❌ No Corrente solare Sistemi isolati
MANUAL 4 Fisso ❌ No - Tariffa notturna, test
BOOST 5 100% (fisso) ❌ No - Riscaldamento forzato



4.2 Modalità OFF (0) – Disattivata


Descrizione

Spegnimento completo del controllo del dimmer. Utilizzata per manutenzione, debug o quando il controllo del carico non è necessario.


Algoritmo

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


Parametri

Nessun parametro configurabile.


Sensori richiesti

I sensori non sono necessari (le misurazioni continuano ma non vengono utilizzate).


Comportamento

  • Livello dimmer: 0% (costante)
  • P_grid: Non controllato
  • Stato: IDLE
  • Misurazioni: Continuano (PowerMeterADC funziona)
  • Interfaccia web: Disponibile
  • Comandi seriali: Funzionanti


Quando usare

  • ✅ Manutenzione del dispositivo
  • ✅ Test dei sensori senza controllo
  • ✅ Debug del sistema
  • ✅ Disconnessione temporanea del carico


Esempio di utilizzo

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 Modalità AUTO (1) – Router solare automatico


Descrizione

Modalità principale del router solare. Bilancia automaticamente la potenza di rete (P_grid) a zero, reindirizzando l'energia solare in eccesso verso il carico invece di esportarla nella rete.


Algoritmo

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


Comportamento in base al segno di P_grid

Situazione P_grid Errore Delta Azione
Esportazione verso la rete < 0 (negativo) > 0 (positivo) > 0 Aumentare dimmer → più carico
Importazione dalla rete > 0 (positivo) < 0 (negativo) < 0 Diminuire dimmer → meno carico
Equilibrio ≈ 0 (entro la soglia) ≈ 0 0 Mantenere il livello attuale


Parametri

control_gain (Kp)

Descrizione: Coefficiente del regolatore proporzionale. Determina la velocità di risposta ai cambiamenti di P_grid.

Formula: delta = error / control_gain

Intervallo: 10.0 - 1000.0

Predefinito: 200.0

Impatto:

  • Kp inferiore (più veloce):
  • ✅ Risposta rapida ai cambiamenti
  • ❌ Possibili oscillazioni
  • Esempio: Kp = 50 → veloce, ma instabile

  • Kp superiore (più lento):

  • ✅ Controllo morbido
  • ✅ Stabilità
  • ❌ Risposta lenta
  • Esempio: Kp = 500 → lento, ma stabile

Raccomandazioni:

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

Descrizione: Soglia di equilibrio in Watt. Se |P_grid| < soglia, il sistema è considerato in equilibrio.

Intervallo: 0.0 - 100.0 W

Predefinito: 10.0 W

Impatto:

  • Soglia inferiore:
  • ✅ Equilibrio più preciso (P_grid più vicino a 0)
  • ❌ Più aggiustamenti (usura del TRIAC)

  • Soglia superiore:

  • ✅ Meno cicli di commutazione
  • ❌ Equilibrio meno preciso

Raccomandazioni:

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


Sensori richiesti

Minimo:

  • Current Grid (richiesto) – per la determinazione di P_grid
  • Voltage (raccomandato) – per il calcolo della potenza

Opzionale:

  • ⚪ Current Load – per il monitoraggio dei consumi
  • ⚪ Current Solar – per il monitoraggio della produzione


Esempi di funzionamento

Esempio 1: Eccedenza solare

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 ✅

Esempio 2: Una nuvola copre il sole

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 ✅


Configurazione tramite interfacce

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 Modalità ECO (2) – Economia (Anti-Esportazione)


Descrizione

Modalità di prevenzione dell'esportazione. Evita l'esportazione di elettricità verso la rete, ma consente l'importazione. Utilizzata quando l'esportazione non è conveniente o è vietata.


Algoritmo

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


Differenze rispetto ad AUTO

Aspetto AUTO ECO
Esportazione Impedita (dimmer aumenta) Consentita (dimmer non aumenta)
Importazione Impedita (dimmer diminuisce) Consentita (dimmer diminuisce lentamente)
Velocità di risposta Rapida (Kp) Più lenta (Kp × 1,5)
Obiettivo P_grid = 0 P_grid ≥ 0


Comportamento

  • P_grid > soglia (importazione):
  • Diminuire lentamente il dimmer
  • Velocità: Kp × 1,5 (più lento di AUTO)

  • P_grid < 0 (esportazione):

  • NON aumentare il dimmer
  • Mantenere il livello attuale

  • P_grid ≈ 0:

  • Mantenere il livello attuale


Parametri

Identici ad AUTO:

  • control_gain – influenza la velocità di diminuzione durante l'importazione
  • balance_threshold – soglia per la determinazione dell'equilibrio


Sensori richiesti

  • Current Grid (richiesto)
  • Voltage (raccomandato)


Quando usare

  • ✅ Nessun contratto di esportazione verso la rete
  • ✅ Tariffa di esportazione sfavorevole (< costo di importazione)
  • ✅ Restrizione tecnica all'esportazione
  • ✅ Protezione dall'esportazione con rete instabile


Esempio di funzionamento

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 Modalità OFFGRID (3) – Isolato dalla rete


Descrizione

Modalità per sistemi autonomi con pannelli solari e batterie, senza connessione alla rete. Utilizza l'energia solare in eccesso per il carico.


Algoritmo

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


Caratteristiche

  • NON utilizza P_grid (il sensore di rete può essere assente)
  • Utilizza P_solar per determinare la potenza disponibile
  • Conservativo: 80% della potenza disponibile (protezione della batteria)
  • Priorità: Carico principale → Batterie → Riscaldatore


Parametri

  • control_gain – influenza la velocità di aumento del carico
  • balance_threshold – potenza solare minima per l'attivazione
  • Margine di sicurezza: 0,8 (80%) – codificato fisso


Sensori richiesti

Minimo:

  • Current Solar (richiesto) – per la determinazione della produzione
  • Voltage (raccomandato)

Opzionale:

  • ⚪ Current Load – per un controllo più preciso
  • ❌ Current Grid – NON richiesto (può essere assente)


Quando usare

  • ✅ Sistemi isolati dalla rete
  • ✅ Pannelli solari + batterie
  • ✅ Nessuna connessione alla rete
  • ✅ Massimizzare l'uso dell'energia solare


Esempio di funzionamento

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 Modalità MANUAL (4) – Manuale


Descrizione

Livello fisso del dimmer impostato dall'utente. Nessun controllo automatico.


Algoritmo

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


Parametri

  • manual_level – livello del dimmer (0-100%)


Sensori richiesti

I sensori non sono necessari (le misurazioni continuano per il monitoraggio).


Quando usare

  • ✅ Tariffa notturna (impostare 100% per la notte)
  • ✅ Test del carico
  • ✅ Mantenimento della temperatura (impostare 50%)
  • ✅ Debug del sistema


Esempio di utilizzo

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}


Scenario: Tariffa notturna

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 Modalità BOOST (5) – Riscaldamento forzato


Descrizione

Dimmer fisso al 100%. Potenza massima al carico.


Algoritmo

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


Parametri

Nessun parametro configurabile (sempre 100%).


Sensori richiesti

Non richiesti.


Quando usare

  • ✅ Riscaldamento rapido dello scaldacqua
  • ✅ Utilizzo di tariffa vantaggiosa
  • ✅ Modalità di emergenza


Avvisi

⚠️ AVVISO:

  • Elevato consumo dalla rete
  • Possibile surriscaldamento del carico
  • Monitorare la temperatura manualmente
  • Non lasciare incustodito


Esempio di utilizzo

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

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



4.8 Passaggio tra le modalità


Passaggio sicuro

Durante il cambio di modalità, RouterController:

  1. Registra il cambio di modalità
  2. Resetta lo stato interno
  3. Applica il nuovo algoritmo
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;
}


Raccomandazioni per il passaggio

Transizioni sicure:

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

Attenzione:

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


Sequenze di comandi

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 Configurazioni minime dei sensori


Per ogni modalità

Modalità Sensori richiesti Opzionale Nota
OFF - - Sensori non utilizzati
AUTO Voltage, Current Grid Current Load, Current Solar Grid necessario per P_grid
ECO Voltage, Current Grid Current Load, Current Solar Grid necessario per P_grid
OFFGRID Voltage, Current Solar Current Load Grid NON richiesto
MANUAL - Voltage, Current Grid Solo per monitoraggio
BOOST - Voltage, Current Grid Solo per monitoraggio


Configurazione minima (router solare)

Per le modalità 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

Risultato:

  • ✅ Misurazione P_grid (per l'equilibrio)
  • ✅ Controllo del dimmer
  • ❌ Nessun monitoraggio solare/carico


Configurazione completa

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

Risultato:

  • ✅ Monitoraggio completo del sistema
  • ✅ Tutte le modalità supportate
  • ✅ Analisi dettagliate



4.10 Configurazione dei parametri tramite interfacce


Tramite comandi seriali

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


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


Tramite interfaccia web

  1. Aprire la dashboard: http://192.168.4.1/
  2. Selezionare la modalità (6 pulsanti)
  3. Per MANUAL: spostare il cursore
  4. Click "Apply"

← Struttura dell'applicazione | Indice | Avanti: Riferimento API →