fix chargedischarge A #6
@@ -268,7 +268,10 @@ def deye_battery_charge_discharge_amps(
|
|||||||
"""
|
"""
|
||||||
Proud nabíjení / vybíjení (reg 108 / 109) pro zápis Deye.
|
Proud nabíjení / vybíjení (reg 108 / 109) pro zápis Deye.
|
||||||
|
|
||||||
PASSIVE + plán chce nabíjet z PV přebytku i při exportu do sítě: nenulový charge, discharge 0.
|
PASSIVE + plán chce nabíjet (typicky z FVE, i při exportu zbytku do sítě): **108 = max_charge_a**
|
||||||
|
z invertoru — reg. 108 je strop, ne příkaz k proudu; průměrný `battery_w` ze slotu nesmí špičku FVE
|
||||||
|
stíhat do baterie omezovat. **109 = max_discharge_a** (domácnost z baterie při výpadku PV).
|
||||||
|
**CHARGE** (import ze sítě + nabíjení): 108 dál z `battery_w` (řízený importní okamžik). **SELL** beze změny.
|
||||||
"""
|
"""
|
||||||
if lock_battery:
|
if lock_battery:
|
||||||
return 0, 0
|
return 0, 0
|
||||||
@@ -279,7 +282,7 @@ def deye_battery_charge_discharge_amps(
|
|||||||
if self_sustain_local_use:
|
if self_sustain_local_use:
|
||||||
return int(max_charge_a), int(max_discharge_a)
|
return int(max_charge_a), int(max_discharge_a)
|
||||||
if bat_w > 0:
|
if bat_w > 0:
|
||||||
return battery_watts_to_amps(bat_w, max_charge_a), 0
|
return int(max_charge_a), int(max_discharge_a)
|
||||||
return _deye_zero_export_amps_for_passive(
|
return _deye_zero_export_amps_for_passive(
|
||||||
grid_w, bat_w, int(max_charge_a), int(max_discharge_a)
|
grid_w, bat_w, int(max_charge_a), int(max_discharge_a)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""PASSIVE + nabíjení z PV přebytku při současném exportu → nenulový nabíjecí proud."""
|
"""PASSIVE + plán chce nabíjet: 108 = plný strop z DB, 109 = max (PV špička + domácnost)."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -18,6 +18,21 @@ class PassivePvSurplusChargeAmpsTests(unittest.TestCase):
|
|||||||
max_charge_a=100,
|
max_charge_a=100,
|
||||||
max_discharge_a=100,
|
max_discharge_a=100,
|
||||||
)
|
)
|
||||||
|
self.assertEqual(ch, 100)
|
||||||
|
self.assertEqual(dis, 100)
|
||||||
|
|
||||||
|
def test_charge_mode_still_scales_108_from_battery_w(self) -> None:
|
||||||
|
"""CHARGE (síť + baterie): 108 podle plánu, ne vždy plný strop."""
|
||||||
|
ch, dis = deye_battery_charge_discharge_amps(
|
||||||
|
lock_battery=False,
|
||||||
|
deye_mode="CHARGE",
|
||||||
|
self_sustain_local_use=False,
|
||||||
|
bat_w=2000,
|
||||||
|
grid_w=3000,
|
||||||
|
max_charge_a=100,
|
||||||
|
max_discharge_a=100,
|
||||||
|
)
|
||||||
|
self.assertLess(ch, 100)
|
||||||
self.assertGreater(ch, 0)
|
self.assertGreater(ch, 0)
|
||||||
self.assertEqual(dis, 0)
|
self.assertEqual(dis, 0)
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ bits 0–1). Detail registrů: [`modbus-registers.md`](modbus-registers.md) (reg
|
|||||||
| **CHARGE** | `battery_w` > 0 **a** `grid_setpoint_w` > 0 |
|
| **CHARGE** | `battery_w` > 0 **a** `grid_setpoint_w` > 0 |
|
||||||
| **PASSIVE (ZERO)** | vše ostatní — reg. **108/109** z `deye_battery_charge_discharge_amps()` v `setpoints.py` (volá `write_inverter_setpoints`) |
|
| **PASSIVE (ZERO)** | vše ostatní — reg. **108/109** z `deye_battery_charge_discharge_amps()` v `setpoints.py` (volá `write_inverter_setpoints`) |
|
||||||
|
|
||||||
**PASSIVE** (AUTO, ZERO): proudy **108/109** počítá **`deye_battery_charge_discharge_amps`**: pokud plán žádá **nabíjení** (`battery_w > 0`) včetně scénáře **PV přebytek + export do sítě** (`grid_setpoint_w < 0`), nastaví se **kladný nabíjecí proud (108)** a **109 = 0** — nesmí se použít čistě „zero export“ větev, která by při exportu vynutila **108 = 0** a rozbila soulad plán ↔ Deye. Jinak platí `_deye_zero_export_amps_for_passive` (export bez nabíjení → 108 = 0, import bez vybíjení → 109 = 0). **TOU** z plánu. Reg. **142** = `deye_zero_export_mode`. Reg. **143** je tvrdý limit exportu z lokality/invertoru (ne forecast). Reg. **145** (solar sell): **0** při `export_ban` mimo SELL, jinak **1** — význam přepínače a rozdíl vůči neřízeným FVE polím je v [`operating-modes.md`](operating-modes.md) (sekce *ZERO a zakázaný export*).
|
**PASSIVE** (AUTO, ZERO): proudy **108/109** počítá **`deye_battery_charge_discharge_amps`**: pokud plán žádá **nabíjení** (`battery_w > 0`) a režim zůstává **PASSIVE** (typicky FVE přebytek, často i **export** části výroby), **108 = max_charge_a z invertoru** — jde o **horní limit** proudu do baterie; průměrný `battery_w` ze 15min slotu nesmí špičku FVE do baterie uměle omezovat (dřívější odvod z W dával smysl jen u **CHARGE** ze sítě). **109 = max z DB**. Když plán nabíjení nechce (`battery_w ≤ 0`) a exportuje přebytek, platí pass-through: **108 = 0**, **109 = max** (`_deye_zero_export_amps_for_passive`). **TOU** z plánu. Reg. **142** = `deye_zero_export_mode`. Reg. **143** je tvrdý limit exportu z lokality/invertoru (ne forecast). Reg. **145** (solar sell): **0** při `export_ban` mimo SELL, jinak **1** — viz [`operating-modes.md`](operating-modes.md) (sekce *ZERO a zakázaný export*).
|
||||||
|
|
||||||
**SELF_SUSTAIN** zůstává **PASSIVE** v `get_deye_mode`; **108/109** jsou vždy **max z DB** (bez variant ZERO). Rozdíl je **`self_sustain_local_use=True`**: **TOU SOC** = **`min_soc_percent`**, `battery_w=None`.
|
**SELF_SUSTAIN** zůstává **PASSIVE** v `get_deye_mode`; **108/109** jsou vždy **max z DB** (bez variant ZERO). Rozdíl je **`self_sustain_local_use=True`**: **TOU SOC** = **`min_soc_percent`**, `battery_w=None`.
|
||||||
|
|
||||||
@@ -160,8 +160,8 @@ bits 0–1). Detail registrů: [`modbus-registers.md`](modbus-registers.md) (reg
|
|||||||
|
|
||||||
| Registr | Charge | PASSIVE (ZERO) | SELL | Self-consumption |
|
| Registr | Charge | PASSIVE (ZERO) | SELL | Self-consumption |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| **108** (charge A) | škálo dle `battery_w` | max / **0** (export bez `battery_w>0`) / **>0** při `battery_w>0` i při exportu | **0** | dle varianty |
|
| **108** (charge A) | škálo dle `battery_w` | max / **0** (export bez nabíjení) / **max** při PASSIVE + `battery_w>0` (FVE do baterie až po strop) | **0** | dle varianty |
|
||||||
| **109** (discharge A) | **0** | max / **0** (import, držet bat.) / **0** při `battery_w>0` + export z PV | **max z DB** | dle varianty |
|
| **109** (discharge A) | **0** | max / **0** (import, držet bat.) / **max** při PASSIVE + `battery_w>0` | **max z DB** | dle varianty |
|
||||||
| **142** (limit control) | `deye_zero_export_mode` | `deye_zero_export_mode` | **0** (selling first) | `deye_zero_export_mode` |
|
| **142** (limit control) | `deye_zero_export_mode` | `deye_zero_export_mode` | **0** (selling first) | `deye_zero_export_mode` |
|
||||||
| **143** (export cap) | max z DB | max z DB | max z DB (tvrdý limit, bez forecast heuristiky) | max z DB |
|
| **143** (export cap) | max z DB | max z DB | max z DB (tvrdý limit, bez forecast heuristiky) | max z DB |
|
||||||
| **145** (solar sell) | 1 / 0 při `export_ban` | 1 / 0 při `export_ban` | 1 | 1 / 0 při `export_ban` |
|
| **145** (solar sell) | 1 / 0 při `export_ban` | 1 / 0 při `export_ban` | 1 | 1 / 0 při `export_ban` |
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ EMS zapisuje řídící hodnoty přes journal (`modbus_command`) a **`write_regi
|
|||||||
|
|
||||||
| Reg | Název | Rozsah | Jednotka | Použití v EMS |
|
| Reg | Název | Rozsah | Jednotka | Použití v EMS |
|
||||||
|-----|-------|--------|----------|---------------|
|
|-----|-------|--------|----------|---------------|
|
||||||
| 108 | Max charge current | 0 … **max dle modelu** (manuál Deye) | 1 A | Strop **A** z DB (`COALESCE(deye_register_max_charge_a, odvod z kW)` + clamp **350 A**). Ve **PASSIVE** (AUTO) podle `_deye_zero_export_amps_for_passive`: výchozí **max**, u exportu v plánu bez vybíjení **0**. **CHARGE:** proud z `battery_w` přes `battery_watts_to_amps`. **SELL:** **0**. |
|
| 108 | Max charge current | 0 … **max dle modelu** (manuál Deye) | 1 A | Strop **A** z DB (`COALESCE(deye_register_max_charge_a, odvod z kW)` + clamp **350 A**). **PASSIVE** + plán chce nabíjet (`battery_w>0`): **108 = max** (špička FVE nesmí být omezená průměrem slotu). **PASSIVE** + export bez nabíjení: **0**. **CHARGE:** z `battery_w` přes `battery_watts_to_amps`. **SELL:** **0**. |
|
||||||
| 109 | Max discharge current | 0 … **max dle modelu** (manuál Deye) | 1 A | Ve **PASSIVE** (AUTO): výchozí **max**, u importu bez nabíjení **0**; **SELL** max vybíjení; **CHARGE** typicky **0**. |
|
| 109 | Max discharge current | 0 … **max dle modelu** (manuál Deye) | 1 A | Ve **PASSIVE** (AUTO): výchozí **max**, u importu bez nabíjení **0**; při **PASSIVE + `battery_w>0` + export** zůstává **max** (domácnost z baterie při výpadku PV). **SELL** max vybíjení; **CHARGE** typicky **0**. |
|
||||||
| 128 | Grid charge current | 0 … **max dle modelu** (manuál Deye) | 1 A | Nabíjení ze sítě. Firmware automaticky sníží reálný proud tak, aby `load + battery_charge` nepřekročil velikost jističe — proto LP v `planning_engine.py` plánuje `gi[t]` až **do `max_import_power_w + BMS_max_charge`**, aby uměl využít cenově nejlepší 15min okna pro nabíjení na plný BMS strop (viz `planning.md` sekce „Plánovací strop gi[t] vs. fyzický jistič"). Fyzické dodržení jističe drží reg 128 + firmware. |
|
| 128 | Grid charge current | 0 … **max dle modelu** (manuál Deye) | 1 A | Nabíjení ze sítě. Firmware automaticky sníží reálný proud tak, aby `load + battery_charge` nepřekročil velikost jističe — proto LP v `planning_engine.py` plánuje `gi[t]` až **do `max_import_power_w + BMS_max_charge`**, aby uměl využít cenově nejlepší 15min okna pro nabíjení na plný BMS strop (viz `planning.md` sekce „Plánovací strop gi[t] vs. fyzický jistič"). Fyzické dodržení jističe drží reg 128 + firmware. |
|
||||||
| 130 | Grid charge enable | 0/1 | — | 1 = povolit nabíjení ze sítě |
|
| 130 | Grid charge enable | 0/1 | — | 1 = povolit nabíjení ze sítě |
|
||||||
| 141 | Energy mgmt mode | bitmask | — | EMS vždy **0** (neměnit jinak) |
|
| 141 | Energy mgmt mode | bitmask | — | EMS vždy **0** (neměnit jinak) |
|
||||||
|
|||||||
Reference in New Issue
Block a user