Ich habe mal schnell eine mögliche Änderung im Baustein calendar_cal eingebaut.
Bei einem Sommer/Winterzeitwechsel werden die 3 Funktionen mit dem zwischen 2 und 3 Uhr geänderten DST_ON erneut aufgerufen.
Ich habe die Änderungen mit (**************) gekennzeichnet.
Kann das so gehen?
FUNCTION_BLOCK CALENDAR_CALC
VAR_INPUT
SPE : BOOL;
H : REAL := -0.83333333333;
END_VAR
VAR_IN_OUT
XCAL : CALENDAR;
HOLIDAYS : ARRAY[0..29] OF HOLIDAY_DATA;
END_VAR
VAR
last : DT;
last_day : DINT;
holy : HOLIDAY;
sun : SUN_TIME;
last_hour: INT;
utod: TOD;
pos : SUN_POS;
plast: DT;
last_dst_on: BOOL; (**************)
END_VAR
VAR_TEMP
dtemp : DINT;
tmp : INT;
END_VAR
(*
version 1.6 6. apr. 2011
programmer hugo
tested by oscat
calendar_calc liest die weltzeit .UTC aus einer CALENDAR Struktur und berechnet die restlichen Werte der Struktur.
calendar_calc stellt sicher das die Werte fortlaufend aktualisiert werden und dabei funktionen nur dann aufgerufen werden wenn dies nötig ist.
calendar_calc will calculate sun position data when SPE = TRUE;
*)
(* @END_DECLARATION := '0' *)
IF xcal.UTC <> last THEN
(* run once per second *)
(* update utc last calculated *)
last := XCAL.UTC;
utod := DT_TO_TOD(xcal.UTC);
(* calculate ltc from utc *)
XCAL.LDT := UTC_TO_LTIME(XCAL.UTC, XCAL.DST_EN, XCAL.OFFSET);
XCAL.LDATE := DT_TO_DATE(XCAL.LDT);
XCAL.LTOD := DT_TO_TOD(XCAL.LDT);
dtemp := DAY_OF_DATE(XCAL.LDATE);
xcal.night := XCAL.LTOD < XCAL.SUN_RISE OR XCAL.LTOD > XCAL.SUN_SET;
(* run once per hour *)
tmp := HOUR(xcal.LTOD);
IF tmp <> last_hour THEN
XCAL.DST_ON := DST(XCAL.UTC) AND xcal.DST_EN;
last_hour := tmp;
END_IF;
(* run once per day *)
IF dtemp <> last_day THEN
last_day := dtemp;
(* a new day has started, recalculate daily events *)
XCAL.YEAR := YEAR_OF_DATE(XCAL.LDATE);
XCAL.MONTH := MONTH_OF_DATE(XCAL.LDATE);
XCAL.DAY := DAY_OF_MONTH(XCAL.LDATE);
XCAL.WEEKDAY := DAY_OF_WEEK(XCAL.LDATE);
HOLY(date_in := XCAL.LDATE, LANGU := xcal.LANGUAGE, HOLIDAYS := HOLIDAYS);
XCAL.HOLIDAY := HOLY.Y;
XCAL.HOLY_NAME := HOLY.NAME;
sun(latitude := XCAL.LATITUDE, longitude := xcal.LONGITUDE, utc := DT_TO_DATE(xcal.UTC), H := H);
XCAL.SUN_RISE := DINT_TO_TOD(TOD_TO_DINT(sun.sun_rise) + XCAL.OFFSET * 60000 + SEL(XCAL.DST_ON,DINT#0,3600000));
XCAL.SUN_SET := DINT_TO_TOD(TOD_TO_DINT(sun.sun_set) + XCAL.OFFSET * 60000 + SEL(XCAL.DST_ON,DINT#0,3600000));
XCAL.SUN_MIDDAY := DINT_TO_TOD(TOD_TO_DINT(sun.MIDDAY) + XCAL.OFFSET * 60000 + SEL(XCAL.DST_ON,DINT#0,3600000));
XCAL.SUN_HEIGTH := sun.sun_declination;
XCAL.WORK_WEEK := WORK_WEEK(XCAL.LDATE);
END_IF;
(* calculate the suns position every 10 seconds when SPE = TRUE *)
IF SPE AND xcal.UTC - plast >= t#25s THEN
plast := last;
pos(latitude := xcal.LATITUDE, longitude := xcal.LONGITUDE, utc := xcal.UTC);
xcal.SUN_HOR := pos.B;
xcal.SUN_VER := pos.HR;
END_IF;
(**************)
IF last_dst_on <> XCAL.DST_ON THEN
last_dst_on := XCAL.DST_ON;
XCAL.SUN_RISE := DINT_TO_TOD(TOD_TO_DINT(sun.sun_rise) + XCAL.OFFSET * 60000 + SEL(XCAL.DST_ON,DINT#0,3600000));
XCAL.SUN_SET := DINT_TO_TOD(TOD_TO_DINT(sun.sun_set) + XCAL.OFFSET * 60000 + SEL(XCAL.DST_ON,DINT#0,3600000));
XCAL.SUN_MIDDAY := DINT_TO_TOD(TOD_TO_DINT(sun.MIDDAY) + XCAL.OFFSET * 60000 + SEL(XCAL.DST_ON,DINT#0,3600000));
END_IF;
(**************)
END_IF;