Phases: disable instead of scaling down to 1p without sufficient surplus (#32991)
This commit is contained in:
parent
41319dfa39
commit
748d36d130
3 changed files with 23 additions and 3 deletions
|
|
@ -1449,8 +1449,15 @@ func (lp *Loadpoint) pvScalePhases(sitePower, minCurrent, maxCurrent float64) in
|
||||||
lp.log.DEBUG.Printf("available power %.0fW < %.0fW min %dp threshold", availablePower, float64(activePhases)*Voltage*minCurrent, activePhases)
|
lp.log.DEBUG.Printf("available power %.0fW < %.0fW min %dp threshold", availablePower, float64(activePhases)*Voltage*minCurrent, activePhases)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// while charging, scaling down only helps if 1p is sustainable, otherwise it
|
||||||
|
// merely delays the pv disable timer by the phase timer duration
|
||||||
|
useful := !lp.enabled || !lp.charging() || powerToCurrent(availablePower, 1) >= minCurrent
|
||||||
|
if insufficient && !useful {
|
||||||
|
lp.log.DEBUG.Printf("available power %.0fW < %.0fW min 1p threshold, disabling instead of scaling down", availablePower, Voltage*minCurrent)
|
||||||
|
}
|
||||||
|
|
||||||
// scaling down also frees load management headroom for min power on activePhases
|
// scaling down also frees load management headroom for min power on activePhases
|
||||||
scalable = insufficient || !lp.circuitAllowsPhases(activePhases, minCurrent)
|
scalable = insufficient && useful || !lp.circuitAllowsPhases(activePhases, minCurrent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// scale down phases
|
// scale down phases
|
||||||
|
|
|
||||||
|
|
@ -271,6 +271,7 @@ func TestPvScalePhases(t *testing.T) {
|
||||||
// scale down
|
// scale down
|
||||||
min1p := 0.1
|
min1p := 0.1
|
||||||
lp.phaseTimer = time.Time{}
|
lp.phaseTimer = time.Time{}
|
||||||
|
lp.chargePower = float64(lp.ActivePhases()) * minA * Voltage // charging at min current
|
||||||
|
|
||||||
plainCharger.EXPECT().Enable(false).Return(nil).MaxTimes(1)
|
plainCharger.EXPECT().Enable(false).Return(nil).MaxTimes(1)
|
||||||
phaseCharger.EXPECT().Phases1p3p(1).Return(nil).MaxTimes(1)
|
phaseCharger.EXPECT().Phases1p3p(1).Return(nil).MaxTimes(1)
|
||||||
|
|
@ -372,6 +373,17 @@ func TestPvScalePhasesTimer(t *testing.T) {
|
||||||
lp.phaseTimer = elapsed
|
lp.phaseTimer = elapsed
|
||||||
}},
|
}},
|
||||||
|
|
||||||
|
// charging with insufficient power for 1p: disable instead of scaling down
|
||||||
|
{"3/3->1, insufficient for 1p, charging", 3, 3, 0.1, 3, 0, func(lp *Loadpoint) {
|
||||||
|
lp.phaseTimer = elapsed
|
||||||
|
lp.enabled = true
|
||||||
|
}},
|
||||||
|
{"3/3->1, sufficient for 1p, charging", 3, 3, 3 * Voltage * minA / 2, 1, 1, func(lp *Loadpoint) {
|
||||||
|
lp.phaseTimer = elapsed
|
||||||
|
lp.enabled = true
|
||||||
|
lp.chargePower = 3 * Voltage * minA
|
||||||
|
}},
|
||||||
|
|
||||||
// switch down from 3p/0p while not yet charging
|
// switch down from 3p/0p while not yet charging
|
||||||
{"3/0->1, not enough power, not charging", 3, 0, 0, 1, 1, func(lp *Loadpoint) {
|
{"3/0->1, not enough power, not charging", 3, 0, 0, 1, 1, func(lp *Loadpoint) {
|
||||||
lp.status = api.StatusB
|
lp.status = api.StatusB
|
||||||
|
|
|
||||||
|
|
@ -752,8 +752,9 @@ func TestPVHysteresisAfterPhaseSwitch(t *testing.T) {
|
||||||
Disable: loadpoint.ThresholdConfig{
|
Disable: loadpoint.ThresholdConfig{
|
||||||
Delay: dt,
|
Delay: dt,
|
||||||
},
|
},
|
||||||
status: api.StatusC,
|
status: api.StatusC,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
chargePower: 3 * Voltage * minA, // charging 3p at min current
|
||||||
}
|
}
|
||||||
|
|
||||||
start := clock.Now()
|
start := clock.Now()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue