NEWS
Hoymiles WR mit 1600W regeln
-
Guten Abend miteinander,
ich habe folgendes Setup:
mME --> Einspeisung WR auf L1 --> ShellyEM 3 --> Verbraucher
Dieser Aufbau ist den Gegebenheiten geschuldet.
Ich schreibe meine Daten mittels des Shelly-Adapter in iobroker und mqtt mit. Die Daten des WR liefert mir eine OpenDTU - diese soll auch die neue Leistungsgrenze schreiben.
Ich habe folgenden JavaScript-Code erarbeitet:
// Datenpunkte const wrPowerDP = 'opendtu.0.1164a00f8949.ac.phase_1.power'; // Wechselrichter-Leistung const housePowerDP = 'shelly.0.SHEM-3#485519C98888#1.Total.InstantPower'; // Hausverbrauch const mqttLimitDP = 'opendtu.0.1164a00f8949.power_control.limit_nonpersistent_absolute'; // MQTT Limit-Datenpunkt const producingDP = 'opendtu.0.1164a00f8949.producing'; // Producing Status // Konfiguration const thresholdWR = 800; // Mindestleistung des Wechselrichters in Watt const thresholdDifferenceMin = 400; // Mindestdifferenz für das Setzen eines Limits const thresholdDifferenceMax = 50; // Maximale Differenz, um das Limit zu erhöhen const maxWRPower = 1600; // Maximale zulässige Leistung des WR const changeThreshold = 10; // Schwellenwert für signifikante Limitänderung (in Watt) // Initialisiere Zähler-Datenpunkte für Prüfungen und Limitänderungen if (!existsState('0_userdata.0.solar.check_counter')) { createState('0_userdata.0.solar.check_counter', 0, { name: 'Anzahl der Prüfungen', type: 'number', unit: 'Prüfungen', read: true, write: true }); } if (!existsState('0_userdata.0.solar.change_counter')) { createState('0_userdata.0.solar.change_counter', 0, { name: 'Anzahl der Prüfungen mit Limitänderung', type: 'number', unit: 'Prüfungen', read: true, write: true }); } if (!existsState('0_userdata.0.solar.no_change_counter')) { createState('0_userdata.0.solar.no_change_counter', 0, { name: 'Anzahl der Prüfungen ohne Limitänderung', type: 'number', unit: 'Prüfungen', read: true, write: true }); } // Differenz-Datenpunkt für Grafana if (!existsState('0_userdata.0.solar.wr_haus_difference')) { createState('0_userdata.0.solar.wr_haus_difference', 0, { name: 'WR - Haus Leistung Differenz', type: 'number', unit: 'Watt', read: true, write: true }); } // Zustand für Low Power Mode if (!existsState('0_userdata.0.solar.low_power_mode')) { createState('0_userdata.0.solar.low_power_mode', false, { name: 'Low Power Mode aktiv', type: 'boolean', read: true, write: true }); } // Funktion zur Berechnung des Limits function calculateLimit(wrPower, housePower) { let limit = wrPower - thresholdDifferenceMin; if (wrPower - housePower < thresholdDifferenceMax || wrPower - housePower > thresholdDifferenceMin) { limit = housePower + thresholdDifferenceMin; } if (limit < 0) { limit = 0; } else if (limit > maxWRPower) { limit = maxWRPower; } return limit; } // Hauptfunktion zur Leistungsprüfung und Limitsteuerung function checkPower() { const wrPower = getState(wrPowerDP).val; const housePower = getState(housePowerDP).val; const powerDifference = parseFloat((wrPower - housePower).toFixed(2)); const isLowPower = getState('0_userdata.0.solar.low_power_mode').val; const currentLimit = getState(mqttLimitDP).val; // Prüfungszähler erhöhen let checkCount = getState('0_userdata.0.solar.check_counter').val + 1; setState('0_userdata.0.solar.check_counter', checkCount); // WR-Leistung unter Schwellwert → Low Power Mode if (wrPower < thresholdWR) { if (!isLowPower) { console.log('WR-Leistung unter ' + thresholdWR + ' W – Low Power Mode aktiviert'); console.log('Limit wird geändert von ' + currentLimit + ' W auf ' + maxWRPower + ' W'); setState(mqttLimitDP, maxWRPower); setState('0_userdata.0.solar.low_power_mode', true); let changeCount = getState('0_userdata.0.solar.change_counter').val + 1; setState('0_userdata.0.solar.change_counter', changeCount); } else { console.log('Low Power Mode aktiv – WR-Leistung weiter unter ' + thresholdWR + ' W'); console.log('Limit bleibt unverändert bei ' + currentLimit + ' W'); let noChangeCount = getState('0_userdata.0.solar.no_change_counter').val + 1; setState('0_userdata.0.solar.no_change_counter', noChangeCount); } } else { if (isLowPower) { console.log('WR-Leistung über ' + thresholdWR + ' W – Low Power Mode deaktiviert'); setState('0_userdata.0.solar.low_power_mode', false); } if (powerDifference >= 0) { const newLimit = calculateLimit(wrPower, housePower); if (Math.abs(currentLimit - newLimit) >= changeThreshold) { console.log('Limit wird geändert von ' + currentLimit + ' W auf ' + newLimit + ' W'); setState(mqttLimitDP, newLimit); let changeCount = getState('0_userdata.0.solar.change_counter').val + 1; setState('0_userdata.0.solar.change_counter', changeCount); } else { console.log('Limit bleibt unverändert bei ' + currentLimit + ' W – Änderung (' + Math.abs(currentLimit - newLimit) + ' W) unterhalb Schwelle (' + changeThreshold + ' W)'); let noChangeCount = getState('0_userdata.0.solar.no_change_counter').val + 1; setState('0_userdata.0.solar.no_change_counter', noChangeCount); } } else { console.log('Keine Regelung – WR-Haus Differenz negativ (' + powerDifference + ' W)'); } } setState('0_userdata.0.solar.wr_haus_difference', powerDifference); } // Sofort prüfen bei Produktionsstart on({ id: producingDP, val: true }, function () { console.log('Produktion gestartet – Starte erste Prüfung der Leistung'); checkPower(); }); // Zyklische Prüfung alle 15 Sekunden bei aktiver Produktion setInterval(function () { if (getState(producingDP).val === true) { checkPower(); } }, 60000);Ich möchte die Anzahl der Schreibvorgänge auf den WR so gering wie möglich halten, daher die eingebauten Einschränkungen.
Allerdings klappt das schreiben des neuen Limit auf den WR nicht - habe ich irgendwo einen Denkfehler?
Gruß, NobbyNobs
-
Die Logik in "calculateLimit()" ist für mich unklar.
if (wrPower - housePower < thresholdDifferenceMax || wrPower - housePower > thresholdDifferenceMin)Diese Bedingung ist irgendwie logisch nicht richtig, glaube ich. Sie trifft immer zu, wenn powerDifference außerhalb des Bereichs thresholdDifferenceMax bis thresholdDifferenceMin liegt.
Versuche das mal.
// =========================== // Konfiguration // =========================== const wrPowerDP = 'opendtu.0.1164a00f8949.ac.phase_1.power'; const housePowerDP = 'shelly.0.SHEM-3#485519C98888#1.Total.InstantPower'; const mqttLimitDP = 'opendtu.0.1164a00f8949.power_control.limit_nonpersistent_absolute'; const producingDP = 'opendtu.0.1164a00f8949.producing'; const thresholdWR = 800; const thresholdDifferenceMin = 400; const thresholdDifferenceMax = 50; const maxWRPower = 1600; const changeThreshold = 10; const debug = true; // Setze auf false, um Logs zu deaktivieren // =========================== // Datenpunkt-Initialisierung // =========================== const statesToInit = [ { id: '0_userdata.0.solar.check_counter', default: 0, name: 'Anzahl der Prüfungen', type: 'number', unit: 'Prüfungen' }, { id: '0_userdata.0.solar.change_counter', default: 0, name: 'Anzahl der Prüfungen mit Limitänderung', type: 'number', unit: 'Prüfungen' }, { id: '0_userdata.0.solar.no_change_counter', default: 0, name: 'Anzahl der Prüfungen ohne Limitänderung', type: 'number', unit: 'Prüfungen' }, { id: '0_userdata.0.solar.wr_haus_difference', default: 0, name: 'WR - Haus Leistung Differenz', type: 'number', unit: 'Watt' }, { id: '0_userdata.0.solar.low_power_mode', default: false, name: 'Low Power Mode aktiv', type: 'boolean' } ]; statesToInit.forEach(dp => { if (!existsState(dp.id)) { createState(dp.id, dp.default, { name: dp.name, type: dp.type, unit: dp.unit, read: true, write: true }); } }); // =========================== // Limitberechnung // =========================== function calculateLimit(wrPower, housePower) { let powerDiff = wrPower - housePower; let limit; if (powerDiff >= thresholdDifferenceMax && powerDiff <= thresholdDifferenceMin) { limit = housePower + thresholdDifferenceMin; } else { limit = wrPower - thresholdDifferenceMin; } if (limit < 0) limit = 0; else if (limit > maxWRPower) limit = maxWRPower; return limit; } // =========================== // Hauptfunktion // =========================== function checkPower() { const wrPower = getState(wrPowerDP)?.val ?? 0; const housePower = getState(housePowerDP)?.val ?? 0; const powerDifference = parseFloat((wrPower - housePower).toFixed(2)); const isLowPower = getState('0_userdata.0.solar.low_power_mode')?.val ?? false; const currentLimit = getState(mqttLimitDP)?.val ?? 0; // Prüfungszähler erhöhen let checkCount = getState('0_userdata.0.solar.check_counter')?.val ?? 0; setState('0_userdata.0.solar.check_counter', ++checkCount); if (wrPower < thresholdWR) { if (!isLowPower) { if (debug) { console.log(`WR-Leistung unter ${thresholdWR} W – Low Power Mode aktiviert`); console.log(`Limit wird geändert von ${currentLimit} W auf ${maxWRPower} W`); } setState(mqttLimitDP, maxWRPower); setState('0_userdata.0.solar.low_power_mode', true); let changeCount = getState('0_userdata.0.solar.change_counter')?.val ?? 0; setState('0_userdata.0.solar.change_counter', ++changeCount); } else { if (debug) { console.log(`Low Power Mode aktiv – WR-Leistung weiter unter ${thresholdWR} W`); console.log(`Limit bleibt unverändert bei ${currentLimit} W`); } let noChangeCount = getState('0_userdata.0.solar.no_change_counter')?.val ?? 0; setState('0_userdata.0.solar.no_change_counter', ++noChangeCount); } } else { if (isLowPower) { if (debug) console.log(`WR-Leistung über ${thresholdWR} W – Low Power Mode deaktiviert`); setState('0_userdata.0.solar.low_power_mode', false); } if (powerDifference >= 0) { const newLimit = calculateLimit(wrPower, housePower); const diff = Math.abs(currentLimit - newLimit); if (diff >= changeThreshold) { if (debug) console.log(`Limit wird geändert von ${currentLimit} W auf ${newLimit} W`); setState(mqttLimitDP, newLimit); let changeCount = getState('0_userdata.0.solar.change_counter')?.val ?? 0; setState('0_userdata.0.solar.change_counter', ++changeCount); } else { if (debug) console.log(`Limit bleibt unverändert bei ${currentLimit} W – Änderung (${diff} W) unterhalb Schwelle (${changeThreshold} W)`); let noChangeCount = getState('0_userdata.0.solar.no_change_counter')?.val ?? 0; setState('0_userdata.0.solar.no_change_counter', ++noChangeCount); } } else { if (debug) console.log(`Keine Regelung – WR-Haus Differenz negativ (${powerDifference} W)`); } } setState('0_userdata.0.solar.wr_haus_difference', powerDifference); } // =========================== // Event- und Zeitsteuerung // =========================== on({ id: producingDP, val: true }, function () { if (debug) console.log('Produktion gestartet – Starte erste Prüfung der Leistung'); checkPower(); }); // Zyklische Prüfung alle 60 Sekunden setInterval(() => { if (getState(producingDP)?.val === true) { checkPower(); } }, 60000); -
Da du sowieso OPENDTU verwendest, verwende OpenDTU on Battery.
Damit kannst du den Wechselrichter nach aktuellem Strombedarf steuern.
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login