Union Flag


GMT/BST Clock

This routine will automatically setup the current time period, when the PLC is started, then it will move the clock either forward or backward at the correct time. If the PLC is un-powered at the normal changeover time, the change will take place on the first scan after power is restored. No more manually correcting the clock twice-a-year!

Right-Click and choose "Save Target As" to download the ST file.

 

The routine requires the use of the following variables,

Memory Bits (%M)

Util_clock_init - This controls the Initialisation section of the routine. You will need to reset this bit elsewhere in the program when the PLC is performing a Cold or Warm Restart.

Util_clock_fwd - A flag to control the movement of the clock forward by one hour (from GMT to BST).

Util_clock_bwd - A flag to control the movement of the clock backward by one hour (from BST to GMT).

Util_clock_gmtbst_1 - Utility bit indicating current state, GMT or BST.

Clockfwd_inhibit - Flag to inhibit addition of one hour to clock in the period after it has moved one hour backwards.

 

Memory Words (%MW)

Xbt_clock_state - The time period of the clock (0=GMT, 1=BST).

Xbt_clockset_s - Memory of the Real Time Clock (Seconds).
Xbt_clockset_hm - Memory of the Real Time Clock (Hours, Minutes).
Xbt_clockset_dm - Memory of the Real Time Clock (Day, Month).
Xbt_clockset_y - Memory of the Real Time Clock (Year).

NOTE: The Clock_set words have to be in a contiguous block.

 

System Words (%SW)

Sysclock_dow - %SW49 System Clock (Day of the Week)
Sysclock_sec - %SW50 System Clock (Seconds)
Sysclock_hrmin - %SW51 System Clock (Hours, Minutes)
Sysclock_monthday - %SW52 System Clock (Day, Month)
Sysclock_yr - %SW53 System Clock (Year)

 

 

The routine needs only to be accessed periodically, say once every second.

The Routine in ST (Structured Text)

! (* CLOCK GMT/BST ROUTINE *)

! (* Initialisation - find if current time is in GMT or BST / GMT <--> BST Change Setup *)

! (* British Summer Time *)
%L0:
IF BCD_TO_INT(SHR((Sysclock_monthday AND 16#FF00),8))>3 AND BCD_TO_INT(SHR((Sysclock_monthday AND 16#FF00),8))<10 THEN (* April to September *)
IF Util_clockinit THEN
IF Xbt_clock_state=0 THEN SET Util_clock_fwd;END_IF;(* Move clock forward by one hour *)
ELSE
Xbt_clock_state:=1;(* BST *)
END_IF;
JUMP %L2;
END_IF;

!
IF Sysclock_hrmin>16#0059 OR Sysclock_dow<>7 THEN (* 01:00 and after or not Sunday *)
SET Util_clock_gmtbst_1;
ELSE
RESET Util_clock_gmtbst_1;
END_IF;

!
IF BCD_TO_INT(SHR((Sysclock_monthday AND 16#FF00),8))=3 THEN (* March *)
IF(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=31 AND Util_clock_gmtbst_1)(* 31st and after 01:00 or not Sunday *)
OR(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=30 AND(Sysclock_dow<6 OR Sysclock_dow=7)AND Util_clock_gmtbst_1)(* 30th and Sunday after 01:00 or Monday to Friday *)
OR(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=29 AND(Sysclock_dow<5 OR Sysclock_dow=7)AND Util_clock_gmtbst_1)(* 29th and Sunday after 01:00 or Monday to Thursday *)
OR(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=28 AND(Sysclock_dow<4 OR Sysclock_dow=7)AND Util_clock_gmtbst_1)(* 28th and Sunday after 01:00 or Monday to Wednesday *)
OR(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=27 AND(Sysclock_dow<3 OR Sysclock_dow=7)AND Util_clock_gmtbst_1)(* 27th and Sunday after 01:00 or Monday or Tuesday *)
OR(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=26 AND(Sysclock_dow<2 OR Sysclock_dow=7)AND Util_clock_gmtbst_1)(* 26th and Sunday after 01:00 or Monday *)
OR(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=25 AND Sysclock_dow=7 AND Util_clock_gmtbst_1)THEN (* 25th and Sunday after 01:00 *)
IF Util_clockinit THEN
IF Xbt_clock_state=0 THEN SET Util_clock_fwd;END_IF;(* Move clock forward by one hour *)
ELSE
Xbt_clock_state:=1;(* BST *)
END_IF;
JUMP %L2;
END_IF;
END_IF;

!
IF BCD_TO_INT(SHR((Sysclock_monthday AND 16#FF00),8))=10 THEN (* October *)
IF BCD_TO_INT(Sysclock_monthday AND 16#00FF)=31 AND Sysclock_dow=7 AND Sysclock_hrmin<16#0200 AND NOT Clockfwd_inhibit THEN (* 31st, Sunday and before 02:00 *)
IF Util_clockinit THEN
IF Xbt_clock_state=0 THEN SET Util_clock_fwd;END_IF;(* Move clock forward by one hour *)
ELSE
Xbt_clock_state:=1;(* BST *)
END_IF;
JUMP %L2;
END_IF;
IF BCD_TO_INT(Sysclock_monthday AND 16#00FF)<25 THEN (* Before than 25th *)
IF Util_clockinit THEN
IF Xbt_clock_state=0 THEN SET Util_clock_fwd;END_IF;(* Move clock forward by one hour *)
ELSE
Xbt_clock_state:=1;(* BST *)
END_IF;
JUMP %L2;
END_IF;
IF Sysclock_dow<7 OR(Sysclock_hrmin<16#0200 AND NOT Clockfwd_inhibit)THEN
IF(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=30 AND Sysclock_dow>5)(* 30th and Saturday *)
OR(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=29 AND Sysclock_dow>4)(* 29th and Friday or Saturday *)
OR(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=28 AND Sysclock_dow>3)(* 28th and Thursday to Saturday *)
OR(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=27 AND Sysclock_dow>2)(* 27th and Wednesday to Saturday *)
OR(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=26 AND Sysclock_dow>1)(* 26th and Tuesday to Saturday *)
OR(BCD_TO_INT(Sysclock_monthday AND 16#00FF)=25 AND Sysclock_dow>0)(* 25th and Monday to Saturday *)
THEN
IF Util_clockinit THEN
IF Xbt_clock_state=0 THEN SET Util_clock_fwd;END_IF;(* Move clock forward by one hour *)
ELSE
Xbt_clock_state:=1;(* BST *)
END_IF;
JUMP %L2;
END_IF;
END_IF;
END_IF;

! (* Greenwich Mean Time *)
%L1:
IF Util_clockinit THEN
IF Xbt_clock_state=1 THEN SET Util_clock_bwd;END_IF;(* Move clock backward by one hour *)
ELSE
Xbt_clock_state:=0;(* GMT *)
END_IF;

!
%L2:
SET Util_clockinit;
(* END OF INIT/SETUP ROUTINE *)

!
%L3:(* GMT <--> BST Changeover *)
IF Util_clock_fwd THEN (* Move clock forward by one hour *)
Xbt_clockset_s:=Sysclock_sec;
Xbt_clockset_hm:=SHL(INT_TO_BCD((BCD_TO_INT(SHR((Sysclock_hrmin AND 16#FF00),8))+1)),8)OR(Sysclock_hrmin AND 16#00FF);
Xbt_clockset_dm:=Sysclock_monthday;
Xbt_clockset_y:=Sysclock_yr;
WRTC(Xbt_clockset_s:4);
Xbt_clock_state:=1;
RESET Util_clock_fwd;
END_IF;
IF Util_clock_bwd THEN (* Move clock backward by one hour *)
Xbt_clockset_s:=Sysclock_sec;
Xbt_clockset_hm:=SHL(INT_TO_BCD((BCD_TO_INT(SHR((Sysclock_hrmin AND 16#FF00),8))-1)),8)OR(Sysclock_hrmin AND 16#00FF);
Xbt_clockset_dm:=Sysclock_monthday;
Xbt_clockset_y:=Sysclock_yr;
WRTC(Xbt_clockset_s:4);
Xbt_clock_state:=0;
SET Clockfwd_inhibit;(* Clock Forward Inhibit *)
RESET Util_clock_bwd;
END_IF;
(* Reset Clock Forward Inhibit *)
IF Sysclock_hrmin>16#0259 THEN RESET Clockfwd_inhibit;END_IF;

! (* END OF ROUTINE *)

 

 

Updated 06-09-2006 Copyright © AMBsoft UK