Hochregallager mit STEP7 programmieren

KarlOtto

Level-1
Beiträge
29
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin,

Folgendes vorweg: Ich programmiere im Moment ein Modell (Schulungsanlage) eines Hochregallagers mit 16 Stellplätzen (4 Felder, 4 Ebenen). Jedem Stellplatz ist ein Byte in einem DB zugeordnet. Das erste Bit rechtsbündig ist "1" wenn das Fach belegt ist und "0" wenn das Fach leer ist. Das Stückgut (Kunstoff- oder Aluminiumzylinder) wird mit einem "Saugnapf" aufgenommen. Die Achse längs der Fächer (links, rechts [x]) und die Achse quer zu den Fächern (hoch, runter [z]) ist mittels Schlitten, Riementrieb und Motor realisiert. Die Achse, die den Saugnapf in das jeweilige Fach bewegt (y), ist ein einfachwirkender Pneumatikzylinder (Ruhestellung eingefahren). Die Position in Längsrichtung wird mittels Drehgeber erfasst. Die vier Ebenen in Querrichtung haben jeweils eine eigene Abfrage (ind. Näherungsschalter). Der Zylinder (Sauger ein- ausfahren) hat zwei Endlagenabfragen. Der "Automatikbetrieb" funktioniert einwand frei. Prinzip ist eine Schrittkette an deren Beginn eine Funktion (Schleife mit indirekter Adressierung und Pointer) in dem (Global)Datenbaustein in dem (Platzstatus)Byte das "Belegtbit" abfragt und wenn es "0" ist die "Platzdaten" (Feld- und Ebenenkorrdinate sowie Zeilennummer) in einen anderen (Global)Datenbaustein (=Auftragsspeicher) schreibt und dann wird einfach eine Schrittkette abgearbeitet. Einer der Schritte ist dann eben auch das Setzen des Platzbelegtbits. Nun zu meinem Problem:

Wie realisiere ich möglichst einfach (=wenig umfangreich + elegant), dass im "Handbetrieb" Stückgutein- oder Ausgang im DB "vermerkt" wird. Sonst lagert man im Handbetrieb ein und muss immer im DB rumfuschen, da es im Automatikbetrieb sonst kracht.

Mein Gedankengang:

Ich kann 16 mal abfragen: x-koordinate, z-koordinate, y-ausgefahren, FP Vakuumkontrolle ====> Setze Bit
und dann 16 mal: x-koordinate, z-koordinate, y-ausgefahren, FN Vakuumkontrolle ====> Rücksetze Bit

Auch möglich wäre eine Schleife. Die aber bereitet mir dahingehend Kopfschmerzen, dass ich zunächst z.B. die x-Koordinate Abfrage (4 verzweigung) und anschließend für jede Verzweigung noch einmal die z-Koordinate abfrage (sind auch wieder 16).

Wie kann ich das möglichst einfach, wenig umfangrei und elegant realisieren?

Vielen Dank schon einmal im vorab!
 
sry, stimmt ja gar nicht. 4 worte sind nicht ein doppel wort^^ entschuldige...
was bringt mir das? das ich den momentanen zustand nur mit einer "Zeile" im DB vergeleichen muss?
 
ich baue also n db der art:

STRUCT
fach : ARRAY [1 ..16] OF DWORD;
END_STRUCT

BEGIN
fach[1] := DW#16#"was dann halt hier so ist";
.
.
.
.
END_DATA_BLOCK

und dann?

Of word, reicht.

Dann nimmst du die Position die du anfahren willst, multiplizierst dies mit 4 und dann -4 (damit es bei 0 beginnt).
Aus dieser Zahl baust du dir einen Zeiger, dann hast du Werte, die im Datenbaustein hinterlegt sind.

Eine Lösung solltest du selbst versuchen, dann hat du echt etwas gelernt.
Zu Fragen zum Programm, den Teil hier einstellen, der nicht klappt.


bike
 
Zuviel Werbung?
-> Hier kostenlos registrieren
und ich bitte nochmals um entschuldigung da das immer noch quatsch ist. ich muss dann als datentyp auch "INT" sagen, ja.
vielleicht noch ein paar anmerkungen: ich bin noch nicht so lange auf dem gebiet unterwegs und "spreche" nur AWL nicht ST. ein ARRAY kenne ich nur in nem Datenbaustein. zb habe ich ein ARRAY [1..16] OF BYTE für die "Statusbytes" und dann noch ein ARRAY [1..4] OF INT für die ebene und eins (ARRAY [1..4] OF INT) für das feld.
 
Eine UDT erstellen

TYPE "UDT_POSITION"
VERSION : 0.1


STRUCT
beladen : BOOL ; //Fach beladen = 1
res_1 : BOOL ; //hier ist platz für andere Bit Informationen
Position_X : INT ;
Position_Y : INT ;
Positon_Z : INT ;
res_int : INT ; //Lückenfüller für Adressierung
END_STRUCT ;
END_TYPE


Dann einen Datenbaustein.
Der DB kann so aussehen, wenn du den auf die richtige Größe erweiterst

DATA_BLOCK "DB_POSITIONEN"
TITLE =
VERSION : 0.1


STRUCT
Fach_1 : "UDT_POSITION";
Fach_2 : "UDT_POSITION";
Fach_3 : "UDT_POSITION";
END_STRUCT ;
BEGIN
Fach_1.beladen := FALSE;
Fach_1.res_1 := FALSE;
Fach_1.Position_X := 0;
Fach_1.Position_Y := 0;
Fach_1.Positon_Z := 0;
Fach_1.res_int := 0;
Fach_2.beladen := FALSE;
Fach_2.res_1 := FALSE;
Fach_2.Position_X := 0;
Fach_2.Position_Y := 0;
Fach_2.Positon_Z := 0;
Fach_2.res_int := 0;
Fach_3.beladen := FALSE;
Fach_3.res_1 := FALSE;
Fach_3.Position_X := 0;
Fach_3.Position_Y := 0;
Fach_3.Positon_Z := 0;
Fach_3.res_int := 0;
END_DATA_BLOCK


So schauen die Quellen aus, das kannst aber direkt im S7 eingeben, dann schaut es so ähnlich aus.

Mit dieser UDT kannst du auch deine Achsen mit allen Werten ansteuern.
Jetzt musst du dir nur einen Zeiger bilden, die Werte lesen und weiter schicken.

Viel Erfolg


bike
 
Zuviel Werbung?
-> Hier kostenlos registrieren
erst einmal vielen dank für deine schnelle und ausführliche hilfe :)

was ich nicht verstehe ist "Eine UDT erstellen". Wie mache ich das? ich bin eher der quellorientierte programmierer, ja, kenne aber nur die folgende befehle:
FUNCTION FC [] : VOID
FUNCTION_BLOCK FB []
DATA_BLOCK []
ORGANIZATION_BLOCK []
aber UDT sagt mir nichts... muss das ne ST-Quelle sein?

den rest meine ich verstanden zu haben: jedem Platz (1-16) wird einmal die "UDT-POSITION" zugewiesen und die Anfangswerte müssen definiert werden.
Wie greife ich dann auf die zu? mit...

AUF DB "DB_POSITIONEN";
.
.
.
LC Z 0;
BTI;
T x_ist;
.
.
.
LAR1 [P#DBX0.0]
.
.
.
L W [P#16.0] // oder was auch immer als versatz, muss ich halt anpassen
L x_ist
<>I
SPB M002
.
.
.
M002 : +AR1 [P#4.0]
LOOP M001

so oder wie?
 
Du hast doch den Quelltext schon von mir.
Wenn du in der Symbolik UDT_POSITION als UDT 1 deklarierst, dann kannst du die Quelle compilieren.
Mit der UDT kannst du den Datenbaustein bauen.

Nicht veröffentliche Veröffentlichung ;-)

L position // hier steht dein Fach
L 10 //Offsett
*i
l 10 // Damit bei 0 begonnen wird
-I
T t_fachnummer // Speicher wo das Fach im DB ist


l t_fachnummer
SLW 3 // bilde Pointer
LAR1



Jetzt hast du den Pointer und dann mach dir Gedanke wie du auf die Adressen kommst, es werden keine Vergleiche und / oder Sprünge benötigt.



bike


P.S: Streng deinen Grips an, dann verstehst du es auch.
Mehr kann ich dir nicht vorprogrammieren, denn eigener Gehirnschmalz sollte auch in dem Programm sein.
P.S.S: Bei Volker auf der Homepage gibt es ein super Tutorial von und mit und wegen Pointer ;-)
 
ok, ich versuchs mal....
dann hab ich den pointer der auf den beginn der daten des faches zeig. nun würde ich ihm sagen wollen was davon (sprich ab wo [pointerversatz]) und wie lang er in akku 1 laden soll (W, D, X). das würde ich dann aber immer noch mit der momentanen position vergleichen und wenn eine übereinstimmung gegeben ist, dann halt das belegtbit setzen oder rücksetzen. Und den Pointerversatz könnt ich sicher berechnen:
die plätze sind in x bei 0, 20, 40, 60 übereinnander
und in z bei 1, 2, 3, 4 nebeneinnander
aber wenn ich daraus eine gleichung entwickeln könnte, deren ergebnis 1, 2, 3, 4, 5, 6, 7, 8....16 (jenachdem welche x und z kombi) ist, dann... wär ich schon cool =) 1,2, 3,4...16 würde ich dann mit 4 multiplizieren und hätte den anfang der daten (da ich 4 wörter in der UDT hab, für ein platz)

dein quelltext verstehe ich nicht vollständig. was ist mit offsett gemeint und warum 10

aso und im automatikbetrieb, wie gesagt, funktioniert das setzten des entsprechenden bits. problem ist der handbetrieb, da ich da nicht ein bestimmtes (vorher ausgesuchtes, da nächstes leeres fach) anfahre sondern irgendeins und wissen will welches....

ich glaub das ist zu hoch und ich schreib einfach 32 abfragen, 16 für setzen und 16 für rücksetzen... :-S
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du hast den Wert deiner aktuellen Position, richtig?
Dann beginnst du deinen Datenbaustein von Position 0 zu lesen und zu vergleichen.
Wenn das Ergebnis equal ist, dann setzt du in dem angewählten Feld das Bit = gesetzt.
Der Offset sind doch 10 Byte? :confused:
oder doch 20 Byte?
Mist, werde morgen mal mit S7 testen und melde mich dann wieder, habe abends wohl eine Rechenschwäche :)


bike
 
ich hab jetzt ne UDT gebastelt in der das erste wort bit-infos sind, das zweite wort ist die position in x (INT), das dritte wort ist die position in z (INT), das vierte und letzte wort ist reserve (INT). diese UDT hab ich in nem db jedem der 16 fächer zugewiesen und die anfangswerte bestimmt, also alles so wie von dir vorgeschlagen. und nun werd ich morgen die funktion basteln, die dann den vergleich macht und wenn es gleich ist, das belegtbit setzt, jupp.
 
aso, eine frage hab ich noch. die x und die z koordinate (y gibt es nicht) stehen im db ja "hintereinander" und ich kann sie dann beide laden mit:
L DBD [AR1, P#0.0];
kann ich die momentanen werte von x und z (beides zunächst zähler) auch irgendwo hinschreiben und dann zusammenladen? dann muss ich nur einen vergleich machen und nicht zwei für jedes fach. geht das wenn ich nen FB nehme und die zähler mit:
LC Z 0;
BTI;
T x_ist;
LC Z 1;
BTI;
T z_ist;
in den instanzdatenbaustein "packe" (da ich x_ist und z_ist als statische var. deklarieren könnte) und dann aus dem I. DB die richtigen 2 wörter in folge laden und nen "==D" vergleiche? geht das?
 
Zurück
Oben