implmemtace cuttoff genportu
Some checks failed
CI and deploy / migration-check (push) Failing after 9s
CI and deploy / deploy (push) Has been skipped

This commit is contained in:
Dusan Vojacek
2026-04-20 10:41:10 +02:00
parent d8dbb284fd
commit b8515f30df
15 changed files with 265 additions and 5 deletions

View File

@@ -48,6 +48,10 @@ Solver optimalizuje celý horizont (typicky do konce známých OTE dat, strop z
- Při záporné prodejní ceně má nejvyšší prioritu ukládání (baterie → EV → TČ)
- Solver nikdy neexportuje výrobu pole B pokud je prodejní cena záporná
> Poznámka: výše platí pro **home-01** (pv-b jako ongrid GEN se zeleným bonusem), kde pole B **nechceme curtailovat**.
> U instalací typu **BA81** je na GEN portu typicky **AC coupling (mikroinvertory)** bez bonusu výkon nelze plynule škrtit,
> ale lze ho **tvrdě odpojit (cut-off)** přes Deye reg **179** (viz `modbus-registers.md`). To je samostatná logika níže.
### Export / import limity (home-01)
- Max export do sítě: **13.5 kW** (smlouva s distributorem)
- Max import ze sítě: dle `site_grid_connection.max_import_power_w`
@@ -236,6 +240,42 @@ if sell_price[t] < 0:
# (export stejně zakázán výše) a solver automaticky uloží přebytek.
```
### BA81 / GEN port (mikroinvertory): kdy dává smysl „Grid export cut-off“
Kontext (instalace typu BA81):
- **PV1/PV2** (DC stringy na Deye) jsou **řiditelné** při zákazu exportu je Deye umí stáhnout až k nule.
- **GEN port** (AC coupling / mikroinvertory) **řiditelný výkonově není** vyrábí „co dá slunce“.
Při `sell_price < 0` tedy nastává problém:
- baterie má **omezený nabíjecí výkon** (např. BA81 cca **6 kW**) a navíc při vysokém SoC má reálně menší „přijímací schopnost“,
- pokud výroba na GEN portu převýší okamžitou spotřebu + možný charge do baterie, zbytek fyzicky teče do sítě (nechtěný export za zápornou cenu).
Řešení na hardware úrovni:
- **Deye reg 179 bits01** („MI export to Grid cutoff“) umožní GEN port **tvrdě odpojit**.
#### Správné rozhodovací pravidlo (záměr)
Cut-off nechceme spínat „vždy když sell<0“, protože při zataženu / malé výrobě jsou i malé watty z GEN užitečné.
Chceme spínat pouze tehdy, když je v daném slotu očekávaný **přebytek z GEN**, který není kam dát:
\[
pv\_gen\_w \;>\; load\_w \;+\; batt\_charge\_cap\_w \;+\; flexible\_load\_w
\]
kde:
- `pv_gen_w``pv_b_forecast_solver_w` (GEN/mikroinvertory)
- `batt_charge_cap_w` = min(`battery.max_charge_power_w`, \((soc_{max}-soc)_{wh} / 0.25h\)) tj. výkonově omezené a SoC-headroom omezené
- `flexible_load_w` = plánované EV/TČ setpointy v daném slotu (pokud jsou připojené / povolené)
#### Doporučená implementace v EMS (aby se to chovalo správně)
- **Správně (v solveru / plánu)**: řešit cut-off přímo v LP binární proměnnou `z_gen_cutoff[t]` (0/1), která modeluje, zda je GEN port odpojen.
- Efektivní výkon z GEN do bilance: `pv_b_effective[t] = pv_b_forecast_w * (1 - z_gen_cutoff[t])`
- Solver nechá GEN připojený vždy, když je výkon užitečný (sníží import / nabije baterii / pokryje zátěž).
- Při `sell_price < 0` a zároveň hrozícím přebytku (ge je zakázané) solver může zvolit `z_gen_cutoff[t]=1` (cut-off) jako poslední možnost.
- Výstup se ukládá do `planning_interval.deye_gen_cutoff_enabled` (nullable) a exporter pak jen provede reg 179.
**Scope / bezpečnost:** proměnná i flag existují jen na lokalitách, kde je zapnutý `asset_inverter.deye_gen_microinverter_cutoff_enabled` (tj. kde je GEN port s mikroinvertory reálně zapojen). Jinde se nic neřeší ani nezobrazuje.
### Záporná nákupní cena nabíjet ze sítě je výhodné
```python
# Pokud buy_price[t] < 0, grid_import[t] je příjem → solver automaticky maximalizuje import.