Seite auswählen

HM-Skript zur einfachen Sonnenstandsberechnung

,
HM-Skript zur einfachen Sonnenstandsberechnung
Print Friendly
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.

Fähigkeiten

Gepostet am

19. Juni 2013

4 Kommentare

  1. Hi,
    alles auf Null. Ich habe den Code aus
    http://homematic-forum.de/forum/viewtopic.php?f=31&t=17300#
    kopiert und siehe da, die CCU hat den Code akzeptiert. Anscheinend liegt der Fehler hier in der Syntax:

    !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

    !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

  2. Hallo,
    vielen Dank für die tolle Doku. Leider will meine CCU2 (2.25.15) das obige Script nicht akzeptieren. Ich erhalte bei der Fehlerprüfung die Meldung:
    Error 1 at row 11 col 35 near ^„%M“).ToInteger() + 60*system.Date(„%H“).ToInteger();
    integer c_tage
    Parse following code failed:

    Die 2 bzw 4 Systemvariablen sind angelegt.
    Ich bin kein Softy und kann plug and play aber dann ist so ziemlich Schluß.
    Was kann ich tun?
    Wenn ich den Code in den MobaTextEditor eingebe, lautet die Zeile 11 – 13:
    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();

    Danke vorab.
    Beste Grüße
    R. Adamski

  3. Ich würde einfach die Vertikalausrichtung des Kollektors konstant halten und nur die Horizontalausrichtung der Sonne nachführen. Dazu mußt Du den Sonnenkollektor auf den mit dem Sonnenstandsskript berechneten Azimuthwinkel ausrichten. Das kann man aufwendig machen mit Winkelmessung und Soll/Ist-Vergleich. Es geht aber auch einfacher, indem man morgens, wenn die Sonne genau im Osten steht (Azimuthwinkel 90°), den Kollektor nach Osten ausrichtet. Das kann beispielsweise mit einem Endschalter gemacht werden oder man macht einfach einen Anschlag o.ä. Danach stündlich den Stellmotor x-Sekunden bestromen, so daß er einen bestimmten Winkel weiterschwenkt. x muß man ermitteln aus den Stellmotordaten bzw. aus der Stellgeschwindigkeit.
    Ich schätze , damit holt man schon 90% der möglichen Verbesserung und man hat ein relativ einfaches / zuverlässiges System!

    … aber ich habe keine Sonnenkollektoren :))

  4. Ich würde gerne meinen Röhren Kollektor stündlich nachführen damit die Strahlen im rechten Winkel auftreffen, von Ost nach West habe ich schon. Jedes Monat ist es aber anders, wie kann ich das Berechnen, ich verändere die Neugung abhängig von der Uhrzeit und Monat um einige Grade das einen bestimmten Weg, bzw. Drehimpulse am Motor entspricht, ich würde einen Linear Spindel Antrieb wie bei Sat Antennen üblich verwenden, solchen habe ich auch in Verwendung von Ost nach West. Bei der Neigung ist es aber anders, Aufgang bis Mittag in eine Richtung, dann wieder in die andere Richtung, der Weg entspricht aber bestimmte Anzahl von Impulsen, mit meiner SPS kann ich diese verarbeiten.Täglich alles zu ändern will ich nicht aber vielleicht 1 -2 mal im Monat. Vielleicht kennt sich jemand damit aus,

Kommentar absenden

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Translate »