Beiträge von rmac

    Hallo heini0707,


    also eine Funktion dafür kenne ich auch nicht, aber in deiner ursprünglichen Flankenerkennungsmethode hast du was Brauchbares schon (in ähnlicher Form) verwendet. Kann man z.B. so machen:

    Code
    bTest:=(diS10=1);


    D.h. du weist der Variablen bTest den Wert des boolschen/logischen Ausdrucks diS10=1 zu. Ist das Gleiche wie im IF-Befehl...
    Zur besseren Lesbarkeit solltest du aber die vordefinierten Konstanten LOW/HIGH verwenden:

    Code
    bTest:=(diS10=HIGH);


    dann ist das schon auf den ersten Blick erkennbar :zwink:


    Dann habe ich (wiedermal) was zum Klugscheissen :ks: :

    Zitat

    [...]Wie kann ich einem boolschen Operanden den Wert [...] zuweisen [...]


    Operanden nennt man die Beteiligten(!) an einer Operation, in unserem Beispiel wären diS10 und die Konstante HIGH die Operanden bei der Vergleichsoperation mit = als Operator.
    bTest ist aber (nur) eine Variable der ein Wert zugewiesen wird. Würde man also nicht als Operand bezeichnen... :zwink:


    Gruß
    Rainer

    Probier doch aus ob es für deine Zwecke/Belange ausreicht und funzt...
    (unter Beachtung aller Dinge die ich schon in den vorherigen Postings geschrieben habe)


    Wenn du Main() als Endlos-Schleife betreibst und diese lediglich aus den zwei Zeilen besteht, spielt es (fast) keine Rolle welcher Befehl zuerst kommt, es sind dann eigentlich zwei Zeilen die wechselseitig aufgerufen werden, wobei das Problem bleibt, dass eine gedrückte Taste zu Beginn des Programmstarts als steigende Flanke gewertet werden würde, wie in deinem ursprünglichen Ansatz...


    Probieren geht über Studieren (solange du keinen Schrott produzierst...) ;)


    Gruß
    Rainer

    Hallo heini0707,

    Code
    bPosEdge:=(TestDI(diS10) XOR bPrevS10) AND (NOT bPrevS10);
    dovS10:= TestDI(diS10);


    Ab jetzt ist es doch definiert, oder :kopfkratz: ?


    Hmmm, bPrevS10 wird doch dadurch auch nicht definiert , oder ?



    Was ist wenn ich einen virtuellen Ausgang nehme (ist halt besser als Variable da bei Restart auf Null desetzt wird)


    Abhängig von der Startart werden Daten (Variablen etc.) auch auf ihren Initialisierungswert zurückgesetzt (siehe Doku), dafür muß man nicht unbedingt einen (virt.) Ausgang nehmen.



    Nur will ich einen SPS änlichen Aufbau machen und es ist sicherlich möglich (meine ich) :wallbash:.


    jo, das ist es bestimmt.
    Es gibt aber immer (fast) unendlich viele Möglichkeiten ein Programm zu schreiben, jeweils mit jeder Menge kleiner und großer Vor- und Nachteile. Insofern möchte ich es gerne vermeiden, ohne sachgerechte Kenntnis der Anwendung, dir einen Tipp in die falsche Richtung zu geben. Du hast nachher ein Problem und bist sauer weil der Ansatz falsch war...


    Gruß
    Rainer

    Hallo heini07070,


    Wenn du
    bPrevS10 := TestDI(diS10);
    hinter
    bPosEdge:=(TestDI(diS10) XOR bPrevS10) AND (NOT bPrevS10);
    packst, hast du erstmal wieder das gleiche Problem wie bei deiner Lösung:
    bPrevS10 ist bei der ersten Auswertung (bPosEdge:=...) nicht definiert. :???:
    Eine "echte" und verlässliche Zustandsänderung innerhalb bzw. während eines Zyklus kriegst du mit dieser Methode u.U. nicht hin, deswegen ja der Interrupt 8)


    Lass es mich mal mit anderen Worten sagen was die zwei Zeilen da machen:
    um den Tastendruck eines Bedieners damit ermitteln zu können, dürfte der Bediener
    1. die Taste zum Zeitpunkt der Ausführung von bPrevS10 := TestDI(diS10); NICHT drücken und
    2. bei der Ausführung von bPosEdge:=(TestDI(diS10) XOR bPrevS10) AND (NOT bPrevS10); die Taste gedrückt halten, nicht mehr und nicht weniger !!!


    Angenommen die Bedingung 1 ist erfüllt und zwischen der Ausführung dieser beiden Zeilen liegen 10 Sekunden, dann kann dein Anwender in dieser Zeit auf der Taste ein Schlagzeugsolo spielen, solange Bedingung 2 zu diesem Zeitpunkt nicht erfüllt ist, ist es dem Programm völlig wurscht.


    Ich weiß ja nicht genau was mit dem Tastendruck ausgelöst oder unterbrochen werden soll. Da gibt es je nach Anwendungsfall vielleicht auch alternative Programmideen.
    Wenn die Taste z.B. zum Starten/Freigabe eines weiteren Ablaufs verwendet werden soll könnte man das auch so (oder ähnlich) machen:


    WaitDI diS10,0; ! Signal muß erst LOW werden, darf also nicht gedrückt gehalten werden
    WaitDI diS10,1; ! Wenn gedrückt geht's los ...


    Zur Unterbrechung würde ich aber wahrscheinlich wieder einen Interrupt 8) nehmen, aus Sicherheitsgründen...


    Gruß
    Rainer

    Hallo heini0707,


    [...]
    heißt das etwa wenn diS10=1 dann ist es egal welchen Wert bPrevS10 hat :kopfkratz: ?
    [...]


    Das XOR liefert dann TRUE wenn diS10 und bPrevS10 unterschiedliche(!) Werte/Zustände haben, also
    diS10=0 und bPrevS10=1 oder diS10=1 und bPrevS10=0.
    Damit kriegt man raus ob der Signalzustand zwischen der ersten und zweiten Zeile in Main() gewechselt hat, weiß aber noch nicht in welche Richtung (pos/nach oben oder neg/nach unten).
    Wenn der vorherige Zustand (bPrevS10) LOW war und der Zustand gewechselt hat, dann muß die Flanke logischerweise aufsteigend gewesen sein, deswegen das

    Code
    AND (NOT bPrevS10);


    um herauszufinden ob der vorherige Zustand 0/LOW war.


    Wie oben schon gesagt: mit dem XOR kriegst du raus, ob der Zustand zwischen den Zeilen
    bPrevS10 := TestDI(diS10);
    und
    bPosEdge:=(TestDI(diS10) XOR bPrevS10) AND (NOT bPrevS10);
    gewechselt hat.
    Ob das alles so funzt wie gewünscht, hängt natürlich auch stark davon ab ob und was du zwischen diesen Zeilen noch programmierst, bzw. was überhaupt noch im Rest von Main() passiert, deswegen immer noch meine Empfehlung: nimm Interrupt :supi:


    Gruß
    Rainer

    Hallo heini0707,


    hier mal einige Gedanken/Hinweise zu der o.g. Problematik (in Kurzfassung ;)):



    1. Prinzipiell solltest Du für die o.g. Variablen (nFP, nM1) boolsche(=logische=True/False) Datentypen wählen und nicht NUM. Ist erstens nicht im Sinne des Erfinders und zweitens brauchst Du dann nicht ständig auf =0 oder =1 abfragen...


    2. Du willst eine Flanke erkennen, in Deinem Beispiel eine Positive, d.h. einen Übergang(!) von 0 auf 1 (LOW auf HIGH). Wenn ich mal unterstelle, dass die Variable nFP (FP=Flanke Positiv ?) diesen Zustandsübergang(!) speichern soll, wird das aber nicht funzen wenn der Signaleingang diS10 beim Start von Main() bereits HIGH ist. Dann wird nämlich nFP:=1 d.h. eine positive Flanke signalisiert, obwohl ein Übergang LOW auf HIGH nie(!!!) stattgefunden hat (diS10 war ja möglicherweise vorher nie 0 bzw. LOW).
    :ks:


    3. Wenn es denn unbedingt sein müsste, könnte man das auch etwa so programmieren (ungetestet, ohne Gewähr!)


    Wenn nur eine Flankenart gebraucht wird kann natürlich der andere Teil entfallen.
    Der Nachteil dieser Methode bleibt allerdings gleich: kurze Impulse werden u.U. nicht oder nur unzuverlässig erkannt!


    4. Wie bereits gesagt, die beste Methode bleibt der Interrupt. Flanken werden hierbei deutlich schneller und zuverlässiger per Hardware erkannt, der Aufwand geht allerdings auch über einen simplen Dreizeiler hinaus...


    Gruß
    Rainer

    Hallo heini0707,


    also ich würde versuchen so etwas über einen Interrupt zu lösen. Die sind nämlich genau für solche Anwendungen gedacht (u.a.)...


    Lies Dir doch mal zu diesem Thema die Doku durch, ansonsten (bei Problemen) melde Dich nochmal.
    Habe im Augenblick aber nur wenig Zeit zum Schreiben :(


    Gruß
    Rainer

    Hallo mani,


    Also datenmäßig kannst du prinzipiell alles empfangen was nicht bei drei auf den Bäumen ist, sind eh alles nur Bits und Bytes... 8)
    Die Frage ist vielmehr wie du und die Gegenstelle diese Daten interpretierst.


    Vorzeichenbehaftet Ganzzahlen (Integer) werden fast ausschließlich im Zweierkomplement gespeichert/verwendet/berechnet/bla...
    Grundlagen hierzu findest du unter: http://de.wikipedia.org/wiki/Zweierkomplement


    Solange du nur mit einem Byte (0-255) arbeitest, sieht das also folgendermaßen aus:
    Bin.       Dez.    Zw.-Kompl.11111111 = 255 =   -111111110 = 254 =   -211111101 = 253 =   -3...10000001 = 129 = -12710000000 = 128 = -12801111111 = 127 =  127...00000001 =   1 =    100000000 =   0 =    0
    Vorausgesetzt die Gegenstelle schickt dir die Daten im Zweierkomplement (!) und du willst lediglich mit einem Byte arbeiten, mußt du das empfangene Byte entsprechend umrechnen, da die ReadBin-Funktion (laut Doku) nur eine positive Ganzzahl als NUM liefert.
    Für die Umrechnung könntest du die Bit-Funktionen verwenden, die sind allerdings nur in der (kostenpflichtigen) Software-Option "Developer's Function" enthalten (glaub ich).


    Bei Byte-Daten sollte es aber auch ausreichen vom Absolutwert 256 abzuziehen, wenn dieser >= 128 ist.
    Sieht dann in etwa so aus:

    Code
    nVal := ReadBin(channel);
    if nVal >= 128 nVal := nVal - 256;


    Bei größeren Zahlenbereichen muß du das Konzept entsprechend erweitern.
    Viel Spaß dabei.... :mrgreen:


    Gruß
    Rainer

    Kein Ahnung ob's so was schon gibt, aber ich treib mich auch nicht maschinenbaumäßig rum...


    Ich stell mir das vom Arbeitsprinzip so ähnlich wie ein Rüttler/Schwingförderer vor, der in "Mikroschritten am Rad dreht"... :mrgreen:
    Frage ist ob's überhaupt funzt... :?:


    Gruß
    Rainer

    Hallo,


    schonmal drüber nachgedacht,
    - den Impuls per Elektromagnet zu erzeugen, oder
    - einen Greifer mit Stellmotor zu bauen, der sich quasi über das Ventil stülpt und so an Leitung oder Ventil arretiert, dass das Gegenmoment an Ventil/Leitung/Wand/... übertragen wird ?


    Gruß
    Rainer

    ...obwohl mich auch wundert warum das bei 300 nicht funzt, ist ja doch schon volle Pulle...


    Im ersten Posting hast du geschrieben, dass der bei tool0 nicht aussteigt (?)


    tool0 ist mit einer Masse von 0,001kg angegeben.
    Hast du mal versuchsweise die Masse deines Tools bzw. die Verfahr-Geschwindigkeit verringert ?
    Ändert sich da was ?
    Was ist das für ein Werkzeug ? Ein Greifer der noch weitere Last trägt ?
    Wenn ich das Lastdiagramm für den 140 richtig verstehe, hast du bei deinen Werkzeugdimensionen/-gewicht nicht allzuviel Spielraum für weitere Lasten.


    Hab gerade mal die Doku überflogen, aber nichts bzgl. Einstellungen für hängende Montage gefunden. Laut Datenblatt ist der 140 auch für hängende Montage geeignet, d.h. es gibt dafür keine Spezialausführung.
    Also weiterhin .... :kopfkratz:


    Gruß
    Rainer

    Hi,


    wäre schon vorstellbar, da die Steuerung ja nicht weiß, dass die Schwerkraft in die andere Richtung wirkt. :huh:
    Was sagt denn die Doku dazu ?
    Ich hatte so einen Fall noch nicht, weiß garnicht ob man dazu was einstellen kann/soll/muß.


    Gruß
    Rainer

    Hallo hanes@w,


    ja, genau, deswegen meine Frage... ich hatte mich auch schonmal damit vertan :pfeif:


    Also 100 heißt "normal", je höher der Wert, desto "unempfindlicher" wird die Überwachung bzw. "härter" wird verfahren.
    Wie du schon bemerkt hast, mußt du in deinem Fall den Wert also auf > 100 erhöhen damit der in der Überwachung nicht aussteigt.
    In der Doku steht, man sollte diese Wert ggfls. schrittweise in 30% Schritte erhöhen, aber ich würde mich da mit etwas kleineren Werte rantasten.


    Desweiteren hab ich auch irgendwo gelesen, dass die Standzeit des Roboters darunter leidet wenn man über "normal" fährt, was ja durchaus einleuchtet, da die mechanische Belastung und der Verschleiß damit auch größer als "normal" ist.
    Unter diesen Umständen ist es vielleicht auch ratsam die Bewegungsüberwachung nur während der kritischen Bewegungen mit der MotionSup-Instruktion einzustellen und sonst auf dem normalen Wert zu belassen. Auf der S4C ist das allerdings eine kostenpflichtige Softwareoption, ich meine mich aber daran erinnern zu können, dass das bei der IRC5 standardmäßig dabei ist (?)


    Gruß
    Rainer

    Hallo,


    also ich würde eine (sägenunabhängige) Routine zum eigentlichen Sägen schreiben, der das jeweilige Werkobjekt als Parameter übergeben wird:

    Code
    PROC Saegen(PERS wobjdata woSaege)
        ...
        Move... pos,spd,fine,tool\WObj:=woSaege;
        ...
      ENDPROC


    Wenn sich alle Bewegungen innerhalb des Sägevorgangs auf das übergebene Werkobjekt beziehen, brauchst du ja auch nicht für jede Säge einen Startpunkt zu definieren, sondern beziehst dich auf einen Startpunkt relativ zum Werkobjekt. Der gilt dann gleichermaßen für alle Sägen, vorausgesetzt es sind auch alle Werkobjekt gleich erreichbar, wie Werner schon angedeutet hat!


    In jedem Fall wichtig ist eine vernünftige HomePosition außerhalb der Arbeitsbereiche der anderen Einheiten (Sägen, Vision), in die der Roboter zum Service sicher verfahren kann, oder auf Kommandos wartet, etc.......


    Gruß
    Rainer


    [...]Also machen das manche Roboter so,
    dass sie mit zu grossen Achsgeschwindigkeiten aussteigen
    andere begrenzen die Geschwindigkeiten so, dass sie nicht
    aussteigen. Aber die Geschwindigkeit ist eigentlich nicht mehr
    programmtechnisch sauber kontrollierbar.[...]


    Gut, das mag ja alles so sein, hängt aber von der jeweiligen Möglichkeiten/Implementierung der Steuerung ab. Wie schon gesagt, von KUKA habe ich leider keine Ahnung. :bawling:
    Hierzu aber mal ein kurzer Auszug aus der ABB-Doku zu diesem Thema:

    Zitat

    [...]The orientation of the tool remains constant during the entire movement unless a
    reorientation has been programmed. If the tool is reorientated, it is rotated at constant
    velocity. A maximum rotational velocity (in degrees per second) can be specified when rotating
    the tool. If this is set to a low value, reorientation will be smooth, irrespective of the
    velocity defined for the tool centre point.[...]



    [...]Wenn jetzt der TCP auf einer Stelle steht, dann liegen alle drei
    Punkte auf den selben Koordinaten. Da kann beim besten
    Willen keine Kreisbahn berechnet werden.[...]


    Jo, da gebe ich dir Recht, das wird so nicht funzen :uuups_blau:


    Wie wäre es denn ein Werkobjekt in der Mitte des Loches zu definieren, per Programm das gesamte Werkobjekt um Z rotieren und dabei mit dem Werkzeug zu folgen ?
    Wenn ich ein bisschen Zeit hab, dann probier ich das mal in der ABB-Simulation....


    Gruß
    Rainer


    [...]Denn das Problem der ganzen Lösungsvorschläge ist, dass da der
    TCP quasi immer auf ein und der selben Stelle 'steht'.
    Da kommt man weder mit Linear- noch mit Kreisbewegungen weiter.
    Denn der TCP steht ja. Wo soll da eine Kreisbewegung herkommen?[...]


    Die Bewegung kommt halt dadurch, dass sich die Orientierung ändert, nicht notwendigerweise der TCP:
    Stell dir mal vor du sitzt mit deiner vierköpfigen Familie am Sonntagmorgen an eurem kreisrunden Frühstückstisch. Weil ihr ganz sparsame Schwaben seid, teilt ihr euch ein Frühstücksei welches in der Mitte des Tisches steht. Gegessen wird mit einem Löffel, der immer reihum von einer Person zur Nächsten weitergegeben wird. Dabei bleibt die Position des Eis (oder heißt das dann Eies ?) immer an der gleichen Stelle, nur die Orientierung des Löffels ändert sich und der Löffelstiel beschreibt dabei eine Kreisbahn um das Ei.
    :genau:
    Gruß
    Rainer

    ...nochmal zum Verständnis:


    also wie ich das sehe, muß
    1. der TCP zentrisch über dem Loch positioniert werden


    2. während der "Bohr/Entgratbewegung" wird der TCP zum Loch hin abgesenkt (Z), verändert aber bzgl. der Lochmitte seine Position nicht


    3. das Werkzeug wird kreisförmig um den TCP herumgeführt (wobei sich also lediglich die Werkzeug-Orientierung ändert, nicht die TCP-Position!)


    4. der Bewegungsablauf des Werkzeuges beschreibt dabei den Mantel eines, mit der Spitze nach unten zeigenden Kegels, mit dem TCP als Kegelspitze


    5. ich würde das eher als "Rühren" statt "Pendeln" bezeichnen :roll:


    Wenn das soweit alles richtig ist, dann kann ich dir leider keine konkreten Programmieranweisungen geben, da ich von KUKA überhaupt keine Ahnung habe :icon_rofl: aber wie wäre denn folgender Ansatz:


    - erste Position/Orientierung teachen mit 1° "Schräge" nach einer Seite
    - TCP beibehalten (!) und zur gegenüberliegenden Seite mit 1° abkippen (= 2° Rotation im Werkzeug-Koord.-System)
    - zweite Position/Orientierung teachen
    - mit Kreisinterpolation (müsste es ja wohl bei KUKA geben :lol:) zwischen den beiden Orientierungen wechselseitig verfahren


    Weiß zwar nicht ob's geht, aber ich denke bei ABB würde ich das schon so (oder ähnlich) hinbekommen.... :beerchug:


    Gruß
    Rainer