Probleme mit FC

emilio20

Level-1
Beiträge
835
Reaktionspunkte
20
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo

habe mal eine Grundlegende Frage zu den FC s

Ich habe einen FC mit dem ich Sonnenaufgang und Sonnenuntergang berechne. Damit der FC nicht Permanent den Algorithmus durchläuft habe ich eine In Out variable wann der Letzte Tag der Berechnung war. Soweit funktioniert der Baustein auch.

Wenn ich die CPU Stoppe und wieder Starte bekomme ich im DB wo sich die Werte befinden den Zeitwert 00:00:00.000 . Im Speicher steht aber noch der Letzte Tag. Erst bei Tageswechsel wird wieder Berechnet.

Ligt das an der In_Out Variable SP_BERECHNUNG_TAG ?

Code:
(*****************************************************************************************************************************************************)
FUNCTION SUN_TIME:VOID
TITLE = 'Berechnung Sonnenzeiten'
(*****************************************************************************************************************************************************)
// Benötigte Bausteine
// FC131 UHRZEIT


VAR_INPUT
    Aktuelle_Zeit                 :TOD;
    JahresTag                     :INT; // Jahres Tages Nummer
    Zeitzone                      :TIME;//
    geographische_Lange           :REAL;// Länge von Stadt Sandberg ist 10
    geographische_Breite          :REAL;// Breitengrad von Stadt Sandberg ist 50.35
    Daemmerung                    :INT; // 0=geometrische Dämerung, 1=bürgerlicher Dämmerung,2=nautische Dämmerung, 3=Astro Dämerung
END_VAR

VAR_OUTPUT
    Aufgang                       :TOD;
    Untergang                     :TOD;
    Tag                           :BOOL;
    Nacht                         :BOOL;
    SonnenStunden                 :TOD;
END_VAR

VAR_IN_OUT
    SP_BERECHNUNG_TAG             :INT; // Speicher letzte Berechnung TagesNummer
END_VAR
    
VAR_TEMP
        
    TEMP_INT                      :INT;
    AKT_DT                        :DT;
    DT_TIME                       :DT;
    AKT_DATE                      :DATE;
    Jahr_anfang_DATE              :DATE;
    i2                            :INT;
    i3                            :INT;
    Timer1                        :TOD;
    YEAR                          :INT;
    WOZ                           :REAL;
    MOZ                           :REAL;
    T                             :REAL;
    Pi                            :REAL;
    Aufgang_Ortszeit              :REAL;
    Untergang_Ortszeit            :REAL;
    Zeitgleichung                 :REAL;
    Deklination                   :REAL;
    Zeitdifferenz                 :REAL;
    B                             :REAL;
    h                             :REAL;
    D                             :REAL;
           
    END_VAR
 
 BEGIN
 
         
  IF SP_BERECHNUNG_TAG <> JahresTag THEN           
// Berechnung ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

   Pi :=3.14159265359; // Pi
   
// Horizonthöhe Dämmerung  
    CASE Daemmerung OF
        0 : D:=-0.833;
        1 : D:=-6    ;
        2 : D:=-12   ;
        3 : D:=-18   ;
     ELSE:
        D:=-0.833    ;
    END_CASE;
 
   T:=INT_TO_REAL (JahresTag);
   B:= Pi *geographische_Breite / 180 ;
   h:=D /57.29578;
   Zeitgleichung := -0.171*SIN(0.0337 * T + 0.465) - 0.1299*SIN(0.01787 * T - 0.168); 
   Deklination := 0.4095*SIN(0.016906*(T-80.086)) ;
   Zeitdifferenz := 12.0*ACOS((SIN(h) - SIN(B)*SIN(Deklination)) / (COS(B)*COS(Deklination)))/Pi;

   Aufgang_Ortszeit := 12.0 - Zeitdifferenz - Zeitgleichung;
   Untergang_Ortszeit := 12.0 + Zeitdifferenz - Zeitgleichung;
   
   Aufgang:=(DINT_TO_TOD (REAL_TO_DINT   ((Aufgang_Ortszeit - (geographische_Lange /15.0) ) *3600000)))+Zeitzone;
   Untergang:=(DINT_TO_TOD (REAL_TO_DINT   ((Untergang_Ortszeit - (geographische_Lange /15.0) ) *3600000)))+Zeitzone;
   
   SonnenStunden:=DINT_TO_TOD (TOD_TO_DINT (Untergang)-TOD_TO_DINT (Aufgang));
   
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  // Speicher wann letzte berechnung war  
   SP_BERECHNUNG_TAG := JahresTag;  
   
