Skip to content

EV charging cycles to zero under import ceiling despite low phase currents #1674

Open

Description

@segran2

On v0.145.2-beta.1, an Easee Cloud charger repeatedly started and stopped on 16 October 2026 around 23:45–23:47 CEST. The UI reported “protect the main fuse”.

Observed evidence

  • Main fuse configuration: 25 A, 230 V, three phases.
  • Retained phase-current maxima over the incident: 10.01 / 11.19 / 10.02 A. These samples do not show a physical fuse overload.
  • Configured peak-import ceiling: 7,500 W.
  • Planned EV demand: 10,350 W; offered charge was repeatedly reduced to 6,210 W, then 0 W.
  • Minimum supported charging step: 4,140 W.
  • At 23:45:13 and 23:45:18, logs say loadpoint fuse-clamp: below minimum step ... fuse_cap_w=0 min_step_w=4140; analogous stop/start sequences recur at 23:45:43, 23:46:13, 23:46:48 and 23:47:18.
  • Around each start, grid import rises to about 7.0–7.1 kW while the retained charger power sometimes still says zero; around a stop, the inverse disagreement occurs. The snapshot clocks are asynchronous.
  • At 23:56, FTW again requested and offered 9 A / 6,210 W, but actual EV power remained zero. Easee was online, connected, ready (mode 6), with reason 78, “limited by dynamic charger current”. This does not establish which charger/vehicle state prevents recovery.

Investigation, not yet a proven cause

EVFuseBudget bounds a common balance by the latest site observation. When replacement credit for a managed EV cannot yet be confirmed, an approximately 7.1 kW site reading under the 7.5 kW import ceiling leaves only approximately 0.4 kW for a new offer, below the 4.14 kW minimum. This is a plausible start/stop mechanism, not a reconstruction of the internal budget verdict at each field tick: those intermediate values were not persisted.

A household load increase and an EV start with delayed charger telemetry can initially look identical. A fix must not simply credit requested EV power as measured power, reuse stale EV credit, or weaken phase/fuse or configured import limits.

Expected result

  1. Reproduce the low-load, delayed-telemetry start/stop case with deterministic observations.
  2. Expose which bound, raw/common observations, managed-EV replacement credit and pending battery power produced a stop.
  3. Distinguish the configured import ceiling from a physical main-fuse overload in diagnosis.
  4. Validate stable recovery without permitting a delayed EV start to overlap a new household load beyond the protected limits.

This is separate from the daily-history repair in #1667/#1668. No charging configuration or safety limit was changed during this investigation.

Follow-up: 17 October, 00:13–00:20 CEST

The two screenshots show Charge now requesting 15 A / 10,350 W, FTW offering 10 A / 6,900 W, and actual EV power 0 W. The second screenshot shows approximately 1 kW household consumption covered by the battery and near-zero grid exchange.

Rechecked logs from 00:10–00:21:30: 132 clamp records, 131 at 6,900 W and one at 7,590 W; no zero cap, pause or cooldown. At 00:13:13 and 00:19:53 the records both contain want_w=10350 fuse_cap_w=6900 snapped_w=6900. The 7,500 W configured import ceiling is consistent with the 10 A step. This positive cap explains the reduced offer, but does not explain zero delivery. Subsequent charger telemetry remained online/connected, ready (mode 6), reason 78, with a 10 A offer and no measured charging.

Two concrete core problems are addressed in #1675:

  • A positive site clamp took precedence over sustained zero delivery, hiding the no-power response behind “main fuse” wording. After confirmation grace, fresh accepted positive offers with persistent zero power now report not-following/not-drawing; the lower allowed rate remains available as context. Wording identifies site fuse/import limits without asserting a physical overload.
  • Recovery after FTW's own zero offer discarded its resume proof on HTTP acknowledgement. It now waits for measured delivery, retries at 30-second intervals up to three acknowledged attempts, and logs exhaustion. Existing session/device/generation and current safety/plan gates remain authoritative.

