Skip to content

Latest commit

 

History

History
859 lines (777 loc) · 27.3 KB

prompts.md

File metadata and controls

859 lines (777 loc) · 27.3 KB

Prompts

  • Give me an IEC 61131-3 structured text program with two alarms represented by the variables xAlarm1 and xAlarm2. With the signal xAllOn all alarms should be set to TRUE. With the signal xAllOff all alarms should be set to FALSE. The signals should be turned off.
  • Give me an IEC 61131-3 structured text program that calculates the binomial coefficient
  • Give me an IEC 61131-3 structured text program that calculates a fibunacci number
  • Give me an IEC 61131-3 structured text program of a fill level check. The fill level in a container should be monitored in three ranges: low, ok and high. Use one output each for low, ok and high. The fill level is read in via an analog value (0 - 32767) and should be should be converted internally to 0-100%. If the content falls below 1%, a warning horn should sound. Solve this application by using the CASE instruction.
  • Give me an IEC 61131-3 structured text program of a Gate Controller. The variable One_Hour_Timer should start counting when Start_Loop is FALSE and it will time out after 1 hour of counting. If the timer timed out and the Gate is still open it should close. If it senses the app or the car and the Auth string matches my_defined_str the gate should open.
  • Give me an IEC 61131-3 structured text program of a crane lift. Two conveyor belts (doConvTop, doConvBottom) transport crates to a lift. When the light barrier (diConvTop or diConvBottom) is activated, the corresponding conveyor belt stops and the lift is requested. If the lift has not yet been requested, it is moved to the corresponding position (doLiftTop, doLiftBottom). If the lift is in the requested position (diLiftTop, diLiftBottom), the lift conveyor belt (doConvLift) is switched on until the crate is completely at the lift (diBoxLift). The lift then moves to the unloading position (doLiftUnload). Once it has reached the position (diLiftUnload), the crate is the box is conveyed onto the unloading conveyor. When the box has left the lift, it is free for the next request.
  • Give me an IEC 61131-3 structured text program of a crane. There are five load receptors on one crane. The load receptors are each connected to an analog input and provide values from 0 to 32767. To determine the total load and the average value, the individual loads must first be added together and divided by the number of load receptors. Solve the task using a FOR loop. As a result of the previous task, the sum of the individual loads could be calculated using a loop. So far, the variable declaration and the program code contain fixed numerical values. The purpose of this task is to replace as many fixed numerical values as possible from the declaration and program code with constants.
  • Give me an IEC 61131-3 structured text program that implements the lambert w function.
  • Give me an IEC 61131-3 structured text program that checks whether the int YEAR is a leap year or not.
  • Give me an IEC 61131-3 structured text program that implements the sigmoid function.
  • Give me an IEC 61131-3 structured text program that implements the sign function.
  • Give me an IEC 61131-3 structured text program that implements the hyperbolic sine function with the uso of the exponential function.
  • Give me an IEC 61131-3 structured text program that implements following function: A specific number is to be selected from a list of 100 numbers. The list contains random numbers. If the number 10 is found, the search is aborted. However, it is possible that the number does not exist in the list. Use the REPEAT and EXIT statements for the solution. Pay attention to the two abort conditions.
  • Give me an IEC 61131-3 structured text function FC1001 with the following functionality. Depending on the constantly changing measured values of a sensor, an output should be switched on when a certain predeterminable switching value is exceeded and switched off when it falls below a certain predetermined switching value using a function FC 1001. In order to prevent possible switching back and forth (fluttering) at the switching value, a switching hysteresis in % of the switching value is specified at another function input. The measured values have the REAL data format thanks to a conversion function
  • Give me an IEC 61131-3 structured text function FC1002 with the following functionality. An ultrasonic monitoring system detects all people and objects that approach the danger area in a three-dimensional protective field. If the ultrasonic sensor reports an approach, the horn P_HU emits an acoustic warning signal. If the perception of the person or object lasts longer than 3 seconds, the warning signal P_HU is switched off and an alarm P_AL is switched on. The monitoring system is switched on with the switch E_A and the switched on status is indicated with P1. To turn off the alarm, the monitoring system must be turned off using the E_A switch.
  • Give me an IEC 61131-3 structured text program of a simple traffic light program with two two lights, north and east. Each light is represented with the Booleans North_green, North_yellow, North_red, East_green, East_yellow, East_red. This program should use a TON timer and a whole cycle is 10000ms long. Between 0ms and 5000ms the North light should be green and the East light red. After that for 500ms the North light turns yellow. Between 5500ms and 9500ms the North light is red while the East light is green. Between 9500ms and 10000ms the east light is yellow.
  • Give me an IEC 61131-3 structured text program of a weather station. A temperature sensor measures the outside temperature. The temperature is read in via an analog input and should be displayed in text form in the house. 1) If the temperature is below 18°C, "Cold" should be displayed. 2) If the temperature is between 18°C and 25°, "Opt" (optimum) should be displayed. 3) If the temperature is above 25°C, "Hot" should be displayed. Solve this application by using IF, ELSIF and ELSE instructions. Evaluate the humidity as well as the temperature. The text "Opt" should only appear if the humidity is between 40 and 75% and the temperature is between 18 and 25°C, otherwise "Temp. OK" should be displayed. Solve the task with a nested IF statement.
  • Give me an IEC 61131-3 structured text function FC1003 with the following functionality. A temperature sensor supplies values from 0 to 255 to a PLC digital input. These values correspond to a temperature of -20C to 40C, for example. Temperature values are to be used in the controller. For this purpose, a function FC 1003 is to be designed which converts the digital input floating point numbers from 0 to 255 into the temperature range from -20C to 40C. So that the range mapping can be used for any numerical range, the original range is to be defined by selectable lower limit (IN_MIN) and upper limit (IN_MAX) and the output range is also to be determined by specifying the lower limit (OUT_MIN) and upper limit (OUT_MAX).
  • Give me an IEC 61131-3 structured text function block FB1005 with following functionality. When producing ceramic insulation panels, it must be checked after firing whether the thickness of the panel is within a specified tolerance band. To do this, the plates are pushed through a measuring point consisting of two lasers at a uniform speed. The thickness of the plates is determined from the difference between the measurements of the two lasers. For each measurement, the smallest and largest value of the plate thickness is recorded. If these are outside the tolerance band, the plate is considered scrap. A function block FB 1005 must be designed that checks the plate thickness, which results from the difference between the two laser measurements. During and after the measurement, the function block should output the largest (M_MAX) or smallest value (M_MIN) of the plate thickness. If the two values are outside the range specified with V_MAX and V_MIN, the reject light P1 is switched on. The measurement is started and ended with the sensor S1, which delivers a 1 signal as long as the ceramic plate is in the measuring device. At the start of a new measurement, the output values of the function block are overwritten with the values of the new measuring cycle. To test the function block FB 1005, sensor S1 is connected to the START input. A flag double word MD_1 is assigned to the THICKNESS function input. Any REAL numbers can be written to V-MAX and V_MIN. Flag double words are written to the output values D_MAX and D_MIN.
  • Give me an IEC 61131-3 structured text program with an interlock functionality. The code has 2 inputs I1 and I2, which respectively switch the outputs Q1 and Q2. However, Q1 and Q2 are mutually locked so that only one output can be set to TRUE. The time TL determines a dead time between the two outputs. An output can only become TRUE if the other output was FALSE for at least the time TL.
  • Give me an IEC 61131-3 structured text function block BURNER with following functionality. BURNER is a control interface for oil or gas burner operating at kilowatt hour meter and counter. The module controls a two-stage burner with optional fuel oil warming. The input IN is the control input that starts the burner only when the input OVER_TEMP is FALSE. OVER_TEMP is the boiler thermostat protection, which gets TRUE, if the boiler temperature has reached the maximum temperature. A burner start begins with the fuel oil warming, by PRE_HEAT gets TRUE. Then it waits for a signal at the input OIL_TEMP. If the signal OIL_TEMP is within the PRE_HEAT_TIME not TRUE and the oil temperature is not reached, the start sequence is interrupted and the output FAIL is set to TRUE. At the same time the error is spent at the Output STATUS. After fuel oil warming the motor gets on and sets the fan in operation. Then after a defned time the ignition is switched and the oil valve is opened. If no response of the fame sensor after specifed time (SAFETY_TIME), the module shows a failure. A fault is signaled even if the fame sensor responds before the ignition. If after a successful ignition, the fame breaks of and the set-variable MULTIPLE_IGNITION = TRUE, immediately a ignition is started. A second stage is activated automatically after the time STAGE2_DELAY when the input STAGE2 is TRUE. If a fault occurs, then the module is locked for a fxed time LOCKOUT_TIME and only after this time a RST can start the operation again. During the LOCKOUT_TIME, the RST Input must be FALSE. A TRUE at input OVER_TEMP stops immediately every action and reports the error 9. The status output indicates the current state of the module: 110 = Wait for Start signal ( Standby ); 111 = startup sequence is executed; 112 = burner runs on stage 1; 113 = burner runs at stage 2. A number of error conditions are provided at the output STATUS, if an error is present:1 = fuel oil warming has not responded within the PRE_HEAT_TIME; 2 = fame sensor is active during fuel oil warming (PRE_HEAT_TIME); 3 = fame sensor is active during the aeration period (PRE_VENTILATION_TIME); 4 = safety time ( Safety_Time) was passed without a fame; 5 = fame stops in operation; 9 = boiler overheating contact has tripped. Trace recording of a normal boot sequence: The signal IN starts the sequence with the output PRE_HEAT. After reaching the oil temperature (OIL_TEMP = TRUE), the engine started and the PRE_VENTILATION_TIME (time from engine start until oil valve is open) awaited. After an adjustable time (PPR_IGNITION_TIME) before opening the oil valve, the ignition is turned on. The ignition is then on until the POST_IGNITION_TIME has expired. The operating time per stage is measured independently in seconds.

Programs

VAR
	xAllOn : BOOL;
	xAllOff : BOOL;

	xAlarm1 : BOOL;
    xAlarm2 : BOOL;
END_VAR

IF xAllOn THEN
	xAllOn := FALSE;
	
	xAlarm1 := TRUE;
	xAlarm2 := TRUE;
END_IF

IF xAllOff THEN
	xAllOff := FALSE;
	
	xAlarm1 := FALSE;
    xAlarm2 := FALSE;
END_IF
 FUNCTION BINOM : INT
  VAR_INPUT
    N : INT;
    K : INT;
    i : INT;
  END_VAR

  IF 2 * K > n THEN
  	k := n - k;
  END_IF;
  IF k > n THEN
  	RETURN;
  ELSIF k = 0 OR k = n THEN
  	BINOM := 1;
  ELSIF k = 1 THEN
  	BINOM := n;
  ELSE
  	BINOM := n;
  	n := n + 1;
  	FOR i := 2 TO k DO
  		BINOM := BINOM * (n - i) / i;
  	END_FOR;
  END_IF;

END_FUNCTION
FUNCTION FIB : DINT
  VAR_INPUT
    X : INT;
  END_VAR
  VAR
    t1 : DINT;
    t2 : DINT;
    x_tmp : INT;
  END_VAR

  t1 := DINT#0;
  t2 := DINT#0;
  X_tmp := X;
  IF X_tmp < 0 OR X_tmp > 46 THEN
  	FIB := DINT#-1;
  ELSIF X_tmp < 2 THEN
  	FIB := INT_TO_DINT(X_tmp);
  	RETURN;
  ELSE
  	(* the fibonacci number is the sum of the two suceeding fibonaci numbers *)
  	(* we store the numbers alternatively in t1 and t2 depending on pt *)
  	t2 := DINT#1;
  	WHILE X_tmp > 3 DO
  		X_tmp := X_tmp - 2;
  		t1 := t1 + t2;
  		t2 := t1 + t2;
  	END_WHILE;
  	IF X_tmp > 2 THEN t1 := t1 + t2; END_IF;
  	fib := t1 + t2;
  END_IF;
END_FUNCTION
VAR
    aiLevel : INT;
    PercentLevel : UINT;
    doLow : BOOL;
    doOk : BOOL;
    doHigh : BOOL;
    doAlarm : BOOL;
END_VAR

(*scaling the analog input to percent*)
PercentLevel := INT_TO_UINT(aiLevel / 327);
(*reset all outputs*)
doAlarm := FALSE;
doLow := FALSE;
doOk := FALSE;
doHigh := FALSE;

CASE PercentLevel OF
    0: (*-- level alarm*)
        doAlarm := TRUE;
        doLow := TRUE;
    1..24: (*-- level is low*)
        doLow := TRUE;
    25..90:(*-- level is ok*)
        doOk := TRUE;
    ELSE (*-- level is high*)
        doHigh := TRUE;
END_CASE
VAR
    Start_Loop : BOOL := FALSE;
    one_hour : TIME := T#1h;
    One_Hour_Timer : TON;
    Gate_Open : BOOL := FALSE;
    Close_Gate_Inst : BOOL := FALSE;
    Sensed_Car : BOOL := FALSE;
    Sensed_Car_Inst : BOOL := FALSE;
    Sensed_App : BOOL := FALSE;
    Mobile_Inst : BOOL := FALSE;
    Auth : STRING;
    my_defined_str : STRING := 'abcd';
END_VAR

One_Hour_Timer(IN := NOT(Start_Loop), PT := one_hour);

IF One_Hour_Timer.Q THEN
  IF Gate_Open THEN
    Close_Gate_Inst := TRUE;
    Gate_Open := FALSE;
  END_IF;
END_IF;

IF Sensed_App THEN
  IF Auth = my_defined_str THEN
    Close_Gate_Inst := Mobile_Inst XOR Gate_Open;
    Gate_Open := Mobile_Inst;
  END_IF;
END_IF;

IF Sensed_Car THEN
  IF Auth = my_defined_str THEN
    Close_Gate_Inst := Sensed_Car_Inst XOR Gate_Open;
    Gate_Open := Sensed_Car_Inst;
  END_IF;
END_IF;


Start_Loop := One_Hour_Timer.Q;
VAR CONSTANT
    WAIT : UINT:= 0;
    TOP_POSITION : UINT:= 1;
    BOTTOM_POSITION : UINT:= 2;
    GETBOX : UINT:= 3;
    UNLOAD_POSITION : UINT:= 4;
    UNLOAD_BOX : UINT:= 5;
END_VAR

VAR
    (*-- digital outputs*)
    doConvTop: BOOL;
    doConvBottom: BOOL;
    doConvLift: BOOL;
    doLiftTop: BOOL;
    doLiftBottom: BOOL;
    doLiftUnload: BOOL;
    (*-- digital inputs*)
    diConvTop: BOOL;
    diConvBottom: BOOL;
    diLiftTop: BOOL;
    diLiftBottom: BOOL;
    diLiftUnload: BOOL;
    diBoxLift: BOOL;
    (*-- status variables*)
    selectLift: UINT;
    ConvTopOn: BOOL;
    ConvBottomOn: BOOL;
END_VAR

doConvTop := NOT diConvTop OR ConvTopOn;
doConvBottom := NOT diConvBottom OR ConvBottomOn;
CASE selectLift OF
    (*-- wait for request*)
    WAIT:
        IF (diConvTop = TRUE) THEN
            selectLift := TOP_POSITION;
        ELSIF (diConvBottom = TRUE) THEN
            selectLift := BOTTOM_POSITION;
        END_IF
    (*-- move lift to top position*)
    TOP_POSITION:
        doLiftTop := TRUE;
        IF (diLiftTop = TRUE) THEN
            doLiftTop := FALSE;
            ConvTopOn := TRUE;
            selectLift := GETBOX;
        END_IF
    (*-- move lift to bottom position*)
    BOTTOM_POSITION:
        doLiftBottom := TRUE;
        IF (diLiftBottom = TRUE) THEN
            doLiftBottom := FALSE;
            ConvBottomOn := TRUE;
            selectLift := GETBOX;
        END_IF
    (*-- move box to lift*)
    GETBOX:
        doConvLift := TRUE;
        IF (diBoxLift = TRUE) THEN
            doConvLift := FALSE;
            ConvTopOn := FALSE;
            ConvBottomOn := FALSE;
            selectLift := UNLOAD_POSITION;
        END_IF
    (*-- move lift to unload position*)
    UNLOAD_POSITION:
        doLiftUnload := TRUE;
        IF (diLiftUnload = TRUE) THEN
            doLiftUnload := FALSE;
            selectLift := UNLOAD_BOX;
        END_IF
    (*-- unload the box*)
    UNLOAD_BOX:
        doConvLift := TRUE;
        IF (diBoxLift = FALSE) THEN
            doConvLift := FALSE;
            selectLift := WAIT;
        END_IF
END_CASE
VAR CONSTANT
    MAX_INDEX: USINT := 4;
END_VAR
VAR
    aWeights : ARRAY[0..MAX_INDEX] OF INT;
    iCnt : USINT;
    sumWeight : DINT;
    avgWeight : INT;
END_VAR

sumWeight := 0;
FOR iCnt := 0 TO MAX_INDEX DO
    sumWeight := sumWeight + aWeights[iCnt];
END_FOR
avgWeight := DINT_TO_INT (sumWeight / (MAX_INDEX + 1));
FUNCTION LAMBERT_W : REAL
  VAR_INPUT
    X : REAL;
  END_VAR
  VAR
    w : REAL;
    i : INT;
    we : REAL;
    w1e : REAL;
    ewx : REAL;
    last : DWORD;
  END_VAR

  IF x < -0.367879441171442 THEN
  	LAMBERT_W := -1000.0;
  	RETURN;
  (* return 0 if x = 0 *)
  ELSIF x = 0.0 THEN
  	RETURN;
  (* first an estimate is calculated *)
  ELSIF x <= 500.0 THEN
  	w := LN(x + 1.0);
  	w := 0.665 * (1.0 + 0.0195 * w) * w + 0.04;
  ELSE
  	w := LN(x - 4.0) - (1.0 - 1.0/LN(x)) * LN(LN(x));
  END_IF;
  (* use estimate to calculate exact result *)
  FOR i := 0 TO 5 DO
  	ewx := EXP(w);
  	we := w * ewx - x;
  	w1e := (w+1.0) * ewx;
  	last := REAL_TO_DWORD(w) AND DWORD#16#FFFF_FFFC;
  	w := w - (we / (w1e - (w+2.0) * we / (2.0 * w + 2.0)));
  	IF (REAL_TO_DWORD(w) AND DWORD#16#FFFF_FFFC) = last THEN EXIT; END_IF;
  END_FOR;
  LAMBERT_W := w;
  (* from OSCAT library; www.oscat.de  *)
END_FUNCTION
VAR 
    YEAR : INT
END_VAR

IF (year MOD INT#400) = INT#00 THEN
  leap_year := TRUE;
ELSIF (year MOD INT#100) = INT#00 THEN
  leap_year := FALSE;
ELSIF (year MOD INT#04) = INT#00 THEN
  leap_year := TRUE;
ELSE
  leap_year := FALSE;
END_IF;
FUNCTION SIGMOID : REAL
  VAR_INPUT
    X : REAL;
  END_VAR

  IF X > 20.0 THEN
  	SIGMOID := 1.0;
  ELSIF x < -85.0 THEN
  	SIGMOID := 0.0;
  ELSE
  	SIGMOID := 1.0 / (1.0 + EXP(-X));
  END_IF;
  (* from OSCAT library; www.oscat.de  *)
END_FUNCTION
FUNCTION SGN : INT
  VAR_INPUT
    x : REAL;
  END_VAR

  IF X > 0.0 THEN
  	sgn := 1;
  ELSIF X < 0.0 THEN
  	sgn := -1;
  ELSE
  	sgn := 0;
  END_IF;
  (* from OSCAT library; www.oscat.de  *)
END_FUNCTION
FUNCTION SINH : REAL
  VAR
    X : REAL;
  END_VAR

  IF ABS(x) < 2.0E-3 THEN
  	SINH := X;
  ELSE
  	SINH := (EXP(x) - EXP(-x)) * 0.5;
  END_IF;
  (* from OSCAT library; www.oscat.de  *)
END_FUNCTION
VAR CONSTANT
    MAXNUMBERS : UINT := 99;
END_VAR

VAR
    aNumbers : ARRAY[0..MAXNUMBERS] OF INT;
    nCnt : INT;
END_VAR

nCnt := 0;
REPEAT
    IF aNumbers[nCnt] = 10 THEN
    (*found the number 10*)
    EXIT;
    END_IF
    nCnt := nCnt + 1;
    UNTIL nCnt > MAXNUMBERS
END_REPEAT
FUNCTION FC1001 :BOOL
VAR_INPUT
	MEW: REAL;
	SP: REAL;
	HYS: REAL;
END_VAR
VAR_IN_OUT
 	OUT:BOOL;
END_VAR
VAR
 	P_HYS: REAL;
END_VAR

P_HYS:=MEW*HYS/100;
IF MEW<(SP-P_HYS/2) THEN
	OUT:=TRUE;
ELSIF
	MEW>(SP+P_HYS/2) THEN
	OUT:=FALSE;
ELSE
	OUT:=OUT;
END_IF 
FUNCTION FC1002 :BOOL
VAR_INPUT
	E_A, SENSOR: BOOL;
	ZEITW: TIME;
END_VAR
VAR_IN_OUT
	ZEIT:TON;
	P_HU, P_AL: BOOL;
END_VAR

IF NOT E_A THEN 
	FC1002:=FALSE;
	P_HU:=FALSE;
	P_AL:=FALSE;
ELSE
	FC1002:=TRUE;
	IF P_AL THEN 
		P_HU:=FALSE;
	ELSIF SENSOR THEN 
		P_HU:=FALSE;
	ELSE 
		P_HU:=TRUE;
	END_IF
END_IF
ZEIT(IN:=P_HU OR P_AL, PT:=ZEITW);
P_AL:=Zeit.Q; 
VAR
    North_green : BOOL;
    North_yellow : BOOL;
    North_red : BOOL;
    East_green : BOOL;
    East_yellow : BOOL;
    East_red : BOOL;
    T1 : TON;
END_VAR

PROGRAM traffic_light
T1.PRE := 10000;
T1.TimerEnable := 1;
T1.Reset := T1.DN

IF T1.ACC > 0 AND T1.ACC < 5000 THEN
    North_green := TRUE;
    North_yellow := FALSE;
    North_red := FALSE;
    East_green := FALSE;
    East_yellow := FALSE;
    East_red := TRUE;
END_IF

IF T1.ACC > 5000 AND T1.ACC < 5500 THEN
    North_green := FALSE;
    North_yellow := TRUE;
    North_red := FALSE;
    East_green := FALSE;
    East_yellow := FALSE;
    East_red := TRUE;
END_IF

IF T1.ACC > 5500 AND T1.ACC < 9500 THEN
    North_green := FALSE;
    North_yellow := FALSE;
    North_red := TRUE;
    East_green := TRUE;
    East_yellow := FALSE;
    East_red := FALSE;
END_IF

IF T1.ACC > 9500 AND T1.ACC < 10000 THEN
    North_green := FALSE;
    North_yellow := FALSE;
    North_red := TRUE;
    East_green := FALSE;
    East_yellow := TRUE;
    East_red := FALSE;
END_IF

END_PROGRAM
VAR
    aiOutside : INT;
    aiHumidity: INT;
    sShowText : STRING[80];
END_VAR

IF aiOutside < 18 THEN
    sShowText := 'Cold';
ELSIF (aiOutside >= 18) AND (aiOutside <= 25) THEN
    IF (aiHumid >= 40) AND (aiHumid <= 75) THEN
        sShowText := 'Opt';
    ELSE
        sShowText := 'Temp. Ok';
    END_IF
ELSE
    sShowText := 'Hot';
END_IF;
FUNCTION FC1003 : VOID
VAR_INPUT
    IN_R:REAL;
    IN_MAX, IN_MIN:REAL;
    OUT_MAX, OUT_MIN:REAL;
END_VAR
VAR_OUTPUT
    OUT_R:REAL;
    FEH:BOOL;
END_VAR
VAR_TEMP
    DIFF1, DIFF2:REAL;
END_VAR

DIFF1:= IN_MAX-IN_MIN;
DIFF2:= OUT_MAX-OUT_MIN;
FEH := (DIFF1=0) OR (DIFF2=0);
IF NOT FEH THEN
    OUT_R:= (OUT_MAX-OUT_MIN) / DIFF1 * (IN_R-IN_MIN) + OUT_MIN;
ELSE 
    OUT_R:=0.0;
END_IF;
END_FUNCTION 
FUNCTION_BLOCK FB1005
VAR_INPUT
    START:BOOL; 
    DICKE, V_MAX, V_MIN:REAL;
END_VAR
VAR_OUTPUT
    D_MAX, D_MIN:REAL; 
    P1:BOOL;
END_VAR
VAR
    FO:BOOL;
END_VAR

IF NOT START THEN 
    FO:=START; 
    RETURN;
END_IF;
IF START=TRUE AND FO=FALSE THEN 
    D_MAX:=DICKE; 
    D_MIN:=DICKE; 
    P1:=FALSE;
END_IF;
FO:=START;
IF DICKE < D_MIN THEN 
    D_MIN:=DICKE; 
END_IF;
IF DICKE > D_MAX THEN 
    D_MAX:=DICKE; 
END_IF;
IF D_MIN < V_MIN OR D_MAX > V_MAX THEN 
    P1:=TRUE; 
END_IF;
END_FUNCTION_BLOCK 
FUNCTION_BLOCK INTERLOCK
    VAR_INPUT
        I1 : BOOL;
        I2 : BOOL;
        TL : TIME;
    END_VAR
    VAR_OUTPUT
        Q1 : BOOL;
        Q2 : BOOL;
    END_VAR
    VAR
        T1 : TOF;
        T2 : TOF;
    END_VAR

    T1(IN := I1, PT := TL);
    T2(IN := I2, PT := TL);

    Q1 := I1 AND NOT t2.Q;
    Q2 := I2 AND NOT t1.Q;

END_FUNCTION_BLOCK
FUNCTION_BLOCK BURNER
  VAR_INPUT
    IN : BOOL;
    STAGE2 : BOOL;
    OVER_TEMP : BOOL;
    OIL_TEMP : BOOL := TRUE;
    FLAME : BOOL;
    RST : BOOL;
    RST_TIMER : BOOL;
    PRE_HEAT_TIME : TIME := t#5s;
    PRE_VENT_TIME : TIME := t#15s;
    PRE_IGNITE_TIME : TIME := t#15s;
    POST_IGNITE_TIME : TIME := t#25s;
    STAGE2_DELAY : TIME := t#10s;
    SAFETY_TIME : TIME := t#5s;
    LOCKOUT_TIME : TIME := t#10s;
    MULTIPLE_IGNITION : BOOL := TRUE;
    KW1 : REAL;
    KW2 : REAL;
  END_VAR
  VAR_OUTPUT
    MOTOR : BOOL;
    COIL1 : BOOL;
    COIL2 : BOOL;
    PRE_HEAT : BOOL;
    IGNITE : BOOL;
    FAIL : BOOL;
    KWH : REAL;
    STATUS : BYTE;
  END_VAR
  VAR_IN_OUT
    RUNTIME1 : UDINT;
    RUNTIME2 : UDINT;
    CYCLES : UDINT;
  END_VAR
  VAR
    state : INT;
    last : TIME;
    tx : TIME;
    last_change : TIME;
    timer1 : ONTIME;
    timer2 : ONTIME;
    oil_temp_last : BOOL;
    cycles2 : UDINT;
  END_VAR

  tx:= UDINT_TO_TIME(T_PLC_MS(en:=true));

  (* check rst input and overtemp *)
  IF rst OR over_temp OR state = 0 THEN
  	IF status > BYTE#0 AND tx - last_change >= lockout_time AND rst THEN
  		status := BYTE#110;
  		fail := FALSE;
  		state := 1;
  	ELSE
  		(* normaler reset *)
  		motor := FALSE;
  		coil1 := FALSE;
  		coil2 := FALSE;
  		ignite := FALSE;
  		pre_heat := FALSE;
  		IF over_temp THEN
  			status := BYTE#9;
  			fail := TRUE;
  		END_IF;
  		last_change := tx;
  		last := tx;
  		state := 1;
  	END_IF;
  END_IF;

  (* check for timer rst and rst timer if true *)
  IF rst_timer THEN
  	runtime1 := UDINT#0;
  	runtime2 := UDINT#0;
  	cycles := UDINT#0;
  	cycles2 := UDINT#0;
  END_IF;

  (* quit here if an error is present *)
  IF (status > BYTE#0 AND status < BYTE#100) OR rst THEN RETURN; END_IF;

  (* start sequence *)
  CASE state OF

  1:	(* in signal starts oil pre heating *)
  	IF in AND flame THEN
  		state := 7;
  		pre_heat := FALSE;
  		status := BYTE#2;
  		last_change := tx;
  	ELSIF in THEN
  		pre_heat := TRUE;
  		state := 2;
  		last_change := tx;
  	END_IF;

  2:	(* after pre_heating time start motor *)
  	IF (tx- last_change >= pre_heat_time AND oil_temp) OR (oil_temp AND NOT oil_temp_last) THEN
  		motor := TRUE;
  		state := 3;
  		last_change := tx;
  	(* pre_heat_time ist abgelaufen und oil_temp ist nicht aktiv *)
  	ELSIF tx - last_change >= pre_heat_time AND NOT oil_temp THEN
  		state := 7;
  		pre_heat := FALSE;
  		status := BYTE#1;
  		last_change := tx;
  	(* flame monitor cannot be active at this time *)
  	ELSIF flame THEN
  		state := 7;
  		pre_heat := FALSE;
  		status := BYTE#2;
  		last_change := tx;
  	END_IF;

  3:	(* abwarten bis zündung eingeschaltet werden kann *)
  	IF tx - last_change >= pre_vent_time - pre_ignite_time THEN
  		ignite := TRUE;
  		state := 4;
  		last_change := tx;
  	(* flame monitor cannot be active at this time *)
  	ELSIF flame THEN
  		state := 7;
  		pre_heat := FALSE;
  		motor := FALSE;
  		status := BYTE#3;
  		last_change := tx;
  	END_IF;

  4:	(* warten bis oelzufuhr geoeffnet werden darf *)
  	IF tx - last_change >= pre_ignite_time THEN
  		coil1 := TRUE;
  		state := 5;
  		last_change := tx;
  	END_IF;

  5:	(* warten auf flammwaechter und falls noetig abschalten *)
  	IF tx - last_change >= safety_time OR flame THEN
  		IF NOT flame THEN
  			(* notabschaltung da flammwaechster nicht angesprochen hat *)
  			state := 7;
  			motor := FALSE;
  			coil1 := FALSE;
  			pre_heat := FALSE;
  			ignite := FALSE;
  			status := BYTE#4;
  			last_change := tx;
  		ELSE
  			state := 6;
  			last_change := tx;
  		END_IF;
  	END_IF;

  6:	(* brenner läuft, flammueberwachung und nach ablauf der nachigniteszeit ignite abschalten *)
  	IF NOT flame AND NOT multiple_ignition THEN
  		(* notabschaltung da flammwaechster keine flamme meldet *)
  		state := 7;
  		motor := FALSE;
  		coil1 := FALSE;
  		coil2 := FALSE;
  		pre_heat := FALSE;
  		ignite := FALSE;
  		status := BYTE#5;
  		last_change := tx;
  	ELSIF NOT flame AND multiple_ignition THEN
  		ignite := TRUE;
  		state := 5;
  		coil2 := FALSE;
  		last_change := tx;
  	ELSE
  		IF tx - last_change >= post_ignite_time THEN
  			(* post_ignite_time abgelaufen, ignite abschalten *)
  			ignite := FALSE;
  		END_IF;
  		IF tx - last_change >= stage2_delay AND stage2 THEN
  			coil2 := TRUE;
  		ELSE
  			coil2 := FALSE;
  		END_IF;
  	END_IF;
  END_CASE;

  (* abschaltung wenn kein eingangssignal *)
  IF NOT in THEN
  	state := 1;
  	motor := FALSE;
  	coil1 := FALSE;
  	coil2 := FALSE;
  	ignite := FALSE;
  	pre_heat := FALSE;
  	last_change := tx;
  END_IF;

  (* runtimezähler *)
  timer1(in := flame AND in AND motor AND coil1 AND NOT coil2, SECONDS := runtime1, CYCLES := cycles);
  cycles := timer1.CYCLES;
  runtime1 := timer1.SECONDS;

  timer2(in := flame AND in AND motor AND coil1 AND coil2, SECONDS := runtime2, CYCLES := cycles2);
  cycles2 := timer2.CYCLES;
  runtime2 := timer2.SECONDS;

  KWH := UDINT_TO_REAL(runtime1) * KW1 / 3600.0 + UDINT_TO_REAL(runtime2) * KW2 / 3600.0;

  (* zeit fuer naechsten aufruf merken *)
  last := tx;

  (* set fail output IF ERROR and Status  if normal operation *)

  IF status > BYTE#0 AND status < BYTE#100 THEN
  	fail := TRUE;
  ELSE
  	fail := FALSE;
  	IF NOT in THEN
  		status := BYTE#110;
  	ELSIF flame AND in AND motor AND coil2 AND coil1 THEN
  		status := BYTE#113;
  	ELSIF flame AND in AND motor AND coil1 THEN
  		status := BYTE#112;
  	ELSE
  		status := BYTE#111;
  	END_IF;
  END_IF;

  (* From OSCAT Library, www.OSCAT.de *)
  (* T_PLC_MS, ONTIME required *)
END_FUNCTION_BLOCK