fix soc v TOU (ne 100) pri ne-grid-charge
This commit is contained in:
@@ -40,9 +40,6 @@ REG143_SELL_CAP_MIN_W = 200
|
||||
# Ostatní bity zachovat → read-modify-write.
|
||||
REG178_SELL = 0b00100000 # 32, grid peak shaving disable
|
||||
REG178_PASSIVE = 0b00110000 # 48, grid peak shaving enable (PASSIVE i CHARGE)
|
||||
# TOU reg 166+ ve PASSIVE při prioritě baterie: signál střídači „využij celý dostupný rozsah“,
|
||||
# ne provozní strop z DB (ten je pro LP / Wh – viz asset_battery.max_soc_percent).
|
||||
DEYE_TOU_SOC_PASSIVE_BATTERY_PRIORITY_PCT = 100
|
||||
# Verify: jen bity 4–5 (horní byte layout v dokumentaci); ostatní bity mohou mít firmware / Loxone
|
||||
REG178_VERIFY_MASK = 0x0030
|
||||
# Reg 178 bits 0–1: MI export cutoff (AC coupling / GEN).
|
||||
@@ -1411,11 +1408,6 @@ def _clamp_deye_tou_soc_pct(pct: int) -> int:
|
||||
return max(5, min(95, pct))
|
||||
|
||||
|
||||
def _clamp_deye_tou_soc_pct_hi(pct: int, hi: int) -> int:
|
||||
"""Stejné dolní omezení 5 % jako u TOU; horní mez z parametru (např. 100 u priority baterie)."""
|
||||
return max(5, min(int(hi), int(pct)))
|
||||
|
||||
|
||||
def _deye_tou_min_soc_pct(inv: InverterConfig) -> int:
|
||||
if inv.min_soc_percent is not None:
|
||||
return _clamp_deye_tou_soc_pct(int(inv.min_soc_percent))
|
||||
@@ -1429,39 +1421,23 @@ def _deye_tou_reserve_soc_pct(inv: InverterConfig) -> int:
|
||||
|
||||
|
||||
def _deye_passive_tou_battery_soc_pct(
|
||||
inv: InverterConfig,
|
||||
setpoints: ControlSetpoints,
|
||||
inv: InverterConfig, _setpoints: ControlSetpoints
|
||||
) -> int:
|
||||
"""
|
||||
Hodnota SOC u Deye TOU řádku (reg 166+) ve fyzickém PASSIVE.
|
||||
|
||||
Na home-01 Deye interpretuje TOU % jako „kam má směřovat využití baterie“:
|
||||
je-li zapsané procento **nižší než skutečný SoC**, přebytek FVE míří spíš do sítě.
|
||||
Vždy provozní minimum z DB (**``min_soc_percent``**, clamp 5–95 jako u všech TOU SOC)
|
||||
— signál „spodní pásmo“ pro firmware, aby baterii šlo použít pro překrytí zátěže bez
|
||||
snahy o vysoký cílový SoC jen přes TOU.
|
||||
|
||||
Při **záporné vykupní** nebo **plánovaném nabíjení** (kladný ``battery_w``) EMS
|
||||
zapíše **100 %** do TOU (signál střídači „ber přebytek do baterie v celém rozsahu“).
|
||||
**``max_soc_percent`` v DB** je odděleně: horní limit pro **plánovač / Wh bilance**
|
||||
(denní provoz, viz komentář sloupce), **nikoli** časové „do kdy“.
|
||||
Riziko spojené v minulosti s nízkým TOU („přebytek FVE tíhne do sítě“ při nízkém %
|
||||
oproti skutečnému SoC) řeší **LP**, **145** (**``export_ban``** při záporné vykupní),
|
||||
řez GEN (**178**) a další páky — ne zvyšování TOU nad **min_soc**. Přímé dobíjení ze
|
||||
sítě a cílové horní pásmo: větev **CHARGE** v ``_deye_tou_params`` (**``max_soc_percent``**).
|
||||
|
||||
Jinak zůstane provozní podlaha ``min_soc_percent`` (typicky nízká % → přetok do sítě
|
||||
možný dle chování Deye).
|
||||
|
||||
Režim **SELF_SUSTAIN** (``self_sustain_local_use``): vždy ``min_soc_percent`` — nízké
|
||||
TOU drží prioritu „baterie jako buffer“ při plném reg. 108/109 a reg. 142 zero-export;
|
||||
neaplikuje se sem logika 100 % podle ceny (LP se v SELF_SUSTAIN nepoužívá).
|
||||
Argument ``_setpoints`` zůstává kvůli volajícím API; hodnoty z něj PASSIVE SOC nebere.
|
||||
"""
|
||||
mn = _deye_tou_min_soc_pct(inv)
|
||||
if setpoints.self_sustain_local_use:
|
||||
return mn
|
||||
|
||||
bat_w = 0 if setpoints.battery_w is None else int(setpoints.battery_w)
|
||||
sell = setpoints.effective_sell_price_czk_kwh
|
||||
want_battery_priority = bat_w > 0 or (sell is not None and float(sell) < 0)
|
||||
|
||||
if not want_battery_priority:
|
||||
return mn
|
||||
|
||||
return _clamp_deye_tou_soc_pct_hi(DEYE_TOU_SOC_PASSIVE_BATTERY_PRIORITY_PCT, hi=100)
|
||||
return _deye_tou_min_soc_pct(inv)
|
||||
|
||||
|
||||
def _deye_zero_export_amps_for_passive(
|
||||
@@ -1521,7 +1497,8 @@ def _deye_tou_params(
|
||||
) -> tuple[int, int, bool]:
|
||||
"""
|
||||
Parametry jednoho Deye time pointu: výkon W, SOC % (TOU reg 166+), grid_charge.
|
||||
Ve PASSIVE viz _deye_passive_tou_battery_soc_pct (min vs. plný max z DB).
|
||||
Ve PASSIVE: TOU SOC = ``min_soc_percent`` z DB; v CHARGE: horní hraniční SoC =
|
||||
``asset_battery.max_soc_percent`` (clamp 10–100).
|
||||
"""
|
||||
max_batt_w_discharge = int(inv.max_discharge_a * BATT_VOLTAGE_V)
|
||||
tp_discharge_w = 0 if setpoints.lock_battery else max_batt_w_discharge
|
||||
@@ -1534,7 +1511,7 @@ def _deye_tou_params(
|
||||
raw_bat = setpoints.battery_w
|
||||
battery_w = int(raw_bat) if raw_bat is not None else 0
|
||||
cap = int(inv.max_soc_percent) if inv.max_soc_percent is not None else 95
|
||||
target_soc = max(10, min(95, cap))
|
||||
target_soc = max(10, min(100, cap))
|
||||
tp_charge_w = (
|
||||
battery_watts_to_amps(battery_w, int(inv.max_charge_a)) * int(BATT_VOLTAGE_V)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user