EXAMPLE: FC Toggle switch (two-way switch) AND 3D car park controlled by a robot

This example shows a function block that can be used as a Toggle Switch. A Toggle Switch changes status each time the switch is activated, and can be used as a start and stop switch for an electrical component (eg motor, fan or light).

The advantage of a Toggle Switch is that you only need to use one switch, instead of using a switch for on and a switch for off.

To the right, a time diagram is shown. The signal from the switch is CLK and the component to be switched off or on must be connected to QCLK_OLD is an internal variable used as a OneShot and ensures that there is only one change in Q status, every time CLK is activated.

FC Toggle switch

The example is based on the do-it-yourself implementation of the Oneshot, (see page ), which ensures that the solution can be used in all types of PLCs:

FUNCTION_BLOCK FBToggle
VAR_INPUT
  CLK: BOOL; // Input signal
END_VAR
VAR
// Remember previous signal on CLK
  CLK_OLD: BOOL := FALSE;
END_VAR
VAR_OUTPUT
  Q: BOOL; // Output
END_VAR

Change of status is made at #2, where Q is set to the inverted value of Q.

//Code for FUNCTION BLOCK: Toogle
//When CLK is moves from FALSE to TRUE
//Q will be TRUE if FALSE or FALSE if TRUE
//Detect the rising edge on the input signal
IF CLK AND NOT CLK_OLD THEN
  CLK_OLD:= TRUE; //#1
  Q:= NOT Q; //#2
END_IF;
//Reset the rising edge detection
IF NOT CLK THEN
  CLK_OLD:= FALSE;
END_IF;

Program example:

PROGRAM MAIN
VAR
  MyToogle:	FBToggle;
  K1:	BOOL := FALSE;
  S1:	BOOL; //Contact switch
END_VAR
//Example program:
MyToogle (CLK:= S1, Q=> K1);

FC Toggle switch

This chapter shows an example of a PLC program used to handle cars inside a car park.

When the car is inserted into the car park house by the robot, the program has to first find a vacant space to ensure the robot knows where to place the car.

When the car is picked up by the car driver, the car must first be located by the program, so the robot knows where to pick up the car from.

Due to the fact that a car license plate is unique, it is used as the identifier, and as it contains numbers and letters it is set to a STRING data type in the PLC program. The length of the STRING is limited to 15 characters to save memory in the program. The constant for this is named STR15.

It is possible to insert, find or remove cars from the parking house. To reuse as much of the program code as possible, only one function named CarHandle is implemented which takes one of the following parameters: CAR_INSERT, CAR_FIND or CAR_DEL.

A location inside the 3D parking house consists of x, y and z coordinates and therefore a STRUCT named Pos is declared because this gives a clear structure to the code.

TYPE Pos :
 STRUCT
  x: INT;
  y: INT;
  z: INT;
 END_STRUCT
END_TYPE

VAR_GLOBAL CONSTANT
 STR15 : INT:= 15; //Car number
 CAR_INSERT :	INT := 1;
 CAR_FIND :	INT:= 2;
 CAR_DEL :	INT:= 3;
END_VAR

VAR_GLOBAL CONSTANT
 X_MAX: WORD := 2;
 Y_MAX: WORD := 3;
 Z_MAX: WORD := 4;
END_VAR

Below see how the CarHandle function can be used:

PROGRAM Main
VAR
 MyPos: Pos; //Location inside the car park house
 ArCarPark: ARRAY[1.. GVL.X_MAX, 1.. GVL.Y_MAX, 1.. GVL.Z_MAX] OF STRING[GVL.STR15];
END_VAR
// REMEMBER TO run the code only once!
ArCarPark [1,3,1]:= 'YD 12345'; //Insert car directly into the 3D Array
CarHandle ('YD 12345', GVL.CAR_FIND, ArCarPark, MyPos); //MyPos.x = 1, MyPos.y =3, MyPos.z = 1
CarHandle ('AB 12345', GVL.CAR_INSERT, ArCarPark, MyPos);
CarHandle ('AB 12345', GVL.CAR_DEL, ArCarPark, MyPos);
FUNCTION CarHandle : BOOL
VAR_INPUT
 CarStr:	STRING; //Number plate for the car
 Handle:	INT; // What action to take? CAR_FIND, CAR_DEL or CAR_INSERT
END_VAR
VAR_IN_OUT
 arPark:	ARRAY[*, *, *] OF STRING [GVL.STR15]; //Pointer to 3D ARRAY
 CarP:	Pos; // Location of the car
END_VAR
VAR
 Loop, Found : Pos; //Working STRUCT
 Ctrl: BOOL := FALSE; //Control the operation inside this function. If FALSE an error occur
END_VAR
//Copy ARRAY sizes to local variables to maintain readable program code for the LOOPs
Loop.x:= DINT_TO_INT (UPPER_BOUND (arPark, 1)); //Size 1D
Loop.y:= DINT_TO_INT (UPPER_BOUND (arPark, 2)); //Size 2D
Loop.z:= DINT_TO_INT (UPPER_BOUND (arPark, 3)); //Size 3D
//LOOP through all locations in the 3D car park house
FOR CarP.x:= 1 TO Loop.x DO
FOR CarP.y := 1 TO Loop.y DO
FOR CarP.z:= 1 TO Loop.z DO
//Condition only passes when no action has been taken
IF Ctrl = FALSE THEN
IF FIND (ArPark [CarP.x, CarP.y, CarP.z], CarStr) > 0 THEN
CASE Handle OF
GVL.CAR_FIND : Found:= CarP; //Copy coordinates where the car was located
GVL.CAR_DEL : ArPark [CarP.x, CarP.y, CarP.z]:= ''; //Set STRING to empty
END_CASE
Ctrl:= TRUE; //done
END_IF;
//Insert the car at the first free location in the parking house
IF Handle = GVL.CAR_INSERT AND ArPark [CarP.x, CarP.y, CarP.z] = '' THEN
ArPark [CarP.x, CarP.y, CarP.z]:= CarStr; //Insert
Ctrl:= TRUE; //done
END_IF;
END_IF;
END_FOR; //z
END_FOR; //y
END_FOR; //x
//Set return values (copy x, y, z coordinates inside STRUCT) and error code
CarP:= Found;
CarHandle := Ctrl;

 

Leave a Comment