Step 7 Sommer Winter Zeit und das Richtige Datum...

erzteufele

Level-2
Beiträge
738
Reaktionspunkte
167
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin,

bestimmt denkt jetzt die hälfte ohhh wieder das gleiche wie jedes jahr :D gibt ja auch schon genug Themen dazu aber ich wollte es nochmal aufgreifen ;)
wann sommerzeit ist und die Zeit eine Stunde zu addieren kann ja jeder nun gibt es ja auch anlagen bei denen Datum und Uhrzeit gedruckt werden und diese über 3 Schichten laufen
d.h. wenn man mit dem addieren der stunde bei 25 ankommt muss der tag addiert werden ... hat hier jmd was fertiges bevor ich das selbst mache ? :))

grüßel erzi
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
ich wollte eihgentlich schon früher antworten - habe es aber auch jetzt erst geschafft ...
Hier nun der Code - SCL - ich hoffe, du kannst das verwenden ...
Code:
FUNCTION_BLOCK FB11            // UP SPS-Sommerzeit

TITLE   = 'UP SPS-Sommerzeit'  // UP SPS-Sommerzeit
AUTHOR  : 'LL'
VERSION : '1.0'    //    03.01.2012
FAMILY  : 'LL_Std'
//KNOW_HOW_PROTECT

// -----------------------------------------------------------------------------------------------------------------------

VAR_INPUT 
END_VAR

VAR_IN_OUT
END_VAR 

VAR_OUTPUT 
    UhrZeit           : TOD ;          // Systemzeit der SPS in ms seit 0:00 Uhr
    Datum             : DATE ;         // Datum der SPS in Tagen seit dem 01.01.1990
    
    Wochentag         : INT ;          // Wochentag (1=So, 2=Mo, ... , 7=Sa)
    Day_of_Year       : INT ;          // Tag des laufenden Jahres
    Week_of_Year      : INT ;          // Kalenderwoche des laufenden Jahres
END_VAR

// -----------------------------------------------------------------------------------------------------------------------

VAR
    UhrZeit_DINT       : DINT ;         // Systemzeit der SPS in ms seit 0:00 Uhr
       at_UhrZeit AT UhrZeit_DINT : TOD ;
    Datum_INT          : INT ;          // Datum der SPS in Tagen seit dem 01.01.1990
       at_Datum AT Datum_INT : DATE ;
    
    Sommer_Winter_Zeit : STRUCT  
      aktuell          : CHAR ;         // aktuelle Zeitzone 'S'=Sommerzeit , 'W'=Winterzeit
      Set_SZ           : BOOL ;         // - Systemuhr auf Sommerzeit setzen
      Set_WZ           : BOOL ;         // - Systemuhr auf Winterzeit setzen
      Tag_Wechsel_SZ   : INT ;          // - Jahrestag, an dem nach Sommerzeit gewechselt wird
      Tag_Wechsel_WZ   : INT ;          // - Jahrestag, an dem nach Winterzeit gewechselt wird
    END_STRUCT ;
      
    Save : STRUCT                      // Hilfsspeicher Berechnung
        Wochentag      : INT := -1 ;   // Speicher Wochentag
        Stunde         : INT := -1 ;   // Speicher Stunde
        Minute         : INT := -1 ;   // Speicher Minute
    END_STRUCT ;    
END_VAR

VAR_TEMP
    SPS_Datum_Uhrzeit  : DATE_AND_TIME ; // SPS-Datum und -Uhrzeit 
       b_SPS_Datum_Uhrzeit AT SPS_Datum_Uhrzeit : ARRAY [0..7] OF BYTE ;
       
    Error             : INT ;
    b_Jahr            : INT ;
    Jahr              : INT ;
    Schaltjahr        : INT ;
    Monat             : INT ;
    Tag               : INT ;
    Stunde            : INT ;
    Minute            : INT ;
    Sekunde           : INT ;
    MilliSekunden     : INT ;
    MilliSekunden_E   : INT ;
    Anz_SJ            : INT ; 
    Diff_J            : INT ;
    h_Wochentag       : INT ;
    h_Datum           : INT ;
END_VAR


// -----------------------------------------------------------------------------------------------------------------------
BEGIN
// -----------------------------------------------------------------------------------------------------------------------
//    SPS-Systemzeit auslesen ...    
// -----------------------------------------------------------------------------------------------------------------------

  Error := READ_CLK (CDT := SPS_Datum_Uhrzeit) ; 
    
  Stunde  := BCD_TO_INT (b_SPS_Datum_Uhrzeit [3]) ;
  Minute  := BCD_TO_INT (b_SPS_Datum_Uhrzeit [4]) ;
  Sekunde := BCD_TO_INT (b_SPS_Datum_Uhrzeit [5]) ;
  
  MilliSekunden_E := WORD_TO_INT (SHR (IN:=INT_TO_WORD (BCD_TO_INT (b_SPS_Datum_Uhrzeit [7])) , n:=4)) ;
  MilliSekunden := (BCD_TO_INT (b_SPS_Datum_Uhrzeit [6]) *10) + MilliSekunden_E ;

  UhrZeit_DINT := INT_TO_DINT(MilliSekunden) + (INT_TO_DINT(Sekunde) + INT_TO_DINT(Minute)*60 + INT_TO_DINT(Stunde)*3600) * 1000 ;
  UhrZeit      := at_UhrZeit ;
  
  WochenTag := BCD_TO_INT (b_SPS_Datum_Uhrzeit [7] AND 2#0000_1111) ;
  IF (WochenTag <> Save.Wochentag) OR (Stunde <> Save.Stunde) THEN
     b_Jahr := BCD_TO_INT (b_SPS_Datum_Uhrzeit [0]) ; 
        IF b_Jahr < 90 THEN Jahr := 2000 + b_Jahr ; ELSE Jahr := 1900 + b_Jahr ; END_IF ;
     Monat  := BCD_TO_INT (b_SPS_Datum_Uhrzeit [1]) ;
     Tag    := BCD_TO_INT (b_SPS_Datum_Uhrzeit [2]) ;
     IF ((Jahr MOD 4) = 0) THEN Schaltjahr := 1 ; ELSE Schaltjahr := 0 ; END_IF ;
     Day_of_Year := Tag ;
     IF Monat >  1 THEN Day_of_Year := Day_of_Year + 31 ; END_IF ;
     IF Monat >  2 THEN Day_of_Year := Day_of_Year + 28 + Schaltjahr ; END_IF ;
     IF Monat >  3 THEN Day_of_Year := Day_of_Year + 31 ; END_IF ;
     IF Monat >  4 THEN Day_of_Year := Day_of_Year + 30 ; END_IF ;
     IF Monat >  5 THEN Day_of_Year := Day_of_Year + 31 ; END_IF ;
     IF Monat >  6 THEN Day_of_Year := Day_of_Year + 30 ; END_IF ;
     IF Monat >  7 THEN Day_of_Year := Day_of_Year + 31 ; END_IF ;
     IF Monat >  8 THEN Day_of_Year := Day_of_Year + 31 ; END_IF ;
     IF Monat >  9 THEN Day_of_Year := Day_of_Year + 30 ; END_IF ;
     IF Monat > 10 THEN Day_of_Year := Day_of_Year + 31 ; END_IF ;
     IF Monat > 11 THEN Day_of_Year := Day_of_Year + 30 ; END_IF ;
     //            Jahres-Tage              Schaltjahr-Tage      akt. Tag vom lfd. Jahr
     Datum_INT := ((Jahr - 1990) * 365) + ((Jahr - 1992) / 4) - Schaltjahr + Day_of_Year ;
     Datum     := at_Datum ;
     
     h_Wochentag := Wochentag - 1 ; IF h_Wochentag = 0 THEN h_Wochentag := 7 ; END_IF ;
     Week_of_Year := (Day_of_Year + 7 + 3 - h_Wochentag) / 7 ;
     Save.Wochentag := WochenTag ;
  END_IF ;

// -----------------------------------------------------------------------------------------------------------------------
//    Wechsel Sommer-Winterzeit ...    
// -----------------------------------------------------------------------------------------------------------------------

IF (Stunde <> Save.Stunde) THEN 
   IF NOT Sommer_Winter_Zeit.Set_SZ AND NOT Sommer_Winter_Zeit.Set_WZ THEN
    
       // --- Tage, an denen die Zeit-Umstellung erfolgt, ausrechnen ...
       Jahr := REAL_TO_INT(INT_TO_REAL(Datum_INT) / 365.25) + 1990 ;   
       Schaltjahr := 0 ; IF ((Jahr MOD 4) = 0) AND (NOT ((Jahr MOD 100) = 0) OR ((Jahr MOD 400) = 0)) THEN Schaltjahr := 1 ; END_IF ;
   
       Diff_J := Jahr - 1990;
       Anz_SJ := (Diff_J + 2) / 4 ; 
       Anz_SJ := Anz_SJ - ((Diff_J - 10) / 100) ;
       
       h_Datum := Anz_SJ + (Diff_J * 365) + 83 ;  // 83 = Jahrestag vom 24.03. im nicht-Schaltjahr
       h_Wochentag := 6 - (h_Datum MOD 7) ;
       IF (h_Wochentag = 0) THEN h_Wochentag := 7 ; END_IF ;
       
       Sommer_Winter_Zeit.Tag_Wechsel_SZ := 83 + h_Wochentag ;
       
       h_Datum := Anz_SJ + (Diff_J * 365) + 297 ;  // 297 = Jahrestag vom 24.10. im nicht-Schaltjahr
       h_Wochentag := 6 - (h_Datum MOD 7) ;
       IF (h_Wochentag = 0) THEN h_Wochentag := 7 ; END_IF ;
       
       Sommer_Winter_Zeit.Tag_Wechsel_WZ := 297 + h_Wochentag ;
    
      // --- Wechsel nach Sommerzeit ...?
      IF (Sommer_Winter_Zeit.aktuell <> 'S') THEN 
         IF (Day_of_Year = Sommer_Winter_Zeit.Tag_Wechsel_SZ) AND (Stunde >= 02) THEN 
            Sommer_Winter_Zeit.Set_SZ  := true ;
         ELSIF (Day_of_Year > Sommer_Winter_Zeit.Tag_Wechsel_SZ) AND (Day_of_Year < (Sommer_Winter_Zeit.Tag_Wechsel_SZ +7)) THEN  
            Sommer_Winter_Zeit.Set_SZ  := true ;
         ELSIF (Day_of_Year >= (Sommer_Winter_Zeit.Tag_Wechsel_SZ +7)) AND (Day_of_Year < Sommer_Winter_Zeit.Tag_Wechsel_WZ) THEN  
            Sommer_Winter_Zeit.aktuell := 'S' ; 
         END_IF ;   
      END_IF ;  
   
      // --- Wechsel nach Winterzeit ...?
      IF (Sommer_Winter_Zeit.aktuell <> 'W') THEN
         IF (Day_of_Year = Sommer_Winter_Zeit.Tag_Wechsel_WZ) AND (Stunde >= 03) THEN 
            Sommer_Winter_Zeit.Set_WZ  := true ;
         ELSIF (Day_of_Year > Sommer_Winter_Zeit.Tag_Wechsel_WZ) AND (Day_of_Year < (Sommer_Winter_Zeit.Tag_Wechsel_WZ +7)) THEN   
            Sommer_Winter_Zeit.Set_WZ  := true ;
         ELSIF (Day_of_Year >= (Sommer_Winter_Zeit.Tag_Wechsel_WZ +7)) OR (Day_of_Year < Sommer_Winter_Zeit.Tag_Wechsel_SZ) THEN   
            Sommer_Winter_Zeit.aktuell := 'W' ; 
         END_IF ;   
      END_IF ;
      
   END_IF ;   

   Save.Stunde := Stunde ;
 
   IF Sommer_Winter_Zeit.Set_SZ AND (Stunde < 23) THEN
      Sommer_Winter_Zeit.aktuell := 'S' ;
      b_SPS_Datum_Uhrzeit [3]:= WORD_TO_BYTE(INT_TO_BCD (Stunde +1)) ;
   
      Error := SET_CLK (PDT := SPS_Datum_Uhrzeit) ;  

      Sommer_Winter_Zeit.Set_SZ := false ;
      Sommer_Winter_Zeit.Set_WZ := false ;
   END_IF ; 

   IF Sommer_Winter_Zeit.Set_WZ AND (Stunde > 01) THEN 
      Sommer_Winter_Zeit.aktuell := 'W' ;
      b_SPS_Datum_Uhrzeit [3]:= WORD_TO_BYTE(INT_TO_BCD (Stunde -1)) ;
   
      Error := SET_CLK (PDT := SPS_Datum_Uhrzeit) ;      
   
      Sommer_Winter_Zeit.Set_SZ := false ;
      Sommer_Winter_Zeit.Set_WZ := false ;
   END_IF ;   

END_IF ;
 
// -----------------------------------------------------------------------------------------------------------------------
END_FUNCTION_BLOCK
Gruß
Larry
 
das Datum als Text für irgendwelche Drucker oder Datenbanken erzeuge ich immer aktuell aus der zyklisch gelesenen SPS-Zeit. Damit spare ich mir irgendwelche Stunden-Addierereien über den Tag und bin auch im Falle einer (ggf. automatischen) Zeitumstellung richtig.
Bei SPS-Bausteinen zur automatischen Sommer-/Winterzeitumstellung sollte man immer daran denken, dass die SPS zum Umstellzeitpunkt auch ausgeschaltet sein kann.

Gruß
StGo
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi,

ich hätte da auch etwas schönes.

Anhang anzeigen LocalTime_SCLQuelle.txt

Dort wo ich diesen Baustein „einbaue“, ersetze ich einfach den (einmaligen) Aufruf des SFC1 READ_CLK durch meinen LocalTime.

Die CPU Uhr synchronisiere ich einfach mit einem NTP-Server im Netz (manuelles Stellen geht auch, aber halt auf UTC).

Auf der CPU läuft damit nicht mehr MEZ sondern UTC.

Die Umrechnung der Zeitzone (z.Z. nur Berlin und Moskau) erledigt mein LocalTime.

Kleiner Nachteil: Graph-Fehlermeldungen (ProAgent) werden in der Visualisierung mit UTC-Zeit versehen!

An sonsten bin ich von meinem Werk richtig begeistert. :p
Ich hoffe mir nimmt nicht gleich jemand den Wind aus den Segeln. ;)

Gruß
Holger
 
Wie holgero bin auch ich der Meinung, daß es nicht sinnvoll ist, die CPU-Uhr auf Sommerzeit umzustellen. Was außerdem gar nicht möglich ist, wenn die Uhr per NTP synchronisiert wird.
Besser die CPU-Uhr ständig auf Winterzeit laufen lassen (Systemzeit, Basetime) und die Sommerzeit ist nur eine vorübergehende Interpretation (Lokalzeit). Für die Ausgabe der Lokalzeit gibt es den Siemens-Baustein FC61 BT_LT oder meinen abgespeckten BT_LT_3

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
so danke aber
die cpu zeit möchte ich nicht verstellen diese soll schön mit ntp abgeglichen werden also danach draufrechnen und das machen ja holger und harald so
mir ist nur grad nicht ersichtlich was passiert wenn eure basetime z.b. 29.10.2013 23:50 wäre und ihr einfach ne stunde draufrechnet was passiert
 
Am 29.10.2013 wird keine Stunde "draufgerechnet", weil da gar keine Sommerzeit ist ;)
Ansonsten sollte die vom Baustein ausgegebene Localtime benutzt werden, um z.B. die Uhr des/der Panele zu synchronisieren, damit die vom Panel für Zeitstempel benutzte Uhrzeit der tatsächlichen Uhrzeit entspricht - also diese Uhrzeit in den Bereichszeiger "Date/Time SPS" kopieren.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ansonsten sollte die vom Baustein ausgegebene Localtime benutzt werden, um z.B. die Uhr des/der Panele zu synchronisieren, damit die vom Panel für Zeitstempel benutzte Uhrzeit der tatsächlichen Uhrzeit entspricht - also diese Uhrzeit in den Bereichszeiger "Date/Time SPS" kopieren.

ProAgent bekommt die Zeit aus dem Graph ... direkt von der CPU. Also nur wenn man ProAgent, Transline oder solchen Käse einsetzt, hat man das Problem. Aber damit könnte man auch leben :roll:

(Also das Problem, dass ProAgent-Fehlermeldungen mit der UTC versehen werden.)
 
Zuletzt bearbeitet:
Wenn ich meine SPS über einen NTP-Server abgleiche, werden auch meine Panels (177B) mit der Zeit der SPS versorgt, die ist jetzt UTC.
Die Zeitanzeige kann ich ja modifizieren, mittels der Bausteine, die ihr freundlicherweise :) u.a. hier bereitstellt.
Was mache ich mit den Fehlermeldungen auf dem Panel, die ja mit UTC "gestempelt werden" und was mache ich mit den Systemmeldungen der SPS, auch UTC. Die stimmen dann nicht mit der Localzeit überein. Oder irre ich mich hier?
 
Zurück
Oben