Skip to content

Loadpoint: fix fast charging phase scaling#27972

Merged
andig merged 1 commit intoevcc-io:masterfrom
mfuchs1984:fix/fast_charging_circuit_phase_scaling
Mar 7, 2026
Merged

Loadpoint: fix fast charging phase scaling#27972
andig merged 1 commit intoevcc-io:masterfrom
mfuchs1984:fix/fast_charging_circuit_phase_scaling

Conversation

@mfuchs1984
Copy link
Collaborator

@mfuchs1984 mfuchs1984 commented Mar 6, 2026

This should fix the the fastCharging phase-switching logic to take the actual circuit load into account. This makes sure to take available surplus into account as well as circuit nesting.

lp.fastCharging now used circuit.ValidatePower to determine if the minimum power for 3 phase charging is available. Instead of using the heuristic 1.1*maxPower1p, I changed it to explicitly use minPower3p. Everything below will lead to scaling down.

Fixes #24160
Replaces #27907

/cc @eliaslecomte
/cc @McFSR
/cc @joachimbaten

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • In TestFastChargingCircuitPhaseScaling, the for _, tc := range tc loop closes over the loop variable in t.Run, which can cause all subtests to use the last table entry; add a tc := tc inside the loop before t.Run to capture the value per iteration.
  • The test mutates the global Voltage variable without restoring it, which can lead to test ordering issues; consider saving the previous value and deferring its restoration inside the test.
  • The 4140 constant used for the 3‑phase minimum power edge cases in the test seems derived from Voltage * minCurrent * 3; computing it dynamically instead of hardcoding would make the test more robust to future changes in Voltage or minCurrent.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `TestFastChargingCircuitPhaseScaling`, the `for _, tc := range tc` loop closes over the loop variable in `t.Run`, which can cause all subtests to use the last table entry; add a `tc := tc` inside the loop before `t.Run` to capture the value per iteration.
- The test mutates the global `Voltage` variable without restoring it, which can lead to test ordering issues; consider saving the previous value and deferring its restoration inside the test.
- The `4140` constant used for the 3‑phase minimum power edge cases in the test seems derived from `Voltage * minCurrent * 3`; computing it dynamically instead of hardcoding would make the test more robust to future changes in `Voltage` or `minCurrent`.

## Individual Comments

### Comment 1
<location path="core/loadpoint_phases_test.go" line_range="484" />
<code_context>
 }
+
+func TestFastChargingCircuitPhaseScaling(t *testing.T) {
+	Voltage = 230
+
+	tc := []struct {
</code_context>
<issue_to_address>
**issue (testing):** Reset global `Voltage` after the test to avoid leaking state into other tests

This test mutates the package-level `Voltage` and never restores it, which can cause order-dependent test failures elsewhere. Capture the original value and defer restoring it, e.g. `oldVoltage := Voltage; Voltage = 230; defer func() { Voltage = oldVoltage }()` at the start of the test.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@mfuchs1984 mfuchs1984 marked this pull request as draft March 6, 2026 11:04
@mfuchs1984 mfuchs1984 marked this pull request as ready for review March 6, 2026 11:12
@mfuchs1984 mfuchs1984 requested a review from andig March 6, 2026 11:18
@mfuchs1984 mfuchs1984 force-pushed the fix/fast_charging_circuit_phase_scaling branch 3 times, most recently from 6db4166 to 34534f8 Compare March 6, 2026 12:16
@andig andig added the enhancement New feature or request label Mar 6, 2026
@andig
Copy link
Member

andig commented Mar 6, 2026

I didn't check the tests, but the implementation looks perfectly sound. It would be great if we could get a test confirmation before merging. Maybe @eliaslecomte?

@mfuchs1984 mfuchs1984 force-pushed the fix/fast_charging_circuit_phase_scaling branch from 34534f8 to 49782c2 Compare March 6, 2026 12:20
@mfuchs1984 mfuchs1984 force-pushed the fix/fast_charging_circuit_phase_scaling branch from 49782c2 to b4da4fb Compare March 6, 2026 12:23
@mfuchs1984
Copy link
Collaborator Author

Accidentally pushed an invalid local test. Now it's ready.

@mfuchs1984
Copy link
Collaborator Author

Yeah, I can't test it this week unfortunately. @eliaslecomte would be great if you could build and run evcc with the changes from this PR.

@eliaslecomte
Copy link
Contributor

eliaslecomte commented Mar 7, 2026

Nice!

  • You reuse ValidatePower
  • Take all circuits into account, where I was only looking 1 level up.
  • I did not take different A rates into account (16A vs 32A)

I'm looking at how I can best run this. For now I'm thinking to run it locally on my PC. I would need to copy my config (from home assistant) and do an export/restore backup through the UI. And then await some sun on this cloudy day.

@andig andig merged commit 56c1d56 into evcc-io:master Mar 7, 2026
7 checks passed
@andig
Copy link
Member

andig commented Mar 7, 2026

Let‘s merge this for testing. The current implementation on master is clearly wrong and the associated bug is already much too old. Please let us know if this works as expected.

@andig
Copy link
Member

andig commented Mar 7, 2026

Thank you @mfuchs1984 great PR!

@eliaslecomte
Copy link
Contributor

eliaslecomte commented Mar 7, 2026

Now that it got merged: I'll install the (home assistant) nightly and test tomorrow. You can expect my test results in the evening.

@mfuchs1984
Copy link
Collaborator Author

I think you have to wait for the nightly tomorrow.

@andig
Copy link
Member

andig commented Mar 7, 2026

New nightly in 30min

@eliaslecomte
Copy link
Contributor

eliaslecomte commented Mar 7, 2026

Test results 🥳. Good news, first scenario tested and looks good.

Setup

  • Alfen Eve Single Pro
  • Site limit set to 3200W
  • About 3000W solar
  • Running evcc as a home assistant app

Scenario tested

Even with a low site/grid limit, the charger should switch to 3p when there is enough solar.

Before

fast charge (before)

log (before).md

After

Running the nightly.

fast-charge (after)

log (after).md

@mfuchs1984
Copy link
Collaborator Author

Can you do the same later without surplus to verify it switches down?

@eliaslecomte
Copy link
Contributor

eliaslecomte commented Mar 7, 2026

After charging for half an hour, I noticed that it halted charging, while I believe that it could have lowered phases from 3 to 1, so that it could continue charging.

Not sure if I have captured the full relevant log but this might help:

[site ] DEBUG 2026/03/07 13:07:58 ----
[lp-1 ] DEBUG 2026/03/07 13:07:58 charge power: 0W
[lp-1 ] DEBUG 2026/03/07 13:07:58 charge currents: [0 0 0]A
[circuit-main] DEBUG 2026/03/07 13:07:59 power: -957W
[circuit-main] DEBUG 2026/03/07 13:07:59 current: 5.57A
[site ] DEBUG 2026/03/07 13:07:59 grid power: -957W
[site ] DEBUG 2026/03/07 13:07:59 pv 1 power: 2673W
[site ] DEBUG 2026/03/07 13:07:59 !! solar production: accumulate set db:4 13803.100kWh meter total (was: Accumulated: 774.660kWh updated: 2026-03-07 13:07:29 +0100 CET meter: 13803.100kWh)
[site ] DEBUG 2026/03/07 13:07:59 !! solar production: accumulate moved db:4 from 774.660 to 774.660
[site ] DEBUG 2026/03/07 13:07:59 grid currents: [2.77 5.57 0.13]A
[site ] DEBUG 2026/03/07 13:07:59 site power: -957W
[lp-1 ] DEBUG 2026/03/07 13:07:59 charge voltages: [235 238 233]V
[lp-1 ] DEBUG 2026/03/07 13:07:59 charge total import: 7748.519kWh
[lp-1 ] DEBUG 2026/03/07 13:07:59 charger status: B
[lp-1 ] DEBUG 2026/03/07 13:07:59 vehicle soc: 64%
[lp-1 ] DEBUG 2026/03/07 13:07:59 vehicle soc limit: 100%
[lp-1 ] DEBUG 2026/03/07 13:07:59 vehicle range: 250km
[lp-1 ] DEBUG 2026/03/07 13:07:59 soc estimated: 64.54% (vehicle: 64.00%)
[lp-1 ] DEBUG 2026/03/07 13:07:59 vehicle soc (estimator): 65%
[lp-1 ] DEBUG 2026/03/07 13:07:59 !! plan: plan time zero
[circuit-main] DEBUG 2026/03/07 13:07:59 validate power: -957W + (0W -> 12420W) > 3200W capped at 4157W
[lp-1 ] DEBUG 2026/03/07 13:07:59 set charge current limit: 6.02A
[site ] DEBUG 2026/03/07 13:07:59 solar forecast: accumulated 0.034Wh from 2026-03-07 13:07:29 +0100 CET to 2026-03-07 13:07:59 +0100 CET
[site ] DEBUG 2026/03/07 13:07:59 solar forecast: produced 774.660
[site ] DEBUG 2026/03/07 13:07:59 solar forecast: accumulated 1064.599kWh, produced 774.660kWh, scale 0.728
[lp-1 ] DEBUG 2026/03/07 13:08:01 set charge mode: minpv
[site ] DEBUG 2026/03/07 13:08:01 ----
[lp-1 ] DEBUG 2026/03/07 13:08:02 charge power: 0W
[lp-1 ] DEBUG 2026/03/07 13:08:02 charge currents: [0 0 0]A
[circuit-main] DEBUG 2026/03/07 13:08:02 power: -888W
[circuit-main] DEBUG 2026/03/07 13:08:02 current: 5.54A
[site ] DEBUG 2026/03/07 13:08:02 pv 1 power: 2660W
[site ] DEBUG 2026/03/07 13:08:02 grid power: -888W
[site ] DEBUG 2026/03/07 13:08:02 !! solar production: accumulate set db:4 13803.100kWh meter total (was: Accumulated: 774.660kWh updated: 2026-03-07 13:07:59 +0100 CET meter: 13803.100kWh)
[site ] DEBUG 2026/03/07 13:08:02 !! solar production: accumulate moved db:4 from 774.660 to 774.660
[site ] DEBUG 2026/03/07 13:08:02 grid currents: [2.94 5.54 0.13]A
[site ] DEBUG 2026/03/07 13:08:02 site power: -888W
[lp-1 ] DEBUG 2026/03/07 13:08:02 charge voltages: [234 237 233]V
[lp-1 ] DEBUG 2026/03/07 13:08:02 charge total import: 7748.519kWh
[lp-1 ] DEBUG 2026/03/07 13:08:02 charger status: B
[lp-1 ] DEBUG 2026/03/07 13:08:02 vehicle soc: 64%
[lp-1 ] DEBUG 2026/03/07 13:08:02 vehicle soc limit: 100%
[lp-1 ] DEBUG 2026/03/07 13:08:02 vehicle range: 250km
[lp-1 ] DEBUG 2026/03/07 13:08:02 soc estimated: 64.54% (vehicle: 64.00%)
[lp-1 ] DEBUG 2026/03/07 13:08:02 vehicle soc (estimator): 65%
[lp-1 ] DEBUG 2026/03/07 13:08:02 !! plan: plan time zero
[lp-1 ] DEBUG 2026/03/07 13:08:02 pv charge current: min 6A > 1.29A (-888W @ 3p, battery: false)
[circuit-main] DEBUG 2026/03/07 13:08:02 validate power: -888W + (0W -> 4140W) > 3200W capped at 4088W
[lp-1 ] DEBUG 2026/03/07 13:08:02 charger disable
[site ] DEBUG 2026/03/07 13:08:03 solar forecast: accumulated 0.004Wh from 2026-03-07 13:07:59 +0100 CET to 2026-03-07 13:08:03 +0100 CET
[site ] DEBUG 2026/03/07 13:08:03 solar forecast: produced 774.660
[site ] DEBUG 2026/03/07 13:08:03 solar forecast: accumulated 1064.603kWh, produced 774.660kWh, scale 0.728

@mfuchs1984
Copy link
Collaborator Author

The log starts to late to understand what's going on.

@eliaslecomte
Copy link
Contributor

eliaslecomte commented Mar 7, 2026

I've retested the scenario of switching to 1 phase while it was already charging with 3 phases by limiting solar panels downwards.
Now I did see it switch down to 1 phase and then try to use the maximum of the grid 👍.
Maybe I was a bit too impatient the first time. I'll continue follow up this afternoon.

[site ] DEBUG 2026/03/07 13:35:29 grid currents: [5.54 2.83 7.53]A
[site ] DEBUG 2026/03/07 13:35:29 site power: 3509W
[lp-1 ] DEBUG 2026/03/07 13:35:29 charge voltages: [233 234 232]V
[lp-1 ] DEBUG 2026/03/07 13:35:29 detected active phases: 3p
[lp-1 ] DEBUG 2026/03/07 13:35:29 session energy: 2.813kWh
[lp-1 ] DEBUG 2026/03/07 13:35:29 charge total import: 7750.401kWh
[lp-1 ] DEBUG 2026/03/07 13:35:29 charger status: C
[lp-1 ] DEBUG 2026/03/07 13:35:29 vehicle soc: 66%
[lp-1 ] DEBUG 2026/03/07 13:35:29 vehicle soc limit: 100%
[lp-1 ] DEBUG 2026/03/07 13:35:29 vehicle range: 250km
[lp-1 ] DEBUG 2026/03/07 13:35:29 soc estimated: 66.84% (vehicle: 66.00%)
[lp-1 ] DEBUG 2026/03/07 13:35:29 vehicle soc (estimator): 67%
[lp-1 ] DEBUG 2026/03/07 13:35:29 !! plan: plan time zero
[circuit-main] DEBUG 2026/03/07 13:35:29 validate power: 3509W + (5160W -> 4140W) > 3200W capped at 4140W
[circuit-main] DEBUG 2026/03/07 13:35:29 validate power: 3509W + (5160W -> 12420W) > 3200W capped at 4851W
[lp-1 ] DEBUG 2026/03/07 13:35:29 set charge current limit: 7.03A
[site ] DEBUG 2026/03/07 13:35:29 solar forecast: accumulated 0.034Wh from 2026-03-07 13:34:59 +0100 CET to 2026-03-07 13:35:29 +0100 CET
[site ] DEBUG 2026/03/07 13:35:29 solar forecast: produced 776.060
[site ] DEBUG 2026/03/07 13:35:29 solar forecast: accumulated 1066.462kWh, produced 776.060kWh, scale 0.728
[site ] DEBUG 2026/03/07 13:35:58 ----
[lp-1 ] DEBUG 2026/03/07 13:35:58 charge power: 4766W
[lp-1 ] DEBUG 2026/03/07 13:35:58 charge currents: [6.76 6.83 6.92]A
[circuit-main] WARN 2026/03/07 13:35:59 over power detected: 4156W > 3200W
[circuit-main] DEBUG 2026/03/07 13:35:59 current: 6.97A
[site ] DEBUG 2026/03/07 13:35:59 grid power: 4156W
[site ] DEBUG 2026/03/07 13:35:59 pv 1 power: 2326W
[site ] DEBUG 2026/03/07 13:35:59 !! solar production: accumulate set db:4 13804.500kWh meter total (was: Accumulated: 776.060kWh updated: 2026-03-07 13:35:29 +0100 CET meter: 13804.500kWh)
[site ] DEBUG 2026/03/07 13:35:59 !! solar production: accumulate moved db:4 from 776.060 to 776.060
[site ] DEBUG 2026/03/07 13:35:59 grid currents: [6.76 4.75 6.97]A
[site ] DEBUG 2026/03/07 13:35:59 site power: 4156W
[lp-1 ] DEBUG 2026/03/07 13:35:59 charge voltages: [233 233 232]V
[lp-1 ] DEBUG 2026/03/07 13:35:59 detected active phases: 3p
[lp-1 ] DEBUG 2026/03/07 13:35:59 session energy: 2.854kWh
[lp-1 ] DEBUG 2026/03/07 13:35:59 charge total import: 7750.440kWh
[lp-1 ] DEBUG 2026/03/07 13:35:59 charger status: C
[lp-1 ] DEBUG 2026/03/07 13:35:59 vehicle soc: 66%
[lp-1 ] DEBUG 2026/03/07 13:35:59 vehicle soc limit: 100%
[lp-1 ] DEBUG 2026/03/07 13:35:59 vehicle range: 250km
[lp-1 ] DEBUG 2026/03/07 13:35:59 soc estimated: 66.88% (vehicle: 66.00%)
[lp-1 ] DEBUG 2026/03/07 13:35:59 vehicle soc (estimator): 67%
[lp-1 ] DEBUG 2026/03/07 13:35:59 !! plan: plan time zero
[circuit-main] DEBUG 2026/03/07 13:35:59 validate power: 4156W + (4766W -> 4140W) > 3200W capped at 3810W
[lp-1 ] DEBUG 2026/03/07 13:35:59 fast charging: scaled to 1p to match 3810W available circuit power
[lp-1 ] DEBUG 2026/03/07 13:36:00 switched phases: 1p
[lp-1 ] DEBUG 2026/03/07 13:36:00 wake-up timer: start
[circuit-main] DEBUG 2026/03/07 13:36:00 validate power: 4156W + (4766W -> 4140W) > 3200W capped at 3810W
[lp-1 ] DEBUG 2026/03/07 13:36:00 set charge current limit: 16.6A
[site ] DEBUG 2026/03/07 13:36:00 solar forecast: accumulated 0.034Wh from 2026-03-07 13:35:29 +0100 CET to 2026-03-07 13:36:00 +0100 CET
[site ] DEBUG 2026/03/07 13:36:00 solar forecast: produced 776.060
[site ] DEBUG 2026/03/07 13:36:00 solar forecast: accumulated 1066.496kWh, produced 776.060kWh, scale 0.728
[site ] DEBUG 2026/03/07 13:36:28 ----
[lp-1 ] DEBUG 2026/03/07 13:36:28 charge power: 1420W
[lp-1 ] DEBUG 2026/03/07 13:36:29 charge currents: [6.25 0 0]A
[circuit-main] DEBUG 2026/03/07 13:36:29 power: 116W
[circuit-main] DEBUG 2026/03/07 13:36:29 current: 6.11A
[site ] DEBUG 2026/03/07 13:36:29 grid power: 116W
[site ] DEBUG 2026/03/07 13:36:29 pv 1 power: 2296W
[site ] DEBUG 2026/03/07 13:36:29 !! solar production: accumulate set db:4 13804.600kWh meter total (was: Accumulated: 776.060kWh updated: 2026-03-07 13:35:59 +0100 CET meter: 13804.500kWh)
[site ] DEBUG 2026/03/07 13:36:29 !! solar production: accumulate moved db:4 from 776.060 to 776.160
[site ] DEBUG 2026/03/07 13:36:29 grid currents: [6.11 4.57 0.13]A
[site ] DEBUG 2026/03/07 13:36:29 site power: 116W
[lp-1 ] DEBUG 2026/03/07 13:36:29 charge voltages: [233 236 233]V
[lp-1 ] DEBUG 2026/03/07 13:36:29 session energy: 2.862kWh
[lp-1 ] DEBUG 2026/03/07 13:36:29 charge total import: 7750.448kWh
[lp-1 ] DEBUG 2026/03/07 13:36:29 charger status: C
[lp-1 ] DEBUG 2026/03/07 13:36:29 vehicle soc: 66%
[lp-1 ] DEBUG 2026/03/07 13:36:29 vehicle soc limit: 100%
[lp-1 ] DEBUG 2026/03/07 13:36:29 vehicle range: 250km
[lp-1 ] DEBUG 2026/03/07 13:36:29 soc estimated: 66.89% (vehicle: 66.00%)
[lp-1 ] DEBUG 2026/03/07 13:36:29 vehicle soc (estimator): 67%
[lp-1 ] DEBUG 2026/03/07 13:36:29 !! plan: plan time zero
[lp-1 ] DEBUG 2026/03/07 13:36:29 switched phases: 3p
[lp-1 ] DEBUG 2026/03/07 13:36:29 wake-up timer: start
[circuit-main] DEBUG 2026/03/07 13:36:29 validate power: 116W + (1420W -> 12420W) > 3200W capped at 4504W
[lp-1 ] DEBUG 2026/03/07 13:36:29 set charge current limit: 6.53A
[site ] DEBUG 2026/03/07 13:36:29 solar forecast: accumulated 0.033Wh from 2026-03-07 13:36:00 +0100 CET to 2026-03-07 13:36:29 +0100 CET
[site ] DEBUG 2026/03/07 13:36:29 solar forecast: produced 776.160
[site ] DEBUG 2026/03/07 13:36:29 solar forecast: accumulated 1066.529kWh, produced 776.160kWh, scale 0.728

@mfuchs1984
Copy link
Collaborator Author

mfuchs1984 commented Mar 7, 2026

@andig while the change itself seems fine, this might need a phase switching guard timer, like in PV mode, at least before switching up again.

@mfuchs1984
Copy link
Collaborator Author

Created #28174 as follow-up, preventing excessive repeated phase switching.

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fast/Now chargin with loadmanagement does not switch to 3p

3 participants