ESS: zuviel Entladung

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.

Ich habe die Berechnung über ein else erweitert:

		// 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.

Gruß,
klinki

Hallo klinki,

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);
    }
}

Moin @Sn0w3y ,

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.

Anyway - Danke nochmals & schönes Wochenende

klinki

1 Like

@klinki: Wie sah denn der Code aus, der nicht funktioniert hat? Ich weiß leider gerade nicht von welcher Komponente du sprichst.

Die Lösung von Sn0w3y ist gut. Ich würde es vermutlich so lösen wie hier:

Gruß,
Stefan

1 Like

Guten Morgen Stefan,

So sah mein Code vorher aus:

		// 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.

Gruß,
klinki

1 Like

Ah verstanden. Dann kann ich es erklären.

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);
}

Gruß,
Stefan

1 Like

Hi Stefan,

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 :pleading_face: peinlich…

Danke für Deine Hilfe

Gruß,
klinki

1 Like