etisserant@0: (* msousa@277: * This file is part of matiec - a compiler for the programming msousa@277: * languages defined in IEC 61131-3 msousa@277: * msousa@277: * Copyright (C) 2011 Mario de Sousa (msousa@fe.up.pt) msousa@277: * msousa@277: * See COPYING and COPYING.LESSER files for copyright details. msousa@277: * This library is free software; you can redistribute it and/or msousa@277: * modify it under the terms of the GNU Lesser General Public msousa@277: * License as published by the Free Software Foundation; either msousa@277: * version 3 of the License, or (at your option) any later version. msousa@277: * msousa@277: * This library is distributed in the hope that it will be useful, msousa@277: * but WITHOUT ANY WARRANTY; without even the implied warranty of msousa@277: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU msousa@277: * Lesser General Public License for more details. msousa@277: * msousa@277: * You should have received a copy of the GNU Lesser General Public msousa@277: * License along with this library; if not, write to the Free Software msousa@277: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 msousa@277: * USA etisserant@0: * etisserant@0: * This code is made available on the understanding that it will not be etisserant@0: * used in safety-critical situations without a full and competent review. etisserant@0: *) etisserant@0: etisserant@0: (* msousa@276: * An IEC 61131-3 compiler. etisserant@0: * etisserant@0: * Based on the etisserant@0: * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) etisserant@0: * etisserant@0: *) etisserant@0: etisserant@0: (* etisserant@0: * This is part of the library conatining the functions etisserant@0: * and function blocks defined in the standard. etisserant@0: * etisserant@0: * Timer Function Blocks etisserant@0: * --------------------- etisserant@0: * msousa@276: * NOTE: The timing diagrams in the comments (except the state variable) msousa@276: * were taken from the IEC 61131-3 standard. etisserant@0: *) etisserant@0: etisserant@0: etisserant@0: etisserant@0: (**************************************************************** etisserant@0: etisserant@0: TP - pulse timing - state machine etisserant@0: etisserant@0: etisserant@0: +--------+ ++ ++ +--------+ etisserant@0: IN | | || || | | etisserant@0: --+ +-----++-++---+ +--------- etisserant@0: t0 t1 t2 t3 t4 t5 etisserant@0: +----+ +----+ +----+ etisserant@0: Q | | | | | | etisserant@0: --+ +---------+ +--+ +------------- etisserant@0: t0 t0+PT t2 t2+PT t4 t4+PT etisserant@0: PT +---+ + +---+ etisserant@0: : / | /| / | etisserant@0: ET : / | / | / | etisserant@0: : / | / | / | etisserant@0: : / | / | / | etisserant@0: 0-+ +-----+ +--+ +--------- etisserant@0: t0 t1 t2 t4 t5 etisserant@0: etisserant@0: etisserant@0: 2 +---+ + +---+ etisserant@0: STATE 1 +----+ | +----| +----+ | etisserant@0: 0 --+ +-----+ +--+ +--------- etisserant@0: etisserant@0: etisserant@0: ****************************************************************) etisserant@0: etisserant@0: FUNCTION_BLOCK TP etisserant@0: VAR_INPUT etisserant@0: IN : BOOL; (* first input parameter *) etisserant@0: PT : TIME; (* second input parameter *) etisserant@0: END_VAR etisserant@0: VAR_OUTPUT etisserant@0: Q : BOOL := FALSE; (* first output parameter *) etisserant@0: ET : TIME := T#0s; (* second output parameter *) etisserant@0: END_VAR etisserant@0: etisserant@0: VAR etisserant@0: STATE : SINT := 0; (* internal state: 0-reset, 1-counting, 2-set *) etisserant@0: PREV_IN : BOOL := FALSE; etisserant@0: CURRENT_TIME, START_TIME : TIME; etisserant@0: END_VAR etisserant@0: laurent@392: {__SET_VAR(data__->,CURRENT_TIME,__CURRENT_TIME)} etisserant@0: etisserant@0: IF ((STATE = 0) AND NOT(PREV_IN) AND IN) (* found rising edge on IN *) etisserant@0: THEN etisserant@0: (* start timer... *) etisserant@0: STATE := 1; etisserant@0: Q := TRUE; etisserant@0: START_TIME := CURRENT_TIME; etisserant@0: etisserant@0: ELSIF (STATE = 1) etisserant@0: THEN etisserant@0: IF ((START_TIME + PT) <= CURRENT_TIME) etisserant@0: THEN etisserant@0: STATE := 2; etisserant@0: Q := FALSE; etisserant@0: ET := PT; etisserant@0: ELSE etisserant@0: ET := CURRENT_TIME - START_TIME; etisserant@0: END_IF; etisserant@0: END_IF; etisserant@0: etisserant@0: IF ((STATE = 2) AND NOT(IN)) etisserant@0: THEN etisserant@0: ET := T#0s; etisserant@0: STATE := 0; etisserant@0: END_IF; etisserant@0: etisserant@0: etisserant@0: PREV_IN := IN; etisserant@0: etisserant@0: END_FUNCTION_BLOCK etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: (**************************************************************** etisserant@0: etisserant@0: TON - On-delay timing - state machine etisserant@0: etisserant@0: etisserant@0: +--------+ +---+ +--------+ etisserant@0: IN | | | | | | etisserant@0: --+ +--------+ +---+ +------------- etisserant@0: t0 t1 t2 t3 t4 t5 etisserant@0: +---+ +---+ etisserant@0: Q | | | | etisserant@0: -------+ +---------------------+ +------------- etisserant@0: t0+PT t1 t4+PT t5 etisserant@0: PT +---+ +---+ etisserant@0: : / | + / | etisserant@0: ET : / | /| / | etisserant@0: : / | / | / | etisserant@0: : / | / | / | etisserant@0: 0-+ +--------+ +---+ +------------- etisserant@0: t0 t1 t2 t3 t4 t5 etisserant@0: etisserant@0: etisserant@0: 2 +---+ +---+ etisserant@0: STATE 1 +----+ | +---+ +----+ | etisserant@0: 0 --+ +--------+ +---+ +------ etisserant@0: etisserant@0: etisserant@0: ****************************************************************) etisserant@0: etisserant@0: etisserant@0: FUNCTION_BLOCK TON etisserant@0: VAR_INPUT etisserant@0: IN : BOOL; (* first input parameter *) etisserant@0: PT : TIME; (* second input parameter *) etisserant@0: END_VAR etisserant@0: VAR_OUTPUT etisserant@0: Q : BOOL := FALSE; (* first output parameter *) etisserant@0: ET : TIME := T#0s; (* second output parameter *) etisserant@0: END_VAR etisserant@0: etisserant@0: VAR etisserant@0: STATE : SINT := 0; (* internal state: 0-reset, 1-counting, 2-set *) etisserant@0: PREV_IN : BOOL := FALSE; etisserant@0: CURRENT_TIME, START_TIME : TIME; etisserant@0: END_VAR etisserant@0: laurent@392: {__SET_VAR(data__->,CURRENT_TIME,__CURRENT_TIME)} etisserant@0: etisserant@0: IF ((STATE = 0) AND NOT(PREV_IN) AND IN) (* found rising edge on IN *) etisserant@0: THEN etisserant@0: (* start timer... *) etisserant@0: STATE := 1; etisserant@0: Q := FALSE; etisserant@0: START_TIME := CURRENT_TIME; etisserant@0: etisserant@0: ELSE etisserant@0: (* STATE is 1 or 2 !! *) etisserant@0: IF (NOT(IN)) etisserant@0: THEN etisserant@0: ET := T#0s; etisserant@0: Q := FALSE; etisserant@0: STATE := 0; etisserant@0: etisserant@0: ELSIF (STATE = 1) etisserant@0: THEN etisserant@0: IF ((START_TIME + PT) <= CURRENT_TIME) etisserant@0: THEN etisserant@0: STATE := 2; etisserant@0: Q := TRUE; etisserant@0: ET := PT; etisserant@0: ELSE etisserant@0: ET := CURRENT_TIME - START_TIME; etisserant@0: END_IF; etisserant@0: END_IF; etisserant@0: etisserant@0: END_IF; etisserant@0: etisserant@0: PREV_IN := IN; etisserant@0: etisserant@0: END_FUNCTION_BLOCK etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: (**************************************************************** etisserant@0: etisserant@113: TOF - Off-delay timing - state machine etisserant@0: etisserant@0: etisserant@0: +--------+ +---+ +--------+ etisserant@0: IN | | | | | | etisserant@0: ---+ +--------+ +---+ +----------- etisserant@0: t0 t1 t2 t3 t4 t5 etisserant@0: +-------------+ +---------------------+ etisserant@0: Q | | | | etisserant@0: ---+ +---+ +------ etisserant@0: t0 t1+PT t2 t5+PT etisserant@0: PT +---+ +------ etisserant@0: : / | + / etisserant@0: ET : / | /| / etisserant@0: : / | / | / etisserant@0: : / | / | / etisserant@0: 0------------+ +---+ +--------+ etisserant@0: t1 t3 t5 etisserant@0: etisserant@0: etisserant@0: 2 +---+ +------ etisserant@0: STATE 1 +----+ | +---+ +----+ etisserant@0: 0 -------------+ +---+ +--------+ etisserant@0: etisserant@0: etisserant@0: ****************************************************************) etisserant@0: etisserant@113: FUNCTION_BLOCK TOF etisserant@0: VAR_INPUT etisserant@0: IN : BOOL; (* first input parameter *) etisserant@0: PT : TIME; (* second input parameter *) etisserant@0: END_VAR etisserant@0: VAR_OUTPUT etisserant@0: Q : BOOL := FALSE; (* first output parameter *) etisserant@0: ET : TIME := T#0s; (* second output parameter *) etisserant@0: END_VAR etisserant@0: etisserant@0: VAR etisserant@0: STATE : SINT := 0; (* internal state: 0-reset, 1-counting, 2-set *) etisserant@0: PREV_IN : BOOL := FALSE; etisserant@0: CURRENT_TIME, START_TIME : TIME; etisserant@0: END_VAR etisserant@0: laurent@392: {__SET_VAR(data__->,CURRENT_TIME,__CURRENT_TIME)} etisserant@0: etisserant@0: IF ((STATE = 0) AND PREV_IN AND NOT(IN)) (* found falling edge on IN *) etisserant@0: THEN etisserant@0: (* start timer... *) etisserant@0: STATE := 1; etisserant@0: START_TIME := CURRENT_TIME; etisserant@0: etisserant@0: ELSE etisserant@0: (* STATE is 1 or 2 !! *) etisserant@0: IF (IN) etisserant@0: THEN etisserant@0: ET := T#0s; etisserant@0: STATE := 0; etisserant@0: etisserant@0: ELSIF (STATE = 1) etisserant@0: THEN etisserant@0: IF ((START_TIME + PT) <= CURRENT_TIME) etisserant@0: THEN etisserant@0: STATE := 2; etisserant@0: ET := PT; etisserant@0: ELSE etisserant@0: ET := CURRENT_TIME - START_TIME; etisserant@0: END_IF; etisserant@0: END_IF; etisserant@0: etisserant@0: END_IF; etisserant@0: etisserant@0: Q := IN OR (STATE = 1); etisserant@0: PREV_IN := IN; etisserant@0: etisserant@0: END_FUNCTION_BLOCK etisserant@0: