Added JobScheduler and recipe data for stations
This commit is contained in:
170
PLC/LibraryCandidates/Scheduler/POUs/FB_Scheduler.TcPOU
Normal file
170
PLC/LibraryCandidates/Scheduler/POUs/FB_Scheduler.TcPOU
Normal file
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_Scheduler" Id="{af4eba28-c46c-4c30-8885-00e91057da4d}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_Scheduler
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR_IN_OUT
|
||||
fbFlowRecHandler : FB_FlowRecHandler;
|
||||
fbJobQueue : FB_JobQueue;
|
||||
END_VAR
|
||||
VAR
|
||||
// Array needs to start at 1 so that 0 can be an invalid station
|
||||
// Maybe later change this to int ant -1
|
||||
_aiStations : ARRAY[1..(GVL_Scheduler.MAX_STATIONS)] OF I_Station;
|
||||
_uiStationCount : UINT := 0;
|
||||
|
||||
_fbTransport : I_Transport;
|
||||
|
||||
_uiCnt : UINT;
|
||||
_uiNextAvailStation : UINT;
|
||||
|
||||
_iFlowRecIdx : INT;
|
||||
_dwNextProcReq : DWORD;
|
||||
|
||||
_stTmpJob : ST_TransJob;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Call job queue
|
||||
fbJobQueue(xEnableAging := FALSE);
|
||||
|
||||
// Avoid invalid interface refs
|
||||
IF (_uiStationCount = 0) OR (_fbTransport = 0) THEN
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
IF (NOT _fbTransport.P_Available) THEN
|
||||
// No need to check the stations if we don't have a transport ready
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
|
||||
|
||||
FOR _uiCnt := 1 TO _uiStationCount DO
|
||||
IF _aiStations[_uiCnt].P_ProdAvail THEN
|
||||
// Get flow recipe index
|
||||
_iFlowRecIdx := _aiStations[_uiCnt].P_CurrFlowRecIdx;
|
||||
|
||||
// Get next process requirements
|
||||
IF (NOT fbFlowRecHandler.M_GetNextProcReq(iIdx := _iFlowRecIdx, dwProcReq => _dwNextProcReq)) THEN
|
||||
CONTINUE;
|
||||
END_IF
|
||||
|
||||
// Find next available station according to recipe and available station
|
||||
_uiNextAvailStation := M_FindNextAvailStation(_dwNextProcReq);
|
||||
|
||||
// Check if there is a station available
|
||||
IF _uiNextAvailStation <> 0 THEN
|
||||
// Reserve source station
|
||||
_stTmpJob.uiFromStationHandle := _aiStations[_uiCnt].M_Reserve();
|
||||
|
||||
// Reserve target station
|
||||
_stTmpJob.uiToStationHandle := _aiStations[_uiNextAvailStation].M_Reserve();
|
||||
|
||||
// Check if we could reserve the stations
|
||||
IF (_stTmpJob.uiToStationHandle <> 0) AND (_stTmpJob.uiFromStationHandle <> 0) THEN
|
||||
// Create transport job
|
||||
_stTmpJob.uiFromStation := _uiCnt;
|
||||
_stTmpJob.uiToStation := _uiNextAvailStation;
|
||||
_stTmpJob.uiPrio := fbFlowRecHandler.M_GetNextPrio(iIdx := _iFlowRecIdx);
|
||||
|
||||
// Add job to job queue
|
||||
fbJobQueue.M_AddJob(stJob := _stTmpJob);
|
||||
ELSE
|
||||
// Remove registrations from stations
|
||||
_aiStations[_uiCnt].M_Release(_stTmpJob.uiFromStationHandle);
|
||||
_aiStations[_uiNextAvailStation].M_Release(_stTmpJob.uiToStationHandle);
|
||||
END_IF
|
||||
END_IF
|
||||
END_IF
|
||||
END_FOR]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="M_ClearStations" Id="{7c667e8a-38f2-48a9-afff-834e87e4d3f6}">
|
||||
<Declaration><![CDATA[METHOD M_ClearStations
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Remove all registered stations from array
|
||||
MEMSET(destAddr := ADR(_aiStations), fillByte := 0, n := SIZEOF(_aiStations));
|
||||
|
||||
// Reset number of registered stations
|
||||
_uiStationCount := 0;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_FindNextAvailStation" Id="{75382296-32be-4724-b020-39273aa8358c}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE M_FindNextAvailStation : UINT
|
||||
VAR_INPUT
|
||||
dwProcReq : DWORD;
|
||||
END_VAR
|
||||
VAR
|
||||
_uiCnt : UINT;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[FOR _uiCnt := 1 TO _uiStationCount DO
|
||||
IF _aiStations[_uiCnt].M_HasCapabilty(dwProcReq) AND _aiStations[_uiCnt].P_Available THEN
|
||||
M_FindNextAvailStation := _uiCnt;
|
||||
RETURN;
|
||||
END_IF
|
||||
END_FOR
|
||||
|
||||
M_FindNextAvailStation := 0;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_GetStation" Id="{e8451683-3cd1-4d6f-99dd-76f33ecd008d}">
|
||||
<Declaration><![CDATA[METHOD M_GetStation : I_Station
|
||||
VAR_INPUT
|
||||
iStationIdx : INT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF iStationIdx < 1 OR iStationIdx > (GVL_Scheduler.MAX_STATIONS - 1) THEN
|
||||
M_GetStation := 0;
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
M_GetStation := _aiStations[iStationIdx];]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_Register" Id="{6a14034a-d5c0-46c1-a13b-418885a02563}">
|
||||
<Declaration><![CDATA[METHOD M_Register
|
||||
VAR_INPUT
|
||||
fbStation : I_Station;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Check if station is valid interface
|
||||
IF fbStation = 0 THEN
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
// Check if we have free slots
|
||||
IF _uiStationCount < GVL_Scheduler.MAX_STATIONS THEN
|
||||
_uiStationCount := _uiStationCount + 1;
|
||||
_aiStations[_uiStationCount] := fbStation;
|
||||
_aiStations[_uiStationCount].P_StationID := _uiStationCount;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_RegisterTransport" Id="{a85ebd03-27a5-40c5-bd8f-ade9f2eac962}">
|
||||
<Declaration><![CDATA[METHOD M_RegisterTransport
|
||||
VAR_INPUT
|
||||
fbTransport : I_Transport;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Check if transport is valid interface
|
||||
IF fbTransport = 0 THEN
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
// Set transport interface
|
||||
_fbTransport := fbTransport;
|
||||
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
Reference in New Issue
Block a user