TIA Programmbaustein - Datenbaustein mit x/y Koordinaten - Variable Paletten

Hubi123

Level-1
Beiträge
4
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Sehr geehrte Forumsmitglieder,

Ich stehe gerade vor einem großen Problem und komme hier nicht weiter.

Für eine Automatisierungsaufgabe benötige ich einen BAUSTEIN in dem die x-y Koordinaten für eine Pick&Place Anwendung abgelegt werden.

Für diese Aufgabe gibt es standardisierte Trays (Paletten). Auf diesen Trays können sich eine verschiedene Anzahl von Bauteilen befinden (30-500). Die Position der Bauteile lässt sich jedoch durch Rahmenparameter eindeutig bestimmen (Anzahl Zeilen/Spalten, Position Erstes Bauteil X/Y, Offset der Bauteile X/Y)
Dadurch ist es ja theoretisch möglich alle x,y-Kooridinaten der Bauteile zu bestimmen und in einem Datenbaustein abzulegen (x0,y0....x1y1,...x2,y2...usw.)

Leider bekomme ich es nicht hin, hier einen "BAUSTEIN" zu basteln, der mir diese Aufgabe erfüllt.

In der Automatisierungsaufgabe will ich dann die entsprechenden Positonen anfahren. Könnt ihr mir hier weiterhelfen? Ich wäre euch super dankbar.

Falls es sehr aufwendig ist, bin ich auch bereit den Aufwand entsprechenden zu entlohnen.

Vielen Dank im Voraus,

Viele Grüße,
H.Heigl
 
Für eine Automatisierungsaufgabe benötige ich einen BAUSTEIN in dem die x-y Koordinaten für eine Pick&Place Anwendung abgelegt werden.
Ich behaupte einfach mal, dass Du genau das eigentlich nicht brauchst.
Du brauchst vermutlich einen Baustein, der Dir jeweils aktuell die x- und die y-Koordinate berechnet passend zu vorgegebenem TrayTyp, Zeilen- und SpaltenNr.
Vielleicht brauchst Du auch noch einen Baustein, der die Berechnung in umgekehrter Richtung kann, nämlich aus der x- und y-Koordinate berechnet, um welche Zeile und Spalte es sich handelt (sofern z.B. die Positionen von einer Kamera ermittelt werden).
Aber, ob Du wirklich passend zum jeweiligen TrayTyp oder zu allen TrayTypen eine Sammlung von Koordinaten in einem DB ablegen willst bzw. musst???
Das würde ich eigentlich vermeiden wollen.
Mach Dir einen struct für den TrayTyp, z.B. TypNr, AnzahlZeilen, AnzahlSpalten, xOffsetPos0, yOffsetPos0, xOffset, yOffset und leg ein Array of struct an, das so viele Elemente hat, wie es TrayTypen gibt.
Der Baustein wird dann mit TrayTyp (=ArrayIndex), ZeilenNr und SpaltenNr gefüttert und liefert x- und y-Position.
Code:
...
// ZeilenNrn: 0 .. AnzahlZeilen - 1; SpaltenNrn: 0 .. AnzahlSpalten - 1
IF ZeilenNr >= Tray[lfdTypNr].AnzahlZeilen THEN
    // Fehler ZeilenNr zu gross
ELSIF SpaltenNr >= Tray[lfdTypNr].AnzahlSpalten THEN
    // Fehler SpaltenNr zu gross
ELSE
    // Positionen berechnen
    xPos := Tray[lfdTypNr].xOffsetPos0 + SpaltenNr * Tray[lfdTypNr].xOffset;
    yPos := Tray[lfdTypNr].yOffsetPos0 + ZeilenNr * Tray[lfdTypNr].yOffset;
END_IF;
...
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Heinileini,

Wow. Vielen Dank vorab für deine schnelle und umfangreiche Antwort.

Du hast recht, wenn du meinst, dass ich nicht unbedingt Datenbausteine benötige, in der alle x/y-Positionen abgelegt werden. Es ist natürlich eleganter, wie du vorgeschlagen hast, eine Formel zu verwenden, die mir immer die aktuelle X-Y-Position "berechnet". Das kann sehr umfangreich werden.

