(* * (c) 2005 Mario de Sousa * * Offered to the public under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * This code is made available on the understanding that it will not be * used in safety-critical situations without a full and competent review. *) (* * An IEC 61131-3 IL and ST compiler. * * Based on the * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) * *) (* * This is part of the library conatining the functions * and function blocks defined in the standard. * * Timer Function Blocks * --------------------- * * NOTE: The timing diagrams in the comments were taken from the * IEC 61131-3 standard. *) (**************************************************************** TP - pulse timing - state machine +--------+ ++ ++ +--------+ IN | | || || | | --+ +-----++-++---+ +--------- t0 t1 t2 t3 t4 t5 +----+ +----+ +----+ Q | | | | | | --+ +---------+ +--+ +------------- t0 t0+PT t2 t2+PT t4 t4+PT PT +---+ + +---+ : / | /| / | ET : / | / | / | : / | / | / | : / | / | / | 0-+ +-----+ +--+ +--------- t0 t1 t2 t4 t5 2 +---+ + +---+ STATE 1 +----+ | +----| +----+ | 0 --+ +-----+ +--+ +--------- ****************************************************************) FUNCTION_BLOCK TP VAR_INPUT IN : BOOL; (* first input parameter *) PT : TIME; (* second input parameter *) END_VAR VAR_OUTPUT Q : BOOL := FALSE; (* first output parameter *) ET : TIME := T#0s; (* second output parameter *) END_VAR VAR STATE : SINT := 0; (* internal state: 0-reset, 1-counting, 2-set *) PREV_IN : BOOL := FALSE; CURRENT_TIME, START_TIME : TIME; END_VAR {__SET_VAR(data__->CURRENT_TIME,__CURRENT_TIME)} IF ((STATE = 0) AND NOT(PREV_IN) AND IN) (* found rising edge on IN *) THEN (* start timer... *) STATE := 1; Q := TRUE; START_TIME := CURRENT_TIME; ELSIF (STATE = 1) THEN IF ((START_TIME + PT) <= CURRENT_TIME) THEN STATE := 2; Q := FALSE; ET := PT; ELSE ET := CURRENT_TIME - START_TIME; END_IF; END_IF; IF ((STATE = 2) AND NOT(IN)) THEN ET := T#0s; STATE := 0; END_IF; PREV_IN := IN; END_FUNCTION_BLOCK (**************************************************************** TON - On-delay timing - state machine +--------+ +---+ +--------+ IN | | | | | | --+ +--------+ +---+ +------------- t0 t1 t2 t3 t4 t5 +---+ +---+ Q | | | | -------+ +---------------------+ +------------- t0+PT t1 t4+PT t5 PT +---+ +---+ : / | + / | ET : / | /| / | : / | / | / | : / | / | / | 0-+ +--------+ +---+ +------------- t0 t1 t2 t3 t4 t5 2 +---+ +---+ STATE 1 +----+ | +---+ +----+ | 0 --+ +--------+ +---+ +------ ****************************************************************) FUNCTION_BLOCK TON VAR_INPUT IN : BOOL; (* first input parameter *) PT : TIME; (* second input parameter *) END_VAR VAR_OUTPUT Q : BOOL := FALSE; (* first output parameter *) ET : TIME := T#0s; (* second output parameter *) END_VAR VAR STATE : SINT := 0; (* internal state: 0-reset, 1-counting, 2-set *) PREV_IN : BOOL := FALSE; CURRENT_TIME, START_TIME : TIME; END_VAR {__SET_VAR(data__->CURRENT_TIME,__CURRENT_TIME)} IF ((STATE = 0) AND NOT(PREV_IN) AND IN) (* found rising edge on IN *) THEN (* start timer... *) STATE := 1; Q := FALSE; START_TIME := CURRENT_TIME; ELSE (* STATE is 1 or 2 !! *) IF (NOT(IN)) THEN ET := T#0s; Q := FALSE; STATE := 0; ELSIF (STATE = 1) THEN IF ((START_TIME + PT) <= CURRENT_TIME) THEN STATE := 2; Q := TRUE; ET := PT; ELSE ET := CURRENT_TIME - START_TIME; END_IF; END_IF; END_IF; PREV_IN := IN; END_FUNCTION_BLOCK (**************************************************************** TOF - Off-delay timing - state machine +--------+ +---+ +--------+ IN | | | | | | ---+ +--------+ +---+ +----------- t0 t1 t2 t3 t4 t5 +-------------+ +---------------------+ Q | | | | ---+ +---+ +------ t0 t1+PT t2 t5+PT PT +---+ +------ : / | + / ET : / | /| / : / | / | / : / | / | / 0------------+ +---+ +--------+ t1 t3 t5 2 +---+ +------ STATE 1 +----+ | +---+ +----+ 0 -------------+ +---+ +--------+ ****************************************************************) FUNCTION_BLOCK TOF VAR_INPUT IN : BOOL; (* first input parameter *) PT : TIME; (* second input parameter *) END_VAR VAR_OUTPUT Q : BOOL := FALSE; (* first output parameter *) ET : TIME := T#0s; (* second output parameter *) END_VAR VAR STATE : SINT := 0; (* internal state: 0-reset, 1-counting, 2-set *) PREV_IN : BOOL := FALSE; CURRENT_TIME, START_TIME : TIME; END_VAR {__SET_VAR(data__->CURRENT_TIME,__CURRENT_TIME)} IF ((STATE = 0) AND PREV_IN AND NOT(IN)) (* found falling edge on IN *) THEN (* start timer... *) STATE := 1; START_TIME := CURRENT_TIME; ELSE (* STATE is 1 or 2 !! *) IF (IN) THEN ET := T#0s; STATE := 0; ELSIF (STATE = 1) THEN IF ((START_TIME + PT) <= CURRENT_TIME) THEN STATE := 2; ET := PT; ELSE ET := CURRENT_TIME - START_TIME; END_IF; END_IF; END_IF; Q := IN OR (STATE = 1); PREV_IN := IN; END_FUNCTION_BLOCK