Regression tests reproduce the accepted 10 A / actual 0 W case and acknowledgement-without-delivery recovery, including intentional zero, freshness, grace, charging, session changes and safety/plan stops. Full make verify and all 729 web tests pass on e7b210d.

The initial 23:45 start/stop budget cause remains unproven; the bounded budget diagnostics are retained. Recovery is now tested in software, but requires validation on affected hardware. The running installation has not been updated by this PR.

Diagnostic build: 17 October 01:32–01:37 CEST

The local e7b210d-derived build still cycles. At 01:32:37 the common balance reserves 9,009.628 W of battery increase with 6.832 W grid import, while latest-site reservation is 0.628 W. At 01:34:42 common EV credit is 286 W versus latest credit 7,527 W, common cap 607.745 W versus latest cap 7,813.744 W. These are direct decision records, not later status reconstructions.

Code probes reproduce two mechanisms: a missing after-bracket makes the common battery baseline fall back to the configured -10 kW discharge bound even where the latest-site calculation can use a preceding fresh battery reading; and a later EV low sample retroactively reduces credit for an older bracketed site observation. This establishes the arithmetic mechanisms, not every underlying physical sample's accuracy.

Follow-up in #1675: align the fallback reservation with the latest site bound and keep historical EV brackets historical in the common balance, while retaining the independent latest-site and phase bounds and conservative later-stop handling there. Add regressions for observed stop/restart, true household increases, pending battery orders, and unknown/stale readings. Hardware validation remains required.

Budget fix available: 815e305 / PR #1675

The common EV balance now evaluates its historical brackets without a later stop/restart retroactively removing that site's credit. Independent latest-site and phase bounds remain authoritative and retain later-stop handling. The no-common-bracket battery path uses a fresh preceding measurement instead of inventing a full configured discharge loss; a first battery sample after the site read retains its conservative unknown-history fallback. Pending loss-of-discharge orders remain reserved.

Regression tests fail on the prior revision and pass with this fix. Entire control suite and full make verify pass on both PR and cumulative v0.145.2-beta.1 personal trees; web tests pass (729 / 731, TZ=UTC). Linux ARM64 personal patch revision 2 is built. Hardware validation and human review of earlier UI changes remain pending; no installation or charging command was performed for this budget revision.

Revision 2 field result and latest-site fallback correction

Revision 2 (815e305-derived ARM64 build) was installed and its executable checksum verified. FTW restarted at 01:52:54 CEST. Stable charging is not validated: it still emitted zero offers. At 01:55:36 the common path used grid 6,587 W with EV credit 0 W, yielding 913 W, while latest-site EV credit was 6,820 W and cap 7,733 W. At 01:58:16 an older 6,640 W grid sample with zero EV credit constrained the offer to 821.932 W while latest grid was -99.39 W.

New regressions reproduce both paths. When no common bracket is found, the fallback now retains EV credit already qualified by the existing latest-site guard; it previously left that field zero. When no positive eligible EV measurement exists, obsolete older site candidates are skipped rather than retaining grid demand from before an EV stop. Freshness, missing-data, latest-site, phase and pending-battery limits remain authoritative. Tests include a real household increase, a later EV reading that cannot fund an earlier site reading, unavailable EV data, and the worst-phase bound. Hardware validation of this follow-up remains pending.

Revision 3 source fix is pushed as 1fe1195 in #1675. Full local verification passes on both source trees, and all executed GitHub CI checks pass. Personal revision 3 ARM64 package is built, copied/extracted on the RPi and checksum-verified. It is not installed; stable charging is still unverified.

Further investigation after revision 3 field failure

The 02:19 incident contains a real household increase: history changes from approximately 0.9 kW household demand / 7.1 kW grid with 6.183 kW EV to approximately 2.0 kW household / 8.15 kW grid. Reducing the EV offer under the 7.5 kW import ceiling was justified. Offers then fell from 9 A to 8 A at 02:19:41 and 7 A at 02:19:46, before the zero-cap verdict at 02:19:51. This is not evidence of physical 25 A fuse overload. History aggregates cannot reconstruct every decision's raw source sample.

