FUNCTION_BLOCK "FB_StationUnloadPin" { S7_Optimized_Access := 'TRUE' } VERSION : 0.1 VAR_INPUT xInStartUnloading : Bool; xInStopUnloading : Bool; xInNextHanger : Bool; xInBefore : Bool; stInPartAfterSwitch : "UDT_Sensor"; nInBarcode : DInt; sInBarcode : String; xInReRouteAllowed : Bool := TRUE; xInUnloadingCheckSensor : Bool; xInMonitorUnloading : Bool; xInQuitLocal : Bool; xInBypass : Bool; END_VAR VAR_OUTPUT xOutUnloadingDone : Bool; nOutBarcode : DInt; sOutBarcode : String; xOutSwitch : Bool; xOutLineOverloaded : Bool; xOutLineOverloadAhead : Bool; wOutErrorWord : Word; xOutLineOverloadedHigh : Bool; xOutLineOverloadedLow : Bool; xOutUnloadingFail : Bool; xOutUnloadingError : Bool; END_VAR VAR_IN_OUT stInOutControlUnitCabinet : "UDT_MainState"; stInOutConveyorStations : "stConveyorStations"; arInOutCarrier : Array[*] of "stCarrier"; nNoReadCounter : UDInt; stInOutHMI : "UDT_HMI_UnloadingStation"; END_VAR VAR nState : Int := -10; TOnLineFullTimer {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME; tOnUnloadingCheck {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME; END_VAR VAR RETAIN CountSwitch {InstructionName := 'CTU_UDINT'; LibVersion := '1.0'} : CTU_UDINT; nCount : UDInt; END_VAR VAR rTrigSwitch {InstructionName := 'R_TRIG'; LibVersion := '1.0'} : R_TRIG; rTrigUnload {InstructionName := 'R_TRIG'; LibVersion := '1.0'} : R_TRIG; tUnloadingCheckTime : Time := T#5s; xUnloadingCheck : Bool; tLineFullTime : Time := T#3s; tOnStateTimer {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME; xStateTimer : Bool; tStateTimer : Time; xFlgTrolleySensor : Bool; xFlgStartUnloading : Bool; fbMonitoringLineOverload : "FB_Monitoring"; fbMonitoringUnloadError : "FB_Monitoring"; xEdgeStoreLineOverload : Bool; stHangerStatus { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Struct xOnline { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; nTarget { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; xDoubleHangerOkay { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; xTargetDoubleHanger { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; xNoRead { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; xPartMissing { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; xTargetSetByMFS { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; xReportedToMFS { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; xReRouteOverflow { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; xReRouteBalancing { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; xReRouteUnavailable { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; END_STRUCT; END_VAR VAR_TEMP t_status : Bool; tmpSuccess : Bool; END_VAR BEGIN REGION xOutLineOverloaded Stau IF #TOnLineFullTimer.Q THEN //OR //#tOnUnloadingCheck.Q THEN #xFlgTrolleySensor := TRUE; #xOutLineOverloaded := 1; ELSE #xFlgTrolleySensor := FALSE; #xOutLineOverloaded := 0; END_IF; // Detect change of Line Overload #xOutLineOverloadedHigh := #TOnLineFullTimer.Q AND NOT #xEdgeStoreLineOverload; #xOutLineOverloadedLow := NOT #TOnLineFullTimer.Q AND #xEdgeStoreLineOverload; #xEdgeStoreLineOverload := #TOnLineFullTimer.Q; END_REGION IF #xInStartUnloading AND #xFlgTrolleySensor AND #xInReRouteAllowed THEN #xOutUnloadingFail := TRUE; #nOutBarcode := #nInBarcode; #sOutBarcode := #sInBarcode; "FC_SHR_TargetSet_ReRoutePin"(nInBarcodeNo := #nInBarcode, nInTarget := INT_TO_USINT(#stInOutConveyorStations.stData.nStations), xOutSuccess => #tmpSuccess, stInOutConveyorStations := #stInOutConveyorStations); ELSE #xOutUnloadingFail := FALSE; END_IF; #rTrigUnload(CLK:=#xInStartUnloading); REGION Schrittkette CASE #nState OF -10: // Init #xOutSwitch := 0; #xStateTimer := 0; #xOutUnloadingDone := 0; #nState := 0; 0: // Standby #xOutUnloadingDone := 0; // IF #tOnStateTimer.Q (* #xFlgTrolleySensor *)THEN // Wenn Weiche voll //VON MYTHERESA -> STÖRT HIER, TEST // #xUnloadingCheck := FALSE; // nicht möglich, da Flankenauswertung, bei dauerbelegtem Sensor sinnfrei // #xOutSwitch := 0; // Switch schliessen // END_IF; IF #rTrigUnload.Q (* AND NOT #tOnStateTimer.Q *)THEN //VON MYTHERESA -> STÖRT HIER, TEST #xOutSwitch := 1; #nOutBarcode := #nInBarcode; #sOutBarcode := #sInBarcode; IF #xInMonitorUnloading THEN #xUnloadingCheck := 1; END_IF; "FC_SHR_ExtractedHangerPin"(xInUnloadingDone := TRUE, nInBarcode := #nOutBarcode, xInBypass:= #xInBypass, stInOutConveyorStations := #stInOutConveyorStations, arInOutCarrier:= #arInOutCarrier); #xOutUnloadingDone := 1; ELSIF #xInStopUnloading THEN #xOutSwitch := 0; END_IF; 1100: // Warten bis fertig mit Switch offen lassen #xOutSwitch := 1; IF NOT #xInStartUnloading THEN #nState := 1110; // Switch offen lassen END_IF; 1110: // Switch offen lassen #xOutSwitch := 1; #xOutUnloadingDone := 1; #nState := 0; 1200: // Warten bis fertig mit Switch offen lassen #xOutSwitch := 1; IF NOT #xInStartUnloading THEN "FC_SHR_ExtractedHangerPin"(xInUnloadingDone := NOT #xInStartUnloading, nInBarcode := #nOutBarcode, xInBypass:=#xInBypass, stInOutConveyorStations := #stInOutConveyorStations, arInOutCarrier:= #arInOutCarrier); #nState := 1210; // Switch offen lassen END_IF; 1210: // Switch schließen #xOutSwitch := 0; #xOutUnloadingDone := 1; #nState := 0; 1300: //Switch vorher öffnen #xOutSwitch := 1; #nState := 0; END_CASE; END_REGION REGION Counter #rTrigSwitch(CLK := #xOutSwitch); #CountSwitch(CU := #rTrigSwitch.Q, PV := 1, CV => #nCount); END_REGION ; REGION Timer #tOnStateTimer(IN := #xFlgTrolleySensor,//xStateTimer, PT := T#800ms);//#tStateTimer); #TOnLineFullTimer(IN := #stInPartAfterSwitch.xDbncdSensor, PT := #tLineFullTime); IF #xInUnloadingCheckSensor AND // Sensor nach Weiche #xUnloadingCheck AND // Monitoring aktiviert NOT #tOnUnloadingCheck.Q // Monitoring nicht bereits ausgeschlagen THEN #xUnloadingCheck := FALSE; END_IF; IF #tOnUnloadingCheck.Q AND // Monitoring ausgeschlagen? (#stInOutControlUnitCabinet.xQuitError OR #xInQuitLocal) // dann am Schaltschrank zu quittieren THEN #xUnloadingCheck := FALSE; // Monitoring Ende END_IF; // Timer bis Teil am Sensor vorbei muss #tOnUnloadingCheck(IN := #xUnloadingCheck AND #stInOutControlUnitCabinet.xRunning, PT := #tUnloadingCheckTime); #xOutUnloadingError := #tOnUnloadingCheck.Q; END_REGION REGION Flanken #xFlgStartUnloading := #xInStartUnloading; END_REGION REGION Monitoring #fbMonitoringLineOverload.stSettings.nErrorType := 1; #fbMonitoringLineOverload.stSettings.xErrLedIfMachineIsOff := TRUE; #fbMonitoringLineOverload.stSettings.xSelfQuit := TRUE; #fbMonitoringLineOverload(sInFctnName := #stInOutHMI.sName, wInTextListId_Function := 500, wInTextListId_Message := 500, sInSuffix := #stInPartAfterSwitch.sName, InOutMachineState := #stInOutControlUnitCabinet, xInQuitError := #stInOutControlUnitCabinet.xQuitError OR #xInQuitLocal, xInSignal := NOT #TOnLineFullTimer.Q, sInAlarmMessage := 'Die Linie ist voll'); #fbMonitoringUnloadError.stSettings.nErrorType := 1; #fbMonitoringUnloadError.stSettings.xErrLedIfMachineIsOff := TRUE; #fbMonitoringUnloadError.stSettings.xSelfQuit := TRUE; #fbMonitoringUnloadError(sInFctnName := #stInOutHMI.sName, wInTextListId_Function := 500, wInTextListId_Message := 501, sInSuffix := #stInPartAfterSwitch.sName, InOutMachineState := #stInOutControlUnitCabinet, xInQuitError := #stInOutControlUnitCabinet.xQuitError OR #xInQuitLocal, xInSignal := NOT #xOutUnloadingError, sInAlarmMessage := 'Laufzeitfehler bei Weiche/Abwurf'); END_REGION REGION Visu REGION Status IF NOT #xOutUnloadingError AND (NOT #wOutErrorWord > 0) THEN IF #stInOutHMI.xEnableControl THEN #stInOutHMI.bStatus := 3; ELSE CASE #nState OF -10: #stInOutHMI.bStatus := 0; // NOT_AVAILABLE 0, 1100, 1110, 1200, 1210, 1300: #stInOutHMI.bStatus := 1; // AVAILABLE ELSE //Fallback #stInOutHMI.bStatus := 0; // NOT AVAILABLE END_CASE; END_IF; ELSE // Fehler #stInOutHMI.bStatus := 2; // ERROR END_IF; END_REGION REGION Modes // Int16 Bit-codiert #stInOutHMI.nMode.%X0 := (#nState = -10); // The device is turned off #stInOutHMI.nMode.%X1 := (#nState = 0) OR (#nState = 1100) OR (#nState = 1110) OR (#nState = 1200) OR (#nState = 1210) OR (#nState = 1300); // The device is turned on #stInOutHMI.nMode.%X2 := #stInOutHMI.xEnableControl; //Hand #stInOutHMI.nMode.%X3 := FALSE; //NIU #stInOutHMI.nMode.%X10 := #xOutUnloadingError; // Timeout Error END_REGION // Idee: Schrittkette setzt im Normalfall den Switch. // Wenn EnableControl TRUE ist, dann wird der Ausgang hier einfach überschrieben mit dem HMI-Wert REGION Handbetrieb IF #stInOutHMI.xEnableControl THEN #xOutSwitch := #stInOutHMI.xSetSwitch; ELSE #stInOutHMI.xSetSwitch := #xOutSwitch; END_IF; #stInOutHMI.xInHome := NOT #xOutSwitch; #stInOutHMI.xInWork := #xOutSwitch; END_REGION #stInOutHMI.xLineFull := #TOnLineFullTimer.Q; END_REGION END_FUNCTION_BLOCK