WIFFI-pump-2… die intelligente Steuerung der Zirkulationspumpe mit Heizungsüberwachung

WIFFI-pump-2… die intelligente Steuerung der Zirkulationspumpe mit Heizungsüberwachung

Die Vorgeschichte

Ich verwende meine  intelligente Steuerung für die  Trinkwasser-Zirkulationspumpe schon seit Jahren. Dafür habe ich eine Lösung mit einem Mikrocontroller Attiny entwickelt , die sehr gut als preiswerte standalone-Lösung funktioniert. Mit einem zusätzlichen Aktor mit allerdings zusätzlichen Kosten ist die Steuerung auch in die Homematic-Hausautomation integrierbar. Diese Lösung wird als Bausatz in meinem Webshop angeboten, weil sie kostengünstig und einfach ist. Zirkulationspumpensteuerung Attiny

Das neue  WIFFI_pump-2  Konzept eröffnet aber viel mehr Möglichkeiten, die über die Funktionalität der „alten“ Zirkulationspumpen-Steuerung weit hinausgehen. Mit dem WIFFI-pump-2 wird wie bisher die intelligente Steuerung der WW-Zirkulationspumpe erreicht aber mit der jetzt verfügbaren WLAN-Anbindung ist ein Datenaustausch sowohl mit der Homematic als auch mit anderen Servern  einfach möglich. Darüberhinaus  lassen sich beim WIFFI-pump-2  zwei 1wire-Temperatursensoren anschließen , um beispielsweise  die Vor- und Rücklauftemperatur zu messen und an die Homematic zu übertragen. Zusätzlich ist sogar im Hutschienengehäuse ein lichtstarkes OLED-Minidisplay optional verfügbar. So kann man zusätzlich auch die Funktion der Heizung überwachen und mit diesen Informationen mit der Homematic  geeignete Aktionen auslösen. Der WIFFI-pump-2 löst das Vorläufermodell  WIFFI-pump ab.

Grundsätzliche Aspekte

Eine Warmwasser-Zirkulation ist ein in der Hausinstallation heute oft eingesetztes Komfortmerkmal, um an allen Zapfstellen im Haus nahezu sofort nach Aufdrehen des Wasserhahnes warmes Wasser verfügbar zu haben. Dazu verwendet man eine Ringleitung, in der eine kleine sog. Zirkulationspumpe  das warme Wasser dauernd oder nur zu bestimmmten Tagesabschnitten im Kreis pumpt. Im Hinblick auf Energieeinsparung kommt schnell der Gedanke auf, durch „intelligentere“ Steuerung das System zu verbessern.

Der erste Gedanke ist meist die Verringerung des Verbrauchs von elektrischer Leistung durch die Zirkulationspumpe. In einem typischen Einfamilienhaus hat die heute meist nur 5W. Das heißt im Dauerbetrieb verbraucht diese Pumpe übers Jahr ganze 44KWh, also mit 25ct/KWH macht das etwa 11€. Allerdings wird  meist eine Schaltuhr  verwendet, die vielleicht 12h schaltet und demnach die Verbrauchskosten auf 6€/Jahr halbiert. Für 6€/Jahr lohnt sich wohl keine  „intelligentere“ Steuerung als eine einfache Schaltuhr!

Also warum denn hier was machen??
Der Grund liegt darin, dass die eigentlichen Verluste nicht elektrisch sind, sondern die erheblichen Wärmverluste der Ringleitung. Dazu habe ich Messungen gemacht, die hier auf der Webseite nachgelesen werden können:

zirkulationspumpe-warmebedarfsgerecht-geschaltet

Das Ergebnis kann man mit wenigen Kennzahlen trendmässig beschreiben:

– Elektrische Verluste  der Zirkulationspumpe:  5W   >> Jahreskosten 11€
– Wärmeverluste  der Ringleitung ohne Schwerkraftzirkulation:  60W   >>  Jahreskosten 132€    (mit einem Absperrhahn im Rücklauf wurde die natürliche Zirkulation abgeschaltet )
– Wärmeverluste der Ringleitung mit Schwerkraftzirkulation: 128W   >>  Jahreskosten 282€ !!
– Wärmeverluste der Ringleitung mit 12h/Tag laufender Zirkulationspumpe : 562W   >>  Jahreskosten 616€ !!!

Ohne jetzt das nur als „Hausnummer“  zu wertende Ergebnis weiter im Einzelnen zu diskutieren, wird eines klar:

Eine intelligente Steuerung der Zirkulationspumpe ist nicht wegen der elektrischen Energieeinsparung sinnvoll, sondern hauptsächlich wegen der damit möglichen Reduzierung der Verlustwärme !!

Das intelligentes Steuerungskonzept

Optimal ist danach, daß die Zirkulationspumpe auch nur dann läuft, wenn auch irgendwo im Haus warmes Wasser möglichst ohne Wärmeverzug gezapft werden soll. Dazu gehört erst mal eine Strategie, um den Nutzerwunsch nach warmem Wasser zu erkennen. Denkbar wäre  ein Bewegungssensor im Badezimmer oder ein  Geräuschmelder in den „Wasserräumen“. Aber oftmals geht man in diese Räume, ohne den Warmwasserhahn zu betätigen . Also doch vielleicht einen Taster in Wasserhahnnähe installieren, den man anstößt, wenn warmes Wasser benötigt wird ? Das widerspricht aber einer „intelligenten“ automatischen Bedienung!
Also vielleicht einen Sensor installieren, der den Durchfluss mißt? Zu teuer und das erfordert   einen geeigneten Sensor und einen Eingriff in die Installation… Nein, lieber nicht!

Die Lösung ist einfach und auch nicht neu: Am Vorlauf-Ausgang des Warmwasserspeichers wird einfach mit einem Temperatursensor die Temperatur gemessen. Wenn dann warmes Wasser gezapft wird, dann erhöht sich schlagartig dort die Temperatur. Diese Temperaturerhöhung wertet man mit einer Elektronik entsprechend aus und schaltet umgehend die Zirkulationspumpe ein. Diese schiebt nun das warme Wasser schnellstens in die Ringleitung, so dass bereits nach relativ kurzer Zeit  das warme Wasser an der Zapfstelle ist.  Und spätestens jetzt wird klar, daß hierfür eine Pumpe mit möglichst hoher Leistung viel besser geeignet wäre, als die heute mit Schaltuhr eingesetzten Kleinleistungs-Typen.

Abgeschaltet wird die Pumpe entweder nach 3 bis 4 Minuten ( wenn die Ringleitung gut und komplett durchspült ist) oder wenn im Rücklauf am Warmwasserspeicher die Temperatur angestiegen ist. Dazu würde allerdings noch ein zweiter Temperatursensor benötigt.

Nach mehreren Versuchen mit und ohne zweiten Temperatursensor im Rücklauf wurde die einfache Lösung mit nur einem Temperatursensor im Vorlauf praktisch umgesetzt. Die Vorteile mit einem zweiten Sensor wären nur sehr gering!

Die erste Steuerung war analog mit wenigen Bauelementen umgesetzt (siehe Link oben) und hat ein Jahr problemlos gelaufen. Allerdings hatten einige Nachbauer mit Bauteiltoleranzen der analogen Steuerung zu kämpfen, so daß der Wunsch nach einer robusteren digitalen Lösung aufkam, die zudem optional in meine Homematic-Haussteuerung gut integriert werden kann. Damit meine ich, daß die Homematic sowohl die Zirkulationspumpe einschalten kann, als auch bei selbsttätiger Einschaltung die Homematic über den Schaltzustand rückinformiert wird. (bidirektionale Einbindung).

Vielleicht wird der eine oder andere Leser die Frage stellen, warum denn nicht gleich die Zirkulationspumpe mit der Homematic steuern?
Die Antwort ist einfach, weil die aktuell verfügbaren Homematic-Temperatursensoren mit Aktualisierungsintervallen von 3 und mehr Minuten  viel zu langsam sind!

Technische Daten

Mit Verwendung des WeMos D1 mini Controllermoduls mit dem  hochintegrierten Wifi-Chip ESP8266 eröffnen sich ganz neue Möglichkeiten für die kompakte Realisierung eines Steuerungsmoduls im praktischen Hutschienengehäuse. Dabei wird nicht nur die intelligente Steuerung der Zirkulationspumpe nach oben beschriebenen Steuerungsprinzip möglich sondern zusätzlich werden mit dem Modul auch zwei sog. 1wire-Temperatursensoren abgefragt, deren Meßsignal an die Homematic-CCU übertragen und auf einem optionalen OLED-Minidisplay angezeigt wird.

Hier die wesentlichen Eigenschaften des WIFFI-pump-2:

  • schnelle Temperaturmessung am Warmwasser (WW)-Ausgang mit NTC und …
  • Einschalten der Zirkulationspumpe in Abhängigkeit von der WW-Temperaturerhöhung
  • Einschalten mit integrierter Internet-Wochenzeitschaltuhr mit 10 Schaltzeiten
  • beliebiges Einschalten der Zirkulationspumpe auch von der Homematic-CCU direkt
  • zusätzliche Messung von zwei Heizungstemperaturen mit optionalen 1wire-Sensoren (z.B. Vorlauf- und Rücklauftemperatur )
  • optionales lichtstarkes OLED-Minidisplay zur Anzeige  der Temperaturen
  • kompaktes Hutschienengehäuse nur 2TE
  • einfache Einstellung auf eigenen Webseiten mit dem Browser
  • WLAN-Kommunikation mit dem heimischen Router
  • automatische Kommunikation mit  der Homematic-CCU  oder unabhängiger Standalone-Betrieb
  • Einfaches Update über WLAN  (OTA) auch im verbauten Zustand
  • JSON-Datentelegramm abrufbar für die Integration in andere Systeme der Hausautomation

Die elektronische Schaltung

Die gesamte Schaltung konnte auf einer so kleinen Platine realisiert werden, daß sie in ein 2TE Hutschienengehäuse paßt. Auf der einen Seite werden die 5V-Spannungsversorgung (externes 5V-Netzteil mit mindestens  0,5A)  an die Schraubklemmen geschaltet. Auf der anderen Netzspannungsseite ist der Einschaltkontakt für die Zirkulationspumpe verfügbar. Die Statusanzeige erfolgt mit einer LED, die im Betrieb durch ein Schraubklemmenloch erkennbar ist. Diese LED-Anzeige benötigt man nur zum Anlernen und oder zur Funktionskontrolle.

wiffi_pump2_13

Die gesamte Verschaltung des Moduls zeigt das folgende Bild. Der NTC-Temperaturfühler mißt die WW-Auslauftemperatur und schaltet bei schnellen Temperaturerhöhungen am WW-Auslauf das Relais zum Einschalten der Zirkulationspumpe. Danach bleibt die Zirkulationspumpe für etwa 4min eingeschaltet, damit das warme Wasser in der WW-Zirkulationsleitung verteilt wird. Die Einschaltzeit von 4min kann an die individuellen Bedürfnisse  im sog. Expertenmodus angepasst werden. Wie das geht, ist weiter unten beschrieben. Aber die gewählten 4min sind für typische Zirkulationsleitungen ein guter Wert. Darüberhinaus können wie im Bild dargestellt sog. 1wire Temperatursensoren angeschaltet werden, mit denen ohne Eichung eine recht genaue Temperaturmessung möglich ist. Ich verwende diese Sensoren für die Messung der Vorlauftemperatur im Kesselkreis und zur Messung der Vorlauftemperatur für die Fussbodenheizung (nach dem Mischer). Aber was man letztlich damit macht,  kann man flexibel nach eigenen Bedürfnissen anpassen.

Folie13

Wichtige Anmerkung zu den 1Wire-Temperatursensoren mit dem DS18B20:
Die Sensoren werden teilweise mit unterschiedlichen Farben der Anschlussdrähte geliefert. Ich kenne aktuell folgende Versionen:
– wie Bild oben :    SCHWARZ=gnd, BLAU=data, ROT=+3.3V
– oder alternativ :  GELB = gnd,  GRÜN = data, ROT = +3.3V
– oder alternativ:   SCHWARZ = gnd,   GELB = data,  ROT = +3.3V

Der Nachbau

Zum Nachbau des WIFFI-pump habe ich einen Bausatz zusammen gestellt, der auch weniger löterfahrenen Elektronikern den Nachbau möglich macht.  Beim WeMos  D1 mini Modul müssen nur die Buchsenleisten eingelötet werden. Die wenigen restlichen Bauteile lassen sich mit meiner Bauanleitung recht schnell zusammenbauen.

wiffi_pump2_8

Den Bausatz gibt es optional auch mit den zusätzlich verwendbaren  zwei  1wire-Temperatursenoren vom Typ DS18B20. Diese Sensoren sind schon fertig mit einem 1m Kabel konfektioniert, wobei der Sensor in einer Edelstahlhülse sitzt.

Darüberhinaus gibt es optional ein lichtstarkes OLED-Minidisplay, das auch nachträglich einfach hinzugefügt werden kann. Nur das Displaymodul aufstecken, die Software erkennt automatisch das Modul. Damit das auch alles sehr professionell aussieht gibt´s zum Display einen passenden Kunststoffrahmen und eine Blende im 3D-Druck für das Hutschienengehäuse dazu.

wiffi_pump2_1

Die Inbetriebnahme