Two additional code defects are reproduced locally by focused probes, without changing the running installation or PR production source:

  1. recordControlObservation clears the observation ring when source At is over 10 seconds old, even when ControlPowerObservation returns known=true with fresh ConfirmedAt. The probe uses 6183 W source age one minute, confirmation age one second: current reading is valid but the ring is empty. Repeated same-source confirmations are also discarded rather than updating the anchor, and copyControlPoints filters on source time alone. A steady change-only source can therefore lose its pre-transition evidence. Retaining one confirmed anchor must not manufacture multiple physical samples or a usable response window; unavailable/unconfirmed data and observed stops must still invalidate/bound proof.
  2. resumeAfterZeroOffer deletes recovery evidence after any sample >= DeliveringW (100 W). A 130 W startup pulse clears it despite a 4140 W minimum charge step. The history includes ~130 W startup pulses. A focused probe reproduces proof deletion. Recovery should require sustained meaningful delivery rather than one low transient; do not globally change the shared delivery threshold without assessing its other consumers.

These are verified code behaviors and plausible contributors. Raw Easee source/confirmation times from the exact stop ticks were not retained, so they are not claimed as a complete field replay. Reason 78 remains observed during refusal to resume, but does not identify the underlying vehicle/contactor condition. The user's cable disconnect/reconnect, rather than demonstrated FTW recovery, started the successful charge.

The new probes are retained outside the source checkout as investigation artifacts; no intentionally failing tests were committed. Revision 3 is still not a validated charging fix. No fourth package or further control mutation was installed during this investigation.

Two further fixes implemented: revision 4 / 8a02c0a

The confirmed-power buffer now keeps one sample at its original source time and advances only its confirmation time. Freshness of that confirmation prevents an unchanged change-only sample from being discarded solely for an old source timestamp. Missing/unconfirmed data and contradictory values at one source time invalidate proof; stops remain in the bounded ring. A separate confirmed-window view serves time-aligned power bounds; independent response verification still uses physical source samples, so repeated confirmations cannot manufacture measurement windows.

Recovery after FTW's own zero offer now requires ten seconds of fresh, advancing meaningful delivery (90% of the lower of configured minimum and actual offer). 130/800 W pulses, one high sample and cached/unavailable observations do not clear it. The shared DeliveringW constant, existing session/safety gates and three-acknowledgement/30-second retry bound remain unchanged.

New before/after and integration tests pass, including a steady confirmed EV followed by a rate decrease, real household increases, missing data, observed stops, one-phase offers and sustained delivery. Full make verify passes on PR and cumulative personal source. Linux ARM64 revision 4 is built; installation and hardware validation remain pending. No automatic reboot or new authorization commands are introduced.

Revision 4 validation update: all executed GitHub checks on 8a02c0a pass, including core (Go) and go test + vet in 38988812967. Final focused regressions pass 20 repeats. The ARM64 revision 4 package is copied to the RPi, extracted and checksum-verified. It has since been installed and checksum-verified; see the revision 4 field-test update below for the current result.

Revision 4 installed: controlled stop/recovery test — 17 October 2026 (CEST)

The personal cumulative v0.145.2-beta.1 ARM64 revision 4, derived from 8a02c0a, is now installed. The running executable SHA-256 matches the revision 4 manifest. FTW restarted at 03:08:08.

Observed on the affected Easee/Pixii installation:

  • Before the test, with the import cap disabled: 10.315 kW measured charging, 15 A offered, at 03:09:54.
  • With 7,500 W import cap: at 03:13:20, measured EV 6.209 kW, offer 9 A / 6,210 W, grid 7.058 kW, phase currents 9.85 / 11.16 / 9.88 A. Initial offers varied between 6–10 A, then held 9 A for approximately the last minute. No zero offer was recorded in that cap-on interval.
  • With 3,000 W cap: at 03:14:02, FTW offered 0 A, actual EV 0 W, grid 851 W. Easee reason 52, max dynamic charger current too low, was consistent with the intentional zero offer. The below-minimum diagnostic reported approximately 2.16 kW available against the 4.14 kW charging minimum.
  • After the user disabled the cap, without disconnecting the cable or manually sending Start/Resume: at 03:15:19, offer 15 A / 10,350 W, actual 10.328 kW, charging mode 3. Reason 78 was no longer reported. At 03:16:49, charging remained 10.328 kW, status Following, with no new stop logged in that follow-up interval.

This controlled cap-reduction / below-minimum stop / automatic-recovery scenario passed. It does not establish long-term stability, recovery from every charger state, or correct response to a separate real household load step. The observations do not isolate which individual revision 4 change caused the improved result or establish whether the bounded resume retry path was needed. Human review of the earlier UI changes also remains pending.

Leave the issue open and PR draft. The user has no current peak-tariff requirement, so the import ceiling is disabled for normal charging; configured 25 A per-phase protection remains active. Next validation is a longer charging period and inspection of history around these transitions. History coverage/invalid_balance work remains separately tracked in #1667/#1668; this charging test does not verify that fix.

Activity

  1. segran2 commented on Oct 17, 2026

    @segran2
    ContributorAuthor

    Longer field/history check — 17 October 2026, 12:27 CEST

    The car now reports the requested 80% SoC (vehicle reading about 105 minutes old at inspection), and retained session delivery is approximately 42.73 kWh. Current command and actual charging are both zero; the command reason is no_plan_budget. The service has continued running since revision 4 installation. No exhausted-resume warning was found in the inspected post-test journal.

    This is not a continuous, interruption-free charging result. At 05:49:15, with the import ceiling disabled, the controller issued a below-minimum zero offer: grid 12,323 W, eligible EV credit 0 W, phase bound approximately 2,449.5 W, minimum 4,140 W. Aggregated history shows EV zero from 05:49:25 through 05:50:25 and positive power again at 05:50:40 (10.230 kW by 05:50:45). This documents later recovery in telemetry; it does not independently establish whether any user action occurred or whether that zero decision was physically justified. Other short zero/low-power intervals also exist. The initial controlled test remains passed, but long-term stability and that later decision's raw alignment/phase evidence still need investigation.

    History API review (range=12h&points=4320, 10-second aggregated rows):

    • 03:13:35–03:16:50, covering the controlled stop/restart: 20 returned rows, all complete.
    • 03:11–03:17, including the earlier rate reduction: 35 complete rows and one balance_mismatch / invalid_balance row.
    • 03:17–07:15: 1,428 returned rows, 14 with balance_mismatch, the remainder complete. These are aggregate rows, not counts of original failed measurements; averaged columns and last embedded driver values must not be treated as simultaneous raw samples.
    • The daily API still provides a non-null estimated household total for 17 October (15.268 kWh at this inspection), recorded coverage 44,855,239 ms against elapsed period 44,871,653 ms (about 16.4 seconds uncovered). 16 October remains estimated at 33.461 kWh with reported full-day coverage.

    Thus #1668's deployed daily estimate is present while rejected instantaneous rows remain visible; live balance failures are not eliminated. This API inspection does not independently audit every estimate-table entry, exact missing interval or database provenance. No database repair or hardware/configuration change was made in this check.

  2. segran2 commented on Oct 17, 2026

    @segran2
    ContributorAuthor

    05:49 zero-credit investigation and remaining uncertainty

    The retained per-driver series adds an important ordering detail. The Easee ev_w 10-second bucket has two samples, first receipt 05:49:13.164 and last receipt 05:49:18.275, min 0 W, max/last 10,241.9996 W. Thus the first sample was zero before the FTW zero-offer decision at 05:49:15.240; ev_dynamic_current_a was 15 A at both receipts. The preceding power sample at 05:49:08.117 was 10,241.9996 W. These timestamps are local recording/receipt times, not original Easee physical sample times.

    Pixii's first receipt at 05:49:14.910 recorded 12,323 W and phase currents 20.45 / 17.05 / 15.87 A. The decision log used zero eligible EV credit and a 2,449.5 W phase bound, below the 4,140 W minimum. No sampled phase here exceeded the configured 25 A. This explains the conservative stop arithmetic; it does not prove a charger fault, physical pause or delayed/out-of-order cloud response. The zero was received from the Easee driver, not vehicle SoC telemetry.

    Add per-EV evidence to the bounded DEBUG budget record using the same reading considered by the calculation: raw/control power, source time, receipt time, confirmation time, source validity, qualification, driver telemetry health, retained-point count and latest-site credit. Reasons distinguish observed nonpositive power, invalid/unavailable source, stale/future receipts or control observations, offline telemetry, and absent brackets/observed stops. No requested power is used as measured credit, and zero observations are not ignored.

    This closes a diagnostic gap, not the uncertainty in the historical event or the runtime stop mechanism. Preventing that stop by retaining a previous positive EV value without contemporaneous proof could authorize excess current after a real EV stop plus household increase. No such hold/filter/debounce is introduced. A future recurrence must capture the new evidence with DEBUG enabled in a diagnostic build before a prevention fix can be justified. The currently installed personal revision 4 has not been replaced by this code.

    Implemented on cde5cdb in #1675. Regression tests retain the declared source timestamp even when a source is unavailable, distinguish confirmed zero from unavailable data, and retain the below-minimum safety verdict. Full make verify passes (tests, vet and build). Hardware validation of this diagnostic addition is pending.

  3. frahlg commented on Oct 17, 2026

    @frahlg
    Member

    v0.147.2-beta.1 is out with a new EV guard (#1695). Please move from your personal build to this beta and tell us about any stop.

    What changed: the EV hard limit now reads only the site meter and FTW's own commands. It never uses the Easee's power readings.

    • It cuts at once by the overage the meter measures, on the worst phase or in total import.
    • It holds the offer while the site is inside its limits.
    • It raises one step (1 A) at a time, once the meter shows the last step.
    • After a stop it waits until the meter has shown room for 35 seconds.
    • A Core restart keeps FTW's last offer while the same charging session is plugged in.

    In the simulated replay of your 05:49 case the offer holds at 10,350 W. The 23:45 case under the 7.5 kW ceiling starts once and no longer cycles. Nobody has run it on hardware yet, so your site is the first real test.

    Not in this beta: the resume check, the not-following status and the diagnostics from #1675. #1675 needs a rebase onto the new master.

    To install, on the box:

    ftw status
    ftw update --channel beta
    ftw status
    

    Check that the last ftw status names v0.147.2-beta.1. If ftw update refuses because of your personal build, please post the output.

    Please report any stop or start/stop cycle with:

    • the time,
    • the EV hard limit: site meter over limit lines from journalctl -u ftw around it,
    • the phase currents and grid power at that moment,
    • whether the car started again without a cable replug.

    If you can, try one charge with the 7.5 kW import ceiling on as well, since that is where the cycling started.

    Known limits, also listed in #1695:

    • If the car pauses and house load fills its room, the site can be over the limit for a few seconds when the car resumes, until the next meter reading.
    • Under a tight ceiling the car runs one step lower than before, because each rise leaves one step free.
  4. frahlg commented on Oct 17, 2026

    @frahlg
    Member

    v0.150.0-beta.1 is out. Could you test it with the 7.5 kW import ceiling on?

    Changes since v0.147.2-beta.1, all from your dumps:

    To install, on the box:

    ftw update --channel beta
    ftw status
    

    Check that ftw status names v0.150.0-beta.1.

    Please report any stop or start/stop cycle with the time and the EV hard limit lines from journalctl -u ftw around it. If you can, also include peak_import_limit_w and peak_import_hour_left_wh from /api/status. Nobody has run this on hardware yet.

  5. frahlg commented on Oct 18, 2026

    @frahlg
    Member

    Review update, 18 October:

    Keep this incident and #1718 open. The supplied records do not establish the physical cause of the 23:32 stop, and the startup pulse is a separate unresolved case. No customer box, database or release was changed. The field checklist is in #1719.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions