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