Ich hatte bei meinem Setup das Problem, dass zuviel Entladungsenergie ausgewiesen wurde - mehr als beladen wurde. Kann ja nicht sein. Ein Blick in die DB zeigte, dass um ca. 5 Uhr morgens es einen Sprung von ca. 2kWh gab - obwohl die Leistung zu der Zeit auf 0W war. Ein Blick in´s (erweiterte) Log zeigte einen Wert “UNDEFINED” um diese Zeit. Ich vermute ein Problem in der CalculateEnergyFromPower-Methode - habe aber keinen Ansatz wie man so etwas simulieren oder debuggen kann.
// Actual Power DC from or to battery
var activeDcPower = this.getDcDischargePower().get(); // Instantaneous power to or from battery
if (activeDcPower == null ) {
// Not available
this.calculateDcChargeEnergy.update(null);
this.calculateDcDischargeEnergy.update(null);
} else if (activeDcPower > 0) {
// DisCharging Battery
this.calculateDcChargeEnergy.update(0);
this.calculateDcDischargeEnergy.update(activeDcPower);
} else if (activeDcPower < 0) {
// Charging Battery
this.calculateDcChargeEnergy.update(activeDcPower * -1);
this.calculateDcDischargeEnergy.update(0);
}
else { //UNDEFINED??
this.calculateDcChargeEnergy.update(null);
this.calculateDcDischargeEnergy.update(null);
}
Seit dem funktioniert es. Der Grund ist mir allerdings nicht klar.
wir haben ja schon kurz darüber gesprochen, aber versuchs mal so:
// Actual Power DC from or to battery
Optional<Integer> activeDcPowerOpt = this.getDcDischargePower().getNextValue();
if (!activeDcPowerOpt.isPresent()) {
// Not available
this.calculateDcChargeEnergy.update(null);
this.calculateDcDischargeEnergy.update(null);
} else {
int activeDcPower = activeDcPowerOpt.get(); // Now safely retrieved
if (activeDcPower > 0) {
// Discharging Battery
this.calculateDcChargeEnergy.update(0);
this.calculateDcDischargeEnergy.update(activeDcPower);
} else if (activeDcPower < 0) {
// Charging Battery
this.calculateDcChargeEnergy.update(activeDcPower);
this.calculateDcDischargeEnergy.update(0);
} else {
// Power is 0 - Battery is neither charging nor discharging
this.calculateDcChargeEnergy.update(0);
this.calculateDcDischargeEnergy.update(0);
}
}
Vielen Dank. Den Code habe ich gestern eingesetzt. Funktioniert!
Damit kann ich gut leben, verstehe die Ursache aber dennoch nicht so ganz. Eigentlich sollte CalculateEnergyFromPower bei einem nicht definierten Wert auch nichts tun - zumindest nach meinem Verständnis.
Den ursprünglichen Code-Block zur Energieberechnung findet man auch in vielen Implementierungen - hatte ich mir seinerzeit bei der Fenecon Home abgeschaut.
// Actual Power DC from or to battery
var activeDcPower = this.getDcDischargePower().get(); // Instantaneous power to or from battery
if (activeDcPower == null) {
// Not available
this.calculateDcChargeEnergy.update(null);
this.calculateDcDischargeEnergy.update(null);
} else if (activeDcPower > 0) {
// DisCharging Battery
this.calculateDcChargeEnergy.update(0);
this.calculateDcDischargeEnergy.update(activeDcPower);
} else if (activeDcPower < 0) {
// Charging Battery
this.calculateDcChargeEnergy.update(activeDcPower * -1);
this.calculateDcDischargeEnergy.update(0);
}
Es fehlte also der Fall Power = 0. Dann aber gar nichts zu tun, sollte eigentlich auch kein Problem sein, oder?
Mit meiner, bzw. @Sn0w3y ´s, Lösung funktioniert es jedenfalls. Ich verstehe es nur nicht.
Beim update() merkt sich CalculateEnergyFromPower die Leistung und den zugehörigen Timestamp:
// keep last data for next run
this.lastTimestamp = Instant.now();
this.lastPower = power;
Die eigentliche Berechnung (calculateEnergy()) sieht so aus:
// calculate duration since last value
var duration /* [msec] */ = Duration.between(this.lastTimestamp, Instant.now()).toMillis();
// calculate energy since last run in [Wmsec]
var continuousEnergy /* [Wmsec] */ = this.lastPower /* [W] */ * duration /* [msec] */;
Wenn du bei 0 das update() nicht aufrufst, bleibt jeweils der vorherige Wert (also irgendwas != 0) stehen. Das führt dann dazu, dass die continuousEnergy verfälscht wird.
Ich würde dir deshalb diese Lösung empfehlen:
var dcDischargePower = this.getDcDischargePower().getNextValue().get();
if (dcDischargePower == null) {
// Not available
this.calculateDcChargeEnergy.update(null);
this.calculateDcDischargeEnergy.update(null);
} else if (dcDischargePower > 0) {
// Discharge
this.calculateDcChargeEnergy.update(0);
this.calculateDcDischargeEnergy.update(dcDischargePower);
} else {
// Charge
this.calculateDcChargeEnergy.update(dcDischargePower * -1);
this.calculateDcDischargeEnergy.update(0);
}
ja, verstanden.
Ich bin einfach davon ausgegangen, dass wenn sich keine Änderung ergibt (Power 0), der letzte Wert mit Zeitstempel genommen wird. Keine Änderung über lange Zeit erhöht die Energie genauso wenig wie keine Änderung über kurze Zeit.
Solange das innerhalb von 100 Tagen passiert (Limit der Abfrage in die Vergangenheit).
Im normalen Betrieb war das auch nie ein Problem, da gegen Ende der Entladung 0-Werte kamen NULL-Werte kamen. In der morgendliche Aufweck-Minute aber nicht.
Aber logisch: wenn der letzte Wert für Power stehen bleibt wird eine Energie berechnet. Oh je, das alte Problem mit dem Wald und den Bäumen peinlich…