Reduce idle during power fluctuations - #1488
Conversation
…ure#1461) When the grid direction flips from export to import, the manager arms a hold-off window (60s when flips repeat within 5 minutes) during which the charge setpoint is forced to 0. Previously all discharging devices were stopped for the whole window, leaving the batteries idle during short grid fluctuations such as a slowly ramping EV charger. Devices that were discharging are now kept at a minimal output (SmartMode.POWER_IDLE, 10W) while the window is running. If the grid flips back to export before the window expires, they resume discharging immediately without an idle period or an extra inverter mode switch. Once the window expires and real charging starts, they are stopped as before (the hold power exceeds POWER_TOLERANCE, so the stop command is not skipped). Offgrid and SOC-empty devices keep the previous behavior.
…endure#1461) Mirror of the previous commit for the charging direction. When the grid flips from charging to discharging, charging devices were stopped immediately; when the grid flipped back within 5 minutes, the 60s hold-off window then kept them idle before charging could resume. Charging devices are now kept at a minimal input (POWER_IDLE, 10W) for HOLD_TIMEOUT (300s, the same horizon used to arm the 60s window) after the flip, as long as the discharging devices can cover the setpoint on their own (setpoint below POWER_START or within discharge_limit). Because they never leave charge mode, power_charge now also holds them at minimal input during the hold-off window instead of stopping them, and they ramp straight back up once the window expires - no idle period and no inverter mode switch at all. If real discharge power is needed beyond what the discharging devices can deliver, the chargers are released (stopped) as before, making them available for the regular idle-device start. Offgrid and SOC-full devices keep the previous behavior. power_discharge now takes the update time as parameter, like power_charge already did.
…e#1461) Simulation against master showed a one-cycle (2-4s) delay when a hold window ends: a device parked at POWER_IDLE is still classified as discharging (or charging), so after being stopped it was not part of the idle list and could only be restarted by the next update. Appending it to the idle list right after the stop lets the regular idle-device start pick it up in the same cycle, matching the timing of the previous code exactly.
|
I've had this code running for some time, looking back at the HA data, at no point during the last 3 days was sensor.zendure_manager_power 10W, which is the idle power consumption to reduce switching. Perhaps the 10W value is too low? Also, based on the described algorithm, perhaps it would be of value to offer an option that has a bias towards charging instead of discharging. |
|
This is a code reading of the current diff (head The hold-off is still re-armed on every direction flip. In - self.charge_time = time + timedelta(seconds=2 if (time - self.charge_last).total_seconds() > 300 else 60)
+ self.charge_time = time + timedelta(seconds=2 if (time - self.charge_last).total_seconds() > SmartMode.HOLD_TIMEOUT else 60)and in One narrower point on the new hold branch: On master None of this is an objection to merging. Cutting mode switches from 22 to 3 and removing the cold start is clearly an improvement, and the ±10 W trade-off looks well argued. The point is only that it makes the hold cheaper rather than bounded — a cap on total hold time, or arming once per real transition instead of once per call, would be a separate and complementary change. |
|
Thanks for the detailed feedback. You’re right that this PR does not bound the total charge delay during repeated discharge/charge transitions; it only makes those transitions less costly. I think limiting that delay would be better handled in a separate PR. For a single-battery setup, releasing the charging battery when demand exceeds 50 W is intentional, since no other battery can cover the requested discharge. Also, your measurements were made on the original 1.4.3 behavior. Testing this branch would help quantify the remaining impact. |
|
Thanks — that clears up both points. Agreed that bounding the total delay belongs in its own PR, and good to know that releasing the charging battery above 50 W is intentional for a single-battery setup; that answers my question. Happy to test, with one honest caveat on timing: the effect only shows up when there is real surplus and the battery is well below full, so I need a suitable day rather than a slot I can pick. I cannot promise a date, but I will run it and report with the same metrics as in my comment on #1525 — flip-to-first-charge-command latency, idle plateaus, and the Wh balance over the window — so the numbers are directly comparable to the 1.4.3 baseline. Excitation would be the same thermostat-cycling ~2.2 kW load as in the original report, so it is like-for-like. Could you rebase the branch before I do? It is currently 3 ahead / 14 behind master and For what it is worth, I did check whether the staleness would invalidate the comparison, and it would not: between your merge base |
|
Hello, |
|
@zoic21 — short status so you are not waiting on me. I am not going to get the staged A/B run done. The excitation I can reproduce is a Two things that may still be useful. The 1.4.3 behaviour is unchanged and still reproducing here. During those 22 minutes The part that matters for #1525 is the separate PR you mentioned. You wrote that Also worth a look for the underlying issue: in #1525 @uwegoexe-boop independently reported |
|
I don't have much experience with formal testing, so I can't offer a proper A/B test. Just my practical experience running this for a while. I've been running this on the rebased branch for over a week now, and I can confirm this feature works well for my situation. I noticed that when running my oven, it doesn't draw power steadily but fluctuates during operation. This caused my batteries (2x 800+) to keep switching between discharging, idle, and charging, especially when there was enough solar surplus to charge from. This change now keeps the batteries at a steady ~10W discharge most of the time, while still being able to ramp up quickly when the oven draws more power. So for my setup, it makes the charging/discharging behavior noticeably more stable. |
|
@Mrdauphi Perhaps I didn't notice an issue because my focus has been more on the excess surplus not being captured. While this fix might perhaps do more for preventing import when the battery is not yet empty. |
Implements #1461: during rapid grid direction flips (e.g. a slowly ramping EV charger), the battery no longer sits fully idle in the anti-hysteresis hold-off window. Instead, devices are kept at a minimal power of ±10 W (
SmartMode.POWER_IDLE) so they stay in their current inverter mode and can resume full power instantly, without extra mode switches.Flip to charging: during the 60 s hold-off window, devices that were discharging are held at +10 W instead of being stopped. If the grid flips back to export before the window expires, they ramp straight back up — no idle period, no cold start, no mode switch.
Flip to discharging: charging devices are held at -10 W for up to
HOLD_TIMEOUT(300 s, the same horizon already used to arm the 60 s window), but only when the discharging devices can cover the setpoint on their own. If more power is needed, they are released immediately, exactly as before. Held devices never leave charge mode, so charging resumes with no idle period at all once the window expires.Offgrid (SF 2400), SOC-full and SOC-empty devices keep the previous behavior.
POWER_IDLEis 10 W rather than the ±1 W suggested in the issue because it must exceedPOWER_TOLERANCE(5 W), otherwise the stop command at the end of a hold would be swallowed by the device-level tolerance check.Testing
Simulated the real
powerChanged/power_charge/power_dischargecode (HA 2026.2, fake devices reproducing the device-level clamp/tolerance logic, 2 s update ticks) and compared this branch tick-by-tick against master, with 1 and 2 devices:Fixes #1461
Other
I think it's need to be test because leave 10W inplace of idle is beter to restart faster charge/discharge but it's consume 0,0001667 kWh (about 0,167 Wh), it's small but not 0.