Eine Kamera kommt in Zulunft eventuell ins Spiel, da bietet es sich an, umgekehrt auch die Positionen herauszulesen.

Ich bin "leider" nur ein Praktiker, und kenne mich nicht nicht aus mit SCL. Alle Programme wurden von mir in FUP geschrieben. Für einfachere Anwendungen ist das auch Problemlos möglich.

Das Zeil ist so definiert:
- Via HMI sollen Rezepte erstellbar und abrufbar sein, in der diese Punkte (TrayTyp, z.B. TypNr, AnzahlZeilen, AnzahlSpalten, xOffsetPos0, yOffsetPos0, xOffset, yOffset) vom Bediener eingegeben und abgespeichert werden kann. Später kann der jeweilige TrayTyp einfach ausgewählt werden.
- Es exisiteren rein theoretisch 500 verschiedene Tray Typen, aufgrund der verschiedenen Bauteile und Variablen.
- Das Rezept sollte nun via HMI aufrufbar sein, und die Steuerung kann sich die entsprechenden Anfahrpunkte (x/y) berechnen (siehe oben - Dein Kommentar)

Ein Problem sehe ich noch.

Nehmen wir an es existieren z.B. 16 Spalten, 36 zeilen, ergibt das 576 Bauteile auf einem Tray.
Es sollen alle Positionen abgefahren werden, erreicht man die 16te Spalte (16tes Bauteil), muss man ja eine neue Zeile anfahren, da die erste Spalte abgearbeitet ist. Das müsste doch auch in dem Code berücksichtigt werden.

Also wenn die letzte entsprechende Spalte erreicht ist, springe in nächste Zeile und fange wieder an bei Spalte 1. (usw.)

Irgendwie müsste man auch eine Art laufende Nummer haben. In diesem Fall IC1-IC567.

Ich hoffe ich konnte mich hier verständlich ausdrucken. Praktisch gesehen, kann ich festlegen, was passieren muss, aber das Problem ist ein intelligenter Code, der dieses "Zähl"+"Ebenen(x-y-)-Problem löst.

Besteht die Möglichkeit, die Umsetzung bzw. fremd zu vergeben. Hast du hier eventuell ein Ansprechpartner oder Tipps.
Vielen Dank im Voraus,

Viele Grüße,
Hubertus Heigl
 
Heinileini hatte ein gutes Beispiel gepostet. Falls du dies zeilenweise durchläufst, könntest du, sobald die Spaltennummer zu groß wird (siehe Fehlerfall) die Spaltennummer auf 0 bzw. 1 (je nach Zählweise) und die Zeilennummer +1 setzen.

Falls du dich in SCL nicht so wohl fühlst, kannst du in FUP auch einfach nur ein einzelnes Netzwerk mit SCL Code einfügen. In diesem Netzwerk führst du dann die Berechnung aus (siehe Beispiel) und den ganzen Rest machst du wie gewohnt in FUP.
 
Ich bin "leider" nur ein Praktiker, und kenne mich nicht nicht aus mit SCL. Alle Programme wurden von mir in FUP geschrieben. Für einfachere Anwendungen ist das auch Problemlos möglich.

Kleine Programme in SCL solltest du aber verstehen können, siehe Heinileinis Beispielcode. So eine Anwendung macht in einer anderen Sprache als SCL keinen Sinn.

Das Zeil ist so definiert:
- Via HMI sollen Rezepte erstellbar und abrufbar sein, in der diese Punkte (TrayTyp, z.B. TypNr, AnzahlZeilen, AnzahlSpalten, xOffsetPos0, yOffsetPos0, xOffset, yOffset) vom Bediener eingegeben und abgespeichert werden kann. Später kann der jeweilige TrayTyp einfach ausgewählt werden.
- Es exisiteren rein theoretisch 500 verschiedene Tray Typen, aufgrund der verschiedenen Bauteile und Variablen.
- Das Rezept sollte nun via HMI aufrufbar sein, und die Steuerung kann sich die entsprechenden Anfahrpunkte (x/y) berechnen (siehe oben - Dein Kommentar)

