TIA Hochregallager mit Array , abfrage etc.

Die Schrittkette könntest du (da Sequenz ja genau das ist) auch als CASE ausführen - es ist so aber auch nicht falsch.
Du hast die "Funktion" suche freies Array-Feld nicht mit programmiert - dafür hatte dir aber @QuaxBruchpilot in Beitrag #3 schon ein Beispiel gepostet ...
Der Lagerort wäre ja das Array oder ?
Dann müsste ich ja mein Bool Array als "int" umdeklarieren ?

Bloß wie Zählt der dann mit den Zähler ? Denke wahrscheinlich wieder zu kompliziert..

Case ? höre ich zum ersten mal ^^ bin erst 6 Wochen dabei..
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin Steven_85,

zur Bedienung der Hochregallagers benötigst Du (neben den Koordinaten) auch die Positionswerte.

du könntest einen Fach_UDT mit folgenden Daten anlegen:
X_Position : dint;
Y_Position : dint;
belegt : bool;

Dann ein zweidimensionales Array anlegen.
Faecher : Array[1..9,1..6] of Fach_UDT

1-9 = X-Koordinaten
1-6 = Y-Koordinaten
 
Der Lagerort wäre ja das Array oder ?
Ja !
Dann müsste ich ja mein Bool Array als "int" umdeklarieren ?
verstehe ich nicht - warum ?
Es geht doch erstmal um das Finden des ersten freien Index - und da wäre das genannte Beispiel (für dich und deine Variablen-Namen angepasst) schon OK.

Wegen CASE - lies dich mal die die Siemens-Hilfe dazu ein - damit kannst du die Schrittkette auch schick umsetzen ... ;-)
 
So geändert.

Lasse es gerade beladen .. Lager 1 - 12 hat er jetzt beladen und es steht TRUE drin.

Code:
REGION Initialisierung
    IF "Sensor_Loading" = FALSE AND "Stacker_Crane_middle_Limit"
        AND #Sequenz = 0 THEN
        #Sequenz := 1;
        #Time_1_PT := T#0.5S;
        ;
    END_IF;
END_REGION

REGION Timer 1
    #IEC_Timer_0_Instance(IN:=#"Time _1_ Start",
                          PT:=#Time_1_PT,
                          Q=>#Timer_1_done,
                          ET=>#"Timer_ 1_Val");
    
    
END_REGION


REGION Palettenheber links ausfahren
    IF #Sequenz = 1 THEN
        "Hilfs_V".S_Cran_Links := TRUE;
        #Sequenz := 2;
    END_IF;
    
END_REGION

REGION Lift Anheben
    IF "Stacker_Crane_Left_Limit" AND #Sequenz = 2 THEN
        "Hilfs_V".S_Cran_Lift := TRUE;
        #"Time _1_ Start" := TRUE;
        #Sequenz := 3;
    END_IF;
    
END_REGION

REGION Heber zurück fahren
    IF #Sequenz = 3 AND #Timer_1_done THEN
        "Hilfs_V".S_Cran_Links := FALSE;
        #"Time _1_ Start" := FALSE;
        #Sequenz := 4;
    END_IF;
    
END_REGION

REGION Scanne Array
    IF #Sequenz = 4 THEN
        FOR #Zähler := 1 TO 54 DO
            IF #Lager[#Zähler] = 0 THEN
                #Lagerort := #Zähler;
                #freiesFach := TRUE;
                EXIT;
                IF #freiesFach = TRUE THEN
                    EXIT;
                END_IF;
            END_IF;
        END_FOR;
        #Sequenz := 5;
    END_IF;
    
END_REGION

REGION Fahrt ins Regal
    IF "Stacker_Crane_middle_Limit" AND #Sequenz = 5 AND #freiesFach = TRUE THEN
        #Destination := #Destination + 1;
        "Stacker_Crane_Target Pos" := #Destination ;
        #Sequenz := 6;
        #"Time _1_ Start" := TRUE;
    END_IF;
    
END_REGION


REGION Heber Fahrt nach rechts ins Regal
    IF ("Stacker_Crane_Moving X" = FALSE)
        AND ("Stacker_Crane_Moving Z" = FALSE)
        AND #Timer_1_done
        AND #Sequenz = 6 THEN
        "Hilfs_V".S_Cran_Rechts := TRUE;
        #"Time _1_ Start" := FALSE;
        #Sequenz := 7;
    END_IF;
    
