Vorschläge für BLIND_SHADE, BLIND_CONTROL und BLIND_ACTUATOR

Begonnen von mattsches, 07. Februar 2014, 20:13:02

Vorheriges Thema - Nächstes Thema

0 Mitglieder und 1 Gast betrachten dieses Thema.

mattsches

Hallo zusammen,

ich habe seit einiger Zeit die Building Lib (danke dafür!) für die Steuerung unserer Raffstores. Dabei habe ich einige Dinge modifiziert, um das Verhalten besser an meine Vorstellungen anzupassen. Betroffen sind BLIND_SHADE, BLIND_CONTROL und BLIND_ACTUATOR. Vielleicht sind die Punkte ja für den einen oder anderen interessant. Weitere Details gerne bei Bedarf; doch bevor ich mir die Finger hier wund tippe, wollte ich erstmal sehen, ob überhaupt Interesse besteht.

Also los - Folgende Punkte habe ich für meine Zwecke geändert bzw. ergänzt:

  • Winkelberechnung auch für Raffstores, die beim Hochfahren nicht ganz senkrecht (0°) gestellt werden. In meinem Fall sind es 18°, der von BLIND_SHADE errechnete Winkel wurde daher nicht korrekt eingestellt.
  • Winkel- und Positionsangabe von der größenlosen Skalierung 0..255 umgestellt auf 0..90° (für meine Zwecke reicht 1° Auflösung völlig) und 0..100% (mit 100%=geöffnet).
  • Winkelberechnung in BLIND_SHADE erweitert um die Auswirkung des horizontalen Sonnenwinkels. Steht die Sonne beispielsweise bei 200°, also sehr weit im Süden, können die Raffstores auf der Westseite deutlich weiter geöffnet (bezogen auf den Lamellenwinkel) bleiben als auf der Südseite.
  • Zusätzliche Verzögerungszeit in BLIND_SHADE, um den Raffstore nach erkanntem Sonnenschein verzögert zu schließen.
  • ... und noch eine weitere Verzögerungszeit in BLIND_SHADE für die Schattenerkennung; sie führt dazu, dass kurz nach erkanntem Schatten (bei mir nach 10s) die Lamellen waagrecht gestellt werden, um die Sicht zu maximieren. Erst nach weiterer Verzögerung (tofShadeDelayPos, ehemals sun_delay) fährt die Jalousie dann hoch.

Und hier der Code:

BLIND_SHADE:

FUNCTION_BLOCK BLIND_SHADE
VAR_INPUT
UP, DN : BOOL;
S_IN : BYTE;
PI, AI : BYTE;
ENABLE : BOOL;
SUN : BOOL;
DIRECTION : REAL := 180.0;
ANGLE_OFFSET : REAL := 80.0;
DISABLE_TRACKING : BOOL := FALSE; (* disable tracking of sun/slat angle -> always maximize shading *)
END_VAR
VAR_IN_OUT
CX : CALENDAR;
END_VAR
VAR_INPUT CONSTANT
sunrise_offset : TIME := T#1h;
sunset_preset : TIME := T#1h;
slat_width : REAL := 80.0;
Slat_spacing : REAL := 70.0;
Shade_pos : BYTE := 0;

tSunDelay : TIME := t#60s; (* delay after sun detection until slat angle is calculated *)
tShadeDelayAngle : TIME := t#30s; (* delay after shade detection until slat angle is set to 90=horizontal *)
tShadeDelayPos : TIME := t#10m; (* delay after shade detection until slat position is set to 100=fully opened *)
END_VAR
VAR_OUTPUT
QU, QD : BOOL;
STATUS : BYTE;
PO, AO : BYTE;
END_VAR
VAR
angle: REAL;
max_angle : REAL;
angle_old : REAL;

fEffectiveSlatWidth : REAL; (* effective slat width, including effect of horizontal sun angle *)

tonSunDelay : TON; (* timer for delay after sun detection until shade is closed and angle is calculated *)
tofShadeDelayAngle : TOF; (* timer for delay after shade detection until slat angle is set to 90=horizontal *)
tofShadeDelayPos : TOF; (* timer for delay after shade detection until slat position is set to 100=fully opened *)

sun_ver_last : REAL; (* last vertical sun angle (for change detection) *)
sun_hor_last : REAL; (* last horizontal sun angle (dto.) *)
END_VAR



(* delay sun/shade detection in order to prevent shade from constantly going up and down *)
tonSunDelay(IN:=sun, PT:=tSunDelay);
tofShadeDelayAngle(IN:=tonSunDelay.Q OR tofShadeDelayAngle.Q AND sun, PT:=tShadeDelayAngle);
tofShadeDelayPos(IN:=tofShadeDelayAngle.Q, PT:=tShadeDelayPos);


IF UP AND DN AND enable AND (tonSunDelay.Q OR tofShadeDelayPos.Q)
AND cx.SUN_HOR > direction - angle_offset AND cx.SUN_HOR < direction + angle_offset
AND DT_TO_TOD(cx.UTC) > cx.SUN_RISE + sunrise_offset AND DT_TO_TOD(cx.UTC) < cx.SUN_SET - sunset_preset THEN
   status := 151;
   QU := UP;
   QD := DN;

   (* position is predefined *)
   po := shade_pos;

   (* shading is active now calculate the slat angle *)
   (* calculate the max angle for the blind *)
   fEffectiveSlatWidth := slat_width / COS(RAD(ABS(DIRECTION - cx.SUN_HOR)));
   max_angle := DEG(ATAN(slat_spacing / fEffectiveSlatWidth));

   (* check if sun angle is between 0 and max angle *)
   IF cx.SUN_VER > 0.0 AND cx.SUN_VER < max_angle AND NOT DISABLE_TRACKING AND tofShadeDelayAngle.Q THEN
      (* only recalculate blind angle if vertical sun angle has changed *)
      IF   cx.SUN_VER <> sun_ver_last OR cx.SUN_HOR <> sun_hor_last THEN
         angle := cx.SUN_VER + DEG(ACOS(COS(RAD(cx.SUN_VER))*slat_spacing / fEffectiveSlatWidth));
         sun_ver_last := cx.SUN_VER;         (* store current sun angles *)
         sun_hor_last := cx.SUN_HOR;
      END_IF;
      ao := INT_TO_BYTE(LIMIT(0,TRUNC(angle), 90));
   ELSIF DISABLE_TRACKING THEN               (* tracking of sun/slat angle disabled -> always maximize shading *)
      ao := 0;
   ELSE
      ao := 90;
   END_IF;
ELSE
   QU := UP;
   QD := DN;
   po := pi;
   ao := ai;
   status := S_IN;
END_IF;



BLIND_CONTROL:

FUNCTION_BLOCK BLIND_CONTROL
VAR_INPUT
UP, DN : BOOL;
S_IN : BYTE;
PI : BYTE;
AI : BYTE;
T_UD, T_ANGLE : TIME;
END_VAR
VAR_INPUT CONSTANT
SENS : BYTE := 5;
T_LOCKOUT: TIME := T#100ms;
MIN_ANGLE : BYTE := 0; (* minimum slat angle *)
MAX_ANGLE : BYTE := 90; (* maximum slat angle *)
END_VAR
VAR_OUTPUT
POS, ANG : BYTE;
MU, MD : BOOL;
STATUS : BYTE;
END_VAR
VAR
act : BLIND_ACTUATOR;
delta : BYTE;
bTimeTest:BOOL:=FALSE;
iPos:BYTE;
iAngel:BYTE;
END_VAR




(* limit angle setpoint *)
ai := LIMIT(MIN_ANGLE, ai, MAX_ANGLE);


(* Check Position*)
act(T_UD:=T_UD, T_ANGLE:=T_ANGLE, T_lockout := T_Lockout, MIN_ANGLE := MIN_ANGLE, MAX_ANGLE := MAX_ANGLE);

IF UP AND DN THEN
(* automatic modus detected *)
(* first find correct position *)
IF BYTE_TO_INT(act.pos) < BYTE_TO_INT(pi) - delta THEN
act.UP := TRUE;
act.DN := FALSE;
delta := 0;
STATUS := 121;
ELSIF BYTE_TO_INT(act.pos) > BYTE_TO_INT(pi) + delta THEN
act.UP := FALSE;
act.DN := TRUE;
delta := 0;
STATUS := 122;
(* regulate angle *)
ELSIF BYTE_TO_INT(act.ang) < BYTE_TO_INT(ai) - delta AND T_angle > T#100ms THEN
act.UP := TRUE;
act.DN := FALSE;
delta := sens/2;
STATUS := 123;
ELSIF BYTE_TO_INT(act.ang) > BYTE_TO_INT(ai) + delta AND T_angle > T#100ms THEN
act.UP := FALSE;
act.DN := TRUE;
delta := sens/2;
STATUS := 124;
(* correct position reached *)
ELSE
act.UP := FALSE;
act.DN := FALSE;
delta := sens;
STATUS := S_IN;
END_IF;
ELSE
act.UP := UP;
act.DN := DN;
STATUS := S_IN;
END_IF;

(* blind control calls blind_actuator *)
act(T_UD:=T_UD, T_ANGLE:=T_ANGLE, T_lockout := T_Lockout);
pos := act.pos;
ang := act.ang;
MU := act.QU;
md := act.QD;



BLIND_ACTUATOR:

FUNCTION_BLOCK BLIND_ACTUATOR
VAR_INPUT
UP, DN : BOOL;
S_IN : BYTE;
T_UD : TIME := T#10s;
T_ANGLE : TIME := T#3s;
MIN_ANGLE : BYTE := 0; (* minimum slat angle; 0 would equal full vertical position *)
MAX_ANGLE : BYTE := 90; (* maximum slat angle; 90 would equal horizontal position *)
END_VAR
VAR_INPUT CONSTANT
T_LOCKOUT : TIME := t#100ms;
END_VAR
VAR_OUTPUT
POS, ANG : BYTE;
QU, QD : BOOL;
STATUS : BYTE;
END_VAR
VAR
position, angle : RMP_B;
lock : INTERLOCK;
END_VAR



(* make sure only one moto r is active at a given time *)
lock(i1 := UP, I2 := DN, TL := T_lockout);

(* ramp up or down to simulate the angle position of the blind slats *)
angle(e := lock.Q1 OR lock.Q2, UP := lock.Q1, PT := T_Angle);
position(e := lock.Q1 AND angle.high OR lock.Q2 AND angle.low, up := lock.Q1, PT := T_UD);

(* set the outputs *)
pos := position.Out * 100 / 255;
ang := angle.OUT * (MAX_ANGLE - MIN_ANGLE) / 255 + MIN_ANGLE;


(* set the outputs *)
QU := lock.Q1;
QD := lock.Q2;

(* set the status output *)
IF UP AND DN THEN
status := 1; (* error up and down together are not allowed *)
ELSIF UP THEN
status := 121;
ELSIF DN THEN
status := 122;
ELSE
status := S_IN;
END_IF;


Majaestix

Hallo mattsches,

danke!

Interessiert mich auch.
Deinen Code guck ich mir am WE mal an.

Gruss

Majaestix

mattsches

Um die ekstatische Euphorie hier noch weiter anzuheizen  ;), ich hatte noch ein kleines Feature unterschlagen:

Der neue Eingang "DISABLE_TRACKING" am BLIND_SHADE führt dazu, dass die Jalousie zwar geschlossen, der Lamellenwinkel jedoch nicht nachgeführt, sondern bleibt immer voll geschlossen. Ich nutze das im Schlafzimmer, wo ich immer eine maximale Verschattung haben möchte.

Grüße,
mattsches

mattsches

Huch! Es interessiert sich tatsächlich ein einsamer Programmierer für das Thema... Da man per PN offenbar keine Anhänge mit verschicken kann, auf diesem Wege anbei die aktuellen Versionen der von mir modifizierten BLIND_*-Bausteine.

[gelöscht durch Administrator]

fu_zhou


the.neon

So hab es auch mal getestet.
Erstmal danke für die Arbeit es funktioniert auch alles soweit.

Hat aber jemand noch ein Tipp , wie ich es so einstellen kann das beim Stromausfall oder wenn ein Programm eingespielt wird .
Default Mäßig die Position auf oben ist (0) ? Kann die Bausteine leider aus technischen Gründen nicht in RETAIN legen ...
Oder ich irgendwie eine Kalibrierung machen kann ? Pos auf 0 wäre mir lieber da meistens die Jalousien oben sind.

