oscat.lib > Modulentwicklung / Module Development

Jalousiesteuerung

<< < (3/3)

SHendrik:
Hallo.

Habe nun schon mehrere Monate an meiner Rollladensteuerung gespielt und programmiert.

Anbei mein FB als Info ...

in dieser Struktur speichere ich für jeden Rollladen die letzten Bewegungen mit Position und Zeit, je Wochentag + Betriebsstunden

TYPE tRolloConf:
  STRUCT
    iDemandTime:ARRAY[1..MAXROLLSP,1..MAX_DAY] OF TOD;
    iDemandPos:ARRAY[1..MAXROLLSP,1..MAX_DAY] OF INT;
    iDemandIndex:INT:=1;
    iBetrStunden:TIME;
    END_STRUCT
END_TYPE

über diese Struktur erhält man den Namen,Position und kann Automatikbefehle über Sollposition und bChangePosition schicken ..
der if_time Block, dient der Anwesenheitssimulation, die dann die gespeicherten Sollposition aus der oberen Struktur wieder anfährt ...

TYPE tRollo:
   STRUCT
      sName:STRING[20];
      iPosition:INT;
      PositionTime: TIME:= t#0s;
      SollPosition:INT;
      bChangePosition:BOOL;
      if_Time:ARRAY[1..MAXROLLSP] OF IfTime;
   END_STRUCT
END_TYPE

nun der FB ...

FUNCTION_BLOCK Rolladensteuerung
VAR_INPUT
    Taster_Roll_Hoch:BOOL;
    Taster_Roll_Runter:BOOL;
    Gruppe_Roll_Hoch:BOOL;
    Gruppe_Roll_Runter:BOOL;
    Beschattung:BOOL;
    Beschattung_Pos:INT;
    MaxTime: TIME;
   iRoll:INT;
    bExtern:BOOL;
END_VAR
VAR_OUTPUT
    Ausgang_Roll_Hoch:BOOL;
   Ausgang_Roll_Runter:BOOL;
   Position: INT:=0;
END_VAR
VAR

   Eingang_Roll_Hoch :BOOL;
   Eingang_Roll_Runter:BOOL;
   edge_hoch : BOOL;
   edge_runter : BOOL;
   edge_Taster_hoch : BOOL;
   edge_Taster_runter : BOOL;
   t_neu: TIME;
   t_last: TIME;
   t_taster_hoch_alt: TIME;
   t_taster_runter_alt: TIME;
   t_last_time_hoch: TIME;
   t_last_time_runter: TIME;
   t_alt: TIME;
   t_delta: TIME;
   postmp: DINT;
   up_time:IfTime;
   down_time:IfTime;
   bSwitchUpTime: BOOL;
   bSwitchDownTime: BOOL;

   ExternAktiv: BOOL;
   stmp: STRING;
   Index: INT;
   bHandbedienung: BOOL;
   day: INT;
   bCal: BOOL;
END_VAR

(*aktuelle Zeit holen*)
t_neu := TIME();

(*Löschen der Speicherdaten*)
IF ClearRollData=1 THEN
   Config.Rollos[iRoll].iBetrStunden:=T#0s;
   Config.Rollos[iRoll].iDemandIndex:=1;
   FOR day:=1 TO MAX_DAY DO
      FOR Index:=1 TO MAXROLLSP DO
         Config.Rollos[iRoll].iDemandTime[Index,day]:=TOD#00:00:00;
         Config.Rollos[iRoll].iDemandPos[Index,day]:=0;
      END_FOR
   END_FOR
END_IF

(*Verknüpfung des Einzel- u. Gruppeneingangs*)
Eingang_Roll_Hoch:=Taster_Roll_Hoch OR Gruppe_Roll_Hoch;
Eingang_Roll_Runter:=Taster_Roll_Runter OR Gruppe_Roll_Runter;

(*Eingangsabfrage Hoch*)
IF Eingang_Roll_Hoch AND NOT edge_taster_hoch THEN
   (*wenn gedrückt*)
   (*Automatik abbrechen*)
   ExternAktiv:=FALSE;
   edge_taster_hoch := TRUE;
   (*Zeit merken*)
   t_taster_hoch_alt:=t_neu;
ELSIF NOT Eingang_Roll_Hoch AND edge_taster_hoch THEN
   (*wenn losgelassen*)
   edge_taster_hoch := FALSE;
END_IF

(*Eingang Hoch wurde betätigt*)
IF edge_taster_hoch THEN
   (*Abfrage der Tastzeit*)
   IF t_neu-t_taster_hoch_alt>Config.Rollos_TastZeitKurz THEN
      (*Lange Tastzeit -> Automatik / Zeit merken*)
      (*Handbedienungsflag setzen -> keine Fenstertürkontaktprüfung*)
      bHandbedienung:=TRUE;
      Rollos[iRoll].bChangePosition:=TRUE;
      Rollos[iRoll].SollPosition:=0;
   END_IF
END_IF

(*Eingangsabfrage Runter*)
IF Eingang_Roll_Runter AND NOT edge_taster_runter THEN
   (*wenn gedrückt*)
   (*Automatik abbrechen*)
   ExternAktiv:=FALSE;
   edge_taster_runter := TRUE;
   t_taster_runter_alt:=t_neu;
ELSIF NOT Eingang_Roll_Runter AND edge_taster_runter THEN
   (*wenn losgelassen*)
   edge_taster_runter := FALSE;
END_IF

(*Eingang Runter wurde betätigt*)
IF edge_taster_runter THEN
   IF t_neu-t_taster_runter_alt>Config.Rollos_TastZeitKurz THEN
      (*Lange Tastzeit -> Automatik / Zeit merken*)
      bHandbedienung:=TRUE;
      Rollos[iRoll].bChangePosition:=TRUE;
      Rollos[iRoll].SollPosition:=100;
   END_IF
END_IF

(*Simulation*)
IF bSimulation=1 THEN
   FOR Index:=1 TO MAXROLLSP DO
      Rollos[iRoll].if_Time[Index](ActTime:=Times.dActualTime_TOD, SwitchTime:=Config.Rollos[iRoll].iDemandTime[Index,Times.weekday], bSwitchTime=>bSwitchUpTime);
      IF bSwitchUpTime=1 AND bSimulation THEN
         Rollos[iRoll].bChangePosition:=TRUE;
         Rollos[iRoll].SollPosition:=Config.Rollos[iRoll].iDemandPos[Index,Times.weekday];
         bHandbedienung:=TRUE;
      END_IF
   END_FOR
END_IF

(*Ausgang Hoch setzen*)
IF Eingang_Roll_Hoch=1 THEN
   Ausgang_Roll_Hoch:=TRUE;
   Ausgang_Roll_Runter:=FALSE;
(*Ausgang Runter setzen*)
ELSIF Eingang_Roll_Runter=1 THEN
   Ausgang_Roll_Hoch:=FALSE;
   Ausgang_Roll_Runter:=TRUE;
ELSE
   (*Ausgänge löschen*)
   Ausgang_Roll_Hoch:=FALSE;
   Ausgang_Roll_Runter:=FALSE;
END_IF

(*Beschattungsabfrage*)
IF Beschattung THEN
   IF ABS(Beschattung_Pos-Position)>1 THEN
      Rollos[iRoll].bChangePosition:=TRUE;
      Rollos[iRoll].SollPosition:=Beschattung_Pos;
      bHandbedienung:=TRUE;
   END_IF
END_IF

(*Externe Sollwertvorgabe*)
IF Rollos[iRoll].bChangePosition THEN
   Rollos[iRoll].bChangePosition:=FALSE;
   IF ABS(Rollos[iRoll].SollPosition-Position)>1 THEN
      (*Automatikbetriebsarten löschen*)
      (*Externaktiv Flag setzen*)
      ExternAktiv:=TRUE;
      IF Rollos[iRoll].SollPosition<Rollos[iRoll].iPosition THEN
         bHandbedienung:=TRUE;
      END_IF
      IF Rollos[iRoll].SollPosition=0 THEN
         bCal:=1;
      ELSE
         bCal:=0;
      END_IF
   END_IF
END_IF

(*Abfrage Externaktiv*)
IF ExternAktiv THEN
   IF bExtern=TRUE OR bHandbedienung=TRUE THEN
      (*Vergleich Soll-/Ist-Position*)
      IF ABS(Rollos[iRoll].SollPosition-Position)>=1 OR bCal THEN
         IF ABS(Rollos[iRoll].SollPosition-Position)<1 THEN
            IF t_neu-t_last>t#5s THEN
               bCal:=FALSE;
            END_IF
         ELSE
            t_last:=t_neu;
         END_IF
         (*Ausgang Runter setzen*)
         IF Rollos[iRoll].SollPosition>Position THEN
            Ausgang_Roll_Runter:=TRUE;
            Ausgang_Roll_Hoch:=FALSE;
                ELSE
            (*Ausgang Hoch setzen*)
            Ausgang_Roll_Hoch:=TRUE;
            Ausgang_Roll_Runter:=FALSE;
         END_IF;
      ELSE
         stmp:=CONCAT('->',INT_TO_STRING(Rollos[iRoll].SollPosition));
         stmp := CONCAT (Rollos[iRoll].sName,stmp);
         stmp := CONCAT ('Rolladen ',stmp);
         BDEMeldung(MeldungIn:=stmp);

         IF bSimulation=0 THEN
            Config.Rollos[iRoll].iDemandTime[Config.Rollos[iRoll].iDemandIndex,Times.weekday]:=Times.dActualTime_TOD;
            Config.Rollos[iRoll].iDemandPos[Config.Rollos[iRoll].iDemandIndex,Times.weekday]:=Rollos[iRoll].SollPosition;
            IF Config.Rollos[iRoll].iDemandIndex<MAXROLLSP THEN
               Config.Rollos[iRoll].iDemandIndex:=Config.Rollos[iRoll].iDemandIndex+1;
            ELSE
               Config.Rollos[iRoll].iDemandIndex:=1;
            END_IF
         END_IF
         (*wenn Position erreicht -> Beschattungaktiv auf 0*)
         bHandbedienung:=FALSE;
         ExternAktiv:=FALSE;
      END_IF
   ELSE
      ExternAktiv:=FALSE;
   END_IF
END_IF

(*Abfrage, wann letzter Runter Vorgang*)
IF Ausgang_Roll_Hoch THEN
   (*Ausgang Hoch für Zeit sperren*)
   IF t_neu-t_last_time_Runter<Config.Rollos_PauseAufAb THEN
      Ausgang_Roll_Hoch:=FALSE;
   END_IF
   t_last_time_Hoch:=t_neu;
END_IF

(*Abfrage, wann letzter Hoch Vorgang*)
IF Ausgang_Roll_Runter THEN
   (*Ausgang Runter für Zeit sperren*)
   IF t_neu-t_last_time_Hoch<Config.Rollos_PauseAufAb THEN
      Ausgang_Roll_Runter:=FALSE;
   END_IF
   t_last_time_Runter:=t_neu;
END_IF

(*Sicherheitsabfrage, damit nicht beide Ausgänge geschaltet*)
IF Ausgang_Roll_Hoch=1 THEN
   IF  Ausgang_Roll_Runter=1 THEN
      Ausgang_Roll_Hoch:=FALSE;
      Ausgang_Roll_Runter:=FALSE;
   END_IF;
END_IF;

(*Betriebsstunden hochzählen*)
IF Ausgang_Roll_Runter OR Ausgang_Roll_Hoch THEN
      Config.Rollos[iRoll].iBetrStunden:=Config.Rollos[iRoll].iBetrStunden+t_neu-t_alt;
END_IF

(*Abfrage ob Ausgang zugeschaltet*)
IF Ausgang_Roll_Hoch AND NOT edge_hoch THEN
   edge_hoch := TRUE;
ELSIF NOT Ausgang_Roll_Hoch AND edge_hoch THEN
   edge_hoch := FALSE;
END_IF

(*Abfrage ob Ausgang zugeschaltet*)
IF edge_hoch THEN
   t_delta:=t_neu-t_alt;
   (*Berechnung neuer Bestrommungszeit*)
   Rollos[iRoll].PositionTime:=Rollos[iRoll].PositionTime-REAL_TO_TIME(TIME_TO_REAL(t_delta)*(1/Config.Rollos_RollUpFaktor));
   IF Rollos[iRoll].PositionTime>MaxTime THEN
      Rollos[iRoll].PositionTime:=t#0s;
   END_IF
END_IF

(*Abfrage ob Ausgang zugeschaltet*)
IF Ausgang_Roll_Runter AND NOT edge_runter THEN
   edge_runter := TRUE;
ELSIF NOT Ausgang_Roll_Runter AND edge_runter THEN
   edge_runter := FALSE;
END_IF

(*Abfrage ob Ausgang zugeschaltet*)
IF edge_runter THEN
   t_delta:=t_neu-t_alt;
   (*Berechnung neuer Bestrommungszeit*)
   Rollos[iRoll].PositionTime:=Rollos[iRoll].PositionTime+t_delta;
   IF Rollos[iRoll].PositionTime>MaxTime THEN
      Rollos[iRoll].PositionTime:=MaxTime;
   END_IF
END_IF

(*Berechnung Position aus Bestromungszeit*)
postmp:=TIME_TO_DINT(Rollos[iRoll].PositionTime)*100;
Position:=DINT_TO_INT(postmp/TIME_TO_DINT(MaxTime));
Rollos[iRoll].iPosition:=Position;
t_alt:=t_neu;

was an der ganzen Sache interessant ist,

- er speichert alle Position die angefahren wurden
- wenn das Simulation's Bit gesetzt ist, fährt er seine Sollwerte aus dem Speicher
- der FB berechnet sich aus der bisherigen Bestromungszeit die aktuelle Position..
- er fährt nur auf die Sollposition geregelt ..
- eingebauter Faktor für Mehrzeit beim Hochfahren ...
- Selbstkalibrierung beim Hochfahren auf 0 -> längere Bestromung als nötig ...

klaus313:
... interessant !!

Kannst Du noch die Definiotion von "IfTime" nachliefern.

Danke
Klaus

SHendrik:
Hallo.

IfTime:

FUNCTION_BLOCK IfTime
VAR_INPUT
   ActTime:TOD;
   SwitchTime:TOD;
END_VAR
VAR_OUTPUT
   bSwitchTime:BOOL;
END_VAR
VAR
   bEdge:BOOL;
END_VAR

(*Switch Standard auf False*)
bSwitchTime:=FALSE;
(*wenn Zeit kleiner ... *)
IF ActTime<SwitchTime THEN
   bEdge:=TRUE;
END_IF

(*wenn Zeit größer und vorher kleiner*)
IF ActTime>=SwitchTime THEN
   IF bEdge=TRUE THEN
      bSwitchTime:=TRUE;
   END_IF
   bEdge:=FALSE;
END_IF

Viele Grüße

Hendrik

Navigation

[0] Themen-Index

[*] Vorherige Sete

Zur normalen Ansicht wechseln