END_IF;
   
   // Abfrage Tag oder Nacht 
   IF Aktuelle_Zeit > Aufgang AND Aktuelle_Zeit < Untergang THEN
      TAG:=TRUE;
      NACHT:=FALSE;
   ELSE
      TAG:=FALSE;
      NACHT:=TRUE;
   END_IF;      

              
 END_FUNCTION
 
Hallo Emilio,

meinen Respekt wenn's funktioniert! Die Ausgänge einer FC müssen immer zyklisch beschrieben werden. Mache aus den Ausgängen IN_OUTs oder aus der FC einen FB.


Gruß, Onkel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Habe jetzt erst mal im OB 100 den Speicher Wert auf 0 gesetzt.

Ja das Programm funktioniert. Man benötigt allerdiengs diesen Baustein für die Zeiten usw.

Ist deine meinung nach der Aufbau Ok oder zu umständlich ?

Code:
(*****************************************************************************************************************************************************)
DATA_BLOCK AKTUELLE_ZEIT
(*****************************************************************************************************************************************************)

    STRUCT
          
    DatumUhrzeit                          :DT;
    DatumUhrzeit_set                      :DT;
    Datum                                 :DATE;
    Lokalzeit                             :TOD;
    UTC                                   :TOD;
    UTC_Zeitzone                          :TIME:=T#1H;// Berlin
    Zeitzone                              :TIME:=T#1H; //Lokalzeit +1 Winterzeit
    Jahr                                  :INT;
    Jahres_Tag                            :INT;
    Monat                                 :INT;
    Monats_Tag                            :INT;
    Wochen_Tag                            :INT;
    Stunde                                :INT;
    Minute                                :INT;
    Sekunde                               :INT;
    Umstellungs_Sommerzeit                :DT;
    Umstellungs_Winterzeit                :DT;
    Sommerzeit                            :BOOL;
    Winterzeit                            :BOOL;
    P_Sommerzeit                          :BOOL;
    P_Winterzeit                          :BOOL;
    Edge_flag_pos1                        :BOOL;
    Edge_flag_pos2                        :BOOL;  
    HMI_Uhr_Stellen                       :BOOL;
    SOMMER_TO_WINTER                      :BOOL;    
            
    END_STRUCT
BEGIN
 

END_DATA_BLOCK


FUNCTION UHRZEITEN : VOID

VAR_TEMP
    
    TEMP_INT                      :INT;
    TEMP_SFC0                     :INT;
    AKT_DT                        :DT;
    DT_TIME                       :DT;
    DT_TIME1                      :DT;
    Umstellung_Time               :TIME;

    Jahr_anfang_DATE              :DATE;
    Timer1                        :TOD;
    TAG_Sommerzeit                :INT;
    TAG_Winterzeit                :INT;
        
    AT_AKT_DT AT AKT_DT:
              STRUCT 
                JAHR             : BYTE;
                MONAT            : BYTE;
                TAG              : BYTE;
                STUNDE           : BYTE;
                MINUTE           : BYTE;
                SEKUNDE          : BYTE;
                MS_MSD           : BYTE;                          
                MS_LSD           : BYTE;
            END_STRUCT;
            
     AT_DT_TIME AT DT_TIME:
             STRUCT 
                JAHR             : BYTE;
                MONAT            : BYTE;
                TAG              : BYTE;
                STUNDE           : BYTE;
                MINUTE           : BYTE;
                SEKUNDE          : BYTE;
                MS_MSD           : BYTE;                          
                MS_LSD           : BYTE;
            END_STRUCT;
    
    AT_DT_TIME1 AT DT_TIME1:
             STRUCT 
                JAHR             : BYTE;
                MONAT            : BYTE;
                TAG              : BYTE;
                STUNDE           : BYTE;
                MINUTE           : BYTE;
                SEKUNDE          : BYTE;
                MS_MSD           : BYTE;                          
                MS_LSD           : BYTE;
             END_STRUCT;
        
            
            
       
       

END_VAR

    BEGIN
    
    // Uhr Manuell Stellen
    IF AKTUELLE_ZEIT.HMI_Uhr_Stellen THEN    
       TEMP_SFC0:=SET_CLK(PDT :=AKTUELLE_ZEIT.DatumUhrzeit_set);
       AKTUELLE_ZEIT.HMI_Uhr_Stellen:=False;
    END_IF;

        
    // Aktuelle Systemzeit lesen
    TEMP_INT := READ_CLK(CDT := AKT_DT);
    
    // Aktuelles Datum
    AKTUELLE_ZEIT.Datum :=DT_DATE(IN :=AKT_DT); 
    
    // Datum und Zeit in DB verschieben
    AKTUELLE_ZEIT.DatumUhrzeit :=AKT_DT;
    
    // Lokalzeit Berechnen
    AKTUELLE_ZEIT.Lokalzeit:=DT_TOD(IN :=AKT_DT); 

    
    // Jahr in DB verschieben
    AKTUELLE_ZEIT.Jahr:=BCD_TO_INT (AT_AKT_DT.JAHR);   
        
    // Jahrestag Berechnen und in DB verschieben
    Jahr_anfang_DATE:=D#2010-01-01;
    DT_TIME:=D_TOD_DT(IN1 :=Jahr_anfang_DATE,IN2 := Timer1);                   // Jahres anfang auslesen und in DT umwandeln T=Platzhalter
    AT_DT_TIME.JAHR  := AT_AKT_DT.JAHR;                                        // Aktuelle Jahreszahl in AT Sicht Jahr schreiben
    Jahr_anfang_DATE  :=DT_DATE(IN :=DT_TIME);     
    AKTUELLE_ZEIT.Jahres_Tag:=DINT_TO_INT (DATE_TO_DINT (AKTUELLE_ZEIT.Datum) - DATE_TO_DINT (Jahr_anfang_DATE))+1;
    
    // Monat in DB verschieben
    AKTUELLE_ZEIT.Monat:=BCD_TO_INT (AT_AKT_DT.MONAT);
    
    // Monats Tag in DB verschieben
    AKTUELLE_ZEIT.Monats_Tag:=BCD_TO_INT (AT_AKT_DT.TAG);

    // Wochentag in DB verschieben
    AKTUELLE_ZEIT.Wochen_Tag :=DT_DAY(IN :=AKT_DT);
    
    // Stunde in DB verschieben
    AKTUELLE_ZEIT.Stunde:=BCD_TO_INT  (AT_AKT_DT.STUNDE);

    // Minute in DB verschieben
    AKTUELLE_ZEIT.Minute:=BCD_TO_INT (AT_AKT_DT.MINUTE);
    
    // Sekunde in DB verschieben
    AKTUELLE_ZEIT.Sekunde:=BCD_TO_INT (AT_AKT_DT.SEKUNDE);
    
       
    // Berechnung der UmstellungsTag Sommerzeit
    DT_TIME1:=DT#2013-03-31-02:00:00.000;// Achtung Datum muss immer ein Sonntag sein sonst fehler in der Berechnung der Zeit
    AT_DT_TIME1.JAHR:=WORD_TO_BYTE(INT_TO_BCD (AKTUELLE_ZEIT.Jahr));
    TAG_Sommerzeit:=31 -((AKTUELLE_ZEIT.Jahr + 5 + (AKTUELLE_ZEIT.Jahr/4)) MOD 7);
    AT_DT_TIME1.TAG:=WORD_TO_BYTE(INT_TO_BCD (TAG_Sommerzeit));
    AKTUELLE_ZEIT.Umstellungs_Sommerzeit:=DT_TIME1;
    
    // Berechnung der UmstellungsTag Winterzeit
    DT_TIME:=DT#2013-10-27-03:00:00.0; // Achtung Datum muss immer ein Sonntag sein sonst fehler in der Berechnung der Zeit
    AT_DT_TIME.JAHR:=WORD_TO_BYTE(INT_TO_BCD (AKTUELLE_ZEIT.Jahr));
    TAG_Winterzeit:=31 -((AKTUELLE_ZEIT.Jahr + 2 + (AKTUELLE_ZEIT.Jahr/4)) MOD 7);
    AT_DT_TIME.TAG:=WORD_TO_BYTE(INT_TO_BCD (TAG_Winterzeit));
    AKTUELLE_ZEIT.Umstellungs_Winterzeit:=DT_TIME;
    
    // Umstellung von Sommer auf Winterzeit von 3:00 auf 2:00 Uhr. Nach umstellung Bit von 2:00 bis 3:00 Uhr setzten damit Zeit nicht wieder auf Sommerzeit springt  
    AKTUELLE_ZEIT.SOMMER_TO_WINTER:=AKTUELLE_ZEIT.Winterzeit AND (AKT_DT > AKTUELLE_ZEIT.Umstellungs_Winterzeit+-T#1H AND AKT_DT < AKTUELLE_ZEIT.Umstellungs_Winterzeit);
     
    
     //  Sommerzeit 
    IF (AKT_DT>AKTUELLE_ZEIT.Umstellungs_Sommerzeit AND AKT_DT < AKTUELLE_ZEIT.Umstellungs_Winterzeit) AND NOT AKTUELLE_ZEIT.SOMMER_TO_WINTER THEN
       AKTUELLE_ZEIT.Sommerzeit:=TRUE;
       AKTUELLE_ZEIT.Winterzeit:=FALSE;
       AKTUELLE_ZEIT.Zeitzone:=AKTUELLE_ZEIT.UTC_Zeitzone+T#1H;
       Umstellung_Time:=T#1h;
    ELSE // Winterzeit
       AKTUELLE_ZEIT.Sommerzeit:=FALSE;
       AKTUELLE_ZEIT.Winterzeit:=TRUE; 
       AKTUELLE_ZEIT.Zeitzone:=AKTUELLE_ZEIT.UTC_Zeitzone;
       Umstellung_Time:=T#23h;
                                    
    END_IF;
    
    // Flankenmerker   
    //Bildung der positiven Flanke  //get the positive pulse
     AKTUELLE_ZEIT.P_Sommerzeit  := AKTUELLE_ZEIT.Sommerzeit AND NOT AKTUELLE_ZEIT.Edge_flag_pos1;
     AKTUELLE_ZEIT.Edge_flag_pos1   := AKTUELLE_ZEIT.Sommerzeit;
     
     AKTUELLE_ZEIT.P_Winterzeit  := AKTUELLE_ZEIT.Winterzeit AND NOT AKTUELLE_ZEIT.Edge_flag_pos2;
     AKTUELLE_ZEIT.Edge_flag_pos2   := AKTUELLE_ZEIT.Winterzeit;

   
    // Uhr Umstellung Sommer Winterzeit
    IF AKTUELLE_ZEIT.P_Sommerzeit OR AKTUELLE_ZEIT.P_Winterzeit THEN
       AKTUELLE_ZEIT.Lokalzeit:=AKTUELLE_ZEIT.Lokalzeit+Umstellung_Time;
       AKTUELLE_ZEIT.DatumUhrzeit:=D_TOD_DT(IN1 :=AKTUELLE_ZEIT.Datum,IN2 := AKTUELLE_ZEIT.Lokalzeit);
       TEMP_SFC0:=SET_CLK(PDT :=AKTUELLE_ZEIT.DatumUhrzeit); 
    END_IF ; 
     
     //UTC Berechnen
      AKTUELLE_ZEIT.UTC:=AKTUELLE_ZEIT.Lokalzeit +- AKTUELLE_ZEIT.Zeitzone;

    
            
          
    
       
       END_FUNCTION
 
Zuletzt bearbeitet:
Deine Berechnung wird ja nur einmal am Tag ausgeführt.
Beim Neustart der CPU am gleichen Tag findet keine Berechnung mehr statt und deine Parameter bleiben auf 0.
Du kannst im OB100 dein Datenwort für SP_BERECHNUNG_TAG mal auf -1 setzen.
Damit wird die Berechnung bei Neustart durchgeführt.

Gruß
Dieter
 
Zurück
Oben