Beiträge anzeigen

Diese Sektion erlaubt es ihnen alle Beiträge dieses Mitglieds zu sehen. Beachten sie, dass sie nur solche Beiträge sehen können, zu denen sie auch Zugriffsrechte haben.


Nachrichten - mattsches

Seiten: 1 ... 16 17 [18]
256
Richtig, der BLIND_SHADE funktioniert mit der größenlosen Angabe 0..255, die implizit 255=90° voraussetzt, in Deinem Fall nicht. Ich habe hier: http://www.oscat.de/community/index.php/topic,2143.0.html die Anpassungen vorgestellt, wie ich sie für mich vorgenommen habe. Das beinhaltet eine Umstellung auf tatsächliche Winkelangaben, der Ansatz sollte bei Dir eigentlich funktionieren.

Das Thema Anlaufverzögerung habe ich mittlerweile auch berücksichtigt. Ist in oben erwähntem Posting jedoch noch nicht enthalten, der frenetische Beifall auf meinen ersten Vorschlag hat mich zu sehr überwältigt. Falls aber doch noch Interesse bestehen sollte, kann ich das Update noch nachreichen (gerne auch als Export-Datei, mein erster Ansatz mit Code-Tags war bei dem Umfang sicher nicht sehr bequem).

Obacht bei der Sache, die 200 ms können auch ein Maximalwert sein. Bei meinen Somfy-Antrieben steht das auch im Datenblatt, tatsächlich habe ich aber mit 10 oder 20 ms ein gutes Stellverhalten erzielen können. Ist an sich sehr simpel zu programmieren.

Grüße,
mattsches

P.S. Omalik, die Jalousienposition verarbeite ich übrigens in 0..100 (%). Ich teile uLux' Einschätzung, dass größenlose, auf ein Byte skalierte Werte nicht sehr intuitiv sind.

257
... und vielleicht noch eine Präzisierung zur Ergänzung:

Die erwähnte globale Variable "XCAL" wird nicht etwa von CALENDAR_CALC erzeugt. Der Baustein erwartet lediglich, dass an seinem Anschluss "XCAL" eine Variable vom Typ "CALENDAR" übergeben wird. Die kann, muss aber nicht global deklariert sein; global bietet sich in dem Fall jedoch an.

Die Deklaration machst Du dann im Reiter "Ressourcen", "Globale_Variablen". Zum Beispiel so:

XCAL : CALENDAR;

oder aber - wenn Dir der Variablenname besser gefällt:

HansdampfinallenGassen : CALENDAR;

In dem Fall müsstest Du beim Aufruf des CALENDAR_CALC halt "HansdampfinallenGassen" an den Bausteineingang "XCAL" schreiben. Und an jeder beliebigen Stelle in Deinem Programm könntest Du dann mit HansdampfinallenGassen.SUN_RISE die berechnete Sonnenaufgangszeit abgreifen.

Sinnvoll ist das nicht, also bleib' lieber bei Alex' Empfehlung und nenne das Ding XCAL, CalendarData oder so. Aber deklarieren musst Du es selbst, darum ging es mir.

Grüße,
mattsches

258
Modulentwicklung / Module Development / FILTER_MAV_R
« am: 15. März 2014, 12:05:06 »
Hallo,

ein ganz simpler, kleiner Vorschlag: Neben den Bausteinen FILTER_MAV_W und _DW würde sich ein _R für Gleitkommawerte sehr gut machen. Wäre m. E. im Wesentlichen Copy & Paste, auch in der Doku. Ich kann die (sehr überschaubaren) Vorarbeiten gerne übernehmen, falls Ihr das möchtet.

Viele Grüße,

mattsches

259
Bestehende Module / Existing Modules / Bug in FILTER_MAV_W
« am: 15. März 2014, 12:01:59 »
Hallo OSCAT-Team,

der FILTER_MAV_W ist ziemlich vermurkst worden. Array als 1..32 deklariert, die Laufvariable i läuft aber von 0 weg und nur bis N-1. Bei der Initialisierung dann
sum := Y * N;
Y ist das (spätere) Berechnungsergebnis. X wäre richtig. Insgesamt funktioniert er schlicht nicht.

Warum kopiert Ihr nicht einfach den Code vom FILTER_MAV_DW rüber? Der ist korrekt.

Man sollte dort allenfalls noch init mit FALSE initialisieren. Boolesche Variablen allokieren in Codesys 1 Byte (nicht 1 Bit), können daher also ohne Initialisierung durchaus undefiniert sein. Hatte ich gerade auf meiner Beckhoff.

Viele Grüße,

mattsches

P.S. Verstehe ich das richtig, dass die Bilbliotheken zwar Open Source sind (was ich sehr begrüße, wie überhaupt die gesamte Initiative!), die Pflege aber durch Einzelne geschieht? D.h. Fehler in Code oder Doku meldet man ausschließlich hier im Forum und kann sie nicht etwa direkt korrigieren (wie z. B. bei Wikipedia). Richtig?

Edit: Ich muss mich korrigieren, FILTER_MAV_DW scheint schon noch einen Fehler zu haben. Die Summenbildung (Variable sum), die im _W offenbar eingefügt wurde, wird benötigt. Allerdings muss die Initialisierung dann auch korrekt sein (siehe oben).

260
Nein, das kann tatsächlich nicht gehen. Deine Programmierung ist grundsätzlich schon richtig, Du übergibst die (ich nehme an globale?) Variable LDT an CX.
Setz mal an CALENDAR_CALC SPE=TRUE, sonst wird der Sonnenstand nicht berechnet. Das dürfte die Ursache sein.

261
Hallo erdbeerschaeler,

der aktuelle horizontale Sonnenwinkel muss zwischen HORZ1 und HORZ2 liegen, der vertikale < VERT sein. In der Struktur CX kannst Du sehen, dass beide Winkel = 0 sind, also offenbar nicht berechnet wurden. Hast Du den Baustein CALENDAR_CALC denn mit eingebunden? Der macht das dann automatisch.

Insofern hast Du Recht, es hat mit den Winkeln zu tun.

Eine andere Sache ist mir noch aufgefallen: BLIND_NIGHT spuckt Status 141 aus, also "Nachtbetrieb aktiv" (und folgerichtig PO=0). Bei den dargestellten Uhrzeiten dürfte das aber eigentlich nicht der Fall sein. Es sei denn, Du hast die Zeit an DTIN zum Testen manuell verstellt, ohne das Datum zu ändern. BLIND_NIGHT geht erst auf Tagbetrieb zurück, wenn sich auch das Datum geändert hat, also am nächsten Tag. Doch das nur am Rande.

Gruß,
mattsches

262
Mit Deinem Edit liegst Du genau richtig. Wirst Du zwischeneitlich vermutlich auch gemerkt haben. Ein Handeingriff führt zu entsprechendem PO am BLIND_INPUT, morgens schaltet sich der BLIND_NIGHT einfach passiv. Man muss das Rollo von Hand hochfahren. Ab dem nächsten Abend sollte es dann funktionieren, wenn man nach dem automatischen Schließen nicht mehr von Hand eingreift.

Zitat
Nur was passiert denn heute Abend? Rollos fahren runter. POS von BLIND_CONTROL_S meldet an POS von BLIND_INPUT den Positionswert. Der landet doch auch wieder direkt am PO?!

Das passiert eben nur bei MASTER_MODE = FALSE. Bei TRUE leitet der BLIND_INPUT die aktuelle Position von BLIND_CONTROL eben nicht weiter an sein PO. Dort bleibt immer die letzte manuell angefahrene Position stehen.

Zitat
Übrigens, woran kann das liegen, dass wenn ich die wago nach dem überspielen neu starte, die Rollos immer hoch fahren? Ist PO am BLIND_INPUT immer per default 255?

Jau, genau das sind die Default-Werte. Kannst Du einfach im Bibliotheksverwalter nachschauen. Links oben die oscat_building anwählen, dann links darunter in der Kategorie Jalousie den BLIND_INPUT. Rechts siehst Du dann die Deklarationen:

VAR_OUTPUT
QU : BOOL := TRUE;
QD : BOOL := TRUE;
STATUS : BYTE;
PO : BYTE := 255;
AO : BYTE := 255;
D1, D2 : BOOL;
END_VAR

Also: Nach dem Einschalten ist der Automatikmodus aktiv und Sollwert=Rollo geöffnet. Also fährt er hoch. BLIND_NIGHT müsste eigentlich für ein Schließen sorgen. Er ist aber darauf angewiesen, dass die Sonnenuntergangszeit schon berechnet wurde. Das passiert mit CALENDAR_CALC aber nur einmal am Tag.

Du könntest den BLIND_INPUT ändern und die VAR_OUTPUT in VAR_OUTPUT RETAIN PERSISTENT ändern. Dann sollten die Werte auch bei einem Neustart erhalten bleiben. Ich sage sollte, denn ich nutze keine Wago und weiß nicht mit völliger Sicherheit, ob der Hersteller die Funktion so unterstützt. Bei Beckhoff braucht es dafür ein paar Klimmzüge.

263
Genau dieses Weitergeben von Position und Winkel bei MASTER_MODE = FALSE (Standardeinstellung) führt dazu, dass die Rollos morgens nicht hochfahren.

Was passiert also?

BLIND_INPUT gibt bei MASTER_MODE = FALSE die Eingänge POS/ANG an PO/AO weiter. Also die aktuelle Position des Rollos, vorausgesetzt, Du hast die Eingänge wie empfohlen auf die entsprechenden Ausgänge von BLIND_CONTROL verschaltet. Wenn nun also BLIND_NIGHT das Rollo schließt (mittels PO=0), wird POS=0, das Rollo ist ja nun heruntergefahren. BLIND_INPUT reicht diesen Wert an PO durch.

Morgens schaltet sich BLIND_NIGHT nun einfach ab und macht sich "transparent". Folge: Er reicht PI/AI an PO/AO durch. Welcher Wert steht nun am Eingang PI an? Richtig, 0. Eben das, was BLIND_INPUT immer noch ausgibt.

Schaltet man nun MASTER_MODE auf TRUE, dann entfällt diese Weitergabe von POS/ANG an PO/AO beim BLIND_INPUT. PO bleibt dort also z. B. auf 255 stehen, auch wenn die tatsächliche Position des Rollos wegen BLIND_NIGHT 0 ist. Schaltet sich nun BLIND_NIGHT morgens ab, steht an dessen Eingang PI 255 an. Er reicht das weiter, und BLIND_CONTROL fährt das Rollo herauf.

Probier's einfach mal aus.

Kleiner Nachtrag: BLIND_NIGHT will überhaupt nicht wissen, wie die aktuelle Position des Rollos ist. Keiner der "mittleren" Bausteine muss das. Alles, was sie tun, ist die Positions- und Winkelsollwerte PO/AO entsprechend ihren internen Algorithmen zu beschreiben. Dass das Rollo dann tatsächlich auf diese Position fährt, dafür ist BLIND_CONTROL verantwortlich.

264
Zur Verdeutlichung hier noch ein Screenshot, wie das bei mir gerade ausschaut.

QU/QD vom BLIND_INPUT sind TRUE, Automatikbetrieb ist also aktiv. BLIND_INPUT gibt außerdem PO=100 und AO=90 aus. Obacht, wie erwähnt, ich habe die Bausteine angepasst. Bei den Standardbausteinen würde hier jeweils 255 stehen (für ganz geöffnet).

Die Jalousie ist aber geschlossen. Warum? Schauen wir mal weiter.

BLIND_SHADE leitet PI und AI einfach an PO und AO durch. Wenn es nach ihm geht, wäre die Jalousie also auch geöffnet. Logisch, es scheint ja keine Sonne (davon mal abgesehen, dass es sich hier eh um ein Nordfenster handelt).

Wenn Du nun BLIND_NIGHT anschaust, siehst Du PO=0 und AO=18. Denke Dir statt der 18 bitte einfach 0, auch das ist eine Folge meiner Änderungen (meine Jalousien schließen nicht weiter als 18°). QU und QD sind weiterhin beide TRUE. Also überfährt der BLIND_NIGHT hier die anderen Bausteine und fordet ein Schließen der Jalousie an. Prima, es ist ja auch Abend/Nacht.

BLIND_SECURITY stellt gerade keinen besonders starken Wind fest und hat damit keinen Anlass, die an PI und AI anstehenden Werte zu korrigieren. Er kopiert sie daher einfach auf PO und AO.

BLIND_CONTROL bemerkt nun schlussendlich den Automatikbetrieb, weiß also, dass er die Ausgänge MU und MD (an denen der Jalousienmotor hängt) so ansteuern soll, dass die an AI und PI anstehenden Werte erreicht werden. Er hat also die Jalousie herunter gefahren und danach die Ausgänge abgeschaltet.

Ergebnis: Es schaut uns keiner ins Bad.   :)

[gelöscht durch Administrator]

265
Ja, genau:

Zitat
Werden beide Eingänge UP und DN auf TRUE gesetzt so schalten die betrefenden Module auf Automatik Modus und werten die Eingänge PI und AI (Position- und Winkel- Eingang für die Jalousie aus.

PO ist kein reiner Statusausgang, sondern der Positions-Sollwert eines Bausteins.

Beispiel: Bei mir sind die Bausteine in folgender Reihenfolge aufgebaut:

BLIND_INPUT - BLIND_SHADE - BLIND_NIGHT - BLIND_SECURITY - BLIND_CONTROL

Von hinten nach vorne:

  • BLIND_CONTROL macht die tatsächliche Ansteuerung der beiden Digitalausgänge bzw. des Jalousienmotors. Ist nur einer der beiden Eingang UP/DN = TRUE, fährt er die Jalousie in die angegebene Richtung. Sind beide TRUE, steuert er die Ausgänge so an, dass die durch PI definierte Position und der durch AI definierte Lamellenwinkel erreicht wird. Damit das funktioniert, müssen die beiden Zeiten T_UD und T_ANGLE richtig eingestellt sein.
  • BLIND_SECURITY fährt die Jalousie in meinem Fall herauf, wenn die Wetterstation zu viel Wind meldet (indem QU=TRUE und QD=FALSE gesetzt wird). Das macht er immer, unabhängig davon, ob Hand- oder Automatikbetrieb aktiv ist. Ist ja eine Notfunktion.
  • BLIND_NIGHT fährt die Jalousie abends herunter, sofern sie sich im Automatikbetrieb befindet. UP/DN werden nach QU/QD kopiert (in diesem Fall beide TRUE), AI und PI werden ignoriert, stattdessen wird PO=0 und AO=0 geschrieben. Wenn gerade keine Nacht ist, kopiert der Baustein AI/PI nach AO/PO, ist also wirkungslos.(
  • BLIND_SHADE fährt - wenn der Automatikmodus aktiv ist - die Jalousie bei SUN=TRUE und ENABLE=TRUE herunter und führt den Lamellenwinkel nach. Auf AO und PO werden dann errechnete Werte geschrieben, AI und PI werden wieder ignoriert. Scheint keine Sonne, werden AI/PI nach AO/PO kopiert.
  • Nun zu BLIND_INPUT: Im Automatikbetrieb werden wie schon beschrieben QU und QD gleichzeitig auf TRUE gesetzt, um den nachfolgenden Bausteinen eben diesen Automatikbetrieb mitzuteilen. Denn nur in diesem Fall wird z. B. ein BLIND_NIGHT überhaupt aktiv. Im Handbetrieb ist nur einer der beiden Ausgänge aktiv, und auch nur so lange, wie die Jalousie von Hand gefahren werden soll. Die nachfolgenden Bausteine reichen die beiden Signale dann einfach durch, bis sie am BLIND_CONTROL ankommen und der den Motor entspreched ansteuert.

Durch die Reihenfolge der Bausteine ergibt sich, wer letztendlich das Sagen hat. Wenn BLIND_SHADE zwar meint, die Jalousie müsse geschlossen sein, weil es Nacht ist, kann trotzdem noch BLIND_SECURITY dafür sorgen, dass sie oben bleibt (weil z. B. der Wind zu stark ist). Denn jeder Baustein leitet entweder die Eingänge einfach weiter an die jeweiligen Ausgänge, wenn er funktionslos ist. Oder er schreibt andere Werte auf die Ausgänge, wenn er es "für richtig hält". Damit ist klar, dass der letzte in der Kette am meisten "zu sagen" hat. Quasi wie bei stiller Post.

Obacht, die Zahlenwerte an PI und AI sind größenlos und auf 0..255 normiert. Ich fand das nicht so verständlich und habe mir die Bausteine so umprogrammiert, dass ich mit Winkelangaben und 0..100 % für die Positon arbeiten kann. Siehe hier: http://www.oscat.de/community/index.php/topic,2143.0.html

Zweites Obacht: Wenn Du möchtest, dass die Jalousie morgens automatisch wieder hochfährt, muss Du an BLIND_NIGHT E_DAY=TRUE setzen (soweit einleuchtend), zusätzlich am BLIND_INPUT jedoch noch MASTER_MODE auf TRUE nehmen.

Hilft Dir das ein bisschen?

266
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

267
Hallo NightWatcher,

wenn QU und QD beide TRUE sind, ist der Automatikbetrieb aktiv. Nachgeschaltete Bausteine (in Deinem Fall BLIND_NIGHT) können dann Position und Lamellenwinkel nach ihren jeweiligen Regeln über PO und AO steuern. Wird einer der beiden Eingänge S1 oder S2 am BLIND_INPUT TRUE, geht der Baustein in Handbetrieb, und die Jalousie wird manuell gefahren. Nach der Zeit MANUAL_TIMEOUT wechselt der Baustein dann wieder in den Automatikbetrieb.

Schau mal in die Doku der Building Library, in Kap. 7 steht das ganz gut beschrieben.

Grüße,
mattsches

268
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;

Seiten: 1 ... 16 17 [18]