Die Steuerung sollte in einem Installationsgehäuse an einem trockenen Platz in der Nähe der Heizung untergebracht sein. Leitungslängen für die Messsignale sollten möglichst nicht länger als 3m sein. Im Hinblick auf zuverlässige Funktion sind die Messleitungen aber so kurz wie möglich zu dimensionieren. Bei den Signaleitungen sollte man immer Netzleitungen und Signalleitungen getrennt verlegen. Dazu sind alle entsprechenden Sicherheitsregeln für den Umgang mit Netzspannungen unbedingt zu berücksichtigten.

Ohne entsprechende Fachkenntnisse muß die Installation unbedingt von Fachpersonal  durchgeführt werden. Siehe auch nochmal meine Warnhinweise hierzu: Warnhinweise

Anlernen und Einstellen des WIFFI-pump-2

Für die Einstellung des Moduls muß man nur zwei Taster  betätigen:

>> den Reset-Taster an der Seite des WeMos-Moduls

>>  den Prog-Taster auf der Platine

Achtung: nie den PROG-  und RESET-Taster gleichzeitig drücken, da das Modul dann in den Programmiermodus geht und u.U. die Firmware beschädigt wird.

Im Werkszustand weiß der WIFFI-pump-2 noch nicht die Zugangsdaten des heimischen WLAN. Deshalb muß man zuerst diese Zugangsdaten einprogrammieren. Dazu braucht man ein Smartphone oder besser ein Notbook mit WLAN. Und das geht so:

>> Reset-Taster kurz drücken.

>> Nach etwa 12 sec beginnt die LED im 1sec-Takt zu blinken. Damit wird signalisiert, daß ein WLAN-Hotspot gesucht wird. Da aber noch die Zugangsdaten fehlen, macht der WIFFI-pump-2 das einige Zeit so und geht dann nach längstens nach 60sec wegen Erfolglosigkeit in den Standalone-Modus (sehr kurze Blitze im 1sec-Takt).

>>Will man aber seinen WIFFI-pump-2 an den heimischen Router anlernen , dann sollte man während der 60sec-Suchphase den Prog-Taster etwa 2sec drücken. Die LED quittiert das mit einem gleichmäßigen Blinken mit etwa 2Hz. Jetzt ist der WIFFI-pump-2 dauerhaft im sog. Hotspot-Modus. Damit stellt er einen eigenen Hotspot mit dem Namen (ssid)  wiffi auf der festen IP 192.168.4.1 zur Verfügung. Mit einem Smartphone oder besser mit einem Notebook kann man im WLAN-Modus nun mit diesem Hotspot eine gesicherte Verbindung herstellen. Das Passwort (pwd) ist wiffi1234.

> Danach mit dem Browser die Webseite zur Einstellung  des WIFFI-pump-2  aufrufen. Diese Webseite hat die feste IP 192.168.4.1  Achtung, diese IP-Adresse hat nichts mit der späteren IP-Adresse  des WIFFI-pump-2 im Heimnetz zu tun! Also man ruft im Browser einfach folgende Adresse auf   192.168.4.1/?  und erhält als Antwort die Hotspot-Webseite des WIFFI:

>> Mit wenigen verfügbaren Befehlen kann der WIFFI-pump-2  nun an den eigenen Router und die CCU angelernt werden: (… und nie den Doppelpunkt am Ende des Befehls  vergessen!)

  • 192.168.4.1/?ssid:meineSSID:    setzt die SSID des Routers, die SSID muß weniger als 47 Zeichen haben und keine Sonderzeichen enthalten
  • 192.168.4.1/?pwd:meinPasswort:   setzt den Router WLAN-Netzwerkschlüssel   ( WPA2) , Restriktionen wie bei SSID
  • 192.168.4.1/?ccu:192.168.178.41:   setzt die Homematic CCU-IP, dafür muß die CCU eine feste IP haben. Einstellen im Router !!

>> Damit ist schon der WIFFI-pump-2 für das Heimnetz eingestellt und kann mit dem Reset-Taster neu gestartet werden. Wenn die Router-Zugangsdaten richtig eingegeben worden sind, dann müßte nach etwa 12 sec der Wiffi-pump-2 beginnen, sich beim Router einzuloggen (LED blinkt jede Sekunde).  Meist dauert das einige Sekunden, bis das Einloggen erfolgreich ist und die LED dies signalisiert, indem sie jede Sekunde einen Doppelblitz sendet. Jetzt ist der WIFFI-pump-2 im Heimnetz mit einer eigenen IP und dem Namen  wiffi_pump.local  registriert. Welche IP das genau ist, das kann man im Router nachsehen.

>> An dem regelmässigen LED-Blitz kann man die Verbindungssituation erkennen:

  • sehr kurze und schwache regelmässige Blitze im 1sec-Takt: keine WLAN-Verbindung, stand-alone Betrieb!
  • helle regelmässige Blitze im 1sec-Takt: WLAN-Verbindung hergestellt. Aber keine CCU-Verbindung vorhanden!
  • helle regelmässige Doppelblitze  im 1sec-Takt: WLAN und CCU-Verbindung vorhanden!
  • helle regelmässige Blitze im 0,5sec-Takt: im Hotspot-Modus

Wichtig: Die Funktion der temperaturabhängigen Steuerung der Zirkulationpumpe funktioniert völlig unabhängig davon, ob WLAN-Verbindung da ist oder nicht! Ein Stand Alone Betrieb ist immer gewärleistet, auch wenn die CCU oder die WLAN-Verbindung ausfällt!

>> Jetzt läßt sich die Webseite des WIFFI-pump-2 mit jedem beliebigen Browser anzeigen. Man gibt in die Adresszeile einfach nur die IP oder den Namen ein:
http://<ip-wiffi>   oder einfach wiffi_pump.local. Das folgende Bild zeigt das Ergebnis.

Dabei ist zu beachten, daß die Messwerte nur beim Aktualisieren der Webseite oder Bedienen des Buttons „Aktualisierung Messwerte“ auch aktuell sind; eine permanente Aktualisierung der Anzeige erfolgt wegen Minimierung des Datenverkehrs nicht!

Einstellen der CCU

Damit  die Sensordaten und die Zustandsinformationen des Wiffi-pump-2 automatisch an korrespondierende Systemvariable in der Homematic-CCU geschickt werden, müssen einerseits in der CCU entsprechende Systemvariablen festgelegt werden und andererseits müssen die individuellen Namen dieser Systemvariablen auch  im Wiffi-pump-2 gespeichert werden. Das Anlernen des WIFFI-pump-2 an die CCU erfolgt also ganz einfach, indem man in der CCU die folgenden vier  Systemvariablen definiert:

Anmerkung: ab Firmware wiffi_pump_81 kann man mit dem Befehl setvar die u.a. CCU-Systemvariablen auch automatisch auf der CCU anlegen lassen. Einfach den setvar-Link anklicken und ca. 60sec warten. Damit entfällt das folgend beschriebene manuelle Eingeben der Systemvariablen!

>> wiffi_pump_ip  vom Typ Zeichenkette

>> wiffi_pump  vom Typ Logikwert , Werte EIN und AUS

>> wiffi_ww_temp  vom Typ Zahl, Maßeinheit °C    ( Anmerkung: ich verwende diesen Sensor zur Messung der Temperatur im WW-Speicher; kann natürlich individuell geändert werden! )

>> wiffi_vorlauftemp  vom Typ Zahl, Maßeinheit°C  ( Anmerkung: ich verwende diesen Sensor zur Messung derVorlauftemperatur der Heizung; kann natürlich individuell geändert werden! )

>> wiffi_ntc  vom Typ Zahl, Maßeinheit°C  ( Anmerkung:diese Systemvariable ist nur optional und wird nur in der CCU aktualisiert, wenn param 9 auf 1 steht! )

Eine funktionierende Kommunikation zwischen dem Wiffi-pump und der CCU erfordert absolut  gleiche Benamung der Systemvariablen in der CCU und im Wiffi-pump!

Wenn notwendig kann man mit dem name-Befehl  die HM-Systemvariablen auch mit eigenen Namen versehen . Standardmässig sind die oben im Bild gezeigten Systemvariablen benannt worden. Im ersten Schritt sollte man möglichst die von mir verwendeten Namen verwenden und kann dann die Erläuterung der nächsten 4 Befehle einfach überspringen !

  • 192.168.4.1/?name:o:meine_wiffi_ip:   setzt den individuellen Namenskürzel für die  entsprechenden HM-Systemvariable, welche die IP-Adresse dese Wiffi-pump enthält.
  • 192.168.4.1/?name:1:zustand_Pumpe:   setzt den individuellen Namenskürzel für die  entsprechenden HM-Systemvariable, welche den Schaltzustand der Zirkulationspumpe enthält.
  • 192.168.4.1/?name:2:meine_Temp_A:   setzt den individuellen Namenskürzel für die  entsprechenden HM-Systemvariablen, welche die Temperatur des 1Wire-Sensors an D12 /A enthält.
  • 192.168.4.1/?name:3:meine_Temp_B:   setzt den individuellen Namenskürzel für die  entsprechenden HM-Systemvariablen, welche die Temperatur des 1Wire-Sensors an D13 /B enthält.
  • 192.168.4.1/?name:3:meine_Temp_NTC   setzt den individuellen Namenskürzel für die  entsprechenden HM-Systemvariablen, welche die Temperatur des NTC-Sensors enthält.

Und bei der Homematic immer beachten, daß für die Namen der Systemvariablen nie Sonderzeichen außer dem Tiefstrich verwendet werden. Das gibt nur Ärger !!

Firewall-Einstellungen:
Zum Anlernen an die CCU müssen vorher die Firewall-Einstellungen der CCU richtig eingestellt werden:

  • Bei der CCU2 stellt man alles auf Vollzugriff.
  • Bei der CCU3 und bei der RaspberryMatic reichen folgende Einstellungen:

… und kein Häkchen bei Authentifizierung!

Das Modul holt sich die Zeit aus dem Internet von den gängigen Zeitservern. Standardmässig ist pool.ntp.org  als ntp-Zeitserver voreingestellt. Wegen der tageszeitabhängig manchmal schlechten Verfügbarkeit dieser Server wird empfohlen, den Zeitserver z.B. in der Fritzbox (mit der Adresse der Fritzbox)  zu verwenden. Vorher muss diese Funktion allerdings in der Fritzbox freigeschaltet werden:

>>Heimnetz > Netzwerk > Netzwerkeinstellungen > Zeitsynchronisation

Die Befehle des WIFFI-pump-2

Im WIFFI-pump-2 sind eine Reihe von Befehlen integriert, mit denen der WIFFI nach den eigenen individuellene Bedürfnissen eingestellt werden kann (… aber nicht muß!). Dazu sind 3 Webseiten vorhanden, die durch Anklicken der blauen Schrift-Buttons aufgerufen werden. Die Seite Normalmodus  zeigt die Messwerte , alle relevanten Statusinformationen und die möglichen Browser-Befehle.  Mit Anklicken des EIN/AUS-Buttons kann man die Zirkulationspumpe manuell dauerhaft schalten und mit Aktualisierung der Messwerte werden die Messwerte erneut ermittelt.

Folgende Befehle können aktuell per Browsereingabe verwendet werden (Achtung nie den abschließenden Doppelpunkt vergessen !) .

Einige Erklärungen sind noch für den setip-Befehl notwendig. Damit kann man die Vergabe der IP-Adresse regeln. Standardmässig  ist DHCP eingestellt, wobei der Router dem Modul eine IP-Adresse zuteilt.  Wenn man dem Modul aber eine bestimmte IP zuteilen möchte, dann kann das mit dem setip-Befehl folgendermaßen geschehen:

setip:192.168.178.61: >>setzt die IP 192.168.178.61 und DNS ist 192.168.178.1 und Gateway ist 192.168.178.1 und Subnet ist 255.255.255.0

setip:192.168.178.61:3:5: >>setzt die IP 192.168.178.61 und DNS ist 192.168.178.3 und Gateway ist 192.168.178.5 und Subnet ist 255.255.255.0

setip: >> setzt zurück auf DHCP bzw der Standardeinstellung

Wichtig: nach jeder neuen IP-Festlegung muß der WeMos hardwareseitig resettet werden. Dazu entweder den seitlichen Taster am WeMos-Modul tasten oder die Versorgungsspannung einige Sekunden unterbrechen.

Die IP-Einstellungen bleiben auch bei Komplett-Updates erhalten. Lediglich beim Werksreset wird auf die Grundeinstellung DHC zurückgesetzt.

Die Internet-Schaltuhr

Seht praktisch ist eine integrierte Schaltuhr mit 10 Schaltzeiten, die sich automatisch mit der aktuellen Internetzeit setzt. Die Schaltuhr kann hilfreich sein, wenn man beispielsweise in der Heizung feste Zeiten für die Desinfektion eingestellt hat. An diesen festen Zeiten kann man dann automatisch auch die Zirkulationspumpe einschalten. Zwar könnte man das auch über die Homematic machen, aber das Gerät soll auch ohne Homematic komfortabel funktionieren. Die Anwendungsmöglichkeiten einer integrierten Schaltuhr sind sicher vielfältig und müssen nicht näher erläutert werden.

Mit der Webseite „Schaltzeiten“ können insgesamt 10 Schaltsequenzen gesetzt werden. Das folgende Bild zeigt die Einstellseite:

Gesetzt werden die Schaltzeiten mit dem time-befehl in der Adresszeile des Browsers. Will man beispielsweise mit der Schaltzeit 1 die Zirkulationspumpe am Samstag (Wochentag 7) um 7h15 bis 8h15 einschalten, dann erfolgt dies mit dem Befehl in der Adresszeile des Browsers::

<ip-wiffi>/?time:1:7:0715:0815:

Weitere Erklärungen ergeben sich sicher aus dem obigen Bild der Webseite.

Der Experten-Modus

Als dritte Webseite ist der Expertenmodus vorhanden. Normalerweise sind hier keine Veränderungen durchzuführen. Und man sollte dies auch nur dann tun, wenn man weiß was man da einstellt. Ansonsten kann das Gerät u.U. danach nicht mehr funktionieren. Veränderungen von Kennwerten sind mit dem param-Befehl möglich. Wenn man beispielsweise die Laufzeit der Zirkulationspumpe von den eingestellten 240sec auf 300sec vornehmen will, dann macht man das mit dem Befehl:  <IP-wiffi>/?param:7:300:

Update der Firmware über WLAN

Ein Update des WIFFI erfolgt ohne Demontage bzw. Geräteöffnung komplett über das WLAN. Dabei ist der WIFFI im Heimnetz über WLAN eingeloggt und seine Webseite ist mit der vom Router vergebenen IP-Adresse aufrufbar. Hier ist für die ersten Versionen die genaue Beschreibung der Vorgehensweise als pdf-Dokument zum Runterladen :  wiffi_update_anleitung22

Ab der Firmwareversion wiffi_pump2_60a  ist das Update deutlich einfacher über die eigene Update-Webseite des WIFFI durchzuführen !
Im folgenden wird am Beispiel des WEATHERMAN das auch beim WIFFI-pump angewendete  Verfahren gezeigt:

Ein Update des WIFFI-pump kann ohne Demontage bzw. Geräteöffnung komplett über das WLAN erfolgen. Dabei ist der WIFFI-pump vorher im Heimnetz über WLAN eingeloggt und seine Webseite ist mit der vom Router vergebenen IP-Adresse aufrufbar.

Aktuelles Update Zip-Archiv von der Webseite stall.biz runterladen und den *.bin File entpacken und auf dem PC speichern. Achtung nicht das Zip-Archiv zum Update verwenden, das beschädigt u.U. den WIFFI-pump.

Die Update-Seite des WIFFI-pump aufrufen (siehe nächstes Bild). Dort werden zwei Alternativen eines Updates angeboten: das Komplett-Update nur wenn das beim Update-File ausdrücklich angemerkt ist und das normalerweise verwendete Teil-Update.


Das Teil-Update über den Link Teil-Update auslösen und mindestens 15sec warten und erst dann den Link Update-Explorer betätigen.

Nach kurzer Zeit öffnet sich der Browser mit der Möglichkeit per „Durchsuchen“ den neuen update *.bin File einzugeben und dann mit dem Update-Button den Vorgang zu starten:


Nach einigen Sekunden wird ein erfolgreiches Update bestätigt und der WIFFI-pump einige Sekunden später mit der upgedateten Firmware  neu gestartet:

.

… und hier ist die aktuelle Firmware zum Download:

Zum Update das ZIP-Archiv runterladen und entpacken. Zum Update nur die *.bin-Datei aus dem zip-Archiv verwenden. Jedes Update ist immer ein vollständiges Update, so daß man auch wieder auf alte Softwarestände zurück „updaten“ kann. Nach den Updates immer die Parameterliste überprüfen, weil die Parameter beim Update ggf. auf veränderte Standardeinstellungen gesetzt werden!

diese Versionen  werden alle mit und ohne 64×48- Display verwendet:

wiffi_pump_47 mit/ohne 64×48 Display
Ab 10/2016 wird als ein etwas breiteres OLED-Display mit 128×64 Pixel verwendet. Die dafür entsprechend geänderte Firmware ist:

wiffi_pump_53a mit/ohne 128×64 Display   >> besser einstellbarer Schaltalgorithmus (auch bei langsameren  Temperatursteigerungen) , Help-Funktion erweitert, PWD und SSID jetzt auch mit Sonderzeichen möglich

wiffi_pump_57a mit/ohne 128×64 Display  >> PWD und SSID mit Leerzeichen, verbesserte 1Wire-Temperaturmessung,Temperaturen mit Korrekturmöglichkeit, Update mit/ohne Erhalt der Zugangsdaten und Parameter, Parameter für Urlaubsabschaltung

wiffi_pump_60a mit/ohne 128×64 Display  >> vereinfachtes Update , zusätzliche Helpseite

wiffi_pump_61 mit/ohne 128×64 Display  >> verbessertes Verhalten bei WLAN-Störungen, Komplett-Update notwendig (siehe Update Menue)

wiffi_pump_66 mit/ohne 128×64 Display  >> Fix für neue CCU2-Firmware 2.27.7: 8181-Request angepasst, damit systemvariablen aktualisiert werden

wiffi_pump_69 mit/ohne 128×64 Display  >> JSON-Format angepasst, Bitte beachten: param[20] entsprechend der vorhandenen Hardwareversion setzen !

wiffi_pump_71 mit/ohne 128×64 Display  >> Die 1Wire-Eingänge können optional (param[21] einstellen!) auch als Tastereingänge verwendet werden. Taster über 330Ohm nach Ground! Die Taster schalten die Pumpe für die normale Pumpenzeit ein. Alternativ kann anstelle eines Tasters auch ein Bewegungsmelder etc. mit Open-Kollektor-Ausgang verwendet werden.

wiffi_pump_72 mit/ohne 128×64 Display  >> JSON-Telegramm korrigiert

01.11.2017 wiffi_pump_78 mit/ohne 128×64 Display  >> schnellere Browserreaktion, schnelle zyklische JSON-Komplett-Datenabfrage (>8sec) möglich (wichtig für IObroker, MQTT, etc),

30.12.2017 wiffi_pump_81 mit/ohne 128×64 Display  >>  Befehl setvar hinzugefügt: damit ist automatisches Setzen der für den WIFFI-pump relevanten CCU-Systemvariablen möglich

16.01.2018   wiffi_pump_85 mit/ohne 128×64 Display>> alternativ manuelle oder automatische  Browser-Datenaktualisierung möglich

11.03.2018   wiffi_pump_87 mit/ohne 128×64 Display >> Höhere Schaltempfindlichkeit mit Hardwareänderung: R3 jetzt 33k und  Wemos-Modul modifiziert. Siehe aktuelle Bauanleitung. Achtung: param[20] = 4 !

02.04.2018   wiffi_pump_88 mit/ohne 128×64 Display >> Watchdog integriert. Json-Ausgabe mit/ohne html-Header

Stable 07.06.2018   wiffi_pump_89 mit/ohne 128×64 Display >> Anzahl der regelmässigen Resets reduziert. „Schönheitsfehler“!

Stable 28.10.2018   wiffi_pump_90 mit/ohne 128×64 Display >> Fehler bei der Zeitumstellung korrigiert

Beta 14.07.2019   wiffi_pump_91mit/ohne 128×64 Display >> JSON-port einstellbar

Stable 23.10.2019   wiffi_pump_92 mit/ohne 128×64 Display >> DDarstellungsprobleme mit verschiedenen Browsern beseitigt

Beta-Komplett-Update 08.01.2020:  Wiffi_pump_2_96    größeres Update mit vielen Detailverbesserungen zur effektiveren Messwertübertagung an die CCU oder zum Datenserver. Dem Modul kann jetzt mit dem neuen Befehl setip eine feste IP-Adresse zugewiesen werden (Erklärung oben!). Der Update-Server startet jetzt auch mit dieser festen Adresse. Der  Schaltalgorithmus wurde verbessert und ist nun leichter an die individuellen Heizungsverhältnisse anpassbar (mit nur einem Parameter (param 1). 
Nach diesem größerem Update sollte man sicherheitshalber ein Factory-Reset (Taster 10sec  drücken) machen und den Router-Zugang im Hotspotmodus neu einrichten.. 

Beta 21.01.2020   wiffi_pump2_97 Update-Seite überarbeitet

Zum Updaten die heruntergeladenen Zip-Archive in ein temporäres Verzeichnis entpacken und zum Update nur die *.bin Datei verwenden, nicht den  Zip-File !!!

Update der Firmware über USB

Ein Update über USB ist etwas komplizierter als über WLAN. Aber wenn beispielsweise ein neues Ersatz-WeMos-Modul verwendet werden soll, dann ist  ein Update über USB die einzige Lösung.
Hier die Anleitung mit dem Tool ESP Easy Flasher:

  • ESP Easy Flasher Tool runterladen, in ein Verzeichnis ESP_Easy_Flasher-master entpacken
  • Für den WeMos den notwendigen USB-Treiber installieren: windows 32&64bit
  • USB-Kabelverbindung PC <>  WeMos Modul herstellen und ggf. im Gerätemanager unter Anschlüsse (COM & LPT) nachschauen, welcher COM-Port aktiv ist
  • Den für das Flashen notwendigen bin-File in das Unterverzeichnis ESP_Easy_Flasher-master/BIN speichern
  • Mit ESP EASY Flasher.exe das Flash-Programm jetzt starten und es ergibt sich folgendes Fenster:
  • In der obersten Zeile mit dem grünen Refresh-Button den verfügbaren com-Port einstellen
  • In der Zeile darunter den bin-File auswählen, der zuvor in das BIN-Unterverzeichnis gespeichert wurde
  • sonst nichts eingeben und jetzt nur noch den Button Flash ESP Easy FW drücken; danach blinkt die blaue LED auf dem WeMos während des Flashvorganges
  • nach weniger als 1 Minute wird ein erfolgreicher Flashvorgang mit „DONE!“ bestätigt.
  • Dann mit dem Button Open serial monitor das Ausgabefenster der seriellen Ausgabe öffnen
  • Nach dem Reset am WeMos-Modul kommt die  Meldung „In den nächsten 5 Sekunden kann mit Terminaleingabe ‚p‘ das eeprom auf Werkseinstellung gesetzt werden
  • Nun sofort p eingeben  und warten auf die Meldung, dass das eeprom gelöscht ist. Dann nochmal den Reset-Taster drücken
  • Danach das Modul in die Controllerplatine einsetzen und …
  • im Hotspot-Modus auf IP 192.168.4.1 wie oben beschrieben die eigenen Router.Zugangsdaten eingeben.

Optional: Wenn man vor dem Flashen der eigentlichen Firmware explizit das WeMos-EEPROM löschen möchte, dann flashed  man  einfach dieses Programm. Wenn das EEPROM gelöscht ist, dann blinkt die blaue LED auf dem WeMos-Modul mit ca. 2Hz.

Wer sich die Meldungen des WIFFI-pump auf dem USB-Port ansehen möchte, kann dies mit dem Hilfsprogramm putty machen. Dazu das Programm im „Serial“ Modus mit der Angabe des verwendeten com-Ports mit 115200Bd starten.

Rückstellen in den Werkszustand

Manchmal kann es notwendig sein, die im EEPROM abgelegten Zugangsdaten für den heimischen WLAN-Router zu löschen und den WIFFI-pump in den Auslieferungszustand zu versetzen. Hierfür wird durch 2 sec-Drücken des PROG-Tasters zuerst in den  Hotspot-Modus geschaltet, was durch schnelles Blinken der roten LED angezeigt wird. Danach hält man den PROG-Taster für mehr als  10 sec gedrückt, was mit einer langsam blinkenden LED bestätigt wird, die dann in Dauerleuchten übergeht.  Jetzt sind alle Nutzerdaten gelöscht und mit Druck auf den RESET-Taster kann wieder neu gestartet werden.

Achtung: nie den PROG-  und RESET-Taster gleichzeitig drücken, da das Modul dann in den Programmiermodus geht und u.U. die Firmware beschädigt wird.

Alternativ kann man das auch mit dem oben beschrieben factory-Befehl durchführen.

Schalten der Zirkulationspumpe mit der Homematic

Eigentlich braucht man die Zirkulationspumpe nicht von der CCU schalten, da sie ja vom WIFFI-pump-2 automatisch in Abhängigkeit von der Temperaturerhöhung am WW-Auslauf eingeschaltet wird.  Aber aus verschiedenen Gründen ist es dennoch sinnvoll, die Zirkulationspumpe zu bestimmten Zeiten einzuschalten. Beispielsweise wenn die Heizung zur Legionellendesinfektion zu einem bestimmten Zeitpunkt die Temperatur im WW-Speicher hochfährt, dann macht ein gleichzeitiges Spülen der Ringleitung durchaus Sinn. Oder wenn man morgens immer zu einer bestimmten Zeit duscht, dann will man nicht warten, bis nach Aufdrehen des Wasserhahnes die Zirkulationspumpe das warme Wasser erst ranbringt. In all diesen Fällen ist ein vorausschauendes zeitgesteuertes Einschalten absolut sinnvoll.

Das Einschalten erfolgt mit einem einfachen HM-Skript, das zum gewünschten Zeitpunkt die Pumpe eine bestimmte Zeit einschaltet.

HM_wiffi_prog

und hier ist das HM-Skript dazu, das in meinem Beispiel alle 15min zwischen 7h00 und 8h00 aufgerufen wird.

!hiermit wird die z_pump  für 300 sec eingeschaltet 
string befehl = "/?trigger:300:";   
string IP = dom.GetObject("wiffi_pump_ip").Value();  !Holt IP_adresse des WIFFI_wz
var send_data = "http://" + IP  + befehl; !Befehl zusammensetzen
 
WriteLine(send_data);
string stdout; string stderr;           !und Befehl ausgeben
system.Exec("wget -q -O - '"#send_data#"'", &stdout, &stderr);

Man kann auch einfach mit einem Browser dies ausprobieren, indem man folgenden Befehl eingibt:

<ip-wiffi>/?trigger:300:       Danach schaltet die Zirkulationspumpe für 300sec ein.

Natürlich kann man solch einen String auch von anderen Rechnern wie Rasberry und Co. abschicken. Somit ist der WIFFI-pump sehr zukunftssicher. Vielleicht mache ich dazu mal eine einfache App . Anregungen dazu nehme ich gerne entgegen!

Die Montage des NTC-Temperatursensors

Der Temperatursensor muß am vorlaufseitigen Ausgangsrohr des Wasserspeichers so nah angebracht werden, daß bei Zapfen von warmem Wasser möglichst schnell eine Temperaturerhöhung gemessen wird. Andererseits darf der Sensor nicht zu nah am Wasserspeicher sein, weil sonst die wasserseitige Wärmeausstrahlung das Rohr immer erwärmt. Mein Erfahrungswert für die optimale Leitungsentfernung zwischen Sensor und Speicherausgang ist  etwa 40cm bis 60cm; das hängt vom Leitungsquerschnitt und den räumlichen Gegebenheiten ab. Muß man halt etwas probieren!
Test: Wenn die Zirkulationspumpe längere Zeit nicht gelaufen ist, dann sollte der geplante Anbringungsort für den Sensor höchstens handwarm sein!
Folie8

Besonders wichtig für eine gute Funktion ist natürlich eine gut entlüftete Ringleitung. Wenn hier sich Luftblasen angesammelt haben, dann ist eine effektive Pumpfunktion nicht möglich. Besonders die Schwerkraftbremse muß einwandfrei funktionieren, damit bei abgeschalteter Zirkulationspumpe auch wirklich kein Wasser zirkuliert. Prüfen kann man das folgendermaßen:
Zirkulationspumpe stromlos machen und mindestens 2 Stunden den Kreislauf abkühlen lassen. wenn  danach der Rücklauf  kalt ist und der Vorlauf nur auf dem ersten Meter handwarm, dann ist keine natürliche Zirkulation da und die Schwerkraftbremse ist in Funktion.

Danach wird die Zirkulationspumpe eingeschaltet und die Zeit gemessen, bis das warme Wasser am Rücklauf angekommen ist. Wenn nach 2 bis 5 Minuten das warme Wasser im Rücklauf angekommen ist, dann scheint der hydraulische Pumpenkreis wohl in Ordnung zu sein!

Hinweise bei Funktionsproblemen

Ein ganz einfacher Funktionstest ist nun möglich, indem man den noch nicht montierten kalten NTC-Temperatursensor zwischen den Fingern einige Sekunden anwärmt. Dann muß sofort das Relais einschalten und nach etwa 4min die Zirkulationspumpe wieder abschalten. Wenn das so funktioniert, dann funktioniert der Wiffi-pump richtig!

Wenn es nicht funktioniert, dann sind nachfolgend einige mögliche Fehlerursachen aufgelistet:

  • Ist die Leitung für den NTC-Sensor nicht länger als 1 bis 2m und liegt möglichst nicht mit anderen Kabeln nah zusammen
  • Ist das Netzteil in Ordnung ? Oft neigen Billig-Netzteile zu Störungen.
  • Ist der NTC-Sensor an einem metallischen Rohr montiert ? Kunststoffrohre funktionieren nicht !
  • Hat der NTC-Sensor guten Wämekointakt mit dem Rohr am WW-Auslauf ?
  • Ist der Sensor auch nicht zu nah am WW-Auslauf positioniert, so daß bei  Erwärmung des WW_Speichers die Erwärmung bis in das WW-Auslaufrohr einwirkt.
  • Hat die Zirkulationspumpe eine sog. Schwerkraftbremse ? Bei modernen WW-Pumpen ist das Ventil in der Pumpe. Es gibt aber auch Rückschlagventile, um ein Zirkulation bei abgeschalteter Pumpe zu verhindern.
  • Wenn die Pumpe trotzdem zu häufig schaltet, dann kann in den Experteneinstellungen der Wert param[1] erhöht werden. Typischer Einstellbereich 4 (zu empfindlich)  bis 20 ( unempfindlich). Wenn param[11] vorhanden, dann diesen Wert nicht kleiner als param[1] einstellen.

Hier noch entsprechende Hinweise von der Help2-Seite des WIFFI-pump:

 

Daten nach FHEM schicken

Hier ist eine schöne Beschreibung, wie man die Daten zu FHEM schickt und dort auswertet:

https://homematic-forum.de/forum/viewtopic.php?f=31&t=32030&start=40#p519715

… wo gibt´s den Bausatz ?

Einen kompletten Bausatz des WIFFI-pump-2  kann man in meinem Webshop erwerben: 

Bausatz WIFFI-pump-2

 

Haftungs- und Sicherheitshinweise

Beim Nachbau müssen natürlich alle wichtigen einschlägigen Sicherheitsvorschriften für den Umgang mit gefährlichen Spannungen  eingehalten werden. Fundierte theoretische und praktische Fachkenntnisse der Elektrotechnik und für den Umgang mit gefährlichen Spannungen sind unverzichtbar!!

Durch eine unsachgemäße Installation gefährden Sie ihr Leben und das Leben ihrer Mitmenschen! Darüberhinaus riskieren Sie erhebliche Sachschäden , welche durch Brand etc. hervorgerufen werden können ! Für alle Personen- und Sachschäden durch falsche Installation etc. ist nicht der Hersteller sondern nur der Betreiber verantwortlich.

Ich verweise hier unbedingt auf  die  „Sicherheitshinweise und Haftungsausschluss„-Seite dieses Blogs. Auch die notwendigen Eingriffe in das Heizungssystem dürfen nur von ausgebildeten Fachpersonal durchgeführt werden. Es sind die geltenden Sicherheitsvorschriften und die DVGW-Richtlinien einzuhalten.

 

 

Universelles Astro/Zeit-Skript für Rolladen, Lampen …

Universelles Astro/Zeit-Skript für Rolladen, Lampen …

Im Homematic Zeitmodul fehlen eine Reihe wichtiger Zeitfunktionen wie Datumsbereiche, Monate, Wochentage und Kalenderwochen. Aber besonders die Astrofunktion ist unbefriedigend, weil man nur selten genau zum Sonnenaufgang(SA) oder Sonnenuntergang(SU) etwas schalten möchte. Meist benötigt man nämlich Schaltvorgänge vor oder nach diesem Sonnenereignis.

Um diesen Mangel „auszubügeln“ , gibt es in den einschlägigen  Foren eine Vielzahl von mehr oder weniger gelungener Hilfslösungen, die aber meist nur auf spezielle Fragestellungen abgestimmt wurden. Mit diesem universell einsetzbaren Astro/Zeitskript werden verschiedene Systemvariablen berechnet, welche die verschiedenen Zeitinformationen abbilden. Die gewählte Benamung der Systemvariablen erklären selbstredend die Funktion.

Und das geht so:

1. Folgende Systemvariablen anlegen:

Minuten_vor_SA als Zahl , Wertebereich -1000 bis +1000
Minuten_vor_SU als Zahl , Wertebereich -1000 bis +1000
Tageszeit_hh.mm als Zahl in h
Datum_MM.TT als Zahl
Monat als Werteliste Januar;Februar; …
Monatstag als Werteliste 1;2;… 31 oder als Zahl
Wochennummer als Zahl
Woche_gerade logisch wahr ist gerade , unwahr ist ungerade
Wochentag als Zahl
Jahrestag als Zahl
Jahr als Zahl

2. WebUI Programm anlegen, in dem beispielsweise alle 3min das folgende Astro/Zeit-Skript aufgerufen wird:

astro_skript1
Das Skript dazu verwendet nur eine (!) Skriptvariable, was für eine gute „Skripthygiene“ wichtig ist.

 

!Skript zur Berechnung der Minuten vor SA und SU        !  
!stall.biz  04.04.2016  Dieses Skript verwendet nur eine (!) Skript-Variable     
!folgende Systemvariablen anlegen
!Minuten_vor_SA"    als Zahl , Wertebereich  -1000 bis +1000
!Minuten_vor_SU"    als Zahl , Wertebereich  -1000 bis +1000
!"Tageszeit_hh.mm"  als Zahl  in h
!"Datum_MM.TT"    als Zahl  
!"Monat"    als Werteliste Januar;Februar;  ...  
!"Monatstag"    als Zahl oder Werteliste 1;2;...31;
!"Wochennummer"    als Zahl  
!"Woche_gerade"    logisch   wahr ist gerade , unwahr ist ungerade
!"Wochentag"    als Zahl  
!"Jahrestag" als Zahl
!"Jahr" als Zahl 
 
real c_zeit =(system.Date("%M").ToFloat()+ (60.0*system.Date("%H").ToFloat())); 
 
if (c_zeit >720.0) { dom.GetObject("Minuten_vor_SA").State(999); 
  c_zeit = system.SunsetTime("%M").ToFloat() + (60.0*system.SunsetTime("%H").ToFloat());
  c_zeit = c_zeit -  (system.Date("%M").ToFloat()+ (60.0*system.Date("%H").ToFloat()));
  dom.GetObject("Minuten_vor_SU").State(c_zeit); 
}
else {dom.GetObject("Minuten_vor_SU").State(999); 
  c_zeit = system.SunriseTime("%M").ToFloat() + (60.0*system.SunriseTime("%H").ToFloat());
  c_zeit = c_zeit - (system.Date("%M").ToFloat()+ (60.0*system.Date("%H").ToFloat()));
  dom.GetObject("Minuten_vor_SA").State(c_zeit); 
}
 
c_zeit = (1.0*system.Date("%H").ToInteger()) +(0.01*system.Date("%M").ToInteger());                      
dom.GetObject("Tageszeit_hh.mm").State(c_zeit);
 
c_zeit  = (0.01 * system.Date("%d").ToInteger()) + system.Date("%m").ToInteger();
dom.GetObject("Datum_MM.TT").State(c_zeit );
 
c_zeit   = system.Date("%Y").ToInteger();
dom.GetObject("Jahr").State(c_zeit);
 
 
c_zeit   = system.Date("%m").ToInteger();
dom.GetObject("Monat").State(c_zeit  -1);
 
c_zeit    = system.Date("%d").ToInteger();
dom.GetObject("Monatstag").State(c_zeit );
 
c_zeit =  system.Date("%V").ToInteger();
dom.GetObject("Wochennummer").State(c_zeit);
 
if ((c_zeit - 2*(c_zeit/2.0)) == 1) {dom.GetObject("Woche_gerade").State(0);} else {dom.GetObject("Woche_gerade").State(1);}
 
c_zeit = system.Date("%u").ToInteger();
dom.GetObject("Wochentag").State( c_zeit);
 
c_zeit = system.Date("%j").ToInteger();
dom.GetObject("Jahrestag").State( c_zeit);

3. Wer CuxD installiert hat, der kann den manchmal instabilen regelmäßigen Zeitaufruf des Astro/Zeit-Skripts mit einem CuxD-Timer realisieren. Wie das geht, ist an verschiedenen Stellen im Homematic-Forum bereits beschrieben, so daß hier auf eine weitere Erklärung verzichtet wird. Das Programm zum regelmässigen Aufruf des Astro/Zeit-Skriptes sieht mit einem CuxD-Timer dann so aus:

astro_skript5
Der Vorteil bei diesem Verfahren ist, daß fast die gesamten Zeitsteuerungen der WebUI-Programme nun über die neuen Astro/Zeit-Systemvariablen erfolgen kann. Und diese Systemvariablen werden nur über einen(!) viel zuverlässigeren CuxD-Timer aktualisiert. Damit wird das gesamte Zeitmanagement deutlich stabiler und zuverlässiger.

4. So wird das Astro/Zeit-Skript eingesetzt
Zum Beispiel eine Rollade so steuern, daß sie morgens 30min vor Sonnenaufgang hoch geht, aber nicht vor 6h45 und abends 45min nach Sonnenuntergang runter fährt,aber nicht später als 22h00.

Das WebUI -Programm dazu ist mit Verwendung der soeben definierten Systemvariablen ganz einfach:

astro_skript4
…und mit der Verwendung der Systemvariablen aus der Astro/Zeitsteuerung sind die WebUI-Programm viel besser lesbar, als mit dem „verkorksten“Zeitmodul!

Einige User hatten das Problem, daß bei dem obigen Programm der Rolladenaktor jedesmal „klickt“, wenn die Systemvariable Minuten_vor_SA alle 2 Minuten aktualisiert wird. Das kann man verhindern mit folgendem geänderten Programm:

rollladen_astro

 

Hier noch einige Erläuterungen zur Astrofunktion:
Da die meisten Steuerungsaufgaben sehr oft mit dem Sonnenaufgang und -untergang verknüpft ist, hat man die sog. Astrofunktion eingeführt. Diese ist aber oft unzureichend, weil man oft lieber einige Minuten vorher oder nachher den Schaltvorgang ausführen möchte. Dazu wurden in dem Astro/Zeit-Skript die zwei Systemvariablen Minuten_vor_SA und Minuten_vor_SU eingeführt. Der Wert dieser Variablen ändert sich über den Tagesverlauf entsprechend dem folgenden Bild:


Die Systemvariable Minuten_vor_SA ist nur von 00h00 bis 12h00 aktiviert und wird im zweiten Tagesabschnitt auf einen Wert von 999 gesetzt.
Bei der Systemvariablen Minuten_vor_SU ist es genau umgekehrt. Diese Definition hat Vorteile bei Anwendung in WebUI -Programmen.

Viel Spaß mit dem neuen „Zeitgefühl“

Wunderground Wetter mit einfachem HM-Skript holen

Wunderground Wetter mit einfachem HM-Skript holen

Anmerkung 04.06.2019:
Offensichtlich vergibt Wunderground keine kostenlose API-Keys mehr. Deshalb unbedingt vorher zu dem Thema die geeigneten Informationen einholen!

In einem anderen Blog wurde sehr ausführlich und gut beschrieben, wie man die Wetterdaten von wunderground.com in die Homematic bekommt.

http://homematic-forum.de/forum/viewtopic.php?f=31&t=10071&hilit=wunderground
Allerdings verwendet diese Lösung ein TCL-Skript, was insbesondere für den Anfänger nur mit Aufwand implementierbar ist und dementsprechend Fehlermöglichkeiten hat.Hier wird ein „Kochrezept“ für die Implementierung eines wunderground.com-Wetterdatenabrufes beschrieben, der nur mit einem HM-Skript arbeitet:
1  API-Key von Wunderground besorgen wie unter o.a. Link beschrieben
2  Insgesamt 14 Systemvariable entsprechend der Vorgaben im nachfolgenden Skript sorgfältig ohne Schreibfehler (!) anlegen
(schon bei einem kleinsten Schreibfehler oder fehlender Systemvariable läuft das Skript nicht durch!)
3  Im nachfolgenden Skript den API-Key in die URL-Zeile eintragen und vorher die Funktion der URL ausprobieren
(im Browser aufrufen und dann erhält man den aktuellen XML-Wetterfile im Browser angezeigt!).
4  Ein einfaches WebUI-Programm erstellen, das auf Tastendruck oder alle 30min das nachfolgende Skript aufruft.Fertig!
Hinweis: Das Skript benutzt CuxD-zum Aufruf des Wunderground-Servers. Wenn ein entsprecchendes CUxD-Gerät vorher nicht installiert wurde, dann kann man auch die in der CCU standardmässig verfügbare Abfrage mit system.Exec verwenden. Dazu im Skript die entsprecheenden CUxD-Zeilen mit Rufzeichen auskommentieren und im Gegenzug bei den  system-Exec-Zeilen die Ausrufezeichen entfernen.
.

HM-Skript   
!Stand 03.04.2014  http://homematic-forum.de/forum/viewtopic.php?f=31&t=17209
        !zuerst folgende Systemvariablen anlegen
        !Achtung: keine vergessen und exakte Schreibweise mit Drag&Drop
        !W_Station                        Zeichenkette
        !W_Aktualisierung             Zeichenkette
        !W_Bedingungen               Zeichenkette
        !W_Temperatur                  Zahl                     °C
        !W_Luftfeuchte                  Zahl                      %
        !W_Windbedingungen       Zeichenkette
        !W_Windrichtung               Zeichenkette
        !W_Windrichtg                   Zahl                       °
        !W_Windgeschwindigkeit   Zahl                     km/h
        !W_Windboeen                  Zahl                     km/h
        !W_Luftdruck                      Zahl                      mb
        !W_Luftdrucktrend             Zeichenkette
        !W_Taupunkt                      Zahl                     °C
        !W_UV                                Zeichenkette
 
        var url = "http://api.wunderground.com/api/<api-key>/conditions/lang:DL/q/Germany/Neuwied.xml";
 
        !hier ist die Abfrage mit CUxD
        dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("wget -q -O - '"#url#"'");
        dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
        string wetter_xml = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
 
        !hier ist die Abfrage mit system.Exec
        !string stdout;
        !string stderr;
        !system.Exec("wget -q -O - '"#url#"'", &stdout, &stderr);
        !WriteLine(stdout);
        !string wetter_xml = stdout;
        !WriteLine(wetter_xml);
 
        !Beim XML-File den ueberfluessigen Header entfernen
        integer laenge = wetter_xml.Length();
        integer wort_position = wetter_xml.Find("display_location");
        wetter_xml = wetter_xml.Substr(wort_position, (laenge - wort_position));
        !WriteLine(wetter_xml);
 
        !Daten mit Suchworten aus XML-File ausfiltern:
 
        !string word = "full";
        string word = "city";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        dom.GetObject("W_Station").State(daten);
 
        !string word = "observation_time";
        string word = "observation_time_rfc822";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        !daten = daten.Substr(0, (word_position -2));
        daten = daten.Substr(0, (word_position -11));
        dom.GetObject("W_Aktualisierung").State(daten);
 
        string word = "weather";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        dom.GetObject("W_Bedingungen").State(daten);
 
        string word = "temp_c";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        real zahl = daten.ToFloat();
        dom.GetObject("W_Temperatur").State(zahl);
 
        string word = "relative_humidity";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        integer zahl = daten.ToFloat();
        dom.GetObject("W_Luftfeuchte").State(zahl);
 
        string word = "wind_string";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        dom.GetObject("W_Windbedingungen").State(daten);
 
        string word = "wind_dir";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        word_laenge =daten.Length();
        string anfangsbuchstabe = daten.Substr(0,1);
        ! Umlaute korrigieren
        !
        ! N # Nord ***
        if (anfangsbuchstabe == "N") {
           !
            if (daten == "Nordwest") {daten = "Nord-West" ;}
        }
 
        ! S # Süd ***
        if (anfangsbuchstabe == "S") {
           ! 4 # Süd
           if (word_laenge == 4)  {daten = "Süd";}
           ! 8 # Südwest
           if (word_laenge == 8)  {daten = "Süd-West";}
           ! 12 # Süd-Südost
           if (word_laenge == 12) {daten = "Süd-Süd-Ost" ;}
             ! 13
           if (word_laenge == 13) {daten = "Süd-Süd-West" ;}
        }
 
        ! W # Westen
        if (anfangsbuchstabe == "W") {
           ! 13 # West-Südwest
            if (word_laenge == 13) {daten = "West-Süd-West" ;}
        }
 
        ! O # Osten
        if (anfangsbuchstabe == "O") {
           ! 11 # Ost-Südost
           if (word_laenge == 11) {daten = "Ost-Süd-Ost" ;}
        }
        dom.GetObject("W_Windrichtung").State(daten);
        !WriteLine(daten);
 
 
        string word = "wind_degrees";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        integer zahl = daten.ToFloat();
        dom.GetObject("W_Windrichtg").State(zahl);
 
        string word = "wind_kph";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        integer zahl = daten.ToFloat();
        dom.GetObject("W_Windgeschwindigkeit").State(zahl);
 
        string word = "wind_gust_kph";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        integer zahl = daten.ToFloat();
        dom.GetObject("W_Windboeen").State(zahl);
 
        string word = "pressure_mb";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        integer zahl = daten.ToFloat();
        dom.GetObject("W_Luftdruck").State(zahl);
 
        string word = "pressure_trend";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        dom.GetObject("W_Luftdrucktrend").State(daten);
 
        string word = "dewpoint_c";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        real zahl = daten.ToFloat();
        dom.GetObject("W_Taupunkt").State(zahl);
 
        string word = "UV";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        real zahl = daten.ToFloat();
        dom.GetObject("W_UV").State(zahl);

Changelog: 03.04.2014 Umlaute Himmelsrichtungen korrigiert, UV-Kennwert zugefügt.

Sonnenstandsberechnung für die intelligente Betätigung von Rolladen, Markisen und  Lampen

Sonnenstandsberechnung für die intelligente Betätigung von Rolladen, Markisen und Lampen

Update 07.04.2016: Alternatives Skript mit weniger Variablennamen

Grundlagen

Die Sonnenposition wird beschrieben mit der Sonnen_Elevation (Winkel zur Horizontalen) und dem Sonnen_Azimut (Winkel in der Horizontalen, von Norden aus gemessen wie bei der Kompassrose). Beide Grössen sind unentbehrlich für eine jahreszeitabhängige Betätigung von Rolladen für die Nacht, Rolladen für die Beschattung , Jalousien mit variablem Lamellenwinkel, Markisen und letztlich auch für die dämmerungsabhängige Beleuchtung. Professionelle Systeme zur Hausautomation stellen diese Funktion oft nur optional mit Aufpreis zur Verfügung !
Zur Sonnenstandsberechnung hatte ich bereits ein Skript erstellt, das mit mehreren linearen Interpolationsverfahren die Sonnenposition mehr oder weniger genau berechnet. http://homematic-forum.de/forum/viewtopic.php?f=31&t=17300#p140282 Theorie dazu gibt´s hier: http://de.wikipedia.org/wiki/Sonnenstand
Im Hinblick auf die weitere Verbesserung der Berechnung wird hier nun ein umfangreicheres HM-Skript beschrieben, das die Sonnenposition relativ genau für die gesamten 24h eines Tages berechnet. Durch die Verfügbarkeit brauchbarer Daten der Sonnenposition auch in der Nacht (wenn die Sonne bereits unter dem Horizont ist, Elevation negativ), können auch nachtabhängige Steuerungsaufgaben stufenlos und dämmerungsabhängig einfach gelöst werden. Zeitsprünge durch Umstellung von Sommer- auf Winterzeit entfallen durch diese Steuerungsart vollständig.

Hier das Kochrezept

1.) Sicherstellen, dass in der HM-Zeit- und Positionseinstellung auch der richtige Breitengrad des eigenen Standortes (hier hilft Google Earth !) und die richtige Zeitzoneneinstellung für Deutschland „CET/CEST (UTC +1/+2)“ eingetragen sind.
2.) Zwei Systemvariablen anlegen_
sonne_elevation mit Variablentyp Zahl von -180 bis +180 grad
sonne_azimut mit Variablentyp Zahl von-360 bis +360 grad
3.) Ein einfaches WebUI-Programm anlegen, in dem man beispielsweise all 4 Minuten das folgende Skript aufruft:

HM-Skript   
!berechg sonne_elevation, sonne_azimut; stand 14.03.2014
!Verfasser: funkleuchtturm
real phi = system.Latitude(); !Breitengrad holen
phi = 0.017453292 * phi; !umwandeln in bogenmass
!####### sin_phi und cos_phi mit taylorreihe berechnen
real temp = phi * phi;
real sin_phi =phi * ((temp * temp * 0.0083334) +1.0 - (temp * 0.1666667)); !sinus-naeherung
real cos_phi = (temp *temp *0.0416667)  + 1.0 - (temp * 0.5); !cosinus-naeherung
!### berechnung sonnenzeit, alle zeiten in minuten ########
integer zeit_min = system.Date("%M").ToInteger() + 60*system.Date("%H").ToInteger();
integer tagesbeginn_min = system.SunriseTime("%M").ToInteger() + 60*system.SunriseTime("%H").ToInteger();
integer tagesende_min = system.SunsetTime("%M").ToInteger() + 60* system.SunsetTime("%H").ToInteger();
integer sonnenzeit =zeit_min + 720 - 0.5 *(tagesbeginn_min +tagesende_min);
if (sonnenzeit > 1440) {sonnenzeit = sonnenzeit -1440;}
if (sonnenzeit < 1) {sonnenzeit = 1440 + sonnenzeit;}
boolean nachmittag =false;
if (sonnenzeit > 720) {sonnenzeit =sonnenzeit - 720; nachmittag = true; }
else {sonnenzeit =720 -sonnenzeit;}
!##### berechnung sin_tau und cos_tau ############
real tau = 0.00436332313 * sonnenzeit;   ! 15/60  * pi /180 * sonnenzeit  [0 < tau < pi ]
if (tau < 1.570796327)
{temp = tau * tau;
real sin_tau =tau * ((temp * temp *  0.0083334) +1.0 - (temp *0.1666667));
tau= 1.570796327 - tau;
temp = tau * tau;
real cos_tau =tau * ((temp * temp *  0.0083334) +1.0 - (temp * 0.1666667));}
else
{real tau1  =3.141592654 - tau;
temp = tau1 * tau1;
real sin_tau =tau1 * ((temp * temp *  0.0083334) +1.0 - (temp * 0.1666667));
tau = tau  -  1.570796327;
temp = tau * tau;
real cos_tau = (tau) *(-1.0)* ((temp * temp *  0.0083334) +1.0 - (temp * 0.1666667));}
!##### berechnung delta #######################
integer tageszahl = system.Date("%j").ToInteger();
tageszahl = tageszahl +10;
if (tageszahl > 365) {tageszahl = tageszahl - 365;}
if (tageszahl < 92) {real tag = 0.0172142 *tageszahl;temp = tag * tag;
real delta = (-0.410152) *((temp *temp *0.041666)  + 1.0 - (temp * 0.5));}
if ((tageszahl >91) && (tageszahl < 184)) {tageszahl = 183 - tageszahl; real tag = 0.0172142 *tageszahl;
temp = tag * tag;  real delta = (0.410152) *((temp *temp *0.041666)  + 1.0 - (temp * 0.5));}
if ((tageszahl >183) && (tageszahl < 275)) {tageszahl = tageszahl - 183; real tag = 0.0172142 *tageszahl;
temp = tag * tag;  real delta = (0.410152) *((temp *temp *0.041666)  + 1.0 - (temp * 0.5));}
if ((tageszahl >274) && (tageszahl < 366)) {tageszahl = 365 - tageszahl; real tag = 0.0172142 *tageszahl;
temp = tag * tag;  real delta = (-0.410152) *((temp *temp *0.041666)  + 1.0 - (temp * 0.5));}
!##### berechnung sin_delta, cos_delta  #######################
temp = delta * delta;
real sin_delta =delta * ((temp * temp *  0.0083334) +1.0 - (temp * 0.1666667)); !sinus-naeherung
real cos_delta = (temp *temp *0.0416667)  + 1.0 - (temp * 0.5); !cosinus-naeherung
!##### berechnung tan_delta  mit stueckweiser linearisierung des tan  #######################
boolean vvorzeichen = true;
if (delta< 0.0) {vvorzeichen = false; delta = (-1.0) *delta;}
real tan_delta = 1.0233 * delta;
if (delta >=0.2618) {tan_delta = (1.1822*delta) - 0.0416;}
if (vvorzeichen == false) {tan_delta = (-1.0) * tan_delta;}
!##### berechnung sin_elevation und tan_azimut #######################
real sin_elevation = (sin_phi * sin_delta) +( cos_phi * cos_delta * cos_tau);
temp = sin_elevation * sin_elevation;
real sonne_elevation = sin_elevation * (1.0 + (0.1666667 * temp) + (0.075 * temp * temp));
sonne_elevation = 57.29577951 * sonne_elevation;
real nenner = (sin_phi*cos_tau) - (cos_phi * tan_delta);
if (nenner < 0.0) {boolean plus180 = true;}
real tan_azimut = sin_tau / nenner;
!##### berechnung sonne_azimut mit stueckweiser linearisierung des arctan ############
boolean vorzeichen = true;
if (tan_azimut < 0.0) {vorzeichen = false; tan_azimut = (-1.0)*tan_azimut;}
real sonne_azimut = 0.97723 * tan_azimut;
if ((tan_azimut >=0.2679)&&(tan_azimut < 0.5774)) {sonne_azimut = (0.84588* tan_azimut) + 0.035189;}
if ((tan_azimut >= 0.5774)&&(tan_azimut < 1.0)) {sonne_azimut = (0.6195* tan_azimut) + 0.1659;}
if ((tan_azimut >= 1.0)&&(tan_azimut < 1.3032)) {sonne_azimut = (0.43173* tan_azimut) + 0.3537;}
if ((tan_azimut >= 1.3032)&&(tan_azimut < 1.7321))  {sonne_azimut = (0.3052* tan_azimut) + 0.51856;}
if ((tan_azimut >= 1.7321)&&(tan_azimut < 2.4142)) {sonne_azimut = (0.1919* tan_azimut) + 0.7148;}
if ((tan_azimut >= 2.4142)&&(tan_azimut < 2.9459)) {sonne_azimut = (0.123* tan_azimut) + 0.88115;}
if ((tan_azimut >= 2.9459)&&(tan_azimut < 3.7321)) {sonne_azimut = (0.083312* tan_azimut) + 0.9981;}
if ((tan_azimut >= 3.7321)&&(tan_azimut < 5.0))  {sonne_azimut = (0.050792* tan_azimut) + 1.1194;}
if ((tan_azimut >= 5.0)&&(tan_azimut <7.0)) {sonne_azimut = (0.02775* tan_azimut) + 1.23465;}
if ((tan_azimut >= 7.0)&&(tan_azimut <12.0)) {sonne_azimut = (0.01175117* tan_azimut) + 1.346641;}
if ((tan_azimut >= 12.0)&&(tan_azimut <20.0)) {sonne_azimut = (0.004147854* tan_azimut) + 1.437881;}
if ((tan_azimut >= 20.0)&&(tan_azimut <50.0)) {sonne_azimut = (0.0009987* tan_azimut) + 1.5008639;}
if (tan_azimut >= 50.0) {sonne_azimut = (0.000099983* tan_azimut) + 1.54579974;}
if (sonne_azimut> 1.5707963278) {sonne_azimut = 1.5707963278;}
if (vorzeichen == false) {sonne_azimut = (-1.0) * sonne_azimut;}
sonne_azimut = 57.29577951 * sonne_azimut;
if (plus180 == true) {sonne_azimut = sonne_azimut + 180.0;}
!##### tageszeitliche korrektur und werte auf systemvariablen speichern ######
if (nachmittag == false)
{sonne_azimut = 180.0 - sonne_azimut; sonnenzeit = 720 - sonnenzeit;}
else
{sonne_azimut = sonne_azimut + 180.0;sonnenzeit = 720 + sonnenzeit;}
sonne_azimut = 0.1 *((sonne_azimut*10.0) .ToInteger());
sonne_elevation = 0.1 *((sonne_elevation*10.0) .ToInteger());
dom.GetObject("sonne_elevation").State(sonne_elevation);
dom.GetObject("sonne_azimut").State(sonne_azimut);

Ein sehr einfaches beispielhaftes WebUI-Programm zum Betätigen einer Rolllade ist hier:

Mit der Systemvariablen roll_AutoManuell wird die automatische Steuerung ein- und ausgeschaltet. Diese Systemvariable  kann mit einem weiteren WebUI-Programm und z.B. einer Fernbedienung ein- und ausgeschaltet werden. Die Möglichkeiten, mit Elevation und Azimut die Rollladen und Lampen eines Haus intelligent nach Licht und Schatten zu steuern, sind sehr vielfältig. Ich verweise hier auf mein Tutorial zur Rollladensteuerung.

Ach ja, zum Vergleich kann man die Daten mit einem „genauen“ Sonnenstandsrechner vergleichen: http://www.volker-quaschning.de/datserv/sunpos/index.php
Breiten und Längengrad eingeben und Berechnungsart „SUNAE“ wählen. Die Abweichungen sind bei mir meist unter einem Grad, was bei den verwendeten Näherungsverfahren für die trigonometrischen Funktionen ganz ordentlich ist. Für die Heimautomation ist das jedenfalls mehr als genau!

 

Ergänzung 14.03.2014

Wie man an den verwendeten Zahlenkolonnen im Skript erkennt, wurde bewusst weniger auf programmiertechnische „Schönheit“ ausgelegt, sondern vielmehr wurde auf möglichst wenig Rechenoperationen und damit Laufzeit optimiert. Dies ist deshalb wichtig, weil das Skript zyklisch häufig aufgerufen wird!
Geringe Unstetigkeiten im Verlauf des Elevations- und Azimutwinkels bedingt durch die verwendeten Näherungsverfahren wurden weiter optimiert, so dass jetzt für die Heimautomation mehr als ausreichende Genauigkeit der Sonnenkoordinaten erreicht wird. Insbesondere im Bereich des Nulldurchgangs der Elevation ist ein möglichst stetiger Winkelverlauf deshalb wichtig, weil die meisten Steuerungsaufgaben im Bereich der Dämmerung erfolgen und hier ein möglichst gleichmässiger stufenloser Verlauf von grossem Vorteil ist.
Das folgende Bild zeigt sehr schön den Azimut und die Elevation, aufgezeichnet mit Historian über 24h. Diese Kurve verschieben sich täglich um einen geringen Betrag, wie man an dem geringen Sprung in der Elevationskurve um ca 00:00h erkennt:

sonnenstand1

Genauigkeit

Der Vergleich mit Winkelergebnissen der Internet-Sonnenpositionsrechner ist abhängig von dem dort verwendeten Berechnungsverfahren:
Bei dem Berechnungsverfahren SUNAE war der Unterschied bei der Elevation meist weniger als ein halbes Grad. Der Azimutwinkel hatte Abweichungen bis zu etwa 2 Grad. Letztlich ist aber nicht die Genauigkeit entscheidend, sondern dass man im Bereich des Sonnenauf- und -untergangs mit dem Elevationswinkel eine gur aufgelöste stufenlose Zahl hat, von der man Schaltvorgänge reproduzierbar abhängig machen kann. Mit dem Azimut steuert man in der Regel sowieso nur Beschattungseinrichtungen, bei denen eine Winkelgenauigkeit von 2Grad mehr als genau sind.

 

Update 07.04.2016:

Alternatives Skript mit weniger verwendeter Systemvariablen

Vermutlich kann die CCU nur eine begrenzte Zahl von Namen in Skripten stabil verarbeiten. (man spricht von 200 ?!). Deshalb wurde das Sonnenstand-Skript diesbezüglich weiter optimiert, so daß beim nachfolgenden verbesserten Skript nur noch 11 Variablen verwendet werden. Allerdings ist die Lesbarkeit das Verständnis des Programmes dabei verloren gegangen. Aber man kann sich ja dafür das erste Listing ansehen, welches die gleiche Funktion allerdings mit deutlich mehr Variablennamen hat.

!berechnung sonne_elevation, sonne_azimut; stand 07.08.2016  verfasser: eugen stall,  stall.biz
!Zwei Systemvariablen anlegen:
!sonne_elevation  mit Variablentyp Zahl von -180 bis +180 grad
!sonne_azimut mit Variablentyp Zahl von-360 bis +360 grad
!dieses skript alle 4min aufrufen 
real temp;
real sin_phi;
real cos_phi;
integer sonnenzeit;
boolean nachmittag;
real sin_tau;
real cos_tau;
real tau1;
real sin_delta;
real cos_delta;
boolean vorzeichen;
 
integer temp = system.Date("%M").ToInteger() + 60*system.Date("%H").ToInteger();
integer sonnenzeit =temp + 720 - 0.5 *((system.SunriseTime("%M").ToInteger() + 60*system.SunriseTime("%H").ToInteger()) +system.SunsetTime("%M").ToInteger() + 60* system.SunsetTime("%H").ToInteger());
if (sonnenzeit > 1440) {sonnenzeit = sonnenzeit -1440;}
if (sonnenzeit < 1) {sonnenzeit = 1440 + sonnenzeit;}
if (sonnenzeit > 720) {sonnenzeit =sonnenzeit - 720; nachmittag = true; }
   else {sonnenzeit =720 -sonnenzeit;nachmittag =false;}
temp = 0.00436332313 * sonnenzeit;   
if (temp < 1.570796327)
  {real sin_tau =temp * ((temp * temp * temp * temp *  0.0083334) +1.0 - (temp * temp *0.1666667));
   temp= 1.570796327 - temp;
   cos_tau =temp * ((temp * temp * temp * temp *  0.0083334) +1.0 - (temp * temp * 0.1666667));}                   
   else {real tau1  =3.141592654 - temp;
         sin_tau =tau1 * ((tau1 * tau1 * tau1 * tau1 *  0.0083334) +1.0 - (tau1 * tau1 * 0.1666667));
         temp = temp  -  1.570796327;
         real cos_tau = (temp) *(-1.0)* ((temp * temp * temp * temp *  0.0083334) +1.0 - (temp * temp * 0.1666667));}
temp = system.Date("%j").ToInteger() +10;
if (temp > 365) {temp = temp - 365;}
if (temp < 92) {real tag = 0.0172142 *temp;
                tau1 = (-0.410152) *((tag * tag *tag * tag *0.041666)  + 1.0 - (tag * tag * 0.5));}
if ((temp >91) && (temp < 184)) {temp = 183 - temp; real tag = 0.0172142 *temp;
                                 tau1 = (0.410152) *((tag * tag *tag * tag *0.041666)  + 1.0 - (tag * tag * 0.5));}
if ((temp >183) && (temp < 275)) {temp = temp - 183; real tag = 0.0172142 *temp;
                                  tau1 = (0.410152) *((tag * tag *tag * tag *0.041666)  + 1.0 - (tag * tag * 0.5));}
if ((temp >274) && (temp < 366)) {temp = 365 - temp; real tag = 0.0172142 *temp;
                                  tau1 = (-0.410152) *((tag * tag *tag * tag *0.041666)  + 1.0 - (tag * tag * 0.5));}
sin_delta =tau1 * ((tau1 * tau1 * tau1 * tau1 *  0.0083334) +1.0 - (tau1 * tau1 * 0.1666667)); !sinus-naeherung
cos_delta = (tau1 * tau1 * tau1 * tau1 *0.0416667)  + 1.0 - (tau1 * tau1 * 0.5); !cosinus-naeherung
if (tau1 < 0.0) {vorzeichen = false; tau1 = (-1.0) * tau1;} else {vorzeichen = true;}
temp = 0.017453292*system.Latitude(); 
sin_phi =(temp * ((temp * temp * temp * temp * 0.0083334) +1.0 - (temp * temp * 0.1666667)));
cos_phi = ((temp * temp *temp * temp *0.0416667)  + 1.0 - (temp * temp * 0.5));
temp = (sin_phi * sin_delta) +( cos_phi * cos_delta * cos_tau);
temp = temp * (1.0 + (0.1666667 * temp * temp) + (0.075 * temp * temp * temp * temp));     
temp = 57.29577951 * temp;
temp= 0.1 *((temp *10.0) .ToInteger());     
dom.GetObject("sonne_elevation").State(temp);
WriteLine(temp);
 
if (tau1 >=0.2618) {tau1 = (1.1822 * tau1) - 0.0416;}else {tau1 = 1.0233 * tau1;}
if (vorzeichen == false) {tau1 = (-1.0) * tau1;}
temp = (sin_phi*cos_tau) - (cos_phi * tau1);
if (temp < 0.0) {boolean plus180 = true;}  
temp = sin_tau / temp;
vorzeichen = true;
if (temp < 0.0) {vorzeichen = false; temp = (-1.0)*temp;}
tau1 = 0.97723 * temp;
if ((temp >= 0.2679)&&(temp < 0.5774)) {tau1 = (0.84588* temp) + 0.035189;}
if ((temp >= 0.5774)&&(temp < 1.0)) {tau1 = (0.6195* temp) + 0.1659;}
if ((temp >= 1.0)&&(temp < 1.3032)) {tau1 = (0.43173* temp) + 0.3537;}
if ((temp >= 1.3032)&&(temp < 1.7321))  {tau1 = (0.3052* temp) + 0.51856;}
if ((temp >= 1.7321)&&(temp < 2.4142)) {tau1 = (0.1919* temp) + 0.7148;}
if ((temp >= 2.4142)&&(temp < 2.9459)) {tau1 = (0.123* temp) + 0.88115;}
if ((temp >= 2.9459)&&(temp < 3.7321)) {tau1 = (0.083312* temp) + 0.9981;}
if ((temp >= 3.7321)&&(temp < 5.0))  {tau1 = (0.050792* temp) + 1.1194;}
if ((temp >= 5.0)&&(temp <7.0)) {tau1 = (0.02775* temp) + 1.23465;}
if ((temp >= 7.0)&&(temp <12.0)) {tau1 = (0.01175117*temp) + 1.346641;}
if ((temp >= 12.0)&&(temp <20.0)) {tau1 = (0.004147854* temp) + 1.437881;}
if ((temp >= 20.0)&&(temp <50.0)) {tau1 = (0.0009987*temp) + 1.5008639;}
if (temp >= 50.0) {tau1 = (0.000099983* temp) + 1.54579974;}
if (tau1> 1.5707963278) {tau1 = 1.5707963278;}
if (vorzeichen == false) {tau1 = (-1.0) * tau1;}
tau1 = 57.29577951 * tau1;
if (plus180 == true) {tau1 = tau1 + 180.0;}
if (nachmittag == false)
  {tau1 = 180.0 - tau1; sonnenzeit = 720 - sonnenzeit;}
   else {tau1 = tau1 + 180.0;sonnenzeit = 720 + sonnenzeit;}
tau1 = 0.1 *((tau1*10.0) .ToInteger());
dom.GetObject("sonne_azimut").State(tau1);
WriteLine(tau1);

Zufallsgenerator Skript für Anwesenheitssimulation, Lampen..

Zufallsgenerator Skript für Anwesenheitssimulation, Lampen..

Für die Simulation der Anwesenheit werden gerne die Lampen oder die Rolladen oder was auch immer möglichst zufällig ein und ausgeschaltet. In den meisten Programmiersprachen gibt es für die Programmierung geeignete Algorithmen sog. Randomfunktionen, die beispielsweise gleichverteilte Zahlen zwischen 0.0 und 1.0 erzeugen. Obwohl so eine Funktion für die Hausautomation eine relativ sinnvolle Funktionalität bietet, ist keinerlei Randomfunktion in der HM-Skriptsprache abgebildet. Hiermit soll diesem Mangel mit einem HM-Skript abgeholfen werden.Der gewählte Lösungsansatz ist sicher etwas ungewöhnlich, was dem doch sehr beschränkten Befehlssatz der Homemaic-Skriptsprache geschuldet ist:
In der Elektronik verwendet man gerne für die Rauscherzeugung sog. Pseudo-Rauschgeneratoren; Herzstück sind dafür mit XOR-Gattern rückgekoppelte Schieberegister. Wer mehr darüber wissen will: http://de.wikipedia.org/wiki/Linear_r%C3%BCckgekoppeltes_Schieberegister
Dieser eigentlich hardwarenahe Lösungsansatz wird im Folgenden für die softwaremässige Erzeugung von gleichverteilten Zahlen verwendet. Dahinter sind komplizierte Theorien, die aber hier nicht weiter erläutert werden. Deshalb für den reinen Anwender hier mein… Kochrezept:
1   Zwei Systemvariable „random_zahl“ und „random_tp“ vom Variablentyp Zahl anlegen, Wertebereich -2.0 bis 2.0 !
Dabei ist „random_zahl“ eine bei jedem Skriptaufruf neu berechnete Zufallszahl zwischen 0.0 und 1.0 Die Systemvariable „random_tp“ ist eine gemitteltes oder „geglättetes“ Abbild von „random_zahl“ im gleichen Wertebereich.
2   Ein WebUI-Programm anlegen, in dem zyklisch beispielsweise alle 3 Minuten folgendes HM-Skript aufgerufen wird:
HM-Skript   
!Version  2014.06.02 ;  Verfasser :Eugen Stall
!zwei Systemvariablen "random_zahl"  und "random_tp" als Zahl mit Wertebereich -2.0 bis 2.0 anlegen
!Skript speichert  Zufallszahl zwischen 0.0 und 1.0 ungefiltert auf "random_zahl und gemittelt auf "random_tp"
!##############################################
real zahl = 65536.0 * dom.GetObject("random_zahl").State();
zahl = zahl.ToInteger();
if ((zahl <1) || (zahl > 65535)) {zahl= 3757;} !um saubere Startposition sicherzustellen
integer zahl_alt = zahl;
!##############################################
string dualzahl = "";
integer xor ;
integer x;
!hier wird ein 16bit-Schieberegister mit XOR-Rückkopplungen simuliert
if (zahl > 32767) {dualzahl = dualzahl + "1"; zahl = zahl - 32768; x = 1;} else    {dualzahl = dualzahl + "0";  x = 0;}
xor = x;
if (zahl > 16383) {dualzahl = dualzahl + "1"; zahl = zahl - 16384;} else    {dualzahl = dualzahl + "0";}
if (zahl > 8191) {dualzahl = dualzahl + "1";  zahl = zahl - 8192; x = 1;} else    {dualzahl = dualzahl + "0"; x = 0;}
if ((xor + x) ==1) {xor = 1;} else {xor = 0;}
if (zahl > 4095) {dualzahl = dualzahl + "1"; zahl = zahl - 4096; x = 1;} else    {dualzahl = dualzahl + "0"; x = 0;}
if ((xor + x) ==1) {xor = 1;} else {xor = 0;}
if (zahl > 2047) {dualzahl = dualzahl + "1"; zahl = zahl - 2048 ;} else    {dualzahl = dualzahl + "0";}
if (zahl > 1023) {dualzahl = dualzahl + "1"; zahl = zahl - 1024 ; x = 1;} else    {dualzahl = dualzahl + "0"; x = 0;}
if ((xor + x) ==1) {xor = 1;} else {xor = 0;}
!niedrigstes neues bit einschieben
zahl = zahl_alt * 2;
if (zahl > 65535) {zahl = zahl - 65536;}
zahl = zahl + xor;
!auf 1 normieren und auf Systemvariable random_zahl  speichern  ############
zahl = 0.0000152590219* zahl;  !zahl / 65536
dom.GetObject("random_zahl").State(zahl);
!Mittelwertbildung : der Faktor 0.2 bestimmt die Mittelungsstärke. ###########
!Je kleiner, desto "ruhiger" das Rauschsignal  ########################
real tp_random = dom.GetObject("random_tp").State();
tp_random =  tp_random + (0.2 * (zahl - tp_random));
dom.GetObject("random_tp").State(tp_random);
tp_random = dom.GetObject("random_tp").State();
!####################################################


3  Jeweils ein WebUI-Programm für die zufällige Steuerung einer Lampe, Rollade oder was auch immer anlegen.

Hier ein Beispiel für die Zufallsteuerung einer Lampe abends zwischen 18 und 23H:

random1.jpg

Das Einschaltverhältnis (Lampe EIN zu Lampe AUS) kann man mit dem Schaltwert für „random_tp“ beliebig nach den individuellen Wünschen festlegen. Ich habe in den o.a. Beispiel einen Wert von 0.5 gewählt, was bedeutet, dass die Lampe in dem gewählten Zeitraum für etwa 50% der Zeit leuchtet.
Die Zeitdauer von Eingeschaltet und Pause hängt u.a. vom gewählten Aktualisierungsintervall des Skriptes ab. Kleine Zeiten ( 1 bis 2 Minuten) bedeutet häufiges Schalten, große Intervalle das Gegenteil.
Zur Zeit versuche ich noch die für mich geeigneten Einstellparameter zu ermitteln. Ansonsten läuft das Skript sehr schnell durch, aber trotzdem sollte man im Hinblick auf CCU-Belastung nicht zu häufig die Randomfunktion abfragen.
Viel Spass beim „zufälligen“ Steuern und Regeln

Changelog:
01.06.2014: fehlende Programmzeile im Skript ergänzt
02.06.2014: Programm verkürzt, Durchlaufzeit verbessert

Datumsbereiche oder Datumsabfragen im WebUI verwenden

Datumsbereiche oder Datumsabfragen im WebUI verwenden

Meine Teichpumpe sollte nur in einem bestimmten Datumsbereich z.B. vom 2.April bis 10.Oktober oder in einer bestimmten Jahreszeit aktiviert werden. Mit den Funktionen der Zeitsteuerung im WebUI lassen sich aber leider nur einzelne Events (einfach oder wiederholend) festlegen; eine Festlegung eines Datumsbereiches ist nach meinem Kenntnisstand damit nicht möglich.
Mit Verwendung einiger im FHZ-Forum bereits verwendeter Lösungsansätze für die Berechnung von Tageszeiten habe ich für die Aufgabe den folgenden Ansatz gewählt:
1  Definition einer Systemvariablen „Datum_MM.TT“ vom Variablentyp „Zahl“.
2  Übergabe des aktuellen Datums an die Systemvariable „Datum_MM.TT“ mit folgendem Skript, das mindestens einmal am Tag ausgelöst werden sollte:
HM-Skript   
!Skript aktuelles Datum an Systemvariable Datum_MM.TT übergeben
real datum = (0.01 * system.Date("%d").ToInteger()) + system.Date("%m").ToInteger();
dom.GetObject("Datum_MM.TT").State(datum);

3  Im WebUI den gewünschten Datumsbereich durch größer/kleiner/gleich-Abfragen realisieren, so wie im folgenden Beispiel für die Aktivierung meiner Teichpumpe:

Teichpumpe.jpg
Jede Nacht ist anders! dynamische Rolladenbetätigung

Jede Nacht ist anders! dynamische Rolladenbetätigung

Wer schon länger eine automatische Rolladenbetätigung in Abhängigkeit von Sonnenauf- / untergang betreibt, der kennt das Thema: Im Winter gehen die Rolladen viel zu früh runter und im Sommer viel zu spät. Das liegt u.a. daran, dass die Dämmerungsphase im Winter viel länger andauert und im Sommer recht kurz ist. Viele Versuche mit einer Rolladenbetätigung eine feste Zeit nach Sonnenuntergang unter Verwendung des sicher bekannten Tageszeitenskriptes zeigen, dass man zwar für eine bestimmte Jahreszeit die Rolladenschliesszeit optmieren kann, aber man muß jahreszeitabhängig immer wieder anpassen. Seit einigen Monaten fahre ich eine andere Strategie, bei der die Rolladenschliesszeit zwar von der jahreszeitlichen Sonnenuntergangszeit abgeleitet wird, diese Ableitung aber nicht additiv sondern mit einer linearen Umrechnung erfolgt. Mit dem  obigen Bild wird der Sachverhalt deutlich.

Näherungsweise übers Jahr ist die Darstellung der Sonnenuntergangszeit eine Sinuskurve mit einem Minimalwert im Dezember (SUmin) und einem Maximalwert im Juni. Ausgehend von dieser Abhängigkeit (rote Kurve) berechne ich eine gefühlt angenehmere Rolladenschliesszeit in der Weise. dass die Amplitude verkleinert und der Mittelwert vergrößert wird.(grüne Kurve). Die Berechnungsgrundlagen für die Umrechnung sind unten im Bild dargestellt. Vorgegeben aufgrund meiner individuellen Ortslage (Nähe Bonn) sind die Zeiten für SUmax und SUmin (in Winterzeit !) . Bei mir ist SUmax = 1250 (in min entsprechend 20h50) und SUmin = 990 (in min entsprechend 8h30). Die gewünschte Zielkurve wir nur duch die beiden Parameter ROLLmax und ROLLmin festgelegt. Ich habe hier für die grüne kurve ROLLmax = 1320 und ROLLmin = 1170 gewählt. Daraus ergibt sich dann eine einfache Berechnungsformel für die tägliche Rolladenschließzeit ROLL = 0.58 * SU +595 .
Wenn nun die Rolladen zu dieser Zeit geschlossen werden sollen und beispielsweise zu einer festen Zeit am morgen wieder geöffnet werden sollen, dann sieht die WebUI-Umsetzung mit integriertem Skript etwa so aus:
Zuerst definiert man zwei neue Systemvariable „rolladenzeit“ als Zahl und „rolladengeschlossen“ als log. Variable.
Dann ruft man mit einem WebUI-Programm zyklisch alle paar Minuten das folgende Skript auf, das die Systemvariable „rolladengeschlossen“ entsprechend der grünen Kurve abends auf 1 setzt und morgens um 6h45 wieder auf 0 zurücksetzt. Damit man die aktuelle Rolladenschliesszeit sich ansehen kann, wird die Systemvariable „rolladenzeit“ im Skript ebenfalls berechnet.

 

HM-Skript   
!Skript setzt die logische Systemvariable "rolladengeschlossen"  auf true, wenn Rolladen runter
 
!Rolladen-Schliesszeit ROLL berechnet sich aus der aktuellen Sonnenuntergangszeit SU
!Zeitberechnung immer im Minutenschema!aktuellen Sonnenaufgang berechnen
integer SU = system.SunsetTime("%M").ToInteger() + 60* system.SunsetTime("%H").ToInteger();
integer zeit = system.Date("%M").ToInteger() + 60*system.Date("%H").ToInteger();
 
!Systemvariable "rolladengeschlossen" abends auf 1 und morgens um 6h45 auf 0 setzen
boolean rolladennacht =0;
real ROLL = 595.0 + 0.58* SU;
if (zeit < 405)   {rolladennacht = 1;} !Zwischen 0h00 und 6h45 ist rolladennacht = 1
!405 entspricht der Minutenzeit von 6h45, >> Berechnung: (6 * 60) +45 = 405
if (zeit > ROLL)  {rolladennacht = 1;} ! zwischen ROLL und 24h00 ist rolladennacht = 1
dom.GetObject("rolladengeschlossen").State(rolladennacht);
 
!Umformen von der Minutendarstellung von ROLL in Stundendarstellung hh,mm
!und abspeichern auf Systemvariable "rolladenzeit"
real su_zeit = 0.0166 *ROLL;
real su_zeit_h = su_zeit.ToInteger();
real su_zeit_m = (su_zeit - su_zeit_h) *0.6;
real su_zeit= su_zeit_m + su_zeit_h;
dom.GetObject("rolladenzeit").State(su_zeit);

Das eigentliche Rolladenprogramm sieht dann beispielhaft so aus:

dyn_rolladen1

Aktuell steuere ich insgesamt 14 Rolläden im Nachtbetrieb mit der beschriebenen Strategie.Mit dem Schliessverhalten bin ich jetzt sehr zufrieden, weil keine jahreszeitlichen Anpassungen mehr notwendig sind. Im Tagbetrieb wird abhängig vom Sonnenstand, der Sonneneinstrahlung individuell jedes Fenster gesteuert, aber das ist ein anderes Thema.

Sonnenstandsberechnung für die intelligente Betätigung von Rolladen, Markisen und  Lampen

HM-Skript zur einfachen Sonnenstandsberechnung

Wenn ich hier von Sonnenstand spreche, dann meine ich die Position der Sonne mit den Kennzeichen Azimut und Elevation.
Der Azimut ist der Winkel des Sonnenstandes in der Horizontalen: wie bei der Kompassrose ist 0° gleich NORD, 90°gleich OST, 180° gleich SUED und 170°gleich WEST.
Die Elevation ist der Winkel des Sonnenstandes in der Vertikalen: 0° ist der Horizont, 90° ist der „Himmel ganz oben“.
Mit diesen beiden Größen kann man sehr gut feststellen, ob und wann die Sonne bestimmte Elemente „besonnt“ und ggf. ob mit der Homematic bestimmte Aktionen auszulösen sind. Aktionen können das Herunterlassen der Rolladen sein, das Ausfahren der Markisen, das Öffnen von Lüftungsfenstern, das Steuern der Lage von Sonnenkollektoren oder einfach das Schalten von Umwälzpumpen bei thermischen Sonnenkollektoren. Schliesslich kann man sogar mit der Information des Elevationswinkels dämmerungsabhängig bestimmte Aktionen auslösen: Lampen und/oder Rolläden .Leider ist die Berechnung des Sonnenstandes eine relativ schwierige Rechnung, weil einerseits die lokalen Positionsdaten zu berücksichtigen sind, wie auch die lokale Zeit mit dem ganzen Thema Sommer/Winterzeit. siehe auch Google Sonnenstand und u.a. http://de.wikipedia.org/wiki/Sonnenstand
Zudem erfordert die Berechnung leider mathematische Winkelfunktionen, die in der HM-Skriptsprache nicht enthalten sind; also im Hinblick auf Realisierung auf der Homematic ein schwieriges Thema.Lösungsansätze:
– Eine Lösung ist die Auslagerung der komplexen Kalkulation in ein kleines TCL oder PHP-Progrämmchen, was dann per HM-Skript gestartet wird. Aber das ist auch nicht so prickelnd, weil ggf. beim Firmware-Update das Progrämmchen wieder an Ort und Stelle gespeichert werden muss.
– Eine andere Lösung ist, die Sonnenstandsdaten aus dem Internet beispielsweise alle 5 Minuten zu holen, ähnlich wie die Wetterdaten mit z.B. Wunderground. Hierfür gibt es mehrere Server, die aber eher semiprofessionell betrieben werden. Wie lange und wie oft man die Daten dort herunterladen kann ist ungewiss. Gerade im Hinblick auf die besondere Bedeutung der häuslichen Elemente, die man damit steuern will, ist das m.E. nicht so zielführend. Aber trotzdem ist das eine mögliche Lösung. http://homematic-forum.de/forum/viewtopic.php?f=31&t=4942&hilit=sonnenstandMein Lösungsansatz verwendet nur ein HM-Skript, das die Daten Azimut und Elevation für den individuellen Standort mit einem Interpolationsverfahren berechnet, welches nur mit den vier Grundrechenarten arbeitet:
Zuerst dazu hier etwas Theorie oder gleich nach unten zum Kochrezept:
Wichtig bei der Sonnenstandsberechnung ist zuerst die Ermittlung der aktuellen Sonnenzeit. Diese ergibt sich aus der Zeitzonenzeit plus Addon-Zeit , die aus dem Längengrad berechnet wird. Da wir aber auch Winter/Sommerzeit haben, muß das ebenfalls berücksichtigt werden. Ich habe hier ein anderes Verfahren verwendet, bei dem aus den in der Homematic vorhandenen Zeiten für Sonnenaufgang und Untergang einfach der Mittelwert berechnet wird und die Abweichung von 12:00h die Korrekturzeit ist, die zur aktuellen Zeit addiert wird. So erhält man die lokale Sonnenzeit, ohne dass man kompliziert rechnen muss.
In Abhängigkeit von dieser so berechneten Sonnenzeit berechnet sich der Sonnenstand in Abhängigkeit vom Breitengrad über eine komplexe trigonometrische Formel. Zur Berechnung gibt es im Internet schöne Excel-Berechnungsvorlagen. Ich habe diese hier verwendet : http://karena.de/software.htm#Solardiagramm und für meinen Standort ausgedruckt:sonnenstand0Wenn man beispielweise sich den Sonnenstand für 15:00H während des Jahres anschaut, dann verändert sich der Azimut um ca. 25°, was im Rahmen einer Beschattungssteuerung schon wichtig ist. Das zeigt, dass eine rein uhrzeitabhängige Steuerung der Beschattung oder der nachtabhängigen Rolladenbetätigung für die meisten Anwendungen zu ungenau ist.
Für die Berechnung des Sonnenstandes mit einem HM-Skript werden von dem individuellen Chart, nur die mit Kreisen gekennzeichneten Koordinaten abgelesen und in das Skript eingetragen. Das Skript macht dann eine mehrstufige lineare Interpolation und errechnet sich für den aktuellen Tag die rot gekennzeichnete Tagesline . Diese wiederum ergibt mit der Sonnenzeit die gesuchten Werte für Azimut und Elevation.Und jetzt für diejenigen ohne Interesse für die Theorie hier
das Kochrezept:

1. Anlegen der Systemvariablen:
sonne_azimut Zahl grad -360 bis +360
sonne_elevation Zahl grad -90 bis +90

2. Eintragen der lokalen Koordinatenwerte in das Skript. Für Köln sind die Werte bereits eingetragen. Wer einen anderen Breitengrad hat, kann aus folgender Tabelle sich die Werte direkt oder interpoliert herausholen:

stuetzstellen_sonnenstand

3. Folgendes Skript etwa alle 5 Minuten aufrufen, damit die Systemvariablen aktualisiert werden

Code: Alles auswählen
!############################################################################################
!Daten aus lokalem Sonnenbahndiagramm in gerundeten Werten einsetzen:
!(diese  Werte hier sind für  Breitengrad 51grad ,Köln!)
integer a12max = 180; integer a11max = 152; integer a10max = 129; integer a9max = 111;
integer e12max = 63;   integer e11max = 60;   integer e10max = 55;   integer e9max = 46;
integer  a12min = 180; integer a11min  = 166; integer a10min  = 152; integer a9min = 140;
integer e12min = 15;    integer e11min  = 14;   integer e10min = 11;    integer  e9min = 5;
!############################################################################################
!Konstantwerte für alle mitteleuropäischen Breitengerade von 48grad(Wien) bis 54grad(Kiel)
integer a5max = 63;  integer e5max = 7;integer a5min = 95;  integer e5min = -28;
!Alle Zeiten in Minuten
integer c_zeit = system.Date(„%M“).ToInteger() + 60*system.Date(„%H“).ToInteger();
integer c_tagesbeginn = system.SunriseTime(„%M“).ToInteger() + 60*system.SunriseTime(„%H“).ToInteger();
integer c_tagesende = system.SunsetTime(„%M“).ToInteger() + 60* system.SunsetTime(„%H“).ToInteger();
integer sonnenzeit =c_zeit + 720 – 0.5 *(c_tagesbeginn +c_tagesende);
boolean nachmittag = false;
if (sonnenzeit > 720) {sonnenzeit =1440 – sonnenzeit; nachmittag = true; }
integer jahrestag = system.Date(„%j“).ToInteger();
if (jahrestag > 355) {jahrestag =jahrestag -355;} else {jahrestag =jahrestag +10;}
if (jahrestag  > 182) {jahrestag =365 – jahrestag;}
real jahresfortschritt =0.005464 * jahrestag;  ! entspricht /183
!WriteLine(„jahresfortschritt“ #jahresfortschritt);   !wert läuft zwischen 0 (dec ) und 1 (jun) und zurück
!WriteLine(„sonnenzeit“ #sonnenzeit);!Stuetzwerte der heutigen Tageslinie berechnen
real a12 = 180;
real e12 =  e12min + jahresfortschritt * (e12max – e12min);real a11 = a11min + jahresfortschritt * (a11max – a11min);
real e11 =  e11min + jahresfortschritt * (e11max – e11min);real a10 = a10min + jahresfortschritt * (a10max – a10min);
real e10 =  e10min + jahresfortschritt * (e10max – e10min);real a9 = a9min + jahresfortschritt * (a9max – a9min);
real e9 =  e9min + jahresfortschritt * (e9max – e9min);real a5 = a5min + jahresfortschritt * (a5max – a5min);
real e5 =  e5min + jahresfortschritt * (e5max – e5min);

real a0 = a5; real e0 =e5; real a1= a9; real e1= e9;
real a =  a0 + (0.00417 * (sonnenzeit -300) * (a1 – a0));
real e =  e0 + (0.00417 * (sonnenzeit -300) * (e1 – e0));
!WriteLine(„a    e   “ #a #e);

if (sonnenzeit >539)
{a0 = a9; e0 =e9; a1= a10; e1= e10;
real a = a0 +  (0.0167* (sonnenzeit – 540) *(a1 – a0));
real e = e0 +  (0.0167* (sonnenzeit – 540) *(e1 – e0)); }

if (sonnenzeit >599)
{a0 = a10; e0 =e10; a1= a11; e1= e11;
real a = a0 +  (0.0167* (sonnenzeit – 600) *(a1 – a0));
real e = e0 +  (0.0167* (sonnenzeit – 600) *(e1 – e0)); }

if (sonnenzeit >659)
{a0 = a11; e0 =e11; a1= a12; e1= e12;
real a = a0 +  (0.0167* (sonnenzeit – 660) *(a1 – a0));
real e = e0 +  (0.0167* (sonnenzeit – 660) *(e1 – e0)); }

if (nachmittag == true) {a = 360 – a;  sonnenzeit = 1440 – sonnenzeit;}
dom.GetObject(„sonne_elevation“).State(e);
dom.GetObject(„sonne_azimut“).State(a);

!Wer noch was mit der lokalen Sonnenzeit anfangen will, der muss zusaetzlich die folgenden Systemvariablen anlegen:
!“sonnen_zeit“  Zahl   min    und    „sonnen_zeit_hh_mm“     Zahl
!und die Rufzeichen in den folgenden Skriptzeilen entfernen
!dom.GetObject(„sonnen_zeit“).State(sonnenzeit);
sonnenzeit =0.0166 * sonnenzeit;
integer sonnenzeit_h = sonnenzeit.ToInteger();
real sonnenzeit_min = (sonnenzeit – sonnenzeit_h) *0.6;
real sonnenzeit_hhmm = sonnenzeit_min + sonnenzeit_h;
!dom.GetObject(„sonnen_zeit_hh_mm“).State(sonnenzeit_hhmm);

Fertig!

Wie schon gesagt kann man mit den Werten sonnen_azimut und sonnen_elevation tolle Sachen veranstalten, um zu jeder Jahreszeit die richtigen Aktionen der Rolladen- und Jalousiensteuerung auszulösen. Oder man kann sogar das altbekannte Skript für die Berechnung der Tageszeiten durch ein besseres Tool ersetzen, bei dem man die verschiedenen Dämmerungswerte viel felexibler durch den Elevationswinkel ersetzt. Wenn man erst mal verstanden hat, welch wichtige Göße der absolute Sonnestand bei der Hausautomation ist, möchte man auf diese Information nicht mehr verzichten. Ich glaube sogar, dass professionelle Systeme wie KNX auch diese Grössen berechnen.
Vielleicht werde ich hierzu bei Gelegenheit mal meine aktuelle Rolladen- und Jalousiensteuerung vorstellen, die wesentlich von sonnen_azimut und sonnen_elevation gesteuert wird.

Changelog 28.02.2014: Die notwendigen Systemvariablen wurden weiter reduziert, entsprechende Änderungen im Skript eingetragen. Kennwerte für Köln korrigiert.

Translate »