Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shading erweitern für Dachfenster #42

Open
der-oBi opened this issue Jun 30, 2019 · 6 comments
Open

Shading erweitern für Dachfenster #42

der-oBi opened this issue Jun 30, 2019 · 6 comments
Labels
enhancement New feature or request

Comments

@der-oBi
Copy link

der-oBi commented Jun 30, 2019

Hey, wie schon im Forum kurz andiskutiert, würde ich mich sehr freuen, wenn die Beschattungssteuerung so geändert würde, dass auch Dachfenster ideal beschattet werden können.

Als kurze Erklärung: Nur mit festen Grenzen für Azimuth/Elevation kommt man bei der Beschattung Dachfenstern leider nicht weit.

Beispiel:
Dachfenster zeigt nach Norden (ASC_Shading_Pos = 0). Sonne steht voll im Süden (azimuth=180). Sonne steht bei Elevation 60°, Dachneigung wäre 30°. Obwohl die Sonne auf der gegenüberliegenden Seite steht, würde sie dennoch ins Fenster scheinen (mit einem Einfallswinkel von 30°). Das wird leider derzeit nicht erfasst.

Meine Idee, wie ich sie bisher (wohl gemerkt schlecht programmiert) in meinen myUtils umgesetzt habe:
Zusätzlich zum bisherigen Vorgehen müsste für jedes Fenster neben ASC_Shading_Pos die Neigung des Fensters zur Horizontalen angegeben werden (bei einem Wandfenster also per default 90°).
Danach wird das Fenster und der Sonnenstand als 3 dimensionaler Vektor dargestellt und der tatsächliche Einfallwinkel berechnet: ("sonnenstand" ein einfaches twilight Device)

my $sun_az_grad = ReadingsVal("sonnenstand","azimuth",0) ;
my $sun_el_grad = ReadingsVal("sonnenstand","elevation",0) ;
my $sun_az_rad = $sun_az_grad * 3.14 / 180 ;
my $sun_el_rad = $sun_el_grad * 3.14 / 180 ;
my $x_sun = sin($sun_az_rad) * cos($sun_el_rad) ;
my $y_sun = cos($sun_az_rad) * cos($sun_el_rad) ;
my $z_sun = sin($sun_el_rad) ;

$ausrichtung_az = $grenzen[0] / 180 * 3.14 ; #### entspricht ASC_Shading_Pos
$ausrichtung_el = $grenzen[1] / 180 * 3.14 ; #### entspricht der Dachneigung
$x_fenster = sin($ausrichtung_az) * cos($ausrichtung_el) ;
$y_fenster = cos($ausrichtung_az) * cos($ausrichtung_el) ;
$z_fenster = sin($ausrichtung_el) ;

$schnittwinkel = max ( 0, ( asin ( $x_fenster * $x_sun + $y_fenster * $y_sun + $z_fenster * $z_sun ) ) * 180 / 3.14 ) ;

Der tatsächlich berechnete Schnittwinkel könnte dann mit einem Maximal-Schnittwinkel verglichen werden (bei mir z.B. 15°) und wenn der überschritten wird, soll beschattet werden.

Funktioniert bei mir seit 2 Jahren tadellos (auch für Wandfenster). Aber die vielen DOIFs und myUtils sind nicht halb so schick wie dein ASC-Modul :-)

PS: Die festen Grenzen (Shading_Angle, MinMaxElevation) sollten dennoch bleiben und weiterhin abgefragt werden um beispielsweise Beschattung durch nahe stehende Bäume/Häuser mitzunehmen.

@CoolTuxNet
Copy link
Member

Ich danke Dir. Ich werde es mir in den kommenden Wochen einmal genauer anschauen.

@der-oBi
Copy link
Author

der-oBi commented Jul 1, 2019

Freut mich. Wenn du Fragen hast, sag einfach Bescheid.

Ich muss allerdings einen kleinen Schönheitsfehler in meinen Ausführungen korrigieren:
So wie ich es derzeit umgesetzt habe, gibt $ausrichtung_el nicht die Dachneigung in Relation zur Horizontalen wieder, sondern in Relation zur Vertikalen.
Somit ist in meiner Umsetzung ein Wandfenster also nicht per default mit $ausrichtung_el=90 sondern mit $ausrichtung_el=0 (also parallel zur Vertikalen) umzusetzen.
Ist aber eine reine Verständnissache. Könnte man auch einfach ändern, indem man 2mal cos gegen sin tauscht ;-)

