ILSLib hinzugefügt

This commit is contained in:
2026-06-29 16:29:41 +02:00
parent 14a1c5172d
commit cd281dc8b2
249 changed files with 26501 additions and 0 deletions
+227
View File
@@ -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