Repository navigation
fix(loadpoint): an idle 1p or auto pool starts on room for 6 A (C6) - #1917
Merged
Merged
Conversation
FuseConfigs named the tick's phase mode but kept the configured minimum, so EVFuseBudget made an idle 1p or auto pool wait for the three-phase minimum (4,140 W) of room on one phase. On a 16 A fuse that room never exists. FuseConfigs now applies fuseConfig, as freezeFuseBudget and applyFuseClamp already do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
On a 16 A fuse, an idle 1p or auto pool must start at exactly 1,380 W when the worst phase leaves 6.0 A of room under the working line, and wait at 5.7 A. The existing test left about 10 A of room, so a hidden margin on the one-phase minimum (7 A instead of 6 A) still passed it. The new cases are set from the working line, so they follow it when #1910 moves it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ry test The boundary test named evPhaseMarginA, which #1910 removes. The two PRs merge with no text conflict, so whichever landed second would break the control package's test build on master. The test now reads the line from EVFuseBudget's own report on an empty site, and the cases follow it on either side of #1910. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
C6 in the random-rig triage of 27 Oct. Charge now on a
1porautocharger on a three-phase site never starts on a 16 A fuse. The car gets 0 W withfuse_limit, and the log repeatsloadpoint fuse-clamp: below minimum step … fuse_cap_w=0 min_step_w=1380.Rig seeds: 207534 (209 such lines, 16 A,
auto), 207536 (192, 25 A,auto), 207537 (79, 16 A), 207531 (41, 16 A, passed anyway).Cause:
FuseConfigspassedcontrol.EVFuseBudgetthe tick's phase mode but kept the configuredmin_charge_w(4,140 W, the three-phase minimum).evPoolFortakes the pool's minimum from that, so the idle-start test waited for 4,140 W of room on one phase, 18 A. On a 16 A fuse that room never exists. On 25 A it needs a worst phase below about 6 A.freezeFuseBudgetandapplyFuseClampalready usedfuseConfig(1,380 W on one phase), so the controller and the budget disagreed about the least order.Change
One line in
FuseConfigs:configs[i] = c.fuseConfig(configs[i], mode). The budget now waits for room for the least order on the phases the command names: 6 A on one phase for1pandauto, 6 A on each of three for3p. A loadpoint with no command this tick, and one-phase sites, keep their configured values.This is the same line as in open #1865. This PR lands it alone, without #1865's
SnapChargeWchange, which still waits for an owner decision. #1865 should drop this line once this PR lands (it will otherwise conflict on the same hunk).Tests
go/internal/control/ev_fuse_one_phase_start_test.goruns the realEVFuseBudgetagainst the controller, wired asmain.gowires it, after a restart (fresh state, idle charger, min 4,140 W, max 11,040 W, Easee whole-amp table) under a Charge now hold of 3,680 W.TestIdleOnePhasePoolStartsOnSixAmpsOfRoom, cases from triage section 3 item 7:fuse_limit)It requires an order of at least 1,380 W within
evRestartDwell+ one 5 s tick, on one phase, and then 12 more ticks with no phase above the fuse rating.TestIdleOnePhasePoolStartBoundary(added after review) pins the start point, since the cases above leave about 10 A of room. On 16 A, in1pandauto:The test reads the working line from
EVFuseBudgetitself: on a site with no house load, an idle pool'sevLimit.phaseRoomAis the whole line. It does not nameevPhaseMarginA, so it builds before and after #1910 and the cases move with the line.Proof:
fuse_limitafter 40 s, and both boundary start cases fail at 0 W.phaseMinChargeWwith7*voltageinstead of6*voltage): the start test still passes, the boundary test fails in1pandauto("worst phase 9.0 A: offer 0 W; want 1380 W").go test -race ./internal/control/ ./internal/loadpoint/ ./cmd/ftw/: ok.make verify: "vet + test + build clean".go test -race ./internal/control/ ./internal/loadpoint/ok,make verifyclean, and the three proofs above still hold (a 7 A minimum fails the boundary start cases; no fix line fails all start cases).evPhaseMarginA = 0), the probe reads 16 A and all cases pass.go vetclean,go test ./internal/control/ ./internal/loadpoint/ok.TestE2E_WriteMaxChargeLimitingo/cmd/sim-sungrow(expected 100, got 500). This PR touches no simulator code. The cause is a race in the simulator: its tick loop takes a snapshot, a register write lands, thenRegisterBank.Refreshwrites the old snapshot back over the new value. It passes 30 of 30 runs locally. I reran the failed jobs on the same head (run 40611744229); every job now passes, includinggo test + vet.Risk
site_meter_stale, which stops dispatch and stands the chargers down. Trial merge of fix(control): a site meter that repeats one reading counts as stale #1921 (77bcd3d) into this branch, same loop plus the charger's own reading in telemetry andObserveSiteMeterFreeze+SetEVCommandedeach tick asmain.gocalls them: the car starts at 2,070 W (13.5 A) after 5 s, the meter counts as frozen at 40 s (devices_moved_w=2070, 6 samples), and the gate closes there. No phase passes the rating; the climb to 3,680 W at 190 s never comes. Do not merge this PR before fix(control): a site meter that repeats one reading counts as stale #1921. CI cannot enforce that: retargeting this PR onto fix(control): a site meter that repeats one reading counts as stale #1921's branch would stop thetestworkflow, which runs only on PRs tomaster.3pcommand with a configured minimum below 4,140 W now waits for room for 4,140 W before an idle start, not the configured minimum. A three-phase order below 6 A each does not run on any IEC charger, so the old start was not a real start.SiteFuseAmps - evPhaseMarginA(1 A under the rating); fix(control): car and battery work to the fuse rating (fuse stack #1910, #1891, #1913, #1923, #1924, #1925, #1926, #1914) #1910 moves it to the rating.Stack and merge order
GitHub does not enforce this: both PRs are based on master and both show CLEAN, and the only required check is
go test + vet. The owner holds the order by hand.Checked again at 78f357f on 28 Oct: alone, the frozen-meter loop ends at 3,680 W and 20.50 A on a 16 A fuse. With fix(control): a site meter that repeats one reading counts as stale #1921 (77bcd3d) merged in and
ObserveSiteMeterFreezecalled assite_dispatch_safety.gocalls it, the meter counts as frozen at 40 s with the car at 2,070 W, and the gate closes.This branch does not merge fix(control): a site meter that repeats one reading counts as stale #1921 in to force the order. fix(control): a site meter that repeats one reading counts as stale #1921 is still moving (last commit 28 Oct 01:57), and stacking would put its nine-file safety change in this PR. The owner can choose that instead.
FuseConfigsline.evPhaseMarginAand addsfuseLineA(). The boundary test no longer names either, so the two PRs merge in any order with no edit. Before 78f357f it namedevPhaseMarginA; the two PRs have no text conflict and master does not require an up-to-date branch, so the second to land would have broken master's test build. With the line at the rating the cases become 10.0 A starts and 10.3 A waits. The start test asserts only ≥ 1,380 W and ≤ the fuse rating, so it holds before and after fix(control): car and battery work to the fuse rating (fuse stack #1910, #1891, #1913, #1923, #1924, #1925, #1926, #1914) #1910.controller_fuse_budget.go, not this hunk.🤖 Generated with Claude Code