First working implementation
- Currently only with one sided gripper
This commit is contained in:
9
PLC/GVLs/GVL_Product.TcGVL
Normal file
9
PLC/GVLs/GVL_Product.TcGVL
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<GVL Name="GVL_Product" Id="{cd06b28b-40e0-45d6-96ec-08dcaca45fe3}">
|
||||
<Declaration><![CDATA[{attribute 'qualified_only'}
|
||||
VAR_GLOBAL
|
||||
axProductInStation : ARRAY[0..4] OF BOOL;
|
||||
END_VAR]]></Declaration>
|
||||
</GVL>
|
||||
</TcPlcObject>
|
||||
@@ -18,22 +18,20 @@
|
||||
<LibraryReferences>{c5c6b994-f2a1-4a71-b657-f282007c0cd2}</LibraryReferences>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="GVLs\GVL_Product.TcGVL">
|
||||
<SubType>Code</SubType>
|
||||
<LinkAlways>true</LinkAlways>
|
||||
</Compile>
|
||||
<Compile Include="PlcTask.TcTTO">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="POUs\MAIN.TcPOU">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\DUTs\E_TransitCond.TcDUT">
|
||||
<Compile Include="POUs\Scheduler\DUTs\ST_FlowRecipe.TcDUT">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\DUTs\ST_Recipe.TcDUT">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\DUTs\ST_RecipeNode.TcDUT">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\DUTs\ST_Transition.TcDUT">
|
||||
<Compile Include="POUs\Scheduler\DUTs\ST_FlowRecipeNode.TcDUT">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\DUTs\ST_TransJob.TcDUT">
|
||||
@@ -43,7 +41,7 @@
|
||||
<SubType>Code</SubType>
|
||||
<LinkAlways>true</LinkAlways>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\ITFs\I_Product.TcIO">
|
||||
<Compile Include="POUs\Scheduler\ITFs\I_FlowRecHandler.TcIO">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\ITFs\I_Station.TcIO">
|
||||
@@ -54,18 +52,27 @@
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\POUs\FB_JobQueue.TcPOU">
|
||||
<SubType>Code</SubType>
|
||||
<ExcludeFromBuild>false</ExcludeFromBuild>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\POUs\FB_Product.TcPOU">
|
||||
<Compile Include="POUs\Scheduler\POUs\FB_FlowRecHandler.TcPOU">
|
||||
<SubType>Code</SubType>
|
||||
<ExcludeFromBuild>false</ExcludeFromBuild>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\POUs\FB_Scheduler.TcPOU">
|
||||
<SubType>Code</SubType>
|
||||
<ExcludeFromBuild>false</ExcludeFromBuild>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\POUs\FB_StationBase.TcPOU">
|
||||
<Compile Include="POUs\Scheduler\POUs\FB_BaseStation.TcPOU">
|
||||
<SubType>Code</SubType>
|
||||
<ExcludeFromBuild>false</ExcludeFromBuild>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\POUs\FB_TransportBase.TcPOU">
|
||||
<Compile Include="POUs\Scheduler\POUs\FB_BaseTransport.TcPOU">
|
||||
<SubType>Code</SubType>
|
||||
<ExcludeFromBuild>false</ExcludeFromBuild>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Scheduler\POUs\GVL_Test.TcGVL">
|
||||
<SubType>Code</SubType>
|
||||
<LinkAlways>true</LinkAlways>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Stations\FB_Etcher.TcPOU">
|
||||
<SubType>Code</SubType>
|
||||
@@ -82,16 +89,26 @@
|
||||
<Compile Include="POUs\Stations\FB_Output.TcPOU">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="POUs\Stations\FB_Robot.TcPOU">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="POUs\ST_RobotMoveData.TcDUT">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="DUTs" />
|
||||
<Folder Include="GVLs" />
|
||||
<Folder Include="POUs\Scheduler" />
|
||||
<Folder Include="POUs\Scheduler">
|
||||
<ExcludeFromBuild>false</ExcludeFromBuild>
|
||||
</Folder>
|
||||
<Folder Include="POUs\Scheduler\ITFs" />
|
||||
<Folder Include="POUs\Scheduler\DUTs" />
|
||||
<Folder Include="POUs\Scheduler\GVLs" />
|
||||
<Folder Include="POUs\Scheduler\POUs" />
|
||||
<Folder Include="POUs\Stations" />
|
||||
<Folder Include="POUs\Stations">
|
||||
<ExcludeFromBuild>false</ExcludeFromBuild>
|
||||
</Folder>
|
||||
<Folder Include="VISUs" />
|
||||
<Folder Include="POUs" />
|
||||
</ItemGroup>
|
||||
@@ -118,8 +135,8 @@
|
||||
<ProjectExtensions>
|
||||
<PlcProjectOptions>
|
||||
<XmlArchive>
|
||||
<Data>
|
||||
<o xml:space="preserve" t="OptionKey">
|
||||
<Data>
|
||||
<o xml:space="preserve" t="OptionKey">
|
||||
<v n="Name">"<ProjectRoot>"</v>
|
||||
<d n="SubKeys" t="Hashtable" ckt="String" cvt="OptionKey">
|
||||
<v>{192FAD59-8248-4824-A8DE-9177C94C195A}</v>
|
||||
@@ -195,14 +212,14 @@
|
||||
</d>
|
||||
<d n="Values" t="Hashtable" />
|
||||
</o>
|
||||
</Data>
|
||||
<TypeList>
|
||||
<Type n="Boolean">System.Boolean</Type>
|
||||
<Type n="Hashtable">System.Collections.Hashtable</Type>
|
||||
<Type n="OptionKey">{54dd0eac-a6d8-46f2-8c27-2f43c7e49861}</Type>
|
||||
<Type n="String">System.String</Type>
|
||||
</TypeList>
|
||||
</XmlArchive>
|
||||
</Data>
|
||||
<TypeList>
|
||||
<Type n="Boolean">System.Boolean</Type>
|
||||
<Type n="Hashtable">System.Collections.Hashtable</Type>
|
||||
<Type n="OptionKey">{54dd0eac-a6d8-46f2-8c27-2f43c7e49861}</Type>
|
||||
<Type n="String">System.String</Type>
|
||||
</TypeList>
|
||||
</XmlArchive>
|
||||
</PlcProjectOptions>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
15
PLC/PLC.tmc
15
PLC/PLC.tmc
File diff suppressed because one or more lines are too long
@@ -14,8 +14,18 @@ VAR
|
||||
_fbOutput : FB_Output;
|
||||
_fbNIO : FB_NIO;
|
||||
|
||||
// Transport
|
||||
_fbRobot : FB_Robot;
|
||||
|
||||
// Job queue
|
||||
_fbJobQueue : FB_JobQueue;
|
||||
|
||||
// Example recipe
|
||||
_stRecipeSimple : ST_Recipe;
|
||||
_stRecipeSimple : ST_FlowRecipe;
|
||||
|
||||
_fbFlowRecHandler : FB_FlowRecHandler;
|
||||
|
||||
_xStart : BOOL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
@@ -25,18 +35,31 @@ END_VAR
|
||||
END_IF
|
||||
|
||||
// Call all stations
|
||||
_fbInput();
|
||||
_fbEtcher();
|
||||
_fbHVTest();
|
||||
_fbOutput();
|
||||
_fbNIO();
|
||||
_fbInput(fbFlowRecHandler := _fbFlowRecHandler);
|
||||
GVL_Product.axProductInStation[0] := _fbInput.P_HasProduct;
|
||||
|
||||
_fbEtcher(fbFlowRecHandler := _fbFlowRecHandler);
|
||||
GVL_Product.axProductInStation[1] := _fbEtcher.P_HasProduct;
|
||||
|
||||
_fbHVTest(fbFlowRecHandler := _fbFlowRecHandler);
|
||||
GVL_Product.axProductInStation[2] := _fbHVTest.P_HasProduct;
|
||||
|
||||
_fbOutput(fbFlowRecHandler := _fbFlowRecHandler);
|
||||
GVL_Product.axProductInStation[3] := _fbOutput.P_HasProduct;
|
||||
|
||||
_fbNIO(fbFlowRecHandler := _fbFlowRecHandler);
|
||||
GVL_Product.axProductInStation[4] := _fbNIO.P_HasProduct;
|
||||
|
||||
|
||||
// Call scheduler
|
||||
_fbScheduler();]]></ST>
|
||||
_fbScheduler(fbFlowRecHandler := _fbFlowRecHandler, fbJobQueue := _fbJobQueue);
|
||||
|
||||
// Call robot transport
|
||||
_fbRobot(fbJobQueue := _fbJobQueue, fbScheduler := _fbScheduler);]]></ST>
|
||||
</Implementation>
|
||||
<Action Name="A_Init" Id="{203d4406-b6da-4e3d-8378-ac96a0e18ff2}">
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Register stations to scheduler
|
||||
<ST><![CDATA[// // Register stations to scheduler
|
||||
_fbScheduler.M_ClearStations();
|
||||
|
||||
_fbScheduler.M_Register(_fbInput);
|
||||
@@ -45,26 +68,35 @@ _fbScheduler.M_Register(_fbHVTest);
|
||||
_fbScheduler.M_Register(_fbOutput);
|
||||
_fbScheduler.M_Register(_fbNIO);
|
||||
|
||||
// Register transport
|
||||
_fbScheduler.M_RegisterTransport(_fbRobot);
|
||||
|
||||
|
||||
// Create simple recipe
|
||||
_stRecipeSimple.uiRecipeID := 1;
|
||||
_stRecipeSimple.uiStartNode := 0;
|
||||
_stRecipeSimple.uiNodeCnt := 3;
|
||||
_stRecipeSimple.uiNodeCnt := 4;
|
||||
|
||||
// Process nodes
|
||||
_stRecipeSimple.astNodes[0].uiNodeID := 1;
|
||||
_stRecipeSimple.astNodes[0].dwReqCap := 16#0001;
|
||||
_stRecipeSimple.astNodes[0].uiTransCnt := 1;
|
||||
_stRecipeSimple.astNodes[0].astTransitions[0].eCondition := E_TransitCond.ALWAYS;
|
||||
_stRecipeSimple.astNodes[0].astTransitions[0].uiNextNodeID := 1;
|
||||
|
||||
_stRecipeSimple.astNodes[1].uiNodeID := 1;
|
||||
_stRecipeSimple.astNodes[1].dwReqCap := 16#0001;
|
||||
_stRecipeSimple.astNodes[1].uiTransCnt := 2;
|
||||
_stRecipeSimple.astNodes[1].astTransitions[0].eCondition := E_TransitCond.RESULT_OK;
|
||||
_stRecipeSimple.astNodes[1].astTransitions[0].uiNextNodeID := 3;
|
||||
_stRecipeSimple.astNodes[1].astTransitions[1].eCondition := E_TransitCond.RESULT_NIO;
|
||||
_stRecipeSimple.astNodes[1].astTransitions[1].uiNextNodeID := 4;]]></ST>
|
||||
// Etching
|
||||
_stRecipeSimple.astNodes[0].dwReqCap := 16#0001;
|
||||
_stRecipeSimple.astNodes[0].iNextNodeSuccess := 1;
|
||||
_stRecipeSimple.astNodes[0].iNextNodeFail := 3;
|
||||
|
||||
// HV Testing
|
||||
_stRecipeSimple.astNodes[1].dwReqCap := 16#0002;
|
||||
_stRecipeSimple.astNodes[1].iNextNodeSuccess := 2;
|
||||
_stRecipeSimple.astNodes[1].uiMaxRetries := 1;
|
||||
_stRecipeSimple.astNodes[1].iNextNodeRetry := 0;
|
||||
_stRecipeSimple.astNodes[1].iNextNodeFail := 3;
|
||||
|
||||
// Output
|
||||
_stRecipeSimple.astNodes[2].dwReqCap := 16#0004;
|
||||
|
||||
// NIO
|
||||
_stRecipeSimple.astNodes[3].dwReqCap := 16#0008;
|
||||
|
||||
// Set flow recipe in input station
|
||||
_fbInput.M_SetRecipe(_stRecipeSimple);]]></ST>
|
||||
</Implementation>
|
||||
</Action>
|
||||
</POU>
|
||||
|
||||
15
PLC/POUs/ST_RobotMoveData.TcDUT
Normal file
15
PLC/POUs/ST_RobotMoveData.TcDUT
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_RobotMoveData" Id="{94123d39-0745-4fc4-b9ca-f3094a525f9a}">
|
||||
<Declaration><![CDATA[TYPE ST_RobotMoveData :
|
||||
STRUCT
|
||||
rWaitTime : REAL;
|
||||
|
||||
rX : REAL;
|
||||
rY : REAL;
|
||||
rZ : REAL;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="E_TransitCond" Id="{0c8e8042-17f8-4b76-ad0c-96d650245098}">
|
||||
<Declaration><![CDATA[{attribute 'qualified_only'}
|
||||
{attribute 'strict'}
|
||||
{attribute 'to_string'}
|
||||
TYPE E_TransitCond :
|
||||
(
|
||||
ALWAYS := 0,
|
||||
RESULT_OK,
|
||||
RESULT_NIO
|
||||
);
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
31
PLC/POUs/Scheduler/DUTs/ST_FlowRecipe.TcDUT
Normal file
31
PLC/POUs/Scheduler/DUTs/ST_FlowRecipe.TcDUT
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_FlowRecipe" Id="{3e2c2867-3147-4627-bf49-6255dbaf5310}">
|
||||
<Declaration><![CDATA[TYPE ST_FlowRecipe :
|
||||
STRUCT
|
||||
// Index in station recipe arrays
|
||||
// -1 is used to determin if the slot
|
||||
// in the product array is free.
|
||||
// The index number will automatically be
|
||||
// assigned by the FB_ProductHandler
|
||||
iProdIdx : INT := -1;
|
||||
|
||||
// Current node in flow graph
|
||||
iCurrNode : INT := 0;
|
||||
|
||||
// Next node in flow graph
|
||||
// will be set by the station after completed process
|
||||
// 0 means that there is no next node and the
|
||||
// flow recipe is finished
|
||||
iNextNode : INT := 0;
|
||||
|
||||
// Number of flow nodes
|
||||
uiNodeCnt : INT := 0;
|
||||
|
||||
// Flow nodes array
|
||||
astNodes : ARRAY[0..(GVL_Scheduler.MAX_RECIPE_NODES - 1)] OF ST_FlowRecipeNode;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
34
PLC/POUs/Scheduler/DUTs/ST_FlowRecipeNode.TcDUT
Normal file
34
PLC/POUs/Scheduler/DUTs/ST_FlowRecipeNode.TcDUT
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_FlowRecipeNode" Id="{ceb8b626-8a65-4e92-9344-14e330b6c8bd}">
|
||||
<Declaration><![CDATA[TYPE ST_FlowRecipeNode :
|
||||
STRUCT
|
||||
// Priority for transportation after completed node
|
||||
uiPriority : UINT := 100;
|
||||
|
||||
// Required capabilities
|
||||
dwReqCap : DWORD := 0;
|
||||
|
||||
// How many retries are allowed of this node
|
||||
uiMaxRetries : UINT := 0;
|
||||
|
||||
// Current numbers of retries of this node
|
||||
uiCurrRetries : UINT := 0;
|
||||
|
||||
// Was the current process successfull
|
||||
xSuccess : BOOL := FALSE;
|
||||
|
||||
// Transition to node when operation ok
|
||||
iNextNodeSuccess : INT := -1;
|
||||
|
||||
// Transition to node when retrying
|
||||
iNextNodeRetry : INT := -1;
|
||||
|
||||
// Transition to node when operation failed
|
||||
// or max retries reached
|
||||
iNextNodeFail : INT := -1;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_Recipe" Id="{3e2c2867-3147-4627-bf49-6255dbaf5310}">
|
||||
<Declaration><![CDATA[TYPE ST_Recipe :
|
||||
STRUCT
|
||||
uiRecipeID : UINT;
|
||||
uiStartNode : UINT := 0;
|
||||
uiNodeCnt : UINT := 0;
|
||||
astNodes : ARRAY[0..(GVL_Scheduler.MAX_RECIPE_NODES - 1)] OF ST_RecipeNode;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_RecipeNode" Id="{ceb8b626-8a65-4e92-9344-14e330b6c8bd}">
|
||||
<Declaration><![CDATA[TYPE ST_RecipeNode :
|
||||
STRUCT
|
||||
uiNodeID : UINT;
|
||||
// Required capabilities
|
||||
dwReqCap : DWORD;
|
||||
|
||||
// Transition count
|
||||
uiTransCnt : UINT;
|
||||
|
||||
// Transitions
|
||||
astTransitions : ARRAY[0..(GVL_Scheduler.MAX_STATIONS - 1)] OF ST_Transition;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
@@ -4,21 +4,19 @@
|
||||
<Declaration><![CDATA[TYPE ST_TransJob :
|
||||
STRUCT
|
||||
// Station to pick from
|
||||
uiFromNodeID : UINT;
|
||||
// Station to put into
|
||||
uiToNodeID : UINT;
|
||||
// Static priority from recipe
|
||||
iStatPrio : INT;
|
||||
// Dynamic priority from process
|
||||
iDynPrio : INT;
|
||||
// Prio sum
|
||||
iSumPrio : INT;
|
||||
// Time this job was created
|
||||
// The older the job the higher the priority
|
||||
uliTimeCreated : ULINT;
|
||||
uiFromStation : UINT;
|
||||
|
||||
// Is this job in the queue still valid
|
||||
xValid : BOOL := TRUE;
|
||||
// Station to put into
|
||||
uiToStation : UINT;
|
||||
|
||||
// Handle from reserved source station
|
||||
uiFromStationHandle : UINT;
|
||||
|
||||
// Handle from reserved target station
|
||||
uiToStationHandle : UINT;
|
||||
|
||||
// Static priority from recipe
|
||||
uiPrio : UINT;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_Transition" Id="{7b8c5232-d3a6-4d0b-b8ad-e54400018d53}">
|
||||
<Declaration><![CDATA[TYPE ST_Transition :
|
||||
STRUCT
|
||||
eCondition : E_TransitCond;
|
||||
uiNextNodeID : UINT;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
@@ -10,8 +10,10 @@ VAR_GLOBAL CONSTANT
|
||||
// Scheduler constants
|
||||
MAX_STATIONS : UINT := 10;
|
||||
|
||||
// Factor to calc dynmaic priority from age of job in prio/s
|
||||
AGE_FACTOR : REAL := 1.0;
|
||||
// Factor to calc dynamic priority from age of job in prio/s
|
||||
AGING_STEP : UINT := 1;
|
||||
|
||||
MAX_PRIORITY : UINT := 65535;
|
||||
|
||||
// Job queue constants
|
||||
MAX_JOBS_IN_QUEUE : UINT := 10;
|
||||
|
||||
47
PLC/POUs/Scheduler/ITFs/I_FlowRecHandler.TcIO
Normal file
47
PLC/POUs/Scheduler/ITFs/I_FlowRecHandler.TcIO
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<Itf Name="I_FlowRecHandler" Id="{6edbf032-1748-4bdd-83cb-a3d71babaa22}">
|
||||
<Declaration><![CDATA[INTERFACE I_FlowRecHandler
|
||||
]]></Declaration>
|
||||
<Method Name="M_AddFlowRec" Id="{99764a4e-e4e8-4559-8137-ead050289c2f}">
|
||||
<Declaration><![CDATA[METHOD M_AddFlowRec : INT
|
||||
VAR_INPUT
|
||||
stFlowRecipe : ST_FlowRecipe;
|
||||
END_VAR]]></Declaration>
|
||||
</Method>
|
||||
<Method Name="M_GetFlowRec" Id="{acfd7fa8-d012-4f06-a247-ab699d1b3413}">
|
||||
<Declaration><![CDATA[METHOD M_GetFlowRec : REFERENCE TO ST_FlowRecipe
|
||||
VAR_INPUT
|
||||
iIdx : INT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
</Method>
|
||||
<Method Name="M_GetNextProcReq" Id="{b0952230-f0ad-4f72-b4ae-f75c72b5379f}">
|
||||
<Declaration><![CDATA[METHOD M_GetNextProcReq : BOOL
|
||||
VAR_INPUT
|
||||
// Flow recipe pool index
|
||||
iIdx : INT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
// Process requirements bitmask
|
||||
dwProcReq : DWORD;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
</Method>
|
||||
<Method Name="M_RemFlowRec" Id="{24769a0f-680b-4bee-aa98-9f548ec7f78c}">
|
||||
<Declaration><![CDATA[METHOD M_RemFlowRec : BOOL
|
||||
VAR_INPUT
|
||||
iIdx : INT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
</Method>
|
||||
<Method Name="M_ReportResult" Id="{4c4a5c8e-bf65-4842-9e43-a2f8387979e2}">
|
||||
<Declaration><![CDATA[METHOD M_ReportResult : BOOL
|
||||
VAR_INPUT
|
||||
iIdx : INT;
|
||||
xResult : BOOL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
</Method>
|
||||
</Itf>
|
||||
</TcPlcObject>
|
||||
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<Itf Name="I_Product" Id="{78dffc1b-aed6-4622-8b64-e060477179c6}">
|
||||
<Declaration><![CDATA[{attribute 'no_explicit_call' := 'do not call this POU directly'}
|
||||
INTERFACE I_Product
|
||||
]]></Declaration>
|
||||
<Method Name="M_SetCurrProcRes" Id="{afd48187-6008-4813-8fe5-04c632483cf0}">
|
||||
<Declaration><![CDATA[METHOD M_SetCurrProcRes
|
||||
VAR_INPUT
|
||||
xSuccess : BOOL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
</Method>
|
||||
<Property Name="P_CurrNodeID" Id="{2408303a-b81e-4623-9557-4af29ff08776}">
|
||||
<Declaration><![CDATA[PROPERTY P_CurrNodeID : UINT]]></Declaration>
|
||||
<Get Name="Get" Id="{c7773936-77b0-42da-86b5-ef706272183a}">
|
||||
<Declaration><![CDATA[]]></Declaration>
|
||||
</Get>
|
||||
<Set Name="Set" Id="{1ecab2de-a6ae-4a48-a0d3-c65c8bfe8a22}">
|
||||
<Declaration><![CDATA[]]></Declaration>
|
||||
</Set>
|
||||
</Property>
|
||||
<Property Name="P_NextReqCap" Id="{ea007dca-197b-4284-b65b-0f7c1a14e1fa}">
|
||||
<Declaration><![CDATA[PROPERTY P_NextReqCap : DWORD]]></Declaration>
|
||||
<Get Name="Get" Id="{0abf4eb3-351d-4342-a687-7722bc63fdaa}">
|
||||
<Declaration><![CDATA[]]></Declaration>
|
||||
</Get>
|
||||
</Property>
|
||||
</Itf>
|
||||
</TcPlcObject>
|
||||
@@ -10,26 +10,26 @@ VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
</Method>
|
||||
<Method Name="M_InsertProduct" Id="{6d808715-3e3b-47f8-9bce-8110ddf0fadc}">
|
||||
<Method Name="M_InsertProduct" Id="{73df88e2-075f-45f5-90de-892fc737e8cc}">
|
||||
<Declaration><![CDATA[METHOD M_InsertProduct : BOOL;
|
||||
VAR_INPUT
|
||||
fbProduct : I_Product;
|
||||
iFlowRecIdx : INT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
</Method>
|
||||
<Method Name="M_Release" Id="{8a898aac-0cc9-477d-9998-62f5f31391c7}">
|
||||
<Declaration><![CDATA[METHOD M_Release : BOOL
|
||||
VAR_INPUT
|
||||
udiHandle : UDINT;
|
||||
uiHandle : UINT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
</Method>
|
||||
<Method Name="M_RemoveProduct" Id="{90af1fde-9aed-4c2f-990d-d0ad1af5a705}">
|
||||
<Declaration><![CDATA[METHOD M_RemoveProduct : I_Product
|
||||
<Declaration><![CDATA[METHOD M_RemoveProduct : INT
|
||||
]]></Declaration>
|
||||
</Method>
|
||||
<Method Name="M_Reserve" Id="{6c535852-3b02-41fc-a4fc-9b0284412ec7}">
|
||||
<Declaration><![CDATA[METHOD M_Reserve : UDINT
|
||||
<Declaration><![CDATA[METHOD M_Reserve : UINT
|
||||
]]></Declaration>
|
||||
</Method>
|
||||
<Property Name="P_Available" Id="{3075cb0b-1920-4207-a4f7-c06c6ad91a05}">
|
||||
@@ -50,6 +50,12 @@ END_VAR
|
||||
<Declaration><![CDATA[]]></Declaration>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="P_CurrFlowRecIdx" Id="{5ed2ff40-a91e-4a0c-a811-d777c4479d01}">
|
||||
<Declaration><![CDATA[PROPERTY P_CurrFlowRecIdx : INT]]></Declaration>
|
||||
<Get Name="Get" Id="{231435f7-ad8b-4f53-a923-60b6c4b48be9}">
|
||||
<Declaration><![CDATA[]]></Declaration>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="P_HasError" Id="{9d27caa3-2913-4127-9dc4-3c0085468476}">
|
||||
<Declaration><![CDATA[PROPERTY P_HasError : BOOL]]></Declaration>
|
||||
<Get Name="Get" Id="{ce1554ec-8c79-4cec-ba5a-7f52f7858b24}">
|
||||
@@ -62,23 +68,16 @@ END_VAR
|
||||
<Declaration><![CDATA[]]></Declaration>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="P_Product" Id="{20f38cff-89b3-4ebd-9f5f-171721cc7f4c}">
|
||||
<Declaration><![CDATA[PROPERTY P_Product : I_Product]]></Declaration>
|
||||
<Get Name="Get" Id="{54f46645-3bb5-477e-a037-282c55914608}">
|
||||
<Declaration><![CDATA[]]></Declaration>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="P_Result" Id="{703e039e-b718-4d79-86bd-e01bd8c2d16b}">
|
||||
<Declaration><![CDATA[PROPERTY P_Result : UINT]]></Declaration>
|
||||
<Get Name="Get" Id="{5a6206de-d50c-4c20-be99-7f2f851fee69}">
|
||||
<Declaration><![CDATA[]]></Declaration>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="P_StationID" Id="{9004f009-99e0-41c2-a1a1-57af78c8e0c6}">
|
||||
<Declaration><![CDATA[PROPERTY P_StationID : UINT]]></Declaration>
|
||||
<Get Name="Get" Id="{060c4b1d-c578-4e27-95fc-86c34f0eedd4}">
|
||||
<Declaration><![CDATA[]]></Declaration>
|
||||
</Get>
|
||||
<Set Name="Set" Id="{30ef11e6-3d79-4cf4-bd0d-ecf371cdb56f}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
</Set>
|
||||
</Property>
|
||||
</Itf>
|
||||
</TcPlcObject>
|
||||
@@ -1,31 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_StationBase" Id="{e987477c-14c3-4a7d-9e57-317d0837328f}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_StationBase IMPLEMENTS I_Station
|
||||
<POU Name="FB_BaseStation" Id="{e987477c-14c3-4a7d-9e57-317d0837328f}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_BaseStation IMPLEMENTS I_Station
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR_IN_OUT
|
||||
fbFlowRecHandler : FB_FlowRecHandler;
|
||||
END_VAR
|
||||
VAR
|
||||
// Current loaded product flow recipe
|
||||
// Index should also be used to access
|
||||
// additional recipe parameters in designated pools
|
||||
_iFlowRecIdx : INT := -1;
|
||||
|
||||
// Product available for pickup
|
||||
_xProdAvail : BOOL;
|
||||
|
||||
// Station available for new product
|
||||
_xAvailable : BOOL;
|
||||
// No product in station
|
||||
_xEmpty : BOOL;
|
||||
|
||||
// Station busy
|
||||
_xBusy : BOOL;
|
||||
|
||||
// Station done
|
||||
_xDone : BOOL;
|
||||
|
||||
// Station has error
|
||||
_xError : BOOL;
|
||||
|
||||
// Station id which was assigned by the scheduler
|
||||
_uiStationID : UINT := 0;
|
||||
|
||||
// Station capabilities
|
||||
_dwCapabilities : DWORD;
|
||||
_uiResult : UINT;
|
||||
|
||||
// Reserve token handle
|
||||
_xReserved : BOOL;
|
||||
_udiCurrHandle : UDINT;
|
||||
_udiHandleCounter : UDINT := 1;
|
||||
|
||||
_fbProduct : I_Product;
|
||||
_uiCurrHandle : UINT;
|
||||
_uiHandleCounter : UINT := 1;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
@@ -38,33 +52,47 @@ VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[M_HasCapabilty := (dwReqCap AND _dwCapabilities) = dwReqCap;]]></ST>
|
||||
<ST><![CDATA[IF (dwReqCap AND _dwCapabilities) = dwReqCap THEN
|
||||
M_HasCapabilty := TRUE;
|
||||
ELSE
|
||||
M_HasCapabilty := FALSE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_InsertProduct" Id="{d323f806-9a97-49f2-9986-a997415883bf}">
|
||||
<Declaration><![CDATA[METHOD M_InsertProduct : BOOL;
|
||||
VAR_INPUT
|
||||
fbProduct : I_Product;
|
||||
iFlowRecIdx : INT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF fbProduct <> 0 AND _fbProduct = 0 THEN
|
||||
_fbProduct := fbProduct;
|
||||
M_InsertProduct := TRUE;
|
||||
ELSE
|
||||
<ST><![CDATA[// Cant insert product if there is still one
|
||||
// in the station, also dont insert invalid product index
|
||||
IF (_iFlowRecIdx <> -1) OR (iFlowRecIdx = -1) THEN
|
||||
M_InsertProduct := FALSE;
|
||||
END_IF]]></ST>
|
||||
END_IF
|
||||
|
||||
// Save product index
|
||||
_iFlowRecIdx := iFlowRecIdx;
|
||||
|
||||
// Advance one step in the node control flow
|
||||
fbFlowRecHandler.M_AdvJob(iIdx := iFlowRecIdx);
|
||||
|
||||
|
||||
// Report success
|
||||
M_InsertProduct := TRUE;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_Release" Id="{924bffc5-44cc-4d02-a67d-fb0f3ab51cc2}">
|
||||
<Declaration><![CDATA[METHOD M_Release : BOOL
|
||||
VAR_INPUT
|
||||
udiHandle : UDINT;
|
||||
uiHandle : UINT;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF _xReserved AND (udiHandle = _udiCurrHandle) THEN
|
||||
<ST><![CDATA[// Check if we are reserved and the handle to release is corrcet
|
||||
IF _xReserved AND (uiHandle = _uiCurrHandle) THEN
|
||||
_xReserved := FALSE;
|
||||
_udiCurrHandle := 0;
|
||||
_uiCurrHandle := 0;
|
||||
M_Release := TRUE;
|
||||
ELSE
|
||||
M_Release := FALSE;
|
||||
@@ -72,33 +100,40 @@ END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_RemoveProduct" Id="{e5d01ee0-a885-4496-b522-46d093416622}">
|
||||
<Declaration><![CDATA[METHOD M_RemoveProduct : I_Product
|
||||
<Declaration><![CDATA[METHOD M_RemoveProduct : INT
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[M_RemoveProduct := _fbProduct;
|
||||
_fbProduct := 0;]]></ST>
|
||||
<ST><![CDATA[// Return index of product in machine
|
||||
M_RemoveProduct := _iFlowRecIdx;
|
||||
|
||||
// Set product in machine invalid
|
||||
_iFlowRecIdx := -1;
|
||||
|
||||
// There is no more a product to be ready for pickup
|
||||
_xProdAvail := FALSE;
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_Reserve" Id="{42a69458-4b78-4d35-bd61-3bb1ee3cafec}">
|
||||
<Declaration><![CDATA[METHOD M_Reserve : UDINT
|
||||
<Declaration><![CDATA[METHOD M_Reserve : UINT
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF (NOT _xReserved) THEN
|
||||
<ST><![CDATA[// Check if we are not already reserved
|
||||
IF (NOT _xReserved) THEN
|
||||
_xReserved := TRUE;
|
||||
_xAvailable := FALSE;
|
||||
|
||||
_udiCurrHandle := _udiHandleCounter;
|
||||
_uiCurrHandle := _uiHandleCounter;
|
||||
|
||||
// Increment handle
|
||||
_udiHandleCounter := _udiHandleCounter + 1;
|
||||
_uiHandleCounter := _uiHandleCounter + 1;
|
||||
|
||||
// Prevent invalid token when overflowing
|
||||
IF _udiHandleCounter = 0 THEN
|
||||
_udiHandleCounter := 1;
|
||||
IF _uiHandleCounter = 0 THEN
|
||||
_uiHandleCounter := 1;
|
||||
END_IF
|
||||
|
||||
// Return handle
|
||||
M_Reserve := _udiCurrHandle;
|
||||
M_Reserve := _uiCurrHandle;
|
||||
ELSE
|
||||
M_Reserve := 0;
|
||||
END_IF]]></ST>
|
||||
@@ -112,7 +147,10 @@ END_IF]]></ST>
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[P_Available := _xAvailable;]]></ST>
|
||||
<ST><![CDATA[P_Available := (NOT _xReserved) // Station not reserver
|
||||
AND (_iFlowRecIdx = -1) // No product in station
|
||||
AND (NOT _xBusy) // Station not busy
|
||||
AND (NOT _xError); // Station no error]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
@@ -140,6 +178,18 @@ END_VAR
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="P_CurrFlowRecIdx" Id="{d0f37c45-4a5c-4efc-a8ff-f73e6ce76964}">
|
||||
<Declaration><![CDATA[PROPERTY P_CurrFlowRecIdx : INT
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{d05b9f0f-e7a4-4e88-83d5-c67bbca6f978}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[P_CurrFlowRecIdx := _iFlowRecIdx;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="P_HasError" Id="{1126bae7-5dd1-4592-8f95-62ea6e252ed0}">
|
||||
<Declaration><![CDATA[PROPERTY P_HasError : BOOL
|
||||
]]></Declaration>
|
||||
@@ -152,6 +202,17 @@ END_VAR
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="P_HasProduct" Id="{8b974b49-9c67-4d5f-9d0f-defc53b608cd}">
|
||||
<Declaration><![CDATA[PROPERTY P_HasProduct : BOOL]]></Declaration>
|
||||
<Get Name="Get" Id="{b6ba2262-99e3-4626-8d27-178b09d53a84}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[P_HasProduct := (_iFlowRecIdx <> -1);]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="P_ProdAvail" Id="{47526379-0732-4031-8d2b-4380310ef64c}">
|
||||
<Declaration><![CDATA[PROPERTY P_ProdAvail : BOOL
|
||||
]]></Declaration>
|
||||
@@ -164,30 +225,6 @@ END_VAR
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="P_Product" Id="{78d9c0d5-87fc-4940-8596-ddfb9f581df8}">
|
||||
<Declaration><![CDATA[PROPERTY P_Product : I_Product
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{16260053-c4bc-45d7-9a2b-60c60dd338ad}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[P_Product := _fbProduct;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="P_Result" Id="{84eed0af-ed7f-4d3e-964c-fa5fda4093f1}">
|
||||
<Declaration><![CDATA[PROPERTY P_Result : UINT
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{72d03065-7320-43e6-8295-5250a7641abc}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[P_Result := _uiResult;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="P_StationID" Id="{6655f302-05b0-4a57-b6f3-aa70ddd6a9f3}">
|
||||
<Declaration><![CDATA[PROPERTY P_StationID : UINT
|
||||
]]></Declaration>
|
||||
@@ -199,6 +236,14 @@ END_VAR
|
||||
<ST><![CDATA[P_StationID := _uiStationID;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
<Set Name="Set" Id="{2aae20dc-be6d-4d77-adda-bb622f240eb6}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_uiStationID := P_StationID;]]></ST>
|
||||
</Implementation>
|
||||
</Set>
|
||||
</Property>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
@@ -1,13 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_TransportBase" Id="{27acb860-a7d2-4ad3-adc1-3999bf7b2d0f}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_TransportBase IMPLEMENTS I_Transport
|
||||
<POU Name="FB_BaseTransport" Id="{27acb860-a7d2-4ad3-adc1-3999bf7b2d0f}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_BaseTransport IMPLEMENTS I_Transport
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR_IN_OUT
|
||||
fbJobQueue : FB_JobQueue;
|
||||
END_VAR
|
||||
VAR
|
||||
_xAvailable : BOOL;
|
||||
_stTransJon : ST_TransJob;
|
||||
|
||||
_xAvailable : BOOL := TRUE;
|
||||
_xError : BOOL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
263
PLC/POUs/Scheduler/POUs/FB_FlowRecHandler.TcPOU
Normal file
263
PLC/POUs/Scheduler/POUs/FB_FlowRecHandler.TcPOU
Normal file
@@ -0,0 +1,263 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_FlowRecHandler" Id="{3b3f8fad-c882-4122-b8a4-83e042a5706a}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_FlowRecHandler IMPLEMENTS I_FlowRecHandler
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR
|
||||
_astFlowRecPool : ARRAY[0..(POOL_SIZE - 1)] OF ST_FlowRecipe;
|
||||
_iFlowRecCnt : INT := 0;
|
||||
|
||||
// Variable used to safely delete an entry in the pool
|
||||
_stDefaultRecipe : ST_FlowRecipe;
|
||||
END_VAR
|
||||
VAR CONSTANT
|
||||
POOL_SIZE : INT := 100;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="M_AddFlowRec" Id="{f9093d26-eb70-4f53-b224-c0a4e1b5746e}">
|
||||
<Declaration><![CDATA[METHOD M_AddFlowRec : INT
|
||||
VAR_INPUT
|
||||
stFlowRecipe : ST_FlowRecipe;
|
||||
END_VAR
|
||||
VAR
|
||||
i : INT;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Check size
|
||||
IF _iFlowRecCnt >= POOL_SIZE THEN
|
||||
M_AddFlowRec := -1;
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
// Find a free slot in the pool
|
||||
FOR i := 0 TO (POOL_SIZE - 1) DO
|
||||
// If slot is free, set the flow recipe data
|
||||
IF (_astFlowRecPool[i].iProdIdx = -1) THEN
|
||||
_astFlowRecPool[i] := stFlowRecipe;
|
||||
_astFlowRecPool[i].iProdIdx := i;
|
||||
// Increment number of recipes in the pool
|
||||
_iFlowRecCnt := _iFlowRecCnt + 1;
|
||||
// Return index of the added flow recipe
|
||||
M_AddFlowRec := i;
|
||||
RETURN;
|
||||
END_IF
|
||||
END_FOR]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_AdvJob" Id="{896adff3-f1cf-4fbe-80a0-e0d546958fea}">
|
||||
<Declaration><![CDATA[METHOD M_AdvJob : BOOL
|
||||
VAR_INPUT
|
||||
iIdx : INT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF (NOT M_CheckPoolBounds(iIdx := iIdx)) THEN
|
||||
M_AdvJob := FALSE;
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
// Advance one step throught the flow recipe
|
||||
IF (NOT M_CheckNextNodeIdx(iCurrNodeIdx := iIdx, iNextNodeIdx := _astFlowRecPool[iIdx].iNextNode)) THEN
|
||||
M_AdvJob := FALSE;
|
||||
ELSE
|
||||
_astFlowRecPool[iIdx].iCurrNode := _astFlowRecPool[iIdx].iNextNode;
|
||||
END_IF
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_CheckNextNodeIdx" Id="{01c36d2f-aaf6-49a5-816f-6f12c6f68b2a}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE M_CheckNextNodeIdx : BOOL
|
||||
VAR_INPUT
|
||||
iCurrNodeIdx : INT;
|
||||
iNextNodeIdx : INT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF (NOT M_CheckPoolBounds(iIdx := iCurrNodeIdx)) THEN
|
||||
M_CheckNextNodeIdx := FALSE;
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
IF (iNextNodeIdx) < 0 OR (iNextNodeIdx > (_astFlowRecPool[iCurrNodeIdx].uiNodeCnt - 1)) THEN
|
||||
M_CheckNextNodeIdx := FALSE;
|
||||
ELSE
|
||||
M_CheckNextNodeIdx := TRUE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_CheckPoolBounds" Id="{fce02a57-832f-4eaf-9235-5af81ab0f23b}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE M_CheckPoolBounds : BOOL
|
||||
VAR_INPUT
|
||||
iIdx : INT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Check index boundaries
|
||||
IF (iIdx < 0) OR (iIdx > (POOL_SIZE - 1)) THEN
|
||||
M_CheckPoolBounds := FALSE;
|
||||
ELSE
|
||||
M_CheckPoolBounds := TRUE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_GetFlowRec" Id="{6c6a6f91-e451-4cac-88ce-a7a62b58d715}">
|
||||
<Declaration><![CDATA[METHOD M_GetFlowRec : REFERENCE TO ST_FlowRecipe
|
||||
VAR_INPUT
|
||||
iIdx : INT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Check index boundaries
|
||||
IF (NOT M_CheckPoolBounds(iIdx)) THEN
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
// Return product data from pool
|
||||
M_GetFlowRec REF= _astFlowRecPool[iIdx];]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_GetNextPrio" Id="{11bba164-4c45-4988-8c5e-3a922df5613f}">
|
||||
<Declaration><![CDATA[METHOD M_GetNextPrio : UINT
|
||||
VAR_INPUT
|
||||
(* Flow recipe pool index*)
|
||||
iIdx : INT;
|
||||
END_VAR
|
||||
VAR
|
||||
_iNextNodeIdx : INT;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF (NOT M_CheckPoolBounds(iIdx)) THEN
|
||||
M_GetNextPrio := 0;
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
// Get next node index
|
||||
_iNextNodeIdx := _astFlowRecPool[iIdx].iNextNode;
|
||||
|
||||
// Check for next node bounds
|
||||
IF (NOT M_CheckNextNodeIdx(iCurrNodeIdx := iIdx, iNextNodeIdx := _iNextNodeIdx)) THEN
|
||||
M_GetNextPrio := 0;
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
// Return next priority
|
||||
M_GetNextPrio := _astFlowRecPool[iIdx].astNodes[_iNextNodeIdx].uiPriority;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_GetNextProcReq" Id="{c0f8e1bf-d696-4712-b3aa-63621a5789cf}">
|
||||
<Declaration><![CDATA[METHOD M_GetNextProcReq : BOOL
|
||||
VAR_INPUT
|
||||
(* Flow recipe pool index*)
|
||||
iIdx : INT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
(* Process requirements bitmask*)
|
||||
dwProcReq : DWORD;
|
||||
END_VAR
|
||||
VAR
|
||||
_iNextNodeIdx : INT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Check index boundaries
|
||||
IF (NOT M_CheckPoolBounds(iIdx)) THEN
|
||||
dwProcReq := 0;
|
||||
M_GetNextProcReq := FALSE;
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
// Return product data from pool
|
||||
_iNextNodeIdx := _astFlowRecPool[iIdx].iNextNode;
|
||||
|
||||
// Check for valid next node
|
||||
IF (NOT M_CheckNextNodeIdx(iCurrNodeIdx := iIdx, iNextNodeIdx := _iNextNodeIdx)) THEN
|
||||
dwProcReq := 0;
|
||||
M_GetNextProcReq := FALSE;
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
dwProcReq := _astFlowRecPool[iIdx].astNodes[_iNextNodeIdx].dwReqCap;
|
||||
M_GetNextProcReq := TRUE;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_RemFlowRec" Id="{4ca29998-c702-42b0-a307-733174741ab8}">
|
||||
<Declaration><![CDATA[METHOD M_RemFlowRec : BOOL
|
||||
VAR_INPUT
|
||||
iIdx : INT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Check index boundaries
|
||||
IF (NOT M_CheckPoolBounds(iIdx)) THEN
|
||||
M_RemFlowRec := FALSE;
|
||||
END_IF
|
||||
|
||||
// Reset flow recipe in pool slot to default recipe
|
||||
_astFlowRecPool[iIdx] := _stDefaultRecipe;
|
||||
|
||||
// Return success
|
||||
M_RemFlowRec := TRUE;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_ReportResult" Id="{16053eca-a7a6-4800-b521-1a15f3dfce4f}">
|
||||
<Declaration><![CDATA[// Sets the result of the current node operation
|
||||
// and updates the reference to the next node id
|
||||
// depending on the reported result
|
||||
METHOD M_ReportResult : BOOL
|
||||
VAR_INPUT
|
||||
iIdx : INT;
|
||||
xResult : BOOL;
|
||||
END_VAR
|
||||
VAR
|
||||
_iCurrNodeIdx : INT;
|
||||
_iNextNodeIdx : INT;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Check index boundaries
|
||||
IF (NOT M_CheckPoolBounds(iIdx)) THEN
|
||||
M_ReportResult := FALSE;
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
// Set current flow node result flag
|
||||
_iCurrNodeIdx := _astFlowRecPool[iIdx].iCurrNode;
|
||||
_astFlowRecPool[iIdx].astNodes[_iCurrNodeIdx].xSuccess := xResult;
|
||||
|
||||
// Update ref for the next node
|
||||
IF xResult THEN
|
||||
_iNextNodeIdx := _astFlowRecPool[iIdx].astNodes[_iCurrNodeIdx].iNextNodeSuccess;
|
||||
ELSE
|
||||
// Check if we have retries left
|
||||
IF _astFlowRecPool[iIdx].astNodes[_iCurrNodeIdx].uiCurrRetries < _astFlowRecPool[iIdx].astNodes[_iCurrNodeIdx].uiMaxRetries THEN
|
||||
// Increment retry counter
|
||||
_astFlowRecPool[iIdx].astNodes[_iCurrNodeIdx].uiCurrRetries := _astFlowRecPool[iIdx].astNodes[_iCurrNodeIdx].uiCurrRetries + 1;
|
||||
// Get next retry node
|
||||
_iNextNodeIdx := _astFlowRecPool[iIdx].astNodes[_iCurrNodeIdx].iNextNodeRetry;
|
||||
ELSE
|
||||
// Get next fail node
|
||||
_iNextNodeIdx := _astFlowRecPool[iIdx].astNodes[_iCurrNodeIdx].iNextNodeFail;
|
||||
END_IF
|
||||
END_IF
|
||||
|
||||
// Check index boundaries
|
||||
IF (_iNextNodeIdx < 0) OR (_iNextNodeIdx > (_astFlowRecPool[iIdx].uiNodeCnt - 1)) THEN
|
||||
// If there is no next node set to -1
|
||||
// to indicate, that this was the last node in the
|
||||
// flow recipe
|
||||
_astFlowRecPool[iIdx].iNextNode := -1;
|
||||
ELSE
|
||||
_astFlowRecPool[iIdx].iNextNode := _iNextNodeIdx;
|
||||
END_IF
|
||||
|
||||
// Return success
|
||||
M_ReportResult := TRUE;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
@@ -3,6 +3,7 @@
|
||||
<POU Name="FB_JobQueue" Id="{b05c10aa-a132-426c-9adb-9c3d92e348cd}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_JobQueue
|
||||
VAR_INPUT
|
||||
xEnableAging : BOOL := FALSE;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
@@ -12,7 +13,11 @@ VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[]]></ST>
|
||||
<ST><![CDATA[// If aging is enable recalculate priorities
|
||||
IF xEnableAging THEN
|
||||
M_CalcAgingPrio();
|
||||
END_IF
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="FB_Init" Id="{59b2fc0f-4c7e-4fd5-97a2-d54f83d37be4}">
|
||||
<Declaration><![CDATA[//FB_Init is always available implicitly and it is used primarily for initialization.
|
||||
@@ -28,12 +33,7 @@ VAR
|
||||
_uiCnt : UINT;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Set all jobs to false
|
||||
FOR _uiCnt := 0 TO (GVL_Scheduler.MAX_JOBS_IN_QUEUE - 1) DO
|
||||
_astJobQueue[_uiCnt].xValid := FALSE;
|
||||
END_FOR
|
||||
|
||||
// No jobs in queue
|
||||
<ST><![CDATA[// No jobs in queue
|
||||
_uiJobCount := 0;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
@@ -50,22 +50,36 @@ IF _uiJobCount >= GVL_Scheduler.MAX_JOBS_IN_QUEUE THEN
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
_uiJobCount := _uiJobCount + 1;
|
||||
_astJobQueue[_uiJobCount] := stJob;
|
||||
_astJobQueue[_uiJobCount].xValid := TRUE;
|
||||
_astJobQueue[_uiJobCount].uliTimeCreated := F_GetSystemTime();
|
||||
_uiJobCount := _uiJobCount + 1;
|
||||
M_AddJob := TRUE;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_CalcAgingPrio" Id="{7ee1cc23-b7ac-4255-862a-74b0b696f2cb}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE M_CalcAgingPrio
|
||||
VAR
|
||||
i : UINT;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Calculate ageing priority with overflow check
|
||||
FOR i := 0 TO _uiJobCount DO
|
||||
IF _astJobQueue[i].uiPrio < GVL_Scheduler.MAX_PRIORITY THEN
|
||||
IF _astJobQueue[i].uiPrio > (GVL_Scheduler.MAX_PRIORITY - GVL_Scheduler.AGING_STEP) THEN
|
||||
_astJobQueue[i].uiPrio := GVL_Scheduler.MAX_PRIORITY;
|
||||
ELSE
|
||||
_astJobQueue[i].uiPrio := _astJobQueue[i].uiPrio + GVL_Scheduler.AGING_STEP;
|
||||
END_IF
|
||||
END_IF
|
||||
END_FOR]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="M_GetHighest" Id="{26fa0379-d921-41a3-a15c-b3ff597c1d37}">
|
||||
<Declaration><![CDATA[METHOD M_GetHighest : BOOL
|
||||
VAR_OUTPUT
|
||||
stJob : ST_TransJob;
|
||||
END_VAR
|
||||
VAR
|
||||
_iMaxPrio : INT := -32768;
|
||||
_uiIndex : UINT;
|
||||
_ulTimestamp : ULINT;
|
||||
_uiIndex : UINT := 0;
|
||||
_rDynPrio : REAL;
|
||||
|
||||
_uiCnt : UINT;
|
||||
@@ -77,26 +91,25 @@ IF _uiJobCount = 0 THEN
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
_ulTimestamp := F_GetSystemTime();
|
||||
|
||||
// Find job with highest priority also update dyn prio
|
||||
FOR _uiCnt := 0 TO _uiJobCount DO
|
||||
// Only recalc and check if job is valid
|
||||
IF _astJobQueue[_uiCnt].xValid THEN
|
||||
// Recalculate dynamic priority (100ns intervalls to seconds)
|
||||
_rDynPrio := ULINT_TO_REAL(_ulTimestamp - _astJobQueue[_uiCnt].uliTimeCreated) *1E-7 * GVL_Scheduler.AGE_FACTOR;
|
||||
IF _rDynPrio > 32767.0 THEN
|
||||
_rDynPrio := 32767.0;
|
||||
END_IF
|
||||
_astJobQueue[_uiCnt].iDynPrio := REAL_TO_INT(_rDynPrio);
|
||||
|
||||
FOR _uiCnt := 0 TO (_uiJobCount-1) DO
|
||||
// Check for highest priority
|
||||
IF (_astJobQueue[_uiCnt].iStatPrio + _astJobQueue[_uiCnt].iDynPrio) > _iMaxPrio THEN
|
||||
_iMaxPrio :=
|
||||
IF _astJobQueue[_uiCnt].uiPrio > _astJobQueue[_uiIndex].uiPrio THEN
|
||||
_uiIndex := _uiCnt;
|
||||
END_IF
|
||||
END_IF
|
||||
|
||||
END_FOR]]></ST>
|
||||
END_FOR
|
||||
|
||||
// Output job
|
||||
stJob := _astJobQueue[_uiIndex];
|
||||
|
||||
// Close gap with last element
|
||||
_astJobQueue[_uiIndex] := _astJobQueue[_uiJobCount - 1];
|
||||
|
||||
// Adjust job number in queue
|
||||
_uiJobCount := _uiJobCount - 1;
|
||||
|
||||
// Repost success
|
||||
M_GetHighest := TRUE;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
</POU>
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_Product" Id="{aeaa85d2-80b5-4274-aa7e-dadad9f0dcfb}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_Product IMPLEMENTS I_Product
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR
|
||||
// Product recipe
|
||||
_stRecipe : ST_Recipe;
|
||||
|
||||
_uiCurrNodeID : UINT := 0;
|
||||
_uiNextNodeID : UINT := 0;
|
||||
|
||||
_xResult : BOOL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="M_SetCurrProcRes" Id="{478e39cf-00d0-4253-8c4e-ed30567e421d}">
|
||||
<Declaration><![CDATA[METHOD M_SetCurrProcRes
|
||||
VAR_INPUT
|
||||
xSuccess : BOOL;
|
||||
END_VAR
|
||||
VAR
|
||||
_uiCnt : UINT;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Check all possible transition
|
||||
FOR _uiCnt := 0 TO (_stRecipe.astNodes[_uiCurrNodeID].uiTransCnt - 1) DO
|
||||
CASE _stRecipe.astNodes[_uiCurrNodeID].astTransitions[_uiCnt].eCondition OF
|
||||
E_TransitCond.ALWAYS:
|
||||
_uiNextNodeID := _stRecipe.astNodes[_uiCurrNodeID].astTransitions[_uiCnt].uiNextNodeID;
|
||||
EXIT;
|
||||
|
||||
E_TransitCond.RESULT_OK:
|
||||
IF xSuccess THEN
|
||||
_uiNextNodeID := _stRecipe.astNodes[_uiCurrNodeID].astTransitions[_uiCnt].uiNextNodeID;
|
||||
EXIT;
|
||||
END_IF
|
||||
|
||||
E_TransitCond.RESULT_NIO:
|
||||
IF (NOT xSuccess) THEN
|
||||
_uiNextNodeID := _stRecipe.astNodes[_uiCurrNodeID].astTransitions[_uiCnt].uiNextNodeID;
|
||||
EXIT;
|
||||
END_IF
|
||||
END_CASE
|
||||
END_FOR
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Property Name="P_CurrNodeID" Id="{896d8e88-c324-42f7-8ec5-28782223405a}">
|
||||
<Declaration><![CDATA[PROPERTY P_CurrNodeID : UINT
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{e1aeb000-7306-4b12-ab29-6078214076ea}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[P_CurrNodeID := _uiCurrNodeID;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
<Set Name="Set" Id="{6b281f43-823b-4830-a917-2539de62e216}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_uiCurrNodeID := P_CurrNodeID;]]></ST>
|
||||
</Implementation>
|
||||
</Set>
|
||||
</Property>
|
||||
<Property Name="P_NextReqCap" Id="{4c4a03ed-4074-46c1-8f2a-b964a788faf6}">
|
||||
<Declaration><![CDATA[PROPERTY P_NextReqCap : DWORD
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{a7e4e08c-166a-4234-b8b1-9d5ae2650ea7}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[P_NextReqCap := _stRecipe.astNodes[_uiNextNodeID].dwReqCap;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
@@ -6,35 +6,77 @@ 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_Station;
|
||||
_uiTransportCnt : UINT := 0;
|
||||
_fbTransport : I_Transport;
|
||||
|
||||
_uiCnt : UINT;
|
||||
_uiNextAvailStation : UINT;
|
||||
|
||||
_fbProduct : I_Product;
|
||||
_iFlowRecIdx : INT;
|
||||
_dwNextProcReq : DWORD;
|
||||
|
||||
_stTmpJob : ST_TransJob;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF (NOT _fbTransport.P_Available) THEN
|
||||
// No need to check the station if we don't have a transport ready
|
||||
<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(_aiStations[_uiCnt].P_Product);
|
||||
_uiNextAvailStation := M_FindNextAvailStation(_dwNextProcReq);
|
||||
|
||||
// Check if there is a station available
|
||||
IF _uiNextAvailStation <> 0 THEN
|
||||
// Skip reservation for now
|
||||
// _aiStations[_uiNextAvailStation].M_Reserve();
|
||||
// Create transport job
|
||||
// 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>
|
||||
@@ -55,22 +97,37 @@ _uiStationCount := 0;]]></ST>
|
||||
<Method Name="M_FindNextAvailStation" Id="{75382296-32be-4724-b020-39273aa8358c}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE M_FindNextAvailStation : UINT
|
||||
VAR_INPUT
|
||||
_fbProduct : I_Product;
|
||||
dwProcReq : DWORD;
|
||||
END_VAR
|
||||
VAR
|
||||
_uiCnt : UINT;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[FOR _uiCnt := 1 TO _uiStationCount DO
|
||||
IF _aiStations[_uiCnt].M_HasCapabilty(_fbProduct.P_NextReqCap) AND _aiStations[_uiCnt].P_Available THEN
|
||||
IF _aiStations[_uiCnt].M_HasCapabilty(dwProcReq) AND _aiStations[_uiCnt].P_Available THEN
|
||||
M_FindNextAvailStation := _uiCnt;
|
||||
EXIT;
|
||||
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
|
||||
@@ -85,8 +142,9 @@ END_IF
|
||||
|
||||
// Check if we have free slots
|
||||
IF _uiStationCount < GVL_Scheduler.MAX_STATIONS THEN
|
||||
_aiStations[_uiStationCount] := fbStation;
|
||||
_uiStationCount := _uiStationCount + 1;
|
||||
_aiStations[_uiStationCount] := fbStation;
|
||||
_aiStations[_uiStationCount].P_StationID := _uiStationCount;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
@@ -102,11 +160,10 @@ IF fbTransport = 0 THEN
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
// Check if we have free slots
|
||||
IF _uiTransportCnt < GVL_Scheduler.MAX_STATIONS THEN
|
||||
_aiStations[_uiTransportCnt] := fbTransport;
|
||||
_uiTransportCnt := _uiTransportCnt + 1;
|
||||
END_IF]]></ST>
|
||||
// Set transport interface
|
||||
_fbTransport := fbTransport;
|
||||
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
</POU>
|
||||
|
||||
8
PLC/POUs/Scheduler/POUs/GVL_Test.TcGVL
Normal file
8
PLC/POUs/Scheduler/POUs/GVL_Test.TcGVL
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<GVL Name="GVL_Test" Id="{795c0f41-8233-4565-bfb5-a9d7fd82a697}">
|
||||
<Declaration><![CDATA[{attribute 'qualified_only'}
|
||||
VAR_GLOBAL
|
||||
END_VAR]]></Declaration>
|
||||
</GVL>
|
||||
</TcPlcObject>
|
||||
@@ -1,16 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_Etcher" Id="{b81a122a-e5f5-475c-8ee0-2d97c1df7eb4}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_Etcher EXTENDS FB_StationBase
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_Etcher EXTENDS FB_BaseStation
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR
|
||||
_iState : INT;
|
||||
|
||||
_tonProcessDuration : TON;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[]]></ST>
|
||||
<ST><![CDATA[CASE _iState OF
|
||||
// Wait for product
|
||||
0:
|
||||
IF _iFlowRecIdx <> -1 THEN
|
||||
_xDone := FALSE;
|
||||
_xBusy := TRUE;
|
||||
_iState := 10;
|
||||
END_IF
|
||||
|
||||
// Simulate process
|
||||
10:
|
||||
_tonProcessDuration(IN := TRUE, PT := T#10S);
|
||||
IF _tonProcessDuration.Q THEN
|
||||
_tonProcessDuration(IN := FALSE);
|
||||
fbFlowRecHandler.M_ReportResult(iIdx := _iFlowRecIdx, xResult := TRUE);
|
||||
_xProdAvail := TRUE;
|
||||
_xBusy := FALSE;
|
||||
_xDone := TRUE;
|
||||
_iState := 20;
|
||||
END_IF
|
||||
|
||||
// Wait for station to be empty again
|
||||
20:
|
||||
IF _iFlowRecIdx = -1 THEN
|
||||
_iState := 0;
|
||||
END_IF
|
||||
END_CASE]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="FB_Init" Id="{0669fde2-f64d-4e8f-b76d-71a71bfb6cae}">
|
||||
<Declaration><![CDATA[//FB_Init is always available implicitly and it is used primarily for initialization.
|
||||
//The return value is not evaluated. For a specific influence, you can also declare the
|
||||
//methods explicitly and provide additional code there with the standard initialization
|
||||
//code. You can evaluate the return value.
|
||||
METHOD FB_Init: BOOL
|
||||
VAR_INPUT
|
||||
bInitRetains: BOOL; // TRUE: the retain variables are initialized (reset warm / reset cold)
|
||||
bInCopyCode: BOOL; // TRUE: the instance will be copied to the copy code afterward (online change)
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Set station capabilities
|
||||
_dwCapabilities := 16#0001;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
@@ -1,16 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_HVTest" Id="{b3445d38-3c32-4973-bf63-429552f0da50}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_HVTest EXTENDS FB_StationBase
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_HVTest EXTENDS FB_BaseStation
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR
|
||||
_iState : INT;
|
||||
_tonProcessDuration : TON;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[]]></ST>
|
||||
<ST><![CDATA[CASE _iState OF
|
||||
// Wait for product
|
||||
0:
|
||||
IF _iFlowRecIdx <> -1 THEN
|
||||
_xDone := FALSE;
|
||||
_xBusy := TRUE;
|
||||
_iState := 10;
|
||||
END_IF
|
||||
|
||||
// Simulate process
|
||||
10:
|
||||
_tonProcessDuration(IN := TRUE, PT := T#10S);
|
||||
IF _tonProcessDuration.Q THEN
|
||||
_tonProcessDuration(IN := FALSE);
|
||||
fbFlowRecHandler.M_ReportResult(iIdx := _iFlowRecIdx, xResult := TRUE);
|
||||
_xProdAvail := TRUE;
|
||||
_xBusy := FALSE;
|
||||
_xDone := TRUE;
|
||||
_iState := 20;
|
||||
END_IF
|
||||
|
||||
// Wait for station to be empty again
|
||||
20:
|
||||
IF _iFlowRecIdx = -1 THEN
|
||||
_iState := 0;
|
||||
END_IF
|
||||
END_CASE]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="FB_Init" Id="{c40e1a0c-0b45-4ca1-a647-10e90c1b54ce}">
|
||||
<Declaration><![CDATA[//FB_Init is always available implicitly and it is used primarily for initialization.
|
||||
//The return value is not evaluated. For a specific influence, you can also declare the
|
||||
//methods explicitly and provide additional code there with the standard initialization
|
||||
//code. You can evaluate the return value.
|
||||
METHOD FB_Init: BOOL
|
||||
VAR_INPUT
|
||||
bInitRetains: BOOL; // TRUE: the retain variables are initialized (reset warm / reset cold)
|
||||
bInCopyCode: BOOL; // TRUE: the instance will be copied to the copy code afterward (online change)
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Set station capabilities
|
||||
_dwCapabilities := 16#0002;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
@@ -1,16 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_Input" Id="{d51b3f46-877e-4234-99b6-53eb690c6bdc}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_Input EXTENDS FB_StationBase
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_Input EXTENDS FB_BaseStation
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR
|
||||
_tonNewProductReady : TON;
|
||||
|
||||
_stFlowRecipe : ST_FlowRecipe;
|
||||
_xRecipeSet : BOOL;
|
||||
_xStart : BOOL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[]]></ST>
|
||||
<ST><![CDATA[_tonNewProductReady(IN := ((NOT _xProdAvail) AND _xRecipeSet AND _xStart), PT := T#5S);
|
||||
IF _tonNewProductReady.Q THEN
|
||||
_iFlowRecIdx := fbFlowRecHandler.M_AddFlowRec(stFlowRecipe := _stFlowRecipe);
|
||||
|
||||
// Todo create additional recipe data in pool array where the index
|
||||
// is the same as _iFlowRecIdx
|
||||
|
||||
_xProdAvail := TRUE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="M_SetRecipe" Id="{58f2ee2a-65a7-4788-a8f6-1e5a7ab222c9}">
|
||||
<Declaration><![CDATA[METHOD M_SetRecipe
|
||||
VAR_INPUT
|
||||
stRecipe : ST_FlowRecipe;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_stFlowRecipe := stRecipe;
|
||||
_xRecipeSet := TRUE;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
@@ -1,16 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_NIO" Id="{2cf6f855-1738-40a7-bc96-4518cbb192c2}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_NIO EXTENDS FB_StationBase
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_NIO EXTENDS FB_BaseStation
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR
|
||||
_iState : INT;
|
||||
_tonAutoRemove : TON;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[]]></ST>
|
||||
<ST><![CDATA[CASE _iState OF
|
||||
// Wait for product
|
||||
0:
|
||||
IF _iFlowRecIdx <> -1 THEN
|
||||
_iState := 10;
|
||||
END_IF
|
||||
|
||||
// Remove product from line
|
||||
10:
|
||||
_tonAutoRemove(IN := TRUE, PT := T#5S);
|
||||
IF _tonAutoRemove.Q THEN
|
||||
_tonAutoRemove(IN := FALSE);
|
||||
|
||||
fbFlowRecHandler.M_RemFlowRec(iIdx := _iFlowRecIdx);
|
||||
_iFlowRecIdx := -1;
|
||||
_iState := 0;
|
||||
END_IF
|
||||
END_CASE]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="FB_Init" Id="{a2216f45-001c-4771-bc7d-1f63f2637a1e}">
|
||||
<Declaration><![CDATA[//FB_Init is always available implicitly and it is used primarily for initialization.
|
||||
//The return value is not evaluated. For a specific influence, you can also declare the
|
||||
//methods explicitly and provide additional code there with the standard initialization
|
||||
//code. You can evaluate the return value.
|
||||
METHOD FB_Init: BOOL
|
||||
VAR_INPUT
|
||||
bInitRetains: BOOL; // TRUE: the retain variables are initialized (reset warm / reset cold)
|
||||
bInCopyCode: BOOL; // TRUE: the instance will be copied to the copy code afterward (online change)
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Set station capabilities
|
||||
_dwCapabilities := 16#0008;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
@@ -1,16 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_Output" Id="{9711b552-d6a0-4f78-8a70-9ea977b18390}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_Output EXTENDS FB_StationBase
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_Output EXTENDS FB_BaseStation
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR
|
||||
_iState : INT;
|
||||
_tonAutoRemove : TON;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[]]></ST>
|
||||
<ST><![CDATA[CASE _iState OF
|
||||
// Wait for product
|
||||
0:
|
||||
IF _iFlowRecIdx <> -1 THEN
|
||||
_iState := 10;
|
||||
END_IF
|
||||
|
||||
// Remove product from line
|
||||
10:
|
||||
_tonAutoRemove(IN := TRUE, PT := T#5S);
|
||||
IF _tonAutoRemove.Q THEN
|
||||
_tonAutoRemove(IN := FALSE);
|
||||
|
||||
fbFlowRecHandler.M_RemFlowRec(iIdx := _iFlowRecIdx);
|
||||
_iFlowRecIdx := -1;
|
||||
_iState := 0;
|
||||
END_IF
|
||||
END_CASE]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="FB_Init" Id="{ae701a9f-9b93-4e2d-8380-8e14731a8c09}">
|
||||
<Declaration><![CDATA[//FB_Init is always available implicitly and it is used primarily for initialization.
|
||||
//The return value is not evaluated. For a specific influence, you can also declare the
|
||||
//methods explicitly and provide additional code there with the standard initialization
|
||||
//code. You can evaluate the return value.
|
||||
METHOD FB_Init: BOOL
|
||||
VAR_INPUT
|
||||
bInitRetains: BOOL; // TRUE: the retain variables are initialized (reset warm / reset cold)
|
||||
bInCopyCode: BOOL; // TRUE: the instance will be copied to the copy code afterward (online change)
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Set station capabilities
|
||||
_dwCapabilities := 16#0004;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
71
PLC/POUs/Stations/FB_Robot.TcPOU
Normal file
71
PLC/POUs/Stations/FB_Robot.TcPOU
Normal file
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_Robot" Id="{dc28987f-6f20-437a-aca7-b51d3eb98f94}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_Robot EXTENDS FB_BaseTransport
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR_IN_OUT
|
||||
fbScheduler : FB_Scheduler;
|
||||
END_VAR
|
||||
VAR
|
||||
_tonTransportDone : TON;
|
||||
_timTransportTime : TIME := T#5S;
|
||||
|
||||
_itfSourceStation : I_Station;
|
||||
_itfTargetStation : I_Station;
|
||||
|
||||
_iFlowRecIdx : INT;
|
||||
|
||||
_iState : INT;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[CASE _iState OF
|
||||
// Idle, check for new transport job
|
||||
0:
|
||||
IF fbJobQueue.M_GetHighest(stJob => _stTransJon) THEN
|
||||
_xAvailable := FALSE;
|
||||
|
||||
// Get station interfaces
|
||||
_itfSourceStation := fbScheduler.M_GetStation(_stTransJon.uiFromStation);
|
||||
_itfTargetStation := fbScheduler.M_GetStation(_stTransJon.uiToStation);
|
||||
|
||||
_iState := 10;
|
||||
END_IF
|
||||
|
||||
// Move to pickup station
|
||||
10:
|
||||
_tonTransportDone(IN := TRUE, PT := _timTransportTime);
|
||||
IF _tonTransportDone.Q THEN
|
||||
_tonTransportDone(IN := FALSE);
|
||||
|
||||
// Get product from station
|
||||
_iFlowRecIdx := _itfSourceStation.M_RemoveProduct();
|
||||
|
||||
_iState := 20;
|
||||
END_IF
|
||||
|
||||
// Move to drop station
|
||||
20:
|
||||
_tonTransportDone(IN := TRUE, PT := _timTransportTime);
|
||||
IF _tonTransportDone.Q THEN
|
||||
_tonTransportDone(IN := FALSE);
|
||||
|
||||
// Put product into station
|
||||
_itfTargetStation.M_InsertProduct(_iFlowRecIdx);
|
||||
|
||||
_iState := 30;
|
||||
END_IF
|
||||
|
||||
// Release all station reservations
|
||||
30:
|
||||
_itfSourceStation.M_Release(uiHandle := _stTransJon.uiFromStationHandle);
|
||||
_itfTargetStation.M_Release(uiHandle := _stTransJon.uiToStationHandle);
|
||||
_xAvailable := TRUE;
|
||||
_iState := 0;
|
||||
END_CASE]]></ST>
|
||||
</Implementation>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
@@ -12,6 +12,5 @@
|
||||
<Fb_exit>{baf80adf-b0f3-4c1e-958c-6b1cb1610e8e}</Fb_exit>
|
||||
<CycleUpdate>{ff4c396c-9481-47ed-a237-b2f9054f4e68}</CycleUpdate>
|
||||
<PostCycleUpdate>{e06145cf-bc12-4403-9e2e-7beeb337c603}</PostCycleUpdate>
|
||||
<ObjectProperties />
|
||||
</Task>
|
||||
</TcPlcObject>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<TcSmProject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.beckhoff.com/schemas/2012/07/TcSmProject" TcSmVersion="1.0" TcVersion="3.1.4026.20">
|
||||
<Project ProjectGUID="{499C0D3C-2952-40F2-B5CC-1C48D904BF27}" Target64Bit="true" ShowHideConfigurations="#x6">
|
||||
<Project ProjectGUID="{499C0D3C-2952-40F2-B5CC-1C48D904BF27}" TargetNetId="199.4.42.250.1.1" Target64Bit="true" ShowHideConfigurations="#x6">
|
||||
<System>
|
||||
<Tasks>
|
||||
<Task Id="3" Priority="20" CycleTime="100000" AmsPort="350" AdtTasks="true">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<TcSmItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.beckhoff.com/schemas/2012/07/TcSmProject" TcSmVersion="1.0" TcVersion="3.1.4026.20" ClassName="CTComPlcObjDef">
|
||||
<Instance Id="#x08502000" TcSmClass="TComPlcObjDef" KeepUnrestoredLinks="2" XtvPath="PLC\PLC Instance.xtv">
|
||||
<Instance Id="#x08502000" TcSmClass="TComPlcObjDef" KeepUnrestoredLinks="2" XtvPath="PLC\PLC Instance.xtv" TmcPath="PLC\PLC.tmc">
|
||||
<Name>__FILENAME__</Name>
|
||||
<CLSID ClassFactory="TcPlc30">{08500001-0000-0000-F000-000000000064}</CLSID>
|
||||
<Contexts>
|
||||
|
||||
Reference in New Issue
Block a user