Achtung, 500 Rezepte könnte die Speicherkapazität deines HMI sprengen! Das könntest du z.B. umgehen, indem du zwei oder mehr Rezepturen/Rezepturverwaltungen machst die jeweils ein Merkmal abspeichern und dir somit die ganzen doppelten Rezepte sparst. Da hilft wohl nur ausprobieren.



Ein Problem sehe ich noch.

Nehmen wir an es existieren z.B. 16 Spalten, 36 zeilen, ergibt das 576 Bauteile auf einem Tray.
Es sollen alle Positionen abgefahren werden, erreicht man die 16te Spalte (16tes Bauteil), muss man ja eine neue Zeile anfahren, da die erste Spalte abgearbeitet ist. Das müsste doch auch in dem Code berücksichtigt werden.

Also wenn die letzte entsprechende Spalte erreicht ist, springe in nächste Zeile und fange wieder an bei Spalte 1. (usw.)

Irgendwie müsste man auch eine Art laufende Nummer haben. In diesem Fall IC1-IC567.

Ich hoffe ich konnte mich hier verständlich ausdrucken. Praktisch gesehen, kann ich festlegen, was passieren muss, aber das Problem ist ein intelligenter Code, der dieses "Zähl"+"Ebenen(x-y-)-Problem löst.

Das lässt sich relativ einfach lösen.

Code:
IF LaufendeNr > AnzahlTeileProZeile THEN
    FOR i = 1 TO AnzahlZeilen DO
        ZielZeile := RestVon ((LaufendeNr - (i * AnzahlTeileProZeile) //<--Befehl fällt mir grade nicht ein. MOD/RND oder so
        IF ZielZeile <= AnzahlZeilen AND ZielZeile >= 1 THEN
             ZielSpalte := i + 1;
             RETURN;
        END_IF;
    END_FOR;
ELSE
    ZielZeile := LaufendeNr;
    ZielSpalte := 1;
END_IF;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
// ZeilenNrn: 0 .. AnzahlZeilen - 1; SpaltenNrn: 0 .. AnzahlSpalten - 1
// laufende Zählung der TrayPlätze 1 .. Tray[lfdTypNr].AnzahlZeilen * Tray[lfdTypNr].AnzahlSpalten
IF lfdPlatzNr < 1 OR lfdPlatzNr > Tray[lfdTypNr].AnzahlZeilen * Tray[lfdTypNr].AnzahlSpalten THEN
    // Fehler lfdPlatzNr
ELSE
    // Positionen berechnen
    SpaltenNr := (lfdPlatzNr -1) MOD Tray[lfdTypNr].AnzahlSpalten;
    ZeilenNr  := (lfdPlatzNr -1) / Tray[lfdTypNr].AnzahlSpalten;  
       // für alternative Zuordnung zwischen lfdPlatzNr und ZeilenNr/SpaltenNr: 
       // SpaltenNr := (lfdPlatzNr -1) / Tray[lfdTypNr].AnzahlZeilen; 
       // ZeilenNr  := (lfdPlatzNr -1) MOD Tray[lfdTypNr].AnzahlZeilen;
    xPos := Tray[lfdTypNr].xOffsetPos0 + SpaltenNr * Tray[lfdTypNr].xOffset;
    yPos := Tray[lfdTypNr].yOffsetPos0 + ZeilenNr * Tray[lfdTypNr].yOffset;
END_IF;
 
Hallo Heinileini, Stoky, RoboticBeet,

Vielen Dank für eure Zeit und Enthusiasmus mein Problem zu durchdenken. Ihr habt sehr viele gute Anhaltspunkte und die Codes verstehe ich eigentlich soweit.

Ich werde versuchen, obiges umzusetzen. Ich freue mich, dass es Leute wie euch gibt, die so einen tollen Support liefern.

Ich werde zu gegeneber Zeit mal ein Update geben :D

Viele Grüße und nochmals Danke,
Hubertus
 
Zurück
Oben