@linuzer
Copy link

linuzer commented Jul 16, 2019

Hallo, sorry, ich hatte Deine Antwort im Forum übersehen...
Hier also wie gewünscht mein Script, das glaube ich einen ganz ähnlichen Ansatz verfolgt wie das oben von der-oBi.
Die Grundangaben pro Fenster könnten als Readings bei den Rollläden abgelegt werden. Die Logik funktioniert gleichermaßen für vertikale Wandfenster, als auch für Dachfenster. Funktioniert bei mir hervorragend...

Die Idee ist, es wird sowohl der Sonneneinfall als Vektor beschrieben, als auch der Rollo-Fahrweg. Damit kann man dann den Winkel der beiden Vektoren berechnen. Damit und mit den Infos wie groß der Fensterausschnitt, sowie eventuelle Mauervorsprünge oder Aufbauten sind, läßt sich relativ exakt ausrechnen, wie weit der Rollo fahren muß, um das Fenster in der gewünschten Weise zu beschatten.

Würde mich sehr freuen, wenn Du das irgendwie in das Modul integrieren könntest! Wenn Du irgendwelche Fragen hast, sag Bescheid!

######### Rolladensteuerung
sub RolladenHitze 
{
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    my $Elev = ReadingsVal('MyTwilight', 'elevation', '0');
	my $Azim = ReadingsVal('MyTwilight', 'azimuth', '0');
	
	Log 1, "Elev: $Elev";
	Log 1, "Azim: $Azim";
	
	# Fensterdefinitionen (DevName, Breite, Höhe, Tiefe, Dachwinkel, Aufbauhöhe, Fensterausrichtung, Aktiv)
		# 0, DeviceName des Rollos
		# 1, 2: Breit, Höhe (cm) = sichtbare Breite, Höhe des Fensters (Glas innerhalb des Rahmens)
		# 3: Tiefe (cm) = Wie weit darf die Sonne "ins Fenster" scheinen (vom Fensteraussenscheibe messen!)
		# 4: Dachwinkel (Grad) = native Neigung der Fensterscheibe (=Dach), bzw. 90° bei "normalen" Wandfenstern
		# 5: Aufbauhöhe (cm) = Wieviel cm tragen Rollläden, Wandvorsprünge, etc. zur Fensterscheibe auf?
		# 6: Fensterausrichtung (Grad) = In welche Himmelsrichtung "schaut" das Fenster? -> Senkrechte auf die Scheibe, Nord = 0°, Süd = 180°
		# 7: Min Azim. (Grad) = ab welchem Azimut wird beschattet?
		# 8: Max Azim. (Grad) = bis welchem Azimut wird beschattet?
		# 9: Min Elev. (Grad) = ab welcher Elevation wird beschattet?
		# 10: Max Elev. (Grad) = bis welcher Elevation wird beschattet?
		# 11: Min Schatten (%) = minimale schattenrelevante Rollo-Position (z.B. 12%)
		# 12: Max Schatten (%) = maximale schattenrelevante Rollo-Position (z.B. 98%)
		# 13: Aktiv = 0 -> Deaktiviert, 1 -> Aktiv
	my @BU_S = ("BU_RolloS", 77, 98, 15, 39, 13, 276, 90, 360, 25, 90, 16, 100, 1);
	my @BU_N = ("BU_RolloN", 77, 98, 15, 39, 13, 276, 90, 360, 22, 90, 16, 100, 1);
	my @KU = ("KU_Rollo", 77, 100, 15, 39, 13, 276, 90, 360, 21, 90, 16, 100, 1);
	my @WC = ("WC_Rollo", 60, 90, 15, 39, 13, 276, 90, 360, 20, 90, 16, 100, 1);
	my @SZ = ("SZ_Rollo", 300, 200, 25, 90, 15, 96, 0, 186, -10, 90, 14, 100, 1);
	my @WZ = ("WZ_Rollo", 300, 200, 25, 90, 15, 96, 0, 186, 0, 90, 14, 100, 1);
	my @GA = ("GA_Rollo", 105, 130, 15, 39, 13, 96, 0, 270, -10, 90, 13, 100, 1);
	my @GZ_O = ("GZ_RolloO", 105, 130, 15, 39, 13, 96, 0, 270, 0, 90, 13, 100, 1);
	my @GZ_W = ("GZ_RolloW", 125, 130, 15, 39, 13, 276, 90, 360, 15, 90, 14, 100, 1);
	
	my @ArrFenster = (\@BU_S, \@BU_N, \@KU, \@WC, \@SZ, \@WZ, \@GA, \@GZ_O, \@GZ_W);
	
	# Array-Zugriffskonstanten
	my $C_DEVNAME = 0;
	my $C_BREITE = 1;
	my $C_HOEHE = 2;
	my $C_TIEFE = 3;
	my $C_DACHWINKEL = 4;
	my $C_AUFBAU = 5;
	my $C_F_AUSRICHTUNG = 6;
	my $C_MINAZIM = 7;
	my $C_MAXAZIM = 8;
	my $C_MINELEV = 9;
	my $C_MAXELEV = 10;
	my $C_MINPOS = 11;
	my $C_MAXPOS = 12;
	my $C_AKTIV = 13;
	
	# allgemeine Variablen/Konstanten
	my $pi = 3.1415926535897932;
	my @V_Rollo = (0, 0, 0);	# Vektor Rollo
	my @V_Sonne = (0, 0, 0);	# Vektor Sonne
	my $Aufbauwinkel = 0;
	my $Gesamtneigung = 0;
	my $Theta = 0;
	my $Phi = 0;
	my $Winkel = 0;
	my $RolloPos = 0;
	
	# rad = grad * pi / 180; 		grad = rad * 180 / pi
	
	# Sonnenvektor berechnen
	$Theta = (90 + $Elev) * ($pi / 180);
	$Phi = $Azim * ($pi / 180);
	
	$V_Sonne[0] = sin($Theta) * sin($Phi);
	$V_Sonne[1] = cos($Theta);
	$V_Sonne[2] = sin($Theta) * cos($Phi) * -1;
	
	foreach (@ArrFenster) {
		my @Fenster = @$_;
		
		# Gesamtneigung berechnen
		$Aufbauwinkel = atan2($Fenster[$C_AUFBAU], $Fenster[$C_HOEHE]) * (180 / $pi);
		$Gesamtneigung = $Fenster[$C_DACHWINKEL] + $Aufbauwinkel;
		
		# Rollo-Vektor berechnen
		$Theta = (90 + $Gesamtneigung) * ($pi / 180);
		$Phi = $Fenster[$C_F_AUSRICHTUNG] * ($pi / 180);
		
		$V_Rollo[0] = sin($Theta) * sin($Phi) * -1;
		$V_Rollo[1] = cos($Theta);
		$V_Rollo[2] = sin($Theta) * cos($Phi) * -1;
		
		# Sonnenwinkel auf Fensterfläche berechnen (=Winkel der beiden Vektoren)
		$Winkel = acos(($V_Rollo[0] * $V_Sonne[0] + $V_Rollo[1] * $V_Sonne[1] + $V_Rollo[2] * $V_Sonne[2]) /
				  (sqrt($V_Rollo[0] ** 2 + $V_Rollo[1] ** 2 + $V_Rollo[2] ** 2) * 
				  sqrt($V_Sonne[0] ** 2 + $V_Sonne[1] ** 2 + $V_Sonne[2] ** 2)));
		
		# Rollo-Position bestimmen
		if ($Fenster[$C_MINAZIM] < $Azim && $Azim < $Fenster[$C_MAXAZIM] && 
			$Fenster[$C_MINELEV] < $Elev && $Elev < $Fenster[$C_MAXELEV]) {
			$RolloPos = ((($Fenster[$C_TIEFE] + $Fenster[$C_AUFBAU]) / tan($Winkel)) / $Fenster[$C_HOEHE]) * 100;
		} else {
			$RolloPos = 100;
		}
		
		if ($RolloPos < 0) {$RolloPos = 0};
		
		# Rollo-Pos auf schattenrelevanten Bereich skalieren
		$RolloPos = ($Fenster[$C_MAXPOS] - $Fenster[$C_MINPOS]) * ($RolloPos / 100) + $Fenster[$C_MINPOS];
			
		# Rollo auf Position fahren
		if ($Fenster[$C_AKTIV] == 1) {
			fhem("sleep 1; set ".@Fenster[$C_DEVNAME]." pct ".sprintf("%.0f", $RolloPos));
			Log 1, "Rollo ".$Fenster[$C_DEVNAME]." auf ".sprintf("%.0f", $RolloPos);
		}
	}
}

@CoolTuxNet CoolTuxNet added the enhancement New feature or request label Aug 15, 2019
@DrS332
Copy link

DrS332 commented May 2, 2020

Hallo,
ich versuche schön länger meine Dachfenster automatisch zu beschatten. Dabei möchte ich das Fenster nur soweit schließen wie notwendig. Der Code von Linuzer würde diese Aufgabe genau erfüllen.

Jetzt habe ich den Code in eine Excel Tabelle übertragen um herauszufinden ob das bei meiner Loxone Steuerung auch funktionieren würde.

Es schaut schon ziemlich gut aus.
Nur mein Fenster im Westen (245•) will nie ganz zufahren obwohl die Sonne dort NM direkt rein scheint. Vielleicht hab ich die Parameter nicht richtig verstanden. Wie ist das mit AUFBAU und TIEFE gemeint?

Beste Grüße

@linuzer
Copy link

linuzer commented May 2, 2020

Also vorab, die Logik ist nicht 100% perfekt, denn es gibt wahrscheinlich immer Sonder- und Grenzfälle, in denen es nicht (mehr) perfekt funktioniert. Aber ich habe versucht einige Besonderheiten zu berücksichtigen. Dafür sind u.a. die beiden Parameter Aufbau und Tiefe gedacht:

Aufbau = Alles, was "über" (= im 90°-Winkel zur Fensterfläche) "hoch" steht. Bei Dachfenstern ist das z.B. der Rollladenkasten. Wenn die Sonne fast parallel zur Dachfläche scheint, bewirkt der Rollokoasten einen Schatten, der effektiv die Dachneigung erhöht. D.h. die Sonne muss höher stehen als ohne, um ins Fenster zu scheinen. Bei senkrechten Fenstern kann das aber auch ein Mauervorsprung über dem Fenster sein, im Extremfall z.B. ein Balkon über dem Fenster. All das bewirkt, dass der Rollladen bei einem anderen Sonnenwinkel reagieren muss, als bei einem "nackten" Fenster.

Tiefe = Bei mir sind die Rollläden 100% Lichtundurchlässig. D.h. wenn sie zu sind, muss ich das Licht einschalten. Das fühlt sich natürlich im Hochsommer am helligen Tag ziemlich blöd an, weshalb ich möchte, dass der Rolladen die Sonne nicht zu 100% abschattet, sondern zuläßt, dass die Sonne etwas in die Fensterlaibung nach innen scheint und damit das Zimmer noch etwas beleuchtet. Dabei muss man natürlich abwägen zwischen Hitze versus Licht. Der Parameter "Tiefe" steht dabei für das Maß in "cm", bis zu der die Sonne von der Fensterfläche nach innen kommen darf. Bei 20 cm z.B. sollte die Sonne noch 20 cm "rein" scheinen.

Hoffe, das hilft...
LG linuzer

Edit:
Ach so, ich seh grad ich hab das nirgends explizit erwähnt: Das ganze läuft bei mir als notify auf das Twilight-Device, d.h. alle paar Minuten, wenn sich der Sonnenstand ändert, werden alle Rollos in ihrer Position entsprechend angepaßt...

@zivillian
Copy link

@linuzer Ich habe ein Problem in dem Skript identifiziert, was bei flachen Dachfenstern zu extremen Abweichungen führt. Zwar wird die Ausrichtung des Fensters für die Berechnung des Winkels berücksichtigt, aber nicht für Berechnung der Öffnung.
Ich habe hier ein Dachfenster mit Nordausrichtung, wo aber durch den flachen Winkel von ca. 30° in den Abendstunden im Sommer trotzdem die Sonne drauf steht. Durch den extremen Winkel zwischen Fensterausrichtung und Sonnenstand entstehen hier Abweichungen zwischen wenigen Zentimetern zulässiger Öffnung und fast einem Meter berechneter Öffnung.

Zur Veranschaulichung habe ich hier eine Skizze des Fehlers:
Fenster

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants