Scotty.de hat geschrieben: ↑12. Sep 2023 16:08
Das 2. Aggregat soll nur starten wenn das 1. Aggregat schon 60 Sekunden läuft.
Ja, das spielt aber keine Rolle, denn beide Funktionen überlappen sich. Aggregat 1 läuft und die zur Verfügung stehende Einspeisung liegt über 2000 -> Aggregat 2 einschalten. Gleichzeitig aber auch unter 3000 -> Aggregat 1 ausschalten. Die Schwellwerte müssen IMMER so bemessen sein, dass die Ausschaltschwelle unter der Einschaltschwelle liegt.
Scotty.de hat geschrieben: ↑12. Sep 2023 16:08
SF_Power_total beinhaltet den Gesamtverbrauch des Hauses. Wird direkt hinter dem Zähler vom Energieversorger gemessen.
Das ist ein wichtiger Punkt. In dem Moment, wo das Aggregat eingeschaltet wird, wird die Menge an eingespeistem Strom (erheblich) sinken.
Ich nehme an, die Aggregate passen dann von ihrer Leistungsaufnahme ungefähr zu den gewählten Werten? Man muss natürlich aufpassen, weil die Aggregate selbst ja eine eigene Steuerung haben, die dann mindestens mal temperaturgesteuert ist.
Was bildet das Item
Daikin...Power exakt ab? ist das eine Art "Freigabe", die den Zustand erst wieder ändert, wenn man den Ausschaltbefehl sendet? Dann könnte es zu folgender Situation kommen:
1. Aggregat wird aktiviert weil Einspeisung über 3000
1. Aggregat schaltet wegen Erreichen der Solltemperatur ab. Damit steigt die Einspeisung.
2. Aggregat schaltet ein weil die Einspeisung über 2000 ist.
1. Aggregat schaltet wegen Unterschreiten der Solltemperatur ein
gemeinsame Leistungsaufnahme führt zu negativer Einspeisung (also Strombezug)
2. Aggregat wird wieder ausgeschaltet aber 1. Aggregat schaltet ebenfalls aus usw.
Die Rule sieht jetzt natürlich viel komplizierter aus.
Code: Alles auswählen
// globale Variablen müssen vor der ersten Rule in der Datei definiert werden!
var Timer tSplitstart = null // Zeiger für Timer
// 1. Rule in der Datei...
rule "Starte Splitgerät falls Überschuss"
when
Item SF_Power_total changed // Leistung geändert
then
if(AC_AUTOMATIC_TEST.state != ON) { // Automatik inaktiv?
tSplitstart?.cancel // dann Timer abbrechen
tSplitstart = null // Zeiger löschen
return; // und Rule abbrechen
}
val nPower = if(SF_Power_total.state instanceof Number) // falls gültiger Messwert
- (SF_Power_total.state as Number).floatValue // hole Wert
else // ansonsten
0 // nimm 0
var nThresholdOn = 3000 // Schwellwert an für 1. Aggregat
var nThresholdOff = 0 // Dummy Schwellwert aus
if(Daikin_Onecta_AC_DG_Power.state == ON) { // falls 1. Aggregat läuft
nThresholdOn = 2000 // Schwellwert an für 2. Aggregat
nThresholdOff = 1000 // Schwellwert aus für 1. Aggregat
}
if(Daikin_Onecta_AC_1OG_Power.state == ON) { // falls 2. Aggregat läuft
nThresholdOn = 2500 // Schwellwert an für 3. Aggregat
nThresholdOff = 1500 // Schwellwert aus für 2. Aggregat
}
if(Daikin_Onecta_AC_EG_Power.state == ON) { // falls 3. Aggregat läuft
nThresholdOn = 10000 // Dumm Schwellwert an
nThresholdOff = 2500 // Schwellwert aus für 3. Aggregat
}
if(tSplitstart !== null) { // Timer aktiv
if(nPower < nThresholdOn && nPower > nThresholdOff) { // akt. Wert zwischen Grenzwerten
tSplitstart.cancel // Timer abbrechen
tSplitstart = null // Zeiger löschen
}
} else { // Timer inaktiv
if(nPower > nThresholdOn) { // oberer Grenzwert überschritten
tSplitstart = createTimer(now.plusSeconds(60), [| // lege Timer für nächsten Aggregatstart an
if(Daikin_Onecta_AC_DG_Power.state != ON) // Falls Aggregat 1 aus
Daikin_Onecta_AC_DG_Power.sendCommand(ON) // schalte Aggregat 1 ein
else if(Daikin_Onecta_AC_1OG_Power.state != ON) // ansonsten, falls Aggregat 2 aus
Daikin_Onecta_AC_1OG_Power.sendCommand(ON) // schalte Aggregat 2 ein
else if(Daikin_Onecta_AC_EG_Power.state != ON) // ansonsten, falls Aggregat 3 aus
Daikin_Onecta_AC_EG_Power.sendCommand(ON) // schalte Aggregat 3 ein
tSplitstart = null // lösche Zeiger
])
} else if(nPower < nThresholdOff) { // unterer Grenzwert unterschritten
tSplitstart = createTimer(now.plusSeconds(60), [| // lege Timer für nächsten Aggregatstop an
if(Daikin_Onecta_AC_EG_Power.state != OFF) // Falls Aggregat 3 nicht aus
Daikin_Onecta_AC_EG_Power.sendCommand(OFF) // schalte Aggregat 3 aus
else if(Daikin_Onecta_AC_1OG_Power.state != OFF) // ansonsten, falls Aggregat 2 nicht aus
Daikin_Onecta_AC_1OG_Power.sendCommand(OFF) // schalte Aggregat 2 aus
else if(Daikin_Onecta_AC_DG_Power.state != OFF) // ansonsten, falls Aggregat 1 nicht aus
Daikin_Onecta_AC_DG_Power.sendCommand(OFF) // schalte Aggregat 1 aus
tSplitstart = null // lösche Zeiger
])
}
}
end
Aber eigentlich hat sich nichts großartig verändert. Es gibt lediglich zwei unterschiedliche Codeblöcke für den Timer, einmal zum Einschalten, einmal zum Ausschalten, außerdem eine zweite Variable für den Grenzwert zum Ausschalten (und entsprechend eine Namenserweiterung der vorhandenen Variablen)
Ich habe die Schwellwerte mal so definiert, wie ich denke, dass es sein muss. Die Größen werden aber entscheidend auch von der Leistungsaufnahme der drei Aggregate abhängen, das muss gut zueinander passen. Letztlich muss die Einschaltschwelle über der Leistungsaufnahme liegen, die Ausschaltschwelle dann aber so niedrig, dass die Einspeisung auch mit der Leistungsaufnahme des Aggregats über der Ausschaltschwelle liegt (sonst Taktung)
Warum nur eine Rule?
Es gibt im Grunde nur eine Eingangsgröße, das ist die Einspeisung. Die Rule muss jedes Mal triggern, wenn sich die Einspeisung ändert. Man könnte nun also viele kleine Rules bauen, die aber alle auf den gleichen (nein, sogar den selben) Trigger auslösen müssen.
Weiterhin steuert diese eine Rule drei Geräte, aber in Abhängigkeit genau dieser drei Geräte. Würde ich nun die Funktion auf mehrere Rules aufteilen, dann müsste ich mich zusätzlich versichern, dass nicht evtl. eine der anderen Rules gerade an den verwendeten Items rumdoktort...
Man könnte auch eine State Machine programmieren, ich fürchte aber, dass der Code dadurch weder kürzer noch verständlicher wird.
