@dieter_p ganz einfach. Die Abschaltungen kommen, da die Raum Temperatur erreicht ist. Weiter runter als 40% Bedarf geht es nicht.
Für diese Temperatur ist der Raum zu klein oder die Inneneinheit zu groß.
@dieter_p ganz einfach. Die Abschaltungen kommen, da die Raum Temperatur erreicht ist. Weiter runter als 40% Bedarf geht es nicht.
Für diese Temperatur ist der Raum zu klein oder die Inneneinheit zu groß.
Genau so habe ich das damals auch gesehen. Ich habe 3 Logo 8 und den iobroker oben drauf.
Ich habe aber als 24V System. Fand ich besser. Ob ein Schalter in der Wand mit 230V oder mit 24V arbeitet, spielt doch keine Rolle
Danke. Verstanden da Du als Stellgröße nur den Bedarf nutzt.
Ich vermute hier ist noch Potential da der Kompressor noch nicht am Minimum ist.
Es gibt hier im Beitrag irgendwo ein Beispiel wo jemand bei erreichen der Solltemperatur sowohl am Bedarf als auch am Sollwert regelt. Das ergab eine recht perfekte Regelung, allerdings durchaus nicht inkomplex. Daher noch nicht probiert.
Auf IOBroker Javascript transferiert dürfte es etwa so funktionieren aber kann gerade leider nicht testen ![]()
/***************************************************
* CONFIG – bitte anpassen!
***************************************************/
// ioBroker-Datenpunkte (nur lesen!)
const DP = {
power: "daikin.0.wohnzimmer.power",
mode: "daikin.0.wohnzimmer.mode",
fan: "daikin.0.wohnzimmer.fan",
actualTemp: "daikin.0.wohnzimmer.actualTemp",
setTemp: "daikin.0.wohnzimmer.setTemp",
indoorTemp: "daikin.0.wohnzimmer.indoorTemp",
setPoint: "daikin.0.wohnzimmer.setPoint",
maxPower: "daikin.0.wohnzimmer.maxPower",
dcMode: "daikin.0.wohnzimmer.dcMode",
lastChange: "daikin.0.wohnzimmer.lastChange"
};
// MQTT Topics für Kommandos
const MQTT = {
setPoint: "daikin/wohnzimmer/setPoint",
fan: "daikin/wohnzimmer/fan",
demandPower: "daikin/wohnzimmer/demandPower"
};
// Parameter
const minPower = 10;
const maxTemp = 26;
const minTemp = 18;
/***************************************************
* AB HIER NICHTS MEHR ÄNDERN
***************************************************/
schedule("30 */5 * * * *", async () => {
log("Starte Temperaturregelung Wohnzimmer…");
// Wenn Klimagerät aus → nichts tun
if (getState(DP.power).val !== true) {
log("Klimagerät ist aus – abbrechen.", "info");
return;
}
const nowTs = Date.now();
// Werte lesen
const mode = getState(DP.mode).val; // "HEAT" / "COLD"
const fan = getState(DP.fan).val;
const actualTemp = parseFloat(getState(DP.actualTemp).val);
const setTemp = parseFloat(getState(DP.setTemp).val);
const indoorTemp = parseFloat(getState(DP.indoorTemp).val);
let setPoint = parseFloat(getState(DP.setPoint).val);
let demandPower = getState(DP.maxPower).val;
const dcMode = getState(DP.dcMode).val;
// Prüfen ob Änderung vor 5 Minuten
const lastChangeTs = new Date(getState(DP.lastChange).val).getTime();
if (nowTs - lastChangeTs < 5 * 60 * 1000) {
log("Letzte Änderung <5 Minuten – abbrechen.");
return;
}
/***************************************************
* Temperaturverlauf 5 Min & 10 Min (deltaT05/10)
***************************************************/
async function getDelta(seconds) {
// Hole den Wert von vor X Sekunden (History erforderlich)
const hist = await getHistory(DP.actualTemp, {
start: nowTs - seconds * 1000,
end: nowTs,
aggregate: "none",
count: 2
});
if (!hist || hist.length < 1) return 0;
const past = parseFloat(hist[0].val);
return ((actualTemp - past) / seconds) * (seconds === 300 ? 300 : 600);
}
const deltaT05 = (await getDelta(300)) || 0;
const deltaT10 = (await getDelta(600)) || 0;
// Raum-Abweichung vom Soll
const modeFaktor = mode === "COLD" ? -1 : 1;
const limiter = mode === "COLD" ? -1 : 3;
const roomDiff = (actualTemp - setTemp) * modeFaktor;
/***************************************************
* Steuerlogik – exakt aus deiner OpenHAB-Regel
***************************************************/
// Raum-Soll erreicht
if (roomDiff >= 0) {
if (deltaT05 >= 0.1) {
if (setPoint > indoorTemp) setPoint = indoorTemp;
else setPoint -= Math.round(deltaT05 * 10 * modeFaktor);
} else {
if (deltaT05 > 0 && deltaT05 < 0.1)
setPoint -= 0.5 * modeFaktor;
else
setPoint -= Math.round(deltaT05 * 10 * modeFaktor) / 2;
}
if ((setPoint > indoorTemp - limiter && mode === "COLD") ||
(setPoint < indoorTemp - limiter && mode === "HEAT")) {
const diff = Math.abs(setPoint - (indoorTemp - limiter));
if (dcMode === "OFF" || demandPower <= minPower) {
mqttSend(MQTT.fan, "SILENCE");
} else {
demandPower -= Math.round(diff * 10);
demandPower = Math.max(minPower, demandPower);
}
setPoint = indoorTemp - limiter;
}
}
// Kurz vor Raum-Soll
if (roomDiff >= -0.5 && roomDiff < 0) {
if (fan === "SILENCE") mqttSend(MQTT.fan, "AUTO");
if (deltaT05 > 0.1)
setPoint -= Math.round(deltaT05 * 20 * modeFaktor);
if (deltaT05 <= 0)
setPoint -= Math.round(roomDiff * 10 * modeFaktor);
if (mode === "HEAT")
setPoint = Math.max(indoorTemp - limiter + 0.5, setPoint);
if ((mode === "HEAT" && setPoint > maxTemp) ||
(mode === "COLD" && setPoint < minTemp)) {
demandPower = Math.min(demandPower + 5, 95);
setPoint = mode === "HEAT" ? indoorTemp : minTemp;
}
}
// Raum-Soll weit entfernt
if (roomDiff < -0.5) {
if (fan === "SILENCE") mqttSend(MQTT.fan, "AUTO");
if (deltaT05 < 0.1)
setPoint -= Math.round(roomDiff * 10 * modeFaktor) * 0.5;
if ((mode === "HEAT" && setPoint > maxTemp) ||
(mode === "COLD" && setPoint < minTemp)) {
demandPower += 5;
setPoint = mode === "HEAT"
? indoorTemp + (maxTemp - indoorTemp) / 2
: minTemp;
}
}
/***************************************************
* Grenzen einhalten & runden
***************************************************/
setPoint = Math.min(maxTemp, Math.max(minTemp, setPoint));
setPoint = Math.round(setPoint * 2) / 2;
demandPower = Math.max(minPower, Math.min(95, demandPower));
/***************************************************
* MQTT Kommandos senden
***************************************************/
mqttSend(MQTT.setPoint, setPoint);
mqttSend(MQTT.demandPower, demandPower);
log(`Neuer SetPoint: ${setPoint}, DemandPower: ${demandPower}`);
});
/***************************************************
* MQTT Sendehilfe
***************************************************/
function mqttSend(topic, payload) {
setState("mqtt.0." + topic, payload, true);
log(`MQTT → ${topic} = ${payload}`);
}
Prinzipiell ist das natürlich richtig, kannst auch mit 5V Steuersignal arbeiten dann kann der Arduino gleich mit horchen ![]()
Ich hatte nicht unbegrenzt Platz in den Feldverteilern, da kam es mir ganz gelegen auf ein zusätzliches 24V Netzteil für die Hutschiene verzichten zu können. Zudem lassen sich zumindest alle Lichtkreise (mit entsprechender Vorsicherung) direkt über die in der Logo integrierten Relais schalten und ich muss nicht mit lauter Koppelrelais rumhantieren die auch wieder Platz auf der Hutschiene brauchen.
Es gibt da für alles ein für und wider - ich finds jedenfalls cool das du auch etablierte, industrietaugliche Steuerungen einsetzt ![]()
@dieter_p Klingt gut und könnte funktionieren, nur grob überflogen. Aber ich habe nur in der Übergangszeit Abschaltungen. Von daher nicht die höchste Priorität.
Bin mit dem Thermostatmodus auch ganz zufrieden, aber Optimierungen gehen ja immer ![]()
Edit: Habs die transferierte Version auf JavaScript nun für den IOBroker in Funktion bekommen:
/************************************************************
* DAIKIN TEMPERATUR- UND LEISTUNGSREGELUNG (1. OG)
* ----------------------------------------------------------
* Dieses Skript steuert eine Daikin-Klimaanlage über MQTT.
* Alle 5 Minuten werden SetPoint (Zieltemperatur der Daikin)
* und DemandPower (Leistungsanforderung 30–100 %) automatisch
* berechnet und an die Daikin-Anlage gesendet.
*
* Das Skript nutzt:
* - Raumtemperatur (Externer Sensor)
* - Solltemperatur des Nutzers
* - Temperaturtrend der letzten 10 Minuten
* - Innentemperatur der Daikin
* - aktuellen Modus (Heizen/Kühlen)
*
* Dadurch arbeitet die Anlage effizienter, taktet weniger
* und hält die Temperatur stabiler.
************************************************************/
/************************************************************
* 1) KONFIGURATION – HIER AN DIE EIGENE INSTALLATION ANPASSEN
************************************************************/
const DP = {
// Schaltzustand der Klimaanlage (true = AN)
power: "0_userdata.0.Daikin1OG.power",
// Betriebsmodus: "H" = Heat, "C" = Cool, "A" = Auto, "F" = Fan, "D" = Dry
mode: "0_userdata.0.Daikin1OG.Mode",
// Lüftermodus: "A" = Auto, "Q" = Quiet
fan: "0_userdata.0.Daikin1OG.fan",
// aktuelle Raumtemperatur
actualTemp: "0_userdata.0.Daikin1OG.Raumtemperatur",
// Solltemperatur aus dem Smart Home (Ziel des Nutzers)
setTemp: "0_userdata.0.Daikin1OG.Sollwert",
// Innentemperatur des Daikin-Geräts (Sensor in der Einheit)
indoorTemp: "0_userdata.0.Daikin1OG.Innentemperatur",
// aktueller SetPoint, der an Daikin gesendet wurde
setPoint: "0_userdata.0.Daikin1OG.SollwertDaikin",
// aktuelle Leistungsanforderung (wird vom Skript überschrieben)
maxPower: "0_userdata.0.Daikin1OG.demand",
// ob DynamicControl (stufenlose Regelung) aktiv ist
dcMode: "ON"
};
// MQTT Topics der Daikin-Steuerung
// HINWEIS: KEIN mqtt.0 VORANSTELLEN!
const MQTT = {
setPoint: "command/9C139EEF6D28/temp",
fan: "command/9C139EEF6D28/fan",
demandPower: "command/9C139EEF6D28/demand"
};
// WICHTIG: Daikin akzeptiert NUR 30–100 %
const minPower = 30; // minimale Leistungsanforderung
const maxPowerLimit = 100; // maximale Leistungsanforderung
// Temperaturgrenzen der Daikin
const maxTemp = 26;
const minTemp = 18;
/************************************************************
* 2) TEMPERATUR-HISTORIE
* ----------------------------------------------------------
* Hier werden 10 Minuten Temperaturverlauf gespeichert.
* Damit erkennt die Logik Trends:
* - wird es wärmer?
* - wird es kälter?
* - wie stark / wie schnell?
*
* Das ist die Grundlage für die stufenlose Regelung.
************************************************************/
let tempHistory = [];
const defaultTemp = 18;
/**
* Speichert die aktuelle Raumtemperatur mit Timestamp.
*/
function addTemp(value) {
const ts = Date.now();
tempHistory.push({ timestamp: ts, value });
// nur die letzten 10 Minuten behalten
tempHistory = tempHistory.filter(
e => e.timestamp >= ts - 10 * 60 * 1000
);
}
/**
* Berechnet Delta der Temperaturänderung über X Sekunden.
* Rückgabewert = °C pro Sekunde.
*/
function getDelta(seconds) {
const now = Date.now();
const past = tempHistory.find(e => e.timestamp <= now - seconds * 1000);
if (!past) return 0;
const last = tempHistory[tempHistory.length - 1];
return (last.value - past.value) / seconds;
}
/************************************************************
* 3) MQTT SENDEN
* ----------------------------------------------------------
* Sendet korrekt über "sendMessage2Client" an MQTT.
************************************************************/
function mqttSend(topic, payload) {
const message = String(payload);
sendTo("mqtt.0", "sendMessage2Client", {
topic,
message,
retain: false
});
log(`MQTT → ${topic}: ${message}`, "info");
}
/************************************************************
* 4) HAUPTLOGIK — alle 5 Minuten
* ----------------------------------------------------------
* Ablauf:
* 1. Werte einlesen
* 2. Temperaturverlauf analysieren
* 3. Regelungslogik berechnet SetPoint & demandPower
* 4. Werte begrenzen
* 5. Per MQTT senden
************************************************************/
schedule("0 */5 * * * *", () => {
log("Starte Temperaturregelung 1.OG");
// Wenn Gerät ausgeschaltet ist → nicht regeln
if (getState(DP.power).val !== true) {
log("Klimagerät AUS – kein MQTT senden", "info");
return;
}
/********************************************************
* 4.1 Werte aus ioBroker auslesen
********************************************************/
const mode = getState(DP.mode).val || "H";
const fan = getState(DP.fan).val || "A";
const actualTemp = parseFloat(getState(DP.actualTemp).val) || defaultTemp;
const setTemp = parseFloat(getState(DP.setTemp).val) || defaultTemp;
const indoorTemp = parseFloat(getState(DP.indoorTemp).val) || defaultTemp;
let setPoint = parseFloat(getState(DP.setPoint).val) || defaultTemp;
let demandPower = parseFloat(getState(DP.maxPower).val) || minPower;
const dcMode = DP.dcMode;
/********************************************************
* 4.2 Modus-Faktor (Vorzeichen der Regelung)
* Heizen → +1
* Kühlen → -1
********************************************************/
let modeFaktor = 1;
switch (mode) {
case "C":
case "D":
modeFaktor = -1;
break;
case "H":
case "A":
modeFaktor = 1;
break;
case "F": // Nur Lüften
log("Lüftermodus – Logik übersprungen.", "info");
return;
}
/********************************************************
* 4.3 Temperaturhistorie erweitern
********************************************************/
addTemp(actualTemp);
const deltaT05 = getDelta(300); // Änderung über 5 min
const deltaT10 = getDelta(600); // Änderung über 10 min
/********************************************************
* 4.4 Berechnung Temperaturabweichung zum Sollwert
********************************************************/
const limiter = (mode === "C" || mode === "D") ? -1 : 3;
const roomDiff = (actualTemp - setTemp) * modeFaktor;
/********************************************************
* 4.5 REGELALGORITHMUS
* ------------------------------------------------------
* Dieser Teil bestimmt:
* - neuen SetPoint der Daikin
* - Leistungsanforderung (demandPower)
*
* Der Code ist unverändert — nur Kommentare wurden
* umfangreich ergänzt.
********************************************************/
if (roomDiff >= 0) {
// Raum ist "über Soll"
if (deltaT05 >= 0.1) {
// starker Temperaturanstieg → SetPoint stärker absenken
if (setPoint > indoorTemp) setPoint = indoorTemp;
else setPoint -= Math.round(deltaT05 * 10 * modeFaktor);
} else {
// schwacher Trend
if (deltaT05 > 0 && deltaT05 < 0.1)
setPoint -= 0.5 * modeFaktor;
else
setPoint -= Math.round(deltaT05 * 10 * modeFaktor) / 2;
}
// SetPoint darf Grenzwert nicht überschreiten
if ((setPoint > indoorTemp - limiter && modeFaktor === -1) ||
(setPoint < indoorTemp - limiter && modeFaktor === 1)) {
const diff = Math.abs(setPoint - (indoorTemp - limiter));
// falls DynamicControl off oder Power am Minimum → Lüfter reduzieren
if (dcMode === "OFF" || demandPower <= minPower) {
mqttSend(MQTT.fan, "Q");
} else {
// Leistung reduzieren
demandPower -= Math.round(diff * 10);
demandPower = Math.max(minPower, demandPower);
}
setPoint = indoorTemp - limiter;
}
}
if (roomDiff >= -0.5 && roomDiff < 0) {
// knapp unter Soll (Feinregelung)
if (fan === "Q") mqttSend(MQTT.fan, "A");
if (deltaT05 > 0.1)
setPoint -= Math.round(deltaT05 * 20 * modeFaktor);
if (deltaT05 <= 0)
setPoint -= Math.round(roomDiff * 10 * modeFaktor);
if (modeFaktor === 1)
setPoint = Math.max(indoorTemp - limiter + 0.5, setPoint);
// Temperaturgrenzen beachten
if ((mode === "H" && setPoint > maxTemp) ||
((mode === "C" || mode === "D") && setPoint < minTemp)) {
demandPower = Math.min(demandPower + 5, maxPowerLimit);
setPoint = (modeFaktor === 1) ? indoorTemp : minTemp;
}
}
if (roomDiff < -0.5) {
// deutlich unter Soll → heizen/kühlen stärker
if (fan === "Q") mqttSend(MQTT.fan, "A");
if (deltaT05 < 0.1)
setPoint -= Math.round(roomDiff * 10 * modeFaktor) * 0.5;
if ((mode === "H" && setPoint > maxTemp) ||
((mode === "C" || mode === "D") && setPoint < minTemp)) {
demandPower = Math.min(maxPowerLimit, demandPower + 5);
setPoint = (modeFaktor === 1)
? indoorTemp + (maxTemp - indoorTemp) / 2
: minTemp;
}
}
/********************************************************
* 4.6 Werte begrenzen und auf 0.5°C runden
********************************************************/
setPoint = Math.min(maxTemp, Math.max(minTemp, setPoint));
setPoint = Math.round(setPoint * 2) / 2;
demandPower = Math.max(minPower, Math.min(maxPowerLimit, demandPower));
/********************************************************
* 4.7 Werte per MQTT an die Daikin senden
********************************************************/
mqttSend(MQTT.setPoint, setPoint);
mqttSend(MQTT.demandPower, demandPower);
log(`Final → SetPoint: ${setPoint}, Demand: ${demandPower}`, "info");
});
Hab den Faden mal umgetauft, nachdem es mit dem Namen Faikin wohl andernorts Probleme gab …
Sicher ist sicher, keine Frage. Aber ich denke es ging um einen kommerziellen Vertrieb auf Amazon und weniger um einen Austausch von Klimaanlagen-Kunden in einem Forum.
Korrekt. Würde jetzt auch nicht erwarten, daß Foren da belangt werden. Wenn es deswegen jetzt entsprechend Faikout Modul genannt wird, ist es denke ich nicht verkehrt auch die Titel hier entsprechend dazu konsistent zu machen.
Hast Du auch schon Erfahrungswerte über das Regelverhalten? Würde mich interessieren, in wie weit sich mein Ansatz auf andere Gegebenheiten übertragen lässt.
Hab es nur sehr rudimentär in einer Aufheizphase und in der Nähe des Sollwertes mal getestet. Sah ok aus, aber für ein Fazit noch zu früh. Da ich gerade mangels PV-Strom eher möglichst mit Verbrauch spare, habe ich noch keinen ganzen Tag getestet.
Edit: Als Eindruck und auf 1 Minute Regelzyklus reduziert.
Start bei 20,3°C Raumtemperatur (Dunkelgrün) Sollwert 21,5°C (blau)
Econo und Vertikal Swing ist aktiv
Die Regelung fährt primär den Bedarf (hellblau) hoch und weniger stark den SetPoint der Temperatur (braun)
Ist der Sollwert erreicht, fährt erst der SetPoint der Temperatur runter dann der Bedarf.
Wie es sich Einschwingt noch zu beobachten: