Inhalte

Dependency Injection: Devices

Table of Contents

Introduction

We first need a few device driver classes for our stopper.

Sensor

Interface IDigitalSensor
INTERFACE IDigitalSensor EXTENDS __System.IQueryInterface
PROPERTY isFree :BOOL
GET
PROPERTY isOccupied :BOOL
GET
Class SimpleDigitalSensor
FUNCTION_BLOCK SimpleDigitalSensor IMPLEMENTS IDigitalSensor
VAR
	DI_RawSensorSignal	AT %I*		:BOOL;
	maskSensorIsOccupied			:BOOL;
END_VAR
METHOD FB_init
VAR_INPUT
	// if TRUE, the retain variables are initialized (warm start / cold start)
	bInitRetains					:BOOL;
	// if TRUE, the instance afterwards gets moved into the copy code (online change) 
	bInCopyCode 					:BOOL;  
	maskSensorIsOccupied			:BOOL;
END_VAR
	

THIS^.maskSensorIsOccupied := maskSensorIsOccupied;
GET PROPERTY isFree :BOOL


isFree	:= (THIS^.DI_RawSensorSignal <> THIS^.maskSensorIsOccupied);
GET PROPERTY isOccupied :BOOL


isOccupied	:= (THIS^.maskSensorIsOccupied = THIS^.DI_RawSensorSignal);

Cylinder

Interface ICylinder
INTERFACE ICylinder EXTENDS __System.IQueryInterface
METHOD moveToHomePosition :ICylinder
METHOD moveToWorkPosition :ICylinder
PROPERTY isAtHomePosition :BOOL
GET
PROPERTY isAtWorkPosition :BOOL
GET
Class Cylinder0Inputs1Output
FUNCTION_BLOCK Cylinder0Inputs1Output IMPLEMENTS ICylinder
VAR
	DO_CylinderOutput 		AT %Q* 	:BOOL;
	maskMoveToHomePosition 			:BOOL;
	delayUntilPositionIsReached 	:TIME;
	delayTimerToHomePosition 		:TON;
	delayTimerToWorkPosition 		:TON;
END_VAR
METHOD FB_init :BOOL
VAR_INPUT
	// if TRUE, the retain variables are initialized (warm start / cold start)
	bInitRetains				:BOOL;
	// if TRUE, the instance afterwards gets moved into the copy code (online change)
	bInCopyCode					:BOOL;
	maskMoveToHomePosition		:BOOL;
	delayUntilPositionIsReached	:TIME;
END_VAR
THIS^.maskMoveToHomePosition		:= maskMoveToHomePosition;
THIS^.delayUntilPositionIsReached	:= delayUntilPositionIsReached;
METHOD PROTECTED updatePositionState
THIS^.delayTimerToHomePosition(
	IN := (THIS^.DO_CylinderOutput = THIS^.maskMoveToHomePosition),
	PT := (THIS^.delayUntilPositionIsReached),
);

THIS^.delayTimerToWorkPosition(
	IN := (THIS^.DO_CylinderOutput <> THIS^.maskMoveToHomePosition),
	PT := (THIS^.delayUntilPositionIsReached),
);
METHOD moveToHomePosition :ICylinder
THIS^.DO_CylinderOutput := THIS^.maskMoveToHomePosition;
THIS^.updatePositionState();
moveToHomePosition := THIS^;
METHOD moveToWorkPosition :ICylinder
THIS^.DO_CylinderOutput := (NOT THIS^.maskMoveToHomePosition);
THIS^.updatePositionState();
moveToWorkPosition := THIS^;
GET PROPERTY isAtHomePosition :BOOL


THIS^.updatePositionState();
isAtHomePosition := THIS^.delayTimerToHomePosition.Q;
GET PROPERTY isAtWorkPosition :BOOL


THIS^.updatePositionState();
isAtWorkPosition := THIS^.delayTimerToWorkPosition.Q;

Conveyor

Interface IConveyorInterface
INTERFACE IConveyorInterface EXTENDS __SYSTEM.IQueryInterface
METHOD setStartRequest
PROPERTY conveyorIsRunning :BOOL
GET
Class Conveyor
FUNCTION_BLOCK Conveyor IMPLEMENTS IConveyorInterface, IRunable
VAR
	DO_StartMotor AT %Q* :BOOL;
	{attribute 'OPC.UA.DA' := '1'}
	DI_MotorIsInOvertemperature AT %I* :BOOL;
	followUpTimer :TOF;
	followUpTime :TIME;
END_VAR
METHOD FB_init :BOOL
VAR_INPUT
	// if TRUE, the retain variables are initialized (warm start / cold start)
	bInitRetains :BOOL;
	// if TRUE, the instance afterwards gets moved into the copy code (online change)
	bInCopyCode :BOOL;
	followUpTime :TIME;
END_VAR
THIS^.followUpTime := followUpTime;
METHOD PRIVATE updateMotorState
THIS^.followUpTimer(
	IN := FALSE,
	PT := THIS^.followUpTime
);
THIS^.DO_StartMotor := (followUpTimer.Q AND (NOT THIS^.DI_MotorIsInOvertemperature));
METHOD run
THIS^.updateMotorState();
METHOD setStartRequest
VAR
startRequest :BOOL;
END_VAR
startRequest := SEL(THIS^.DI_MotorIsInOvertemperature, TRUE, FALSE);
THIS^.followUpTimer(
	IN := startRequest,
	PT := THIS^.followUpTime
);
THIS^.updateMotorState();
GET PROPERTY conveyorIsRunning :BOOL


THIS^.updateMotorState();
conveyorIsRunning := THIS^.DO_StartMotor;