Es realisiert eine Nulleinspeisung mit einem Raspberry Pi (mit direkt angeschlossenem nRF24L01+-Modul) und einem Hoymiles-Mikrowechselrichter (am Akku). Zur Hausenergiemessung wird (aktuell nur) der Shelly 3EM unterstützt.
Warum sollte ich dieses Script benutzen / was ist besser als an anderen Lösungen?
Der Hauptvorteil besteht für Personen, die bereits einen Raspberry Pi in Betrieb haben und keine weitere Hardware anschaffen wollen (abgesehen vom so oder so notwendigen Funkmodul). Das war ursprünglich auch meine Motivation, da ich noch einen Raspberry Pi 1B herumliegen hatte, die ersten Versuche in Kombination mit AhoyDTU nicht meinen Erwartungen entsprochen hat (zumindest zum damaligen Entwicklungsstand) und ich keinen ESP32 zur Verfügung hatte um OpenDTU zu testen.
Vor allem sehe ich einen Vorteil im Vergleich zu Lösungen, in denen mehrere Geräte benötigt werden. Der Raspberry Pi holt die Daten lokal vom Shelly 3EM per HTTP ab, verarbeitet diese und sendet das neue Limit direkt zum Wechselrichter. Kein MQTT, Hausautomatisierung, "Cloud" oder sonstige Abhängigkeiten.
Wozu die ganzen Konfigurationsparameter (und das Webinterface um die Werte temporär zu überschreiben)?
Flexibilität. Die Idee dahinter ist, dass man die Funktion an die Gegebenheiten anpassen kann:
Ist heute den ganzen Tag Sonnenschein angesagt und der Akku wird schon am Vormittag voll sein? -> Priorität auf "Strombezug vermeiden", d.h. lieber etwas zu viel einspeisen, anstatt auf dem Zähler "0" stehen zu haben.
Ist heute so ungünstiges PV-Wetter, dass der Akku so oder so nicht bis zum nächsten Morgen durchhalten wird? -> Priorität auf "Einspeisung vermeiden", d.h. vom Wechselrichter lieber etwas weniger Leistung anfordern als für die "0" benötigt würde.
Die Dokumentation auf GitHub ist aktuell noch nicht ganz vollständig. Die Grundfunktionalität ist beschrieben, es gibt aber noch ein paar versteckte Features, die man nur aus den Code-Kommentaren bzw. den Commit-Kommentaren ableiten kann. Ich werde dies bei Gelegenheit nachholen und dann auch diesen Post entsprechend anpassen.
Meine Beweggründe mich mit dem Script zu befassen, liegen darin, dass ich meine Balkonanlage über Geräte von Victron steuere (2x SmartSolar 100|30 und SmartShunt) und diese sich sehr einfach über einen RasPi mit Venus OS anbinden lassen (VE.Direct via Duppa TTL UART Adapter). Daher fand ich eine Lösung, in der ich mit demselben RasPi auch die Nulleinspeisung realisieren kann, sehr attraktiv.
Da ich jedoch meinen Stromzähler über Tasmota mit Hitchi Leskopf auslese musste ich das Script etwas anpassen. Aber jetzt funktionierts.
Um mich dem Thema etwas systematischer anzunäheren habe ich mir versch. Basis-Szenarien überlegt unter denen das System arbeiten sollte: a.0 Normalbetrieb
Battery SoC > festgelegte SoC Untergrenze AND
Panels produzieren Strom oder auch nicht
=> Der Output des Inverters passt sich, bis zum Inverter-Maximum, dem Strombedarf an a.1 Batterie voll geladen - Variante 1
Battery SoC = 100% AND
Panels power output > Strombedarf
=> Der Output des Inverters passt sich, bis zum Inverter-Maximum, dem Power Output der Panels an a.2 Batterie voll geladen - Variante 2
Battery SoC = 100% AND
Panels power output <= Strombedarf
=> Der Output des Inverters passt sich, bis zum Inverter-Maximum, dem Strombedarf an b.0 Batterie entladen - Variante 1
Battery SoC <= festgelegte SoC Untergrenze AND
Panels power output > Inverter minimum Output
=> Der Output des Inverters passt sich, bis zum Inverter-Maximum, dem Power Output der Panels an b.1 Batterie entladen - Variante 2
Battery SoC <= festgelegte SoC Untergrenze AND
Panels power output < Inverter minimum Output
=> Inverter abschalten (zunächst egal ob durch Trennung der AC/DC Seite oder per shut-down Befehl an den Inverter) c. Restart Inverter
Battery SoC > festgelegte SoC Untergrenze + Hysterese-Wert (um kurzfristiges An- und Abschalten des Inverters zu vermeiden)
Da in diesen Szenarien der Ladezustand der Batterie die führende Größe ist, würde ich vom SmartShunt den SoC Wert holen und zusätzlich von den beiden SmartSolar den Ladestrom. Erst wenn der SoC = 100% und der Ladestestrom 0A beträgt würde ich die Batterie als voll ansehen.
@eenemeenemuu habe ich deine Scripte richtig verstanden, dass sie die Szenarien a.0, a.1 und a.2 abdecken?
Welches Szenario fehlt noch? Bzw. habe ich irgendwo einen Denkfehler?
@marfeh Alle a- und b-Szenarien sind aktuell möglich, über die (bislang nicht dokumentierte) Möglichkeit die min/max-Werte des Inverters temporär zu überschreiben (die gesetzten Leistungsgrenzen, in denen der Inverter sich grundsätzlich bewegen soll, können dabei jedoch nicht unter-/überschritten werden - dies wird vom Script automatisch entsprechend angepasst).
Es funktioniert so: das Script prüft bei jedem Durchlauf (also 1x pro Sekunde) ob die Datei inverter_power_min und/oder inverter_power_max vorhanden ist und nutzt den darin vorhandenen Wert zur Bestimmung des aktuellen Minimum/Maximum; aber nur, wenn die Datei nicht älter als 60 Sekunden ist.
Für deine Szenarien bedeutet das:
a.0 nichts weiter zu tun
a.1 inverter_power_min auf die aktuelle Leistung der Module setzen
a.2 inverter_power_min löschen, einen kleinen Wert reinschreiben oder einfach nichts unternehmen, da nach 60 Sekunden der Wert ignoriert wird
b.0 inverter_power_max auf die aktuelle Leistung der Module setzen (ich persönlich ziehe hier noch 10% wegen der Wandlungsverluste ab)
Szenario c ist aktuell nicht möglich bzw. vorgesehen. Das Script geht zu jedem Zeitpunkt davon aus, dass irgendetwas nicht funktioniert haben könnte. Daher versendet es in bestimmten Abständen das Limit neu (auch wenn es sich nicht geändert hat), oder das Kommando für Ein- bzw. Ausschalten, auch wenn der Inverter "eigentlich" bereits an/aus sein müsste.
@eenemeenemuu Was ich nicht ganz verstehe, ist warum du die von außen übergebenen Werte nach 60sec. verwirfst? Du schreibst zwar
Aber was könnte bei der Ausführung des Python- oder PHP-Script nicht stimmen, dass durch das Zurücksetzen der Werte verbessert würde?
Was ich auf jeden Fall ändern würde wäre, dass die Übergabe der Werte nicht mehr über ein File erfolgt, sondern z.B. über eine Pipe mit Hilfe des Python STDIN-Objekts [sys.stdin.read()]. Da man in den meisten Sprachen auf das STDIN schreibend und lesend zugreifen kann und darüber auch problemlos einen JSON String übergeben werden kann, könnte man ohne größere Eingriffe in den Code von File auf RAM umstellen.
Wenn man es später noch etwas flexibler handhaben möchte, könnte man das Python-Script auch um eine REST-API erweitern.
Das ist eben das aktuelle Design Ich schreibe da nur Werte rein, wenn bestimmte Zustände zutreffen. Die Daten vom Akku und vom Laderegler erhalte ich jeweils drahtlos über einen ESP32 bzw. ESP8266. Sollte da mit dem Bluetooth oder WLAN irgendetwas nicht funktionieren (oder die Geräte kaputt gehen) habe ich keine aktuellen Daten mehr. Bevor ich nun aber noch irgendwelche Fehlerroutinen einbaue, habe ich mich eben dazu entschieden die Daten für einen gewissen Zeitraum als "aktuell genug" anzusehen.
Beispiel aus der Praxis, bevor ich das erneute Versenden des Limits (oder dem Befehl On/Off) implementiert hatte: Wechselrichter läuft auf Maximum und nun kommt der Befehl das Limit auf das Minimum zu senken. Aus welchen Gründen auch immer setzt der Wechselrichter das aber nicht um und läuft weiterhin auf Maximum. Am Hauszähler steht folglich ein negativer Wert, weiter als das (vermeintlich bereits eingestellte) Minimum geht das Script aber nicht herunter und somit speist der Wechselrichter fälschlicherweise fröhlich weiterhin das Maximum ein und saugt den Akku sinnlos leer.
Puh, äh, ja. So wie es aktuell ist, funktioniert es und ich kann per SSH einfach den Inhalt und Zeitstempel der Dateien prüfen oder ggf. manuell anpassen um bestimmte Zustände zu erzwingen/auszuprobieren. Wie bereits erwähnt, bin ich kein gelernter Programmierer und müsste mich hier erst einlesen - die Zeit habe ich aktuell nicht. Ich selbst werde diesbezüglich daher wohl eher nicht tätig werden, das müsste dann jemand anderes übernehmen
Gibt es auch ein Monitoring / grafische Darstellung / Protokoll der Arbeitsweise?
Soweit mir bekannt ist, kann ein HM Inverter nur alle 10s beschickt werden? Dann ist das keine Nulleinspeisung, sondern eine nachgeführte (träge) Regelung.
Es gibt aktuell nichts davon, jedoch wird im Sekundentakt auf der Standardausgabe angezeigt, was das Script gerade so gemessen und berechnet hat und ob etwas (und was) an den Wechselrichter gesendet wurde oder nicht.
Der Shelly 3EM aktualisiert "nur" im Sekundentakt die Werte, die das Script dann nutzen kann um bei Bedarf nachzusteuern. Nach meinen Erfahrungen setzen die HM-Wechselrichter das Limit innerhalb einer Sekunde um (schneller kann ich wie gesagt nicht messen, auch mit Stromzange würde ich das nicht präziser beurteilen können) und können dann direkt mit einem neuen Limit versorgt werden. In der Konfigurationsdatei kann nach Belieben eine Warteziet eingestellt werden, damit man dem Wechselrichter Zeit gibt das Limit umzusetzen und der Shelly dies auch korrekt wiedergibt. Ich persönlich regle alle 3 Sekunden (sofern es was zu regeln gibt). Es ist daher eine nachgeführte Regelung, aber ist es das zwangsläufig nicht immer (nur eben ggf. schneller, z.B. mit Klappwandlern direkt am Soyo oder Sun)?
Die angesprochenen 10 Sekunden kommen vielleicht von der Verwendung einer DTU? Bei meinen Tests mit AhoyDTU vor einem Jahr habe ich alle 5 Sekunden einen Wert vom Wechselrichter angezeigt bekommen und konnte alle 15 Sekunden ein neues Limit setzen, wenn ich mich recht erinnere.
Eine über die openDTU initiierte Leistungsregelung dauert bei mir physikalisch ca. 10-15s bis sie im HM-1500 (oder auch HM-300) wirkt.
Ich check das mit dem Shelly Pro3EM (der mit einer Beta- oder auch der aktuellen Firmware in etwa alle 1s ein Update zeigt).
Das war "damals" mit der AhoyDTU glaub ich auch schon so.
Das Update der Anzeige (openDTU WebUI) dauert dann noch mal länger ... das hat aber mit dem Abfrageintervall (bei mir 30s) zu tun. - Wie auch immer:
eine echte Nulleinspeisung gibt's ja eigentlich gar nicht.
Hier müsste in Millisekunden gemessen und geregelt werden, Phasen beachten werden. Monetär betrachtet wäre die Integrationszeit des saldierenden Zählers noch wichtig usw.
Ein Kühlschrank geht zum Start des Verdichter für wenige Sekunden auf 600, 700W, um sich dann für 10, 15min. mit vlt. 80W zu begnügen.
Physikalisch betrachtet müsste hier eine Nulleinspeisung sehr schnell agieren.
Kann ich dir nicht sagen. Den Kommunikationsteil habe ich aus einem anderen Projekt übernommen und nur die Einspeiselogik drumherum gebaut. Ich kann das selbst auch nicht testen, da ich nur die HM-Reihe einsetze.
Bin Einsteiger im Kraftwerksforum und Elektro- Laie.Verstehe aus den Beiträgen dass die Kommunikation zwischen Wechselrichter und Hausanlage viele Mängel aufweist. z.B.Bedarfe im Haushalt die unter 150 Watt liegen, können "übersehen" werden.
Gerade diese kleinen Ströme machen bei mir den Hauptanteil des Bedarfs.
Welches handelsübliche BKW soll ich denn nun nehmen im Jahr 2025?
Keine Ahnung wie du zu dieser Schlussfolgerung kommst. Meine Grundlast liegt bei ca. 50W + ca. 50W Kühlschrank (wenn er gerade aktiv ist), also zusammen deutlich unter den erwähnten 150W. Mit den Standardeinstellungen komme ich auf ca. jeweils 1 Wh/h Bezug und Einspeisung.
Es geht hier auch gar nicht um ein handelsübliches Balkonkraftwerk, denn warum sollte ich dort eine Nulleinspeisung realisieren wollen?