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
|
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;
|