END_REGION

REGION Lift absenken & Platz belegt markieren
    IF "Stacker_Crane_right_Limit" AND #Sequenz = 7 THEN
        "Hilfs_V".S_Cran_Lift := FALSE;
        #Lager[#Destination] := 1;
        #"Time _1_ Start" := TRUE;
        #Sequenz := 8;
    END_IF;
END_REGION

REGION Zurück Fahrt zum Zentrum
    IF #Sequenz = 8 AND #Timer_1_done THEN
        "Hilfs_V".S_Cran_Rechts := FALSE;
        #"Time _1_ Start" := FALSE;
        #Sequenz := 9;
    END_IF;
    
END_REGION


REGION Zurückfahrt zur Home Position
    IF #Sequenz = 9 AND "Stacker_Crane_middle_Limit" THEN
        "Stacker_Crane_Target Pos" := 55;
        #Sequenz := 10;
        #"Time _1_ Start" := TRUE;
    END_IF;
    
END_REGION

REGION "Reset"
    IF ("Stacker_Crane_Moving X" = FALSE)
        AND ("Stacker_Crane_Moving Z" = FALSE)
        AND #Sequenz = 10
        AND #Timer_1_done THEN
        #Sequenz := 0;
        #"Time _1_ Start" := FALSE;
    END_IF;
    
END_REGION
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin Steven_85,

zur Bedienung der Hochregallagers benötigst Du (neben den Koordinaten) auch die Positionswerte.

du könntest einen Fach_UDT mit folgenden Daten anlegen:
X_Position : dint;
Y_Position : dint;
belegt : bool;

Dann ein zweidimensionales Array anlegen.
Faecher : Array[1..9,1..6] of Fach_UDT

1-9 = X-Koordinaten
1-6 = Y-Koordinaten
Das mach ich wie ?
in Static anlegen :
x_Position :dint
y_Position : dint
Array [1..9, 1..6] of UDINT ?

was mache ich mit :
1-9 = X-Koordinaten
1-6 = Y-Koordinaten
?

Verzeiht, bin noch am Anfang .. 🙈

EDIT: Beim Hochregallager bei Factory i/o steht er auf Numerical . Spielt das eine Rolle ?
 
Zuletzt bearbeitet:
unter "PLC-Datentypen" kannst Du Dir Deinen eigenen Datentypen (UDT - user defined datatype) erstellen.

In einem Global-DB (oder static-Bereich eines FB) dann eine Variable mit einem Array Deines Datentypes anlegen.

In Static:
Regal : Array[1..9,1..6] of myUDT;

Dies war nur eine Info:
1-9 = X-Koordinaten
1-6 = Y-Koordinaten


Im Code kannst Du dann mit zwei Variablen die Belegung abfragen:

X : int;
Y : int;

Code:
#belegt := Regal[#X,#Y].belegt;
 
... oder in einer Schleife durchsuchen:

Code:
FOR #X := 1 TO 9 DO
    FOR #Y := 1 TO 6 DO
        IF
            NOT REGAL[#X,#Y].belegt
        THEN
            EXIT;
        END_IF;
    END_FOR;
END_FOR;

#Position_X := #REGAL[#X,#Y].X_Position
#Position_Y := #REGAL[#X,#Y].Y_Position;

Dann am besten noch abfangen, dass es einen Fehler gibt, wenn kein Platz mehr frei ist, ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
unter "PLC-Datentypen" kannst Du Dir Deinen eigenen Datentypen (UDT - user defined datatype) erstellen.

In einem Global-DB (oder static-Bereich eines FB) dann eine Variable mit einem Array Deines Datentypes anlegen.

In Static:
Regal : Array[1..9,1..6] of myUDT;

Dies war nur eine Info:
1-9 = X-Koordinaten
1-6 = Y-Koordinaten


Im Code kannst Du dann mit zwei Variablen die Belegung abfragen:

X : int;
Y : int;

Code:
#belegt := Regal[#X,#Y].belegt;
Ok
und in der UDT schreib ich auch was rein ?
bsp.
x_pos DINT
y_Pos DINT

??
 
@Larry Laffer

beim Ausladen wäre es dann so , wenn ich sage :

IF Lager[HMI_Variable] = True then

Crane zur Pos. [HMI_variable]
Rausnehmen und dann zur Home Position fahren
Danach ablegen auf der rechten seite ?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
leg mal einen neuen UDT an. Dann siehst Du, dass er im Grunde so beschrieben wird, wie ein DB oder der Deklarationsteil von FB/FC

Genau:
x_pos : dint;
y_pos : dint;
occ : bool; // belegt
Habe jetzt ein UDT angelegt

1677593902454.png


In Static auch einen Array angelegt Array [1..9, 1..6] of Fach_UDT.

aber er sagt ungültiger Dateityp O.o
 
So geändert.

Lasse es gerade beladen .. Lager 1 - 12 hat er jetzt beladen und es steht TRUE drin.

Code:
REGION Initialisierung
    IF "Sensor_Loading" = FALSE AND "Stacker_Crane_middle_Limit"
        AND #Sequenz = 0 THEN
        #Sequenz := 1;
        #Time_1_PT := T#0.5S;
        ;
    END_IF;
END_REGION

REGION Timer 1
    #IEC_Timer_0_Instance(IN:=#"Time _1_ Start",
                          PT:=#Time_1_PT,
                          Q=>#Timer_1_done,
                          ET=>#"Timer_ 1_Val");
   
   
END_REGION


REGION Palettenheber links ausfahren
    IF #Sequenz = 1 THEN
        "Hilfs_V".S_Cran_Links := TRUE;
        #Sequenz := 2;
    END_IF;
   
END_REGION

REGION Lift Anheben
    IF "Stacker_Crane_Left_Limit" AND #Sequenz = 2 THEN
        "Hilfs_V".S_Cran_Lift := TRUE;
        #"Time _1_ Start" := TRUE;
        #Sequenz := 3;
    END_IF;
   
END_REGION

REGION Heber zurück fahren
    IF #Sequenz = 3 AND #Timer_1_done THEN
        "Hilfs_V".S_Cran_Links := FALSE;
        #"Time _1_ Start" := FALSE;
        #Sequenz := 4;
    END_IF;
   
END_REGION

REGION Scanne Array
    IF #Sequenz = 4 THEN
        FOR #Zähler := 1 TO 54 DO
            IF #Lager[#Zähler] = 0 THEN
                #Lagerort := #Zähler;
                #freiesFach := TRUE;
                EXIT;
                IF #freiesFach = TRUE THEN
                    EXIT;
                END_IF;
            END_IF;
        END_FOR;
        #Sequenz := 5;
    END_IF;
   
END_REGION

REGION Fahrt ins Regal
    IF "Stacker_Crane_middle_Limit" AND #Sequenz = 5 AND #freiesFach = TRUE THEN
        #Destination := #Destination + 1;
        "Stacker_Crane_Target Pos" := #Destination ;
        #Sequenz := 6;
        #"Time _1_ Start" := TRUE;
    END_IF;
   
END_REGION


REGION Heber Fahrt nach rechts ins Regal
    IF ("Stacker_Crane_Moving X" = FALSE)
        AND ("Stacker_Crane_Moving Z" = FALSE)
        AND #Timer_1_done
        AND #Sequenz = 6 THEN
        "Hilfs_V".S_Cran_Rechts := TRUE;
        #"Time _1_ Start" := FALSE;
        #Sequenz := 7;
    END_IF;
   
END_REGION

REGION Lift absenken & Platz belegt markieren
    IF "Stacker_Crane_right_Limit" AND #Sequenz = 7 THEN
        "Hilfs_V".S_Cran_Lift := FALSE;
        #Lager[#Destination] := 1;
        #"Time _1_ Start" := TRUE;
        #Sequenz := 8;
    END_IF;
END_REGION

REGION Zurück Fahrt zum Zentrum
    IF #Sequenz = 8 AND #Timer_1_done THEN
        "Hilfs_V".S_Cran_Rechts := FALSE;
        #"Time _1_ Start" := FALSE;
        #Sequenz := 9;
    END_IF;
   
END_REGION


REGION Zurückfahrt zur Home Position
    IF #Sequenz = 9 AND "Stacker_Crane_middle_Limit" THEN
        "Stacker_Crane_Target Pos" := 55;
        #Sequenz := 10;
        #"Time _1_ Start" := TRUE;
    END_IF;
   
END_REGION

REGION "Reset"
    IF ("Stacker_Crane_Moving X" = FALSE)
        AND ("Stacker_Crane_Moving Z" = FALSE)
        AND #Sequenz = 10
        AND #Timer_1_done THEN
        #Sequenz := 0;
        #"Time _1_ Start" := FALSE;
    END_IF;
   
END_REGION

Kann sich einer mal Bitte die Region "Scanne Array" anschauen?
der sollte eigentlich , wenn das Lager voll ist (sprich 1 bis 54) dann sollte er kein Paket mehr aufnehmen
Habe die Scanfunktion an 2. Stelle geschoben
Er sollte vorm aufnehmen , das scannen.

Jetzt habe ich mal beobachtet. Er hatte bis 54 TRUE , dann hat er das Paket hochgehoben und dann in den Ausgang gleich gesetzt.
Eigentlch sollte er kein Paket mehr hochheben, da freies Fach auf FALSE stellen sollte.
 
Hab es jetzt nur überflogen, aber wird "freiesFach" auch irgendwo wieder rückgesetzt also initialisiert?
Ansonsten bleibt es ja auf dem zugewiesenen Status "TRUE", da es eine Static-Variable ist?!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hab es jetzt nur überflogen, aber wird "freiesFach" auch irgendwo wieder rückgesetzt also initialisiert?
Ansonsten bleibt es ja auf dem zugewiesenen Status "TRUE", da es eine Static-Variable ist?!
Nee , das habe ich mit gekriegt.
Wollte nach der Schleife es zurücksetzen, aber dann bleibt der Lift gleich stehen O.o
Oder muss ich da wieder eine schleife machen ?
 
Nee , das habe ich mit gekriegt.
Wollte nach der Schleife es zurücksetzen, aber dann bleibt der Lift gleich stehen o_O
Oder muss ich da wieder eine schleife machen ?
wo hast du denn den Code gepostet - finde ich gerade nicht ...
Im Grunde würde ich es aber so machen :





freierPlatz := -1 ;
for i := 1 to 48 by 1 do
if not Platz_belegt(i) then
freierPlatz := i ;
exit ;
end_if ;
end_for ;

if freierPlatz > 0 then // Platz gefunden
else // kein Platz gefunden
end_if ;




 
Zuviel Werbung?
-> Hier kostenlos registrieren
wo hast du denn den Code gepostet - finde ich gerade nicht ...
Im Grunde würde ich es aber so machen :
Sorry habe ich vergessen anzuhängen


Code:
REGION Scanne Array
 
        FOR #Zähler := 1 TO 54 DO
            IF #Lager[#Zähler] = FALSE THEN
                #Lagerort := #Zähler;
                #freiesFach := TRUE;
                EXIT;
            ELSIF #Lager[#Zähler] = TRUE THEN
                #freiesFach := FALSE;
            END_IF;
            IF #freiesFach = TRUE THEN
                EXIT;
            END_IF;
                END_FOR;
                
END_REGION

REGION Palettenheber links ausfahren
    IF #Sequenz = 1 AND #freiesFach = TRUE THEN
        "Hilfs_V".S_Cran_Links := TRUE;
        #Sequenz := 2;
    END_IF;
 
Funktioniert deine Fachsuche denn jetzt oder welches Problem hast du mit deinem abgeändertem Code noch?

Code:
        FOR #Zähler := 1 TO 54 DO
            IF #Lager[#Zähler] = FALSE THEN
                #Lagerort := #Zähler;
                #freiesFach := TRUE;
                EXIT;
            ELSE 
                #Lagerort := -1; // evtl. auch noch diese Variable mit initialisieren?
                #freiesFach := FALSE;
            END_IF;
        END_FOR;
Sollte die gleiche Funktion darstellen, nur etwas schmäler.

Der Wert "-1" wird oft als Initialwert verwendet um sauber gegen etwaige Ersatz-/Rückgabewerte (z.B. "0") vergleichen zu können.
Soweit meine Erfahrung.
 
Zurück
Oben