ILSLib hinzugefügt
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
FUNCTION "FC_TargetDecision" : Void
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
VERSION : 0.1
|
||||
VAR_INPUT
|
||||
arInStorageLineCalc : Array[1.."cNoLines"] of Int;
|
||||
arInStorage : Array[*] of "stStorageLine";
|
||||
arInSenStore : Array[*] of "UDT_Sensor";
|
||||
nInDestGeneral : Int;
|
||||
nInNoOfLines : Int;
|
||||
nInStorageThreshold : Int;
|
||||
nInMode : USInt; // 1 = abwechselnd; 2 = gleichmäßig füllen; 3 = nacheinander auffüllen
|
||||
END_VAR
|
||||
|
||||
VAR_OUTPUT
|
||||
xOutBypass : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
nInOutTarget : USInt;
|
||||
xInOutFree : Bool;
|
||||
stInOutConveyorStations : "stConveyorStations";
|
||||
stInOutCarrier : "stCarrier";
|
||||
stInOutJamBypass : "stJamData";
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
nIdx : Int; // Schleifenindex
|
||||
nIdx2 : Int;
|
||||
nIdxMem : Int; // gemerkter Wert vom Schleifenindex
|
||||
nTarget : Int;
|
||||
nTargetMaxOnTheWay : Int;
|
||||
nSum : Int; // Summe der Lagerbestände
|
||||
nAverage : Int; // Durchschnitt der Lagerfüllstände
|
||||
nThrTop : Int; // Obere Schwelle für Durchschnitt
|
||||
nThrLow : Int; // Untere Schwelle für Durchschnitt
|
||||
nNoOfSameTarget1 : Int;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
(*
|
||||
Funktion weist ab AddHanger-Sensor das Ziel des aktuellen Carriers zu, prüft aber vorher ob Ziel frei ist. Falls nicht, wird nächstes freies Ziel gesucht.
|
||||
Falls alles voll ist, wird Stop-Befehl für Band ausgegeben
|
||||
*)
|
||||
|
||||
//Beispiel für Materialnummer Stand IBN:
|
||||
//95001412-95001419 -> Sitz
|
||||
//95001420-9500142x -> Lehne
|
||||
//#nInProductNr DInt
|
||||
|
||||
//************TEST FÜR DURCHSCHNITT**************
|
||||
// FOR #nIdx := 1 TO "cNoLines" DO //Summe der Lagerlinien-Füllstände merken
|
||||
// #nSum += #arInStorage[#nIdx].stData.Status.nCount;
|
||||
// END_FOR;
|
||||
// IF #nSum > 0 AND #nSum <= ("cNoLines" * "cNoPositions") THEN
|
||||
// //Durchschnitt berechnen sowie obere/untere Schwelle, aber nur wenn Durchschnitt oberhalb eines festgelegten Wertes liegt
|
||||
// #nAverage := #nSum / "cNoLines";
|
||||
// #nThrTop := #nAverage * "cAverageThrTop";
|
||||
// #nThrLow := #nAverage * "cAverageThrLow";
|
||||
// END_IF;
|
||||
// "cAverageMin"...
|
||||
|
||||
REGION Normierung für diesen FC
|
||||
IF #nInOutTarget < 11 OR #nInOutTarget > #nInNoOfLines + 10 THEN // > nInNoLines hinzugefügt, für unterschiedlich große Lager-TRO
|
||||
#nTarget := 1; //Wenn Ziel außerhalb des gültigen Bereichs, fange mit 1 an
|
||||
ELSE
|
||||
#nTarget := #nInOutTarget - 10; //nTarget benutzt Zahlen 1-21 statt von außen ab 11 beginnend zur einfacheren Handhabung
|
||||
END_IF;
|
||||
END_REGION
|
||||
|
||||
CASE #nInMode OF
|
||||
1:
|
||||
REGION ABWECHSELND - Ziele prüfen falls aktuelles belegt
|
||||
IF #arInSenStore[#nTarget].xJam OR #arInStorage[#nTarget].stData.Status.nCount >= #nInStorageThreshold OR #arInStorageLineCalc[#nTarget] >= #nInStorageThreshold THEN //Wenn Ziel voll, dann....
|
||||
REGION Ziel korrigieren
|
||||
IF #nTarget = #nInNoOfLines THEN //Wenn Ziel die letzte Linie ist, suche von 1. bis vorletzte Linie
|
||||
REGION Suche von 1. bis vorletzte
|
||||
FOR #nIdx := 1 TO (#nInNoOfLines - 1) DO
|
||||
IF NOT #arInSenStore[#nIdx].xJam AND #arInStorage[#nIdx].stData.Status.nCount < #nInStorageThreshold AND #arInStorageLineCalc[#nIdx] < #nInStorageThreshold THEN
|
||||
#nInOutTarget := INT_TO_USINT(#nIdx + 10); //nächstes freies Ziel. Fertig
|
||||
RETURN;
|
||||
END_IF;
|
||||
END_FOR;
|
||||
END_REGION
|
||||
#xInOutFree := FALSE; //nichts freies gefunden -> Band stoppen
|
||||
RETURN;
|
||||
ELSE
|
||||
REGION Suche bis zum Schluss...
|
||||
FOR #nIdx := (#nTarget + 1) TO #nInNoOfLines DO //Suche AB der aktuellen Linie...
|
||||
IF NOT #arInSenStore[#nIdx].xJam AND #arInStorage[#nIdx].stData.Status.nCount < #nInStorageThreshold AND #arInStorageLineCalc[#nIdx] < #nInStorageThreshold THEN
|
||||
#nInOutTarget := INT_TO_USINT(#nIdx + 10); //nächstes freies Ziel. Fertig
|
||||
RETURN;
|
||||
END_IF;
|
||||
END_FOR;
|
||||
END_REGION
|
||||
REGION ...und ggf. von 1. bis zum aktuellen
|
||||
FOR #nIdx := 1 TO (#nTarget - 1) DO //...falls nichst gefunden, suche BIS zur aktuellen Linie
|
||||
IF NOT #arInSenStore[#nIdx].xJam AND #arInStorage[#nIdx].stData.Status.nCount < #nInStorageThreshold AND #arInStorageLineCalc[#nIdx] < #nInStorageThreshold THEN
|
||||
#nInOutTarget := INT_TO_USINT(#nIdx + 10); //nächstes freies Ziel. Fertig
|
||||
RETURN;
|
||||
END_IF;
|
||||
END_FOR;
|
||||
END_REGION
|
||||
#xInOutFree := FALSE; //nichts freies gefunden -> Band stoppen
|
||||
RETURN;
|
||||
END_IF;
|
||||
END_REGION
|
||||
ELSE
|
||||
REGION Ziel i.O.
|
||||
#nInOutTarget := INT_TO_USINT(#nTarget + 10); //keine Korrektur nötig und übernehme Ziel einfach
|
||||
END_REGION
|
||||
END_IF;
|
||||
END_REGION
|
||||
2:
|
||||
REGION GLEICHMÄßIG BEFÜLLEN - Ziele prüfen
|
||||
FOR #nIdx := 1 TO #nInNoOfLines DO
|
||||
IF #nIdx = 1 THEN
|
||||
IF NOT #arInSenStore[#nIdx].xJam AND #arInStorage[#nIdx].stData.Status.nCount < #nInStorageThreshold THEN
|
||||
#nIdxMem := #nIdx; //Wenn beim 1. Schleifendurchlauf in L1 Platz ist, merke die 1
|
||||
END_IF;
|
||||
ELSIF #nIdx > 1 THEN
|
||||
// ab den folgenden Schleifendurchläufen, merke die Linie, welche weniger drin hat als die zuvor gemerkte (falls Platz ist)
|
||||
IF NOT #arInSenStore[#nIdx].xJam AND #arInStorage[#nIdx].stData.Status.nCount < #nInStorageThreshold AND
|
||||
#arInStorage[#nIdx].stData.Status.nCount < #arInStorage[#nIdxMem].stData.Status.nCount THEN
|
||||
#nIdxMem := #nIdx;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_FOR;
|
||||
// nach der Schleife: Wenn nichts gemerkt wurde, heißt es dass alle Linien voll sind -> Band stoppen
|
||||
IF #nIdxMem = 0 THEN
|
||||
#xInOutFree := FALSE; //nichts freies gefunden -> Band stoppen
|
||||
ELSE
|
||||
#nInOutTarget := INT_TO_USINT(#nIdxMem + 10); //nächstes freies Ziel. Fertig
|
||||
END_IF;
|
||||
END_REGION
|
||||
3:
|
||||
REGION JEDE LINIE NACHEINANDER BEFÜLLEN - Ziele prüfen
|
||||
|
||||
//PRÜFEN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
REGION Richtungswechsel ermitteln TO DO ÜBERARBEITEN
|
||||
(* IF #stInOutConveyorStations.stData.nTrolleysOnline > 0 THEN //wenn etwas unterwegs ist, ermittle ob der aktuelle Carrier ein kleineres Ziel hat als diese
|
||||
FOR #nIdx2 := 1 TO #stInOutConveyorStations.stData.nTrolleysOnline DO
|
||||
IF #nIdx2 = 1 THEN
|
||||
#nTargetMaxOnTheWay := #stInOutConveyorStations.arTrolleysOnline[#nIdx2].stPinValues.nTarget;
|
||||
ELSE
|
||||
IF #stInOutConveyorStations.arTrolleysOnline[#nIdx2].stPinValues.nTarget > #nTargetMaxOnTheWay THEN
|
||||
#nTargetMaxOnTheWay := #stInOutConveyorStations.arTrolleysOnline[#nIdx2].stPinValues.nTarget;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_FOR;
|
||||
IF (#stInOutCarrier.nDestination - #nInDestGeneral) > (#nTargetMaxOnTheWay - 10) THEN //Wenn aktueller Carrier ein höheres Ziel hat als die unterwegs, mach nichts
|
||||
#xInOutFree := FALSE;
|
||||
RETURN;
|
||||
END_IF;
|
||||
END_IF; *)
|
||||
//Bearbeitung kann weiter gehen weil aktueller Carrier niedrigeres Ziel hat oder nichts
|
||||
END_REGION
|
||||
(*
|
||||
Für Änderung dass man abwartet dass CarrierOnline leer ist vor Richtungswechsel:
|
||||
-nicht TargetMaxOnTheWay ermitteln mit Schleife sondern einfach Ziel des ersten OnTheWay abfragen
|
||||
-NoOfSameTarget muss nicht mit Schleife ermittelt werden sondern einfach von TrolleysOnline der nCount abgefragt werden
|
||||
-.....
|
||||
*)
|
||||
REGION Linie ermitteln bzw. prüfen
|
||||
//IF #stInOutCarrier.nDestination = 0 OR (#stInOutCarrier.nDestination >= #nInDestGeneral AND (#stInOutCarrier.nDestination <= #nInDestGeneral + #nInNoOfLines) AND NOT #stInOutCarrier.bStatus.%X5) THEN
|
||||
IF #stInOutCarrier.nDestination = 0 OR (#stInOutCarrier.nDestination = #nInDestGeneral) THEN
|
||||
(*normal Ziel ermitteln für neue Carrier*)
|
||||
FOR #nIdx := 1 TO #nInNoOfLines DO
|
||||
IF #stInOutConveyorStations.stData.nTrolleysOnline > 0 THEN //zähle gleiche Ziele zusammen erst wenn überhaupt etwas unterwegs ist
|
||||
FOR #nIdx2 := 1 TO #stInOutConveyorStations.stData.nTrolleysOnline DO
|
||||
IF #stInOutConveyorStations.arTrolleysOnline[#nIdx2].stPinValues.nTarget = #nIdx + 10 THEN
|
||||
#nNoOfSameTarget1 += 1; //addiere die gleichen vergebenen Ziele auf dem Pinband
|
||||
END_IF;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
IF NOT #arInStorage[#nIdx].stData.Status.bByte.%X2 AND // Einfahrt gesperrt (HMI-Schnittstelle, manueller Eingriff)
|
||||
NOT #arInSenStore[#nIdx].xJam AND //Phys. Stau
|
||||
NOT #arInStorage[#nIdx].stData.Status.bByte.%X5 AND //reservierte Linie nicht anfahren
|
||||
(#arInStorage[#nIdx].stData.Status.nCount + #nNoOfSameTarget1) < #nInStorageThreshold THEN
|
||||
#nInOutTarget := INT_TO_USINT(#nIdx + 10); //nächstes freies Ziel. Fertig
|
||||
#xInOutFree := TRUE;
|
||||
RETURN;
|
||||
END_IF;
|
||||
#nNoOfSameTarget1 := 0; // Nullen
|
||||
IF #nIdx = #nInNoOfLines THEN
|
||||
#xInOutFree := FALSE; //nichts freies gefunden -> Band stoppen
|
||||
END_IF;
|
||||
END_FOR;
|
||||
// ELSIF #stInOutCarrier.nDestination > #nInDestGeneral AND #stInOutCarrier.nDestination <= #nInDestGeneral + 21 THEN //zwischen 21101 und 21121
|
||||
// ELSIF (#stInOutCarrier.nDestination >= #nInDestGeneral AND #stInOutCarrier.nDestination <= #nInDestGeneral + #nInNoOfLines AND #stInOutCarrier.bStatus.%X5) THEN
|
||||
ELSIF ((#stInOutCarrier.nDestination > #nInDestGeneral) AND (#stInOutCarrier.nDestination <= (#nInDestGeneral + #nInNoOfLines))) THEN
|
||||
(*hat schon Ziel in diesem Block, daher prüfen ob diese Linie frei*)
|
||||
|
||||
IF #stInOutConveyorStations.stData.nTrolleysOnline > 0 THEN //zähle gleiche Ziele zusammen erst wenn überhaupt etwas unterwegs ist
|
||||
FOR #nIdx2 := 1 TO #stInOutConveyorStations.stData.nTrolleysOnline DO
|
||||
IF #stInOutConveyorStations.arTrolleysOnline[#nIdx2].stPinValues.nTarget = (#stInOutCarrier.nDestination - #nInDestGeneral) + 10 THEN
|
||||
#nNoOfSameTarget1 += 1; //addiere die gleichen vergebenen Ziele auf dem Pinband
|
||||
END_IF;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
IF NOT #arInSenStore[#stInOutCarrier.nDestination - #nInDestGeneral].xJam AND //phys. Stau
|
||||
NOT #arInStorage[#stInOutCarrier.nDestination - #nInDestGeneral].stData.Status.bByte.%X2 AND //Einfahrt gesperrt (HMI, manuell)
|
||||
(#arInStorage[#stInOutCarrier.nDestination - #nInDestGeneral].stData.Status.nCount + #nNoOfSameTarget1) < #nInStorageThreshold THEN
|
||||
#nInOutTarget := INT_TO_USINT((#stInOutCarrier.nDestination - #nInDestGeneral) + 10); //nächstes freies Ziel. Fertig
|
||||
#xInOutFree := TRUE;
|
||||
RETURN;
|
||||
END_IF;
|
||||
#xInOutFree := FALSE; //nichts freies gefunden -> Band stoppen
|
||||
ELSE
|
||||
(*Bypass*)
|
||||
#nInOutTarget := INT_TO_USINT(#nInNoOfLines + 10 + 1);
|
||||
#xOutBypass := TRUE;
|
||||
IF NOT (#stInOutJamBypass.Status.nCount >= #stInOutJamBypass.Config.nCapacitySet) THEN
|
||||
#xInOutFree := TRUE;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_REGION
|
||||
|
||||
END_REGION
|
||||
ELSE
|
||||
#xInOutFree := FALSE; //falsche Eingabe -> Band stoppen
|
||||
END_CASE;
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
Reference in New Issue
Block a user