Gruß


mattsches

Das verstehe ich nicht... Es ist doch heute schon so, dass nach einem Neustart der Steuerung die Jalousien nach oben fahren. Mich stört das eher, beispielsweise wenn ich abends eine Änderung einspiele, die einen Neustart erfordert. Dann fahren im ganzen Haus die Raffstorees hoch.

Einen konkreten Tipp habe ich dir dazu alber leider nicht, habe mich mit der Initialisierung noch nicht wirklich auseinandergesetzt.

the.neon

Das ist bei mir leider nicht so .
Da sie meisten oben sind fahren sie nicht hoch.
Was aber blöd ist angle und pos steht dann auf 0.

Weist du wo das initialiesieren gemacht wird ? Hätte gern nach reset 100 und 90.

Gruss

mattsches

Setz' mal MASTER_MODE am BLIND_INPUT2 auf TRUE. Dann greifen die Defaults von 100 und 90 für PO und AO, und die Jalousien fahren beim Hochlauf der Steuerung hoch.


the.neon

Leider ist es damit auch nicht optimal.

Mit dem MasterMode fahren die Rollos morgens wieder hoch ... Möchte gerne das die Morgens unten bleiben mit Angle 90 .

Hast du noch ein Tipp ?

Gruß

mattsches

Spontan nein. Wenn Du E_DAY am BLIND_NIGHT auf FALSE nimmst, dann bleibt die Jalousie unten. Allerdings auch komplett geschlossen. Du willst die Lamellen ja waagrecht stellen, das geht so nicht. Du könntest nun den BLIND_NIGHT so umbauen, dass er auch Position und Winkel für den Tagbetrieb ansteuern kann. Oder du setzt einen BLIND_SCENE ein. Den habe ich aber nicht in Betrieb und weiß daher nicht, ob für meinen Umbau auf Position in % und Winkel in ° dort Änderungen erforderlich wären.

the.neon

Danke .

Ich glaub wenn ich den Blind_night umprogramiere bekomm ich mehr probleme. Da das ganze ja in der Kette funktionieren muss. Bedeutet  am Tag muss CONTROL und SHADE die Position bestimmen....

Wie hast du es mit dem SCENE gemeint ? Das ich bei Sonnenaufgang den Scene triggere mit der Position ? Wenn ja muss der vor oder nach dem Night sein ?

Sorry für die viele Fragen ... Funktioniert echt super aber mich nervt das die Jalousien hochfahren .. die sollen schön auf 90 Grad bleiben wie nachts auch ...

mattsches

In der Doku ist der BLIND_SCENE direkt hinter dem BLIND_INPUT eingehängt (Kap. 7.7). Aber wie gesagt, ich habe den nicht in Verwendung.

Ich werde nur gerade stutzig - Du schreibst:

Zitat von: the.neon in 04. April 2017, 20:02:18
.. die sollen schön auf 90 Grad bleiben wie nachts auch ...

Du hast die Jalousien nachts ganz geschlossen, nehme ich an. Oder? Also Lamellen so weit es geht senkrecht? Das sind dann (jedenfalls in meiner Denke) nicht 90°, sondern bei mir z. B. 18°. Aber egal, wenn die Jalousie auch nach Sonnenaufgang genau so bleiben soll, dann reicht es, am BLIND_NIGHT E_DAY auf FALSE zu setzen. Dann bleibt die Jalousie morgens einfach unverändert. So habe ich das z. B. im Bad und im Schlafzimmer parametriert.

the.neon

Hi ,

nochmals danke. Aber jetzt fährt er in Night Mode , aber dann später wieder hoch in Manual Standby ?
Kann es sein es liegt am MasterMode ?

Hab BLIND_INPUT_2 -> BLIND_SHADE-> BLIND_NiGHT-> BLIND_SEC -> BLIND_CONTROL

( ganze Zeit Auto Mode und Sun auf ON)

17:02:40.373  :  State changed from 151 to 141 => Passt Sunset - 60m
18:56:06.495 :  State changed from 141 to 121 =>  Auf Bewegung Position ? Wieso ?

18:57:20.641 : State changed from 121 to 130  => Standby