Skip to content

Anti-conflict guard: hysteresis + per-cycle decision log#131

Merged
partach merged 1 commit into
mainfrom
claude/add-from-grid-plus-mode-iqMQm
May 27, 2026
Merged

Anti-conflict guard: hysteresis + per-cycle decision log#131
partach merged 1 commit into
mainfrom
claude/add-from-grid-plus-mode-iqMQm

Conversation

@partach
Copy link
Copy Markdown
Owner

@partach partach commented May 27, 2026

Customer reported visible flipper behaviour during long discharge windows: discharge → idle → discharge every ~16 seconds. Logs showed the anti-conflict guard tripping on momentary grid imports as small as 281W (just over the 200W threshold). Each flip is two Modbus writes and a physical inverter mode switch — rough on hardware and customers notice the on/off cycling.

The 200W threshold is easily crossed by everyday loads: kettle, oven preheat, EV charging start, even a fridge compressor kick. When the battery is exporting to the grid and load briefly spikes above the inverter discharge power, the meter reads a few hundred W of import for one polling cycle.

Hysteresis added:

  • Small/moderate import (200-2000W) must persist for ≥ 2 consecutive cycles (~32s) before suppression triggers.
  • Large import (> 2000W) suppresses immediately (genuine sustained draw like EV charging or oven preheat).
  • After suppression ends, a 60s cooldown blocks re-suppression so the inverter stabilises before the next decision.

Diagnostic logging:

  • Each tick now logs the full state decision at DEBUG level: desired/current state, SOC, price, threshold, grid_power. Makes flipper investigations straightforward — the customer log pattern would have stood out in seconds with this in place.
  • Anti-conflict ramp-up (tick N of M) logs at DEBUG; suppression trigger stays at INFO with the sustained/large reason.

Customer reported visible flipper behaviour during long discharge
windows: discharge → idle → discharge every ~16 seconds.  Logs showed
the anti-conflict guard tripping on momentary grid imports as small as
281W (just over the 200W threshold).  Each flip is two Modbus writes
and a physical inverter mode switch — rough on hardware and customers
notice the on/off cycling.

The 200W threshold is easily crossed by everyday loads: kettle, oven
preheat, EV charging start, even a fridge compressor kick.  When the
battery is exporting to the grid and load briefly spikes above the
inverter discharge power, the meter reads a few hundred W of import
for one polling cycle.

Hysteresis added:
- Small/moderate import (200-2000W) must persist for ≥ 2 consecutive
  cycles (~32s) before suppression triggers.
- Large import (> 2000W) suppresses immediately (genuine sustained
  draw like EV charging or oven preheat).
- After suppression ends, a 60s cooldown blocks re-suppression so the
  inverter stabilises before the next decision.

Diagnostic logging:
- Each tick now logs the full state decision at DEBUG level:
  desired/current state, SOC, price, threshold, grid_power.
  Makes flipper investigations straightforward — the customer log
  pattern would have stood out in seconds with this in place.
- Anti-conflict ramp-up (tick N of M) logs at DEBUG; suppression
  trigger stays at INFO with the sustained/large reason.
@partach partach merged commit 513b2f8 into main May 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants