Estimator: improve estimating remaining charge duration (#7425)
This commit is contained in:
parent
ef01f9ea6b
commit
75f1841185
2 changed files with 35 additions and 21 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue