@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:
Edit2:
Etwas größere Zeitbereich und zwischenzeitlich 3 Minütiges Regelintervall reduziert.
Die Bedarfssteuerung ist definitiv "nachgelagert". Unschön empfinde ich, dass der Raum bei Sollwert 21,5°C bis auf 22.5°C überheizt wird und bis dahin nur schrittweise der Temperatursetpoint reduziert wird. Erst bei nahezu Setpoint = Sollwert wird auch der Bedarf reduziert. Aktuell aus meiner Sicht, kann man damit arbeiten und erzielt leichte Tendenz zum Komfort statt Sparsamer Fahrweise.
Ich werde mal zum Testen den Bedarf zu limitieren, vielleicht bei 80% und schaue mal wie sich das verhält.
Die Regelung der Bedarfsteuerung nochmal angepasst und allgemein die Anlage für den optimalen Betriebspunkt bis 60% Leistung durch den EconoModus begrenzt aber manuell abschaltbar.
Morgens zum Aufheizen noch Vertikal Swing bis zur Solltemperatur oder max 1h aktiviert.
/***************************************************
* CONFIG – Gerätekonfiguration und Datenpunkte
***************************************************/
const DP = {
power: "0_userdata.0.DaikinWohnzimmer.power", // Einschalten / Ausschalten (interner Zustand)
mode: "0_userdata.0.DaikinWohnzimmer.Mode", // Betriebsmodus: H/C/A/F
fan: "0_userdata.0.DaikinWohnzimmer.fan", // Lüftermodus (A/Q/…)
actualTemp: "alias.0.WohnzimmerEnv.ACTUAL", // Raumtemperatur
setTemp: "0_userdata.0.DaikinWohnzimmer.Sollwert",// Vom Benutzer gewünschte Temperatur
indoorTemp: "0_userdata.0.DaikinWohnzimmer.Innentemperatur", // Innentemperatur der Daikin
setPoint: "0_userdata.0.DaikinWohnzimmer.SollwertDaikin", // Interner Sollpunkt der Anlage
maxPower: "0_userdata.0.DaikinWohnzimmer.demand", // Leistungsanforderung 0–100%
econo: "0_userdata.0.DaikinWohnzimmer.econo", // ECO-Modus AN/AUS
swingv: "0_userdata.0.DaikinWohnzimmer.swingv", // Vertikaler Swing
dcMode: "ON" // Direkte Steuerung aktiv/inaktiv
};
/***************************************************
* MQTT Topics
***************************************************/
const MQTT = {
setPoint: "command/F0F5BD731830/temp", // Solltemperatur
fan: "command/F0F5BD731830/fan", // Lüftermodus
demandPower: "command/F0F5BD731830/demand", // Leistungsanforderung
econo: "command/F0F5BD731830/econo", // ECO-Modus
swingv: "command/F0F5BD731830/control", // Steuerkanal für Swing
power: "command/F0F5BD731830/control" // Steuerkanal für Power { power: true/false }
};
const mqttAdapter = "mqtt.0"; // MQTT Adapter-Instanz in ioBroker
/***************************************************
* Betriebsgrenzen
***************************************************/
const minPower = 30; // Minimale Leistungsanforderung
const maxTemp = 26; // Maximal erlaubte Temperatur
const minTemp = 18; // Minimal erlaubte Temperatur
const optimalMin = 35; // Optimale Leistungsuntergrenze
const optimalMax = 55; // Optimale Leistungsobergrenze
const optimalMaxEcono = 90;// Obergrenze im ECO-Modus
/***************************************************
* ECO-Modus-Konfiguration
***************************************************/
const econoAuto = 0; // 0 = ECO dauerhaft aktiv halten
/***************************************************
* Swing-Automatik
***************************************************/
const swingAuto = true; // Swing aktivieren bei Auto-Start
/***************************************************
* Zeitsteuerung – Start/Stopp-Zeiten pro Wochentag
***************************************************/
const scheduleConfig = {
start: ["10:00", "10:00", "08:30", "10:00", "10:00", "10:00", "10:00"], // SO–SA
stop: ["22:00", "22:00", "22:00", "22:00", "22:00", "23:00", "23:00"]
};
/***************************************************
* Temperaturverlauf zur Berechnung der Änderungsrate
***************************************************/
let tempHistory = [];
const defaultTemp = 18;
/**
* Temperaturwert in Verlauf eintragen
*/
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);
}
/**
* Temperaturänderung pro Zeitraum (Sekunden)
*/
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;
}
/***************************************************
* MQTT-Sende-Funktion
***************************************************/
function mqttSend(topic, payload) {
const message = String(payload);
sendTo(mqttAdapter, "sendMessage2Client", {
topic,
message,
retain: false
});
log(`MQTT → ${topic}: ${message}`, "info");
}
/***************************************************
* Power-Steuerung für Daikin
***************************************************/
function setPower(state) {
setState(DP.power, state, false); // internen Zustand setzen
const payload = JSON.stringify({ power: state });
mqttSend(MQTT.power, payload); // MQTT an Daikin senden
log(`MQTT POWER gesendet → ${payload}`, "info");
}
/***************************************************
* ECO-Modus sicherstellen
***************************************************/
function checkEcono() {
const econoVal = getState(DP.econo).val === true;
if (econoAuto === 0 && !econoVal) {
// ECO im System aktivieren
setState(DP.econo, true, false);
// ECO an Daikin senden
mqttSend(MQTT.econo, "1");
log("ECO-Modus dauerhaft aktiviert", "info");
}
}
/***************************************************
* Swing-Automatik
***************************************************/
let swingTimer = null;
/**
* Swing beim automatischen Start aktivieren
*/
function activateSwingAuto() {
const swingState = getState(DP.swingv).val === true;
if (!swingState) {
mqttSend(MQTT.swingv, JSON.stringify({ swingv: true }));
log("Swing aktiviert (Auto-Start)", "info");
if (swingTimer) clearTimeout(swingTimer);
swingTimer = setTimeout(deactivateSwing, 60 * 60 * 1000); // max. 1 Stunde
}
}
/**
* Swing wieder deaktivieren
*/
function deactivateSwing() {
const swingState = getState(DP.swingv).val === true;
if (swingState) {
mqttSend(MQTT.swingv, JSON.stringify({ swingv: false }));
log("Swing automatisch deaktiviert", "info");
}
swingTimer = null;
}
/***************************************************
* Zeitsteuerung: Start/Stopp (robust)
***************************************************/
let lastStart = ""; // Datum, an dem zuletzt gestartet wurde
let lastStop = ""; // Datum, an dem zuletzt gestoppt wurde
function checkSchedule() {
const now = new Date();
const weekday = now.getDay(); // 0=SO … 6=SA
const currentHM = now.toTimeString().slice(0, 5); // hh:mm
const today = now.toDateString();
const startTime = scheduleConfig.start[weekday];
const stopTime = scheduleConfig.stop[weekday];
/**************** START ****************/
if (currentHM >= startTime && lastStart !== today) {
setPower(true);
lastStart = today;
log("Automatischer Start ausgeführt", "info");
if (swingAuto) activateSwingAuto();
}
/**************** STOP ****************/
if (currentHM >= stopTime && lastStop !== today) {
setPower(false);
lastStop = today;
log("Automatischer Stopp ausgeführt", "info");
if (swingTimer) deactivateSwing();
}
}
/***************************************************
* Schedule jede Minute – prüft NUR Start/Stopp
***************************************************/
schedule("* * * * *", checkSchedule);
/***************************************************
* HAUPT-REGELLOGIK – alle 3 Minuten
***************************************************/
schedule("0 */3 * * * *", () => {
log("Starte Temperaturregelung Wohnzimmer");
// ECO prüfen
checkEcono();
// Wenn Anlage (gewollt) AUS → keine Regelung
if (getState(DP.power).val !== true) {
log("Anlage ist AUS – Regelung übersprungen", "info");
return;
}
/***************************************************
* Werte einlesen
***************************************************/
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) || 50;
const econoState = getState(DP.econo).val === true;
/***************************************************
* Modusrichtung H(+)/C(-)
***************************************************/
let modeFaktor = 1;
switch (mode) {
case "C": case "D": modeFaktor = -1; break; // Kühlen
case "H": case "A": modeFaktor = 1; break; // Heizen/Auto
case "F": // Nur Lüften → keine Regelung
log("Nur-Lüften-Modus – Regelung übersprungen", "info");
return;
}
/***************************************************
* Temperaturverlauf analysieren
***************************************************/
addTemp(actualTemp);
const deltaT05 = getDelta(300); // Veränderung in 5 Minuten
const limiter = (modeFaktor === -1 ? -1 : 3); // interne Begrenzung
const roomDiff = (actualTemp - setTemp) * modeFaktor;
/***************************************************
* REGELLOGIK – reduziert / erhöht Sollwert & Leistung
***************************************************/
/* --- Bereich: zu warm/zu kalt je nach Modus --- */
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;
}
// Hard-Limiter
if ((setPoint > indoorTemp - limiter && modeFaktor === -1) ||
(setPoint < indoorTemp - limiter && modeFaktor === 1)) {
const diff = Math.abs(setPoint - (indoorTemp - limiter));
// Fan reduzieren bei niedriger Power
if (demandPower <= minPower)
mqttSend(MQTT.fan, "Q");
else {
demandPower -= Math.round(diff * 10);
demandPower = Math.max(minPower, demandPower);
}
setPoint = indoorTemp - limiter;
}
}
/* --- Bereich: leicht daneben --- */
if (roomDiff >= -0.5 && roomDiff < 0) {
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);
// Grenzen
if ((modeFaktor === 1 && setPoint > maxTemp) ||
(modeFaktor === -1 && setPoint < minTemp)) {
demandPower = Math.min(
demandPower + 5,
econoState ? optimalMaxEcono : optimalMax
);
setPoint = (modeFaktor === 1) ? indoorTemp : minTemp;
}
}
/* --- Bereich: deutlich daneben --- */
if (roomDiff < -0.5) {
if (fan === "Q") mqttSend(MQTT.fan, "A");
if (deltaT05 < 0.1)
setPoint -= Math.round(roomDiff * 10 * modeFaktor) * 0.5;
if ((modeFaktor === 1 && setPoint > maxTemp) ||
(modeFaktor === -1 && setPoint < minTemp)) {
demandPower = Math.min(
econoState ? optimalMaxEcono : 95,
demandPower + 5
);
setPoint =
(modeFaktor === 1)
? indoorTemp + (maxTemp - indoorTemp) / 2
: minTemp;
}
}
/***************************************************
* Begrenzen & runden
***************************************************/
setPoint = Math.min(maxTemp, Math.max(minTemp, setPoint));
setPoint = Math.round(setPoint * 2) / 2; // 0.5 Schritte
demandPower = Math.max(minPower,
Math.min(econoState ? optimalMaxEcono : 95, demandPower)
);
/***************************************************
* Frühzeitige Swing-Abschaltung
***************************************************/
if (swingTimer && actualTemp >= setTemp) deactivateSwing();
/***************************************************
* MQTT AUSGABE
***************************************************/
mqttSend(MQTT.setPoint, setPoint);
mqttSend(MQTT.demandPower, demandPower);
log(`Final → SetPoint: ${setPoint}, Demand: ${demandPower}`, "info");
});
Anmerkungen, Tips, Feedback würde mich freuen.
Wurde eigentlich eine Möglichkeit gefunden, die Lüfterdrezahl des IG bewusst hochzuhalten? Aktuell ist ja selbst auf Stufe 5 alles an Leistung möglich und es läuft nicht optimal beim beheizen anderer Räume.
Heisst das, dass es die Funktion Auto -Bedarfsteuerung mit angeschlossem faikout Modul nicht gibt?
Die gibt es schon noch. Man kann sie nur nicht über das Faikout einstellen.
Die Funktion des Faikout basiert auf dem Reverseengineering des S21-Protokolls. Also wenn jemand ein Kommando findet, worüber die Auto-Bedarfssteuerung gesetzt werden kann, wird revk das sicher ratzfatz einbauen.
Gleiches gilt z.B. für den Bodenauslass bei Truhen.
Naja mit dem Boden Auslass bei den Truhen hatte ich beim Entwickler bereits probiert zu implementierten. Bisher ohne Erfolg.
Da das Wetter momentan im den Nullpunkt ist, taut das Außengerät auch mal ab. Jedes Mal beim Abtauen wird die untere Klappe geschlossen und danach wieder geöffnet. Boa ist die Sch… Klappe laut. Und das im Schlafzimmer.
Habe diese heute aus der Platine abgeklemmt. Heute Nacht der erste Versuch ohne Klappe.
Das Thema mit der Klappe gibt es nur bei der Truhe. Bei den Decken Geräten passiert am Innengerät nichts.
Wie meinst du das? Hast du das S21-Kommando dafür?
Nein, bisher ohne Erfolg. Wegen dem Abtauen bleibt für Klappe einfach immer offen. Funktioniert beim Heizen und Kühlen. So ist der Plan
Nein, das Faikout kennt den Auto Modus nicht. Ob er sich er parallel über Onecta betreiben lässt findet sich häufiger. Es gibt aber Nutzeberichte die das Faikout anstatt eines teureren Daikin WLAN Moduls gekauft haben und berichten, dass die Bedarfssteuerung überhaupt nicht nutzbar ist.
Ist aber alles Angelesen und bei meinen ATXD funktioniert beides soweit ich es getestet hab und der Auto Modus ist schon länger nicht mehr in diesem Spektrum.
Danke für die Info. Nur den letzten Satz habe ich nicht verstanden.