Estimator: improve estimating remaining charge duration (#7425)

This commit is contained in:
premultiply 2023-04-16 17:35:07 +02:00 • committed by GitHub
parent ef01f9ea6b
commit 75f1841185
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 21 deletions

View file

@ -38,23 +38,7 @@ func (lp *Loadpoint) planRequiredDuration(maxPower float64) time.Duration {
targetSoc = 100
}
requiredDuration := lp.socEstimator.RemainingChargeDuration(targetSoc, maxPower)
if requiredDuration <= 0 {
return 0
}
// anticipate lower charge rates at end of charging curve
var additionalDuration time.Duration
if targetSoc > 80 && maxPower > 15000 {
additionalDuration = time.Duration(float64(targetSoc-80) / (float64(targetSoc) - lp.vehicleSoc) * float64(requiredDuration))
lp.log.DEBUG.Printf("add additional charging time %v for soc > 80%%", additionalDuration.Round(time.Minute))
} else if targetSoc > 90 && maxPower > 4000 {
additionalDuration = time.Duration(float64(targetSoc-90) / (float64(targetSoc) - lp.vehicleSoc) * float64(requiredDuration))
lp.log.DEBUG.Printf("add additional charging time %v for soc > 90%%", additionalDuration.Round(time.Minute))
}
return requiredDuration + additionalDuration
return lp.socEstimator.RemainingChargeDuration(targetSoc, maxPower)
}
func (lp *Loadpoint) GetPlannerUnit() string {

View file

@ -27,6 +27,9 @@ type Estimator struct {
prevSoc float64 // previous vehicle Soc in %
prevChargedEnergy float64 // previous charged energy in Wh
energyPerSocStep float64 // Energy per Soc percent in Wh
minChargePower float64 // Lowest charge power (just before vehicle stops charging at 100%)
maxChargePower float64 // Highest charge power the battery can handle on any charger
maxChargeSoc float64 // SoC at/after which maxChargePower is degressive
}
// NewEstimator creates new estimator
@ -51,15 +54,42 @@ func (s *Estimator) Reset() {
s.capacity = float64(s.vehicle.Capacity()) * 1e3 // cache to simplify debugging
s.virtualCapacity = s.capacity / ChargeEfficiency // initial capacity taking efficiency into account
s.energyPerSocStep = s.virtualCapacity / 100
s.minChargePower = 1000 // default 1 kW
s.maxChargePower = 50000 // default 50 kW
s.maxChargeSoc = 50 // default 50%
}
// RemainingChargeDuration returns the estimated remaining duration
func (s *Estimator) RemainingChargeDuration(targetSoc int, chargePower float64) time.Duration {
energy := s.RemainingChargeEnergy(targetSoc) * 1e3 / chargePower
if math.IsInf(energy, 0) {
energy = 0
const minChargeSoc = 100
dy := s.minChargePower - s.maxChargePower
dx := minChargeSoc - s.maxChargeSoc
var rrp float64 = 100
if dy > 0 && dx > 0 {
m := dy / dx
b := s.minChargePower - m*minChargeSoc
// Relativer Reduktionspunkt
rrp = (chargePower - b) / m
}
return time.Duration(float64(time.Hour) * energy).Round(time.Second)
var t1, t2 float64
// Zeit von vehicleSoc bis Reduktionspunkt (linear)
if s.vehicleSoc < rrp {
t1 = (math.Min(float64(targetSoc), rrp) - s.vehicleSoc) / minChargeSoc * s.virtualCapacity / chargePower
}
// Zeit von Reduktionspunkt bis targetSoc (degressiv)
if float64(targetSoc) > rrp {
t2 = (float64(targetSoc) - math.Max(s.vehicleSoc, rrp)) / minChargeSoc * s.virtualCapacity / ((chargePower-s.minChargePower)/2 + s.minChargePower)
}
return time.Duration(float64(time.Hour) * (t1 + t2)).Round(time.Second)
}
// RemainingChargeEnergy returns the remaining charge energy in kWh