Beiträge von scheff

    Hallo,


    wie heisst eigentlich der ENUM-Typ fuer den Parameter CaseSens, der bei StrComp und StrFind verwendet wird?
    In meiner Doku (KSS 5.5 V1.1) stehen leider nur die Werte #CASE_SENS, #NOT_CASE_SENS.
    Falls man die CaseSensitivity per Variable uebergeben will, sollte man den Typ wissen...


    Ganz nebenbei:
    Welchen Wert hat eigentlich der erste Aufzaehler in einer Aufzaehlung, i.e. ist #CASE_SENS = 0 (wie z.B. bei C und C++) oder 1?
    Im KRL-Programm ist es eigentlich egal, aber wenn man den Wert per CWrite oder CAST_TO rausschreibt, ist es relevant.


    Gruss, Dirk.

    Hallo,


    dort, wo ich bisher Programmnr. oder aehnliches gesehen habe, die per Ports/SIGNAL uebergeben wurden, gab es immer noch einen Extra-Port fuer die Gueltigkeit.
    Also etwa so:


    Code
    SIGNAL NR_VALID $IN[70] ; TRUE ... NR ist angelegt und gueltig
    SIGNAL NR $IN[71] TO $IN[74] ; 4-Bit-Integer
    INT aNR
    ...
    WAIT FOR NR_VALID
    aNR = NR


    Meist folgt dann noch eine Bestaetigungs-Ausgabe per $OUT-Port, damit die Gegenstelle (also z.B. die SPS) "weiss", dass die angelegte Zahl verarbeitet wurde und wieder geaendert werden kann. Diese wiederum loescht dann als erstes den Gueltigkeits-Port, so dass NR_VALID wieder FALSE wird.


    Gruss, Dirk.


    P.S.: Meine Schreibtischlampe flackert auch. Die ist wohl kaputt... ;)

    Hallo,


    1. Wenn eine Funktion mit ENDFCT abgeschlossen wird, sollte sie auch als solche definiert sein. Da hat sich Dirk aber sicher nur vertippt.


    In der Tat - Tippfehler. Es muss natuerlich END heissen.



    2. Wenn die Variable POSi in der Funktion deklariert wird, ist sie nur dort gültig. Wenn die Funktion beendet ist, verliert sie ihre Gültigkeit und kann nicht weiter verarbeitet werden. Zudem bin ich mir nicht sicher, ob das Programm so überhaupt kompiliert werden kann, da beim Aufruf der Funktion die mit Call by Reference referenzierte Variable noch nicht bekannt ist. Ich würde sie deshalb ebenfalls in der .dat deklarieren.


    Da haben wir uns evtl. missverstanden.
    POSi ist der formale Parameter in SetPos, der Call-By-Reference uebergeben werden soll.


    Also z.B. so:


    Code
    DECL POS aPos;
    ...
    aPos = {POS:X 1.1,Y 1.2,Z 1.3, A 0.0,B 45.0,C 90.0}
    SetPos(aPos, 1, 1, 17)


    oder alternativ so:


    Code
    SetPos({POS:X 1.1,Y 1.2,Z 1.3, A 0.0,B 45.0,C 90.0}, 1, 1, 17)


    Der koennte eigentlich auch als :IN vereinbart werden, aber als "alter" C/C++-Programmierer weiss ich natuerlich, dass man Speicher und Zeit sparen kann, wenn man groessere Datenstrukturen (die in der Funktion/Prozedur nicht geaendert werden) als :OUT (also call-by-reference, sprich: per Speicher-Adresse) uebergibt.


    Das DECL mag an der Stelle falsch sein. Das liegt daran, dass ich bis heute leider nicht verstanden habe, wann man es genau verwenden muss.
    Das Handbuch ist leider auch ueberhaupt nicht hilfreich dabei. In meinen Beispielquellen habe ich es teils so und teils so gefunden.
    Daher habe ich fuer mich beschlossen, dass DECL ein Relikt ist, dass man verwenden kann aber nicht muss.
    Fuer Er-/Aufklaerung bin ich natuerlich (wie immer) sehr dankbar.


    Da ihr (wie ich inzwischen feststellen konnte) groesstenteils ausgemachte Pragmatiker seid, und die Datenlisten aus irgendwelchen CAD-Tools bezieht, koennte man diese SetPos-Prozedur u.U. auch einfach ersatzlos streichen.
    GetPos() sollte man uebrigens direkt ueberall dort verwenden koennen, wo urspruenglich die Variable stehen sollte.


    z.B. so:


    Code
    PTP GetPos(1, 2, 27)


    oder so:


    Code
    FOR I1 = 1 TO 3
      FOR I2 = 1 TO 2
        FOR I3 = 1 TO 350
          PTP GetPos(I1,I2,I3)
        ENDFOR ; I3
      ENDFOR ; I2
    ENDFOR ; I1


    Gruss, Dirk.

    Hallo Stefan,



    Felder vom Datentyp POS können ja nur 906 Elemente enthalten, also:

    Code
    DECL POS Test1Pos[906]         ; Maximum = 906 Elemente (gesamt)
    DECL POS Test2Pos[2,453]       ; Maximum = 906 Elemente (gesamt)
    DECL POS Test3Pos[2,2,226]     ; Maximum = 906 Elemente (gesamt)


    Kann diese maximale Anzahl erhöht werden?
    Problem ist, dass wir in der 1. Dimension statt 2 -> 3 haben sollten.


    Da hilft dann wohl nur zerlegen, vielleicht so:


    .dat-Datei:

    Code
    DECL POS Pos1[2,350]
    DECL POS Pos2[2,350]
    DECL POS Pos3[2,350]


    .src-Datei:


    Aber, das hast Du Dir wahrscheinlich schon selbst so ueberlegt.


    Gruss, Dirk.

    Hallo,


    schau mal ins Handbuch, wo die ganzen Systemvariablen aufgelistet sind. (Neulich hat die hier auch jemand als PDF reingestellt.)
    Dort gibt es u.a. eine Variable $PRO_NAME1.
    Moeglicherweise steht da drin, was Du suchst.


    Gruss, Dirk.

    Hallo,


    verstehe ich das richtig, das LIN- und CIRC-Befehle nur mit kartesischen Koordinaten aufgerufen werden duerfen?
    Keine Joint-Koordinaten (Achswerte)?
    Ist das auch so, wenn man das Programm nicht mit dem Programmiergeraet, sondern einem Texteditor schreibt?
    (Soll heissen, ist das Programmiergeraet oder sind die Befehle selbst limitiert?)


    Sicher gibt es gute(/praktische) Gruende dafuer, aber rein mathematisch ginge beides.
    Nebenbei habe ich es tatsaechlich beim (japanischen) Wettbewerber schon anders gesehen.


    Gruss, Dirk.

    Hallo LindePaul,



    lokale Variable im UP werden schon auf den Stack gelegt.
    Im Grunde ist es daher möglich reentrant zu sein (nur lokale Vars).
    Es muss aber auf die Schachteltiefe geachtet werden.
    Bei so einer komplizierten Programmstruktur (interrupts prios, reentrant, globale Variablen,..) muss der Programmierer sehr sorgfältig sein (Zähler einbauen, Interrupts sperren, Flags setzen,..) um den Komplex in den Griff zu bekommen.


    Da stimme ich uneingeschraenkt zu.
    Interrupts sind schon ein Ding fuer sich, sollten aber zumindest den Interpreter anhalten, waehrend sie laufen.
    Bei dem Submit bin ich mir nicht so sicher. Das koennte ja nebenlaeufig sein.



    Besser wäre es aber, komplexe Anforderungen in einfachere Schritte aufzulösen.


    Genau: kleine Dienstfunktionen, die man ueberall brauchen kann und aufruft, naemlich sowohl aus dem Hauptprogramm, als auch aus dem einen oder anderen Interrupt, oder aus dem Submit-Programm. Wenn diese dann nicht reentrant sind, muessten Sie (z.B. per Semaphor) gegen gleichzeitiges/mehrfaches Aufrufen geschuetzt sein. Entweder ist das im System enthalten, oder muss durch den Nutzer realisiert werden. (Letzteres ist u.U. gar nicht so einfach.)


    Da es offensichtlich einen Stapel fuer die lokalen Variablen gibt, denke ich, dass die Reentranz letztendlich vom programmierten Code abhaengt. (Schreib-Zugriffe auf globale Variablen sind z.B. potenziell gefaehrlich, wie auch Bewegungsbefehle, und im Prinzip alles, was die sogenannte Lokalitaet des Effekts nicht gewaehrleistet.)


    Eine Frage habe ich aber noch:
    Wenn Funktionen reentrant sind, warum ist dann Rekursion verboten?
    (Kuka's mangelndes Vertrauen in die Kompetenz der Anwendungs-Programmierer?) ;)


    Gruss, Dirk.

    Hallo,



    Hab schonmal sowas gemacht - Aufruf des eigenen UP's aus nem UP - hat aber sofort nen Stapelüberlauffehler gegeben.
    War bereits vor Aufruf in der Schachtelungstiefe 4 und bei ca 10 ist beim KUKA schon Schluß.


    Dazu das Handbuch (KR C1 R2.2):
    "Von einem Unterprogramm bzw. einer Funktion aus koennen weitere Unterprogramm und/oder Funktionen aufgerufen werden. Die hierbei zulaessige Schachtelungstiefe ist 19. Darueber hinaus erfolgt die Fehlermeldung "UEBERLAUF PROGRAMMSCHACHTELUNG". Der rekursive Aufruf von Unterprogrammen oder Funktionen ist nicht erlaubt."


    Das deutet darauf hin, dass lokale Variablen nicht auf einem Stapelspeicher angelegt werden,
    und wenn das so ist, dann sind Unterprogramme und Funktionen nicht reentrant.


    Gruss, Dirk.

    Hallo,


    hier mal eine Frage an die Spezialisten: ;)


    Laut Handbuch ist der rekursive Aufruf von Funktionen verboten.
    So dachte ich, dass in Ermangelung von Rekursionen Funktionen (/Unterprogramme) auch nicht re-entrant zu sein brauchen.
    Nun, da ich Interrupts und Submit-Programme in mein Gedankenmodell mit einbezogen habe, ist mir die Frage mit der Re-entranz wieder "auf die Fuesse" gefallen. Da koennte ja doch mal eine Funktion(/ein Unterprogramm) aufgerufen werden, die(/das) der unterbrochene (Interrupt) oder laufende (Submit) Haupt-Interpreter bereits "betreten" hat.
    Wie ist denn das? Gibt's da dann Zahlensalat, oder haben sie sich bei Kuka dafuer was spezielles ausgedacht?


    Gruss, Dirk.


    P.S.: Was ist eine reentrante Funktion: steht kurz und knackig unter http://de.wikipedia.org/wiki/Eintrittsinvarianz.

    Hallo,



    aber was mich nur wunder das ich es so schon versucht habe
    ...
    und es so nicht funktioniert hat.


    Es sollte funktionieren.


    Wenn es vorher nicht ging, lag's wahrscheinlich nicht an der OR-Verknuepfung der IF-Ausdruecke.
    Vielleicht hast Du irgendeine andere Kleinigkeit uebersehen, die Du dann beim weiteren Probieren womoeglich korrigiert hast, ohne es zu merken. Solche Situationen habe ich schon oefter erlebt, und am Anfang fand ich das ganz schoen angsteinfloessend seltsam. Wenn's jetzt funktioniert, vergiss die Sache einfach.


    Gruss, Dirk.


    P.S.: Ein Kumpel von mir hat mal gesagt: "Der Computer macht immer genau, was man ihm sagt. Das Problem dabei ist, das wir dem Computer nicht immer genau das sagen, was wir eigentlich meinten."


    P.S.2: Woanders habe ich das sogar noch kuerzer gelesen: "Das (Software-)Problem sitzt vor dem Bildschirm." ;)


    PorscheRobAdmin kann's vielleicht. Meine Quelltexte kann ich nicht senden, weil ich die von Kunden erhalten habe, und Geheimhaltung (bei Androhung von Strafe) schwoeren musste. Ich werde aber bei Gelegenheit beim Verursacher nachfragen, und die Sache dann aufklaeren.
    Mir faellt's immer nicht ganz leicht, zu unterscheiden, ob was kunden-spezifisch ist, oder einfach nur nicht in den Handbuechern steht, die mir zur Verfuegung stehen. Die Sache mit den Technologie-Paketen muss ich mir auch erst noch aneignen, die habe ich bisher immer ueberblaettert. Meine Arbeits-Tage sind einfach zu kurz... :(


    Gruss, Dirk.

    Hallo,


    was mir noch dazu einfaellt:


    Die Zeilenlaenge ist begrenzt, was im Beispiel aber noch nicht zutreffen duerfte.
    Den IF-Ausdruck ueber mehrere Zeilen zu verteilen, ist nicht erlaubt. (Der Interpreter ist wohl zeilen-orientiert, und Zeilenumbrueche scheint's keine zu geben.)
    Man kann aber die Einzelausdruecke vorher in einer Hilfsvariablen berechnen, und dann diese testen.
    Z.B. so:

    Code
    DECL BOOL Ueberlauf = FALSE
    ...
    Ueberlauf = (MESSWERT_1_Y > 0.7) OR (MESSWERT_1_Y < -0.7)
    Ueberlauf = Ueberlauf OR (MESSWERT_2_Y > 0.7) OR (MESSWERT_2_Y < -0.7)
    IF Ueberlauf THEN
      ABLEGEN_RE ()
      RECHNEN ()
      GOTO STA
    ENDIF


    Gruss, Dirk.

    Code
    IF (MESSWERT_1_Y > 0.7) OR (MESSWERT_1_Y < -0.7) OR (MESSWERT_2_Y > 0.7) OR (MESSWERT_2_Y < -0.7) THEN
    ABLEGEN_RE ()
    RECHNEN ()
    GOTO STA
    ENDIF


    Ganz nebenbei: Anstaendige Programmierer vermeiden GOTO. ;)


    Gruss, Dirk.

    Hallo,


    nach den Regeln der Programmierkunst werden ueblicherweise Bezeichner erst im lokalen Scope aufgeloest, und dann (aufsteigend) in den globaleren Scopes.
    D.h. in USER_INIT wird auf das Prozedur-Arg. Test zugegriffen. Die globale Var. Test in der .dat-Datei sollte "eclipsed" (nicht zugreifbar) sein, solange eine lokale Var./Arg. mit dem gleichen Namen existiert.
    Mit der Aufloesung des Variablenbezeichners ist (im Interpreter) die Bestimmung der Speicheradresse der Variablen verbunden.
    Globale und lokale Var. haben immer getrennte Speicheradressen. (Ausnahme: Argumente, die call-by-reference - also mit :OUT - vereinbart wurden.) Daher kann der Wert der globalen Variablen in der lokalen nicht auftauchen, solange nicht eine entspr. Zuweisung stattgefunden hat.


    In meinem (etwas aeltlichen) Handbuch steht uebrigens dazu:
    "In lokalen Unterprogrammen bzw. Funktionen sind alle im Hauptprogramm deklarierten Variablen bekannt, sofern sie nicht im Unterprogramm bzw. in der Funktion noch einmal unter dem selben Namen deklariert wurden."


    Gruss, Dirk.

    Hallo,


    bei dem Design von Status und Turn ging es wahrscheinlich KUKA weniger um eine mathematisch voellig redundanzfreie Beschreibung, und mehr um eine pragmatische Hilfe um ueber die Singularitaeten hinwegzukommen. Da mag einiges ueberbestimmt sein.


    Aber das koennen Dir die Cracks bestimmt noch viel besser erklaeren.


    Gruss, Dirk.

    Hallo LindePaul,


    danke fuer die hilfreiche Antwort.


    So in etwa hatte ich mir das schon gedacht.


    Nebenbei: Schrecklich sind fuer mich alle Dinge, die ueberraschend in Quelltexten auftauchen, aber nirgends im Handbuch stehen, weil nicht dokumentiert, eigentlich schon veraltet, oder aus sonstigen Gruenden.
    Vielleicht liegt's aber auch daran, dass ich einfach nur schwache Nerven habe... ;)


    Gruss, Dirk.

    Hallo,


    Sind die Datei-Endungen bindend fuer die Verwendung der Dateien, oder eher eine Konvention?


    Soll heissen:
    Darf man
    - DEF/DEFFCT auch in .dat-Dateien
    - DEFDAT auch in .src-Dateien
    verwenden?


    Soweit ich weiss, bestimmt der Compiler die oeffentliche (globale) Hauptprozedur(/-funktion?) eines Moduls anhand der Uebereinstimmung des Prozedurnamens mit dem Dateinamen.
    Ausserdem werden in Dateien mit anfuehrendem Dollarzeichen im Dateinamen alle Symbole (Typ-/Variablen-Bezeichner) global.


    Weiss jemand mehr darueber?


    Gruss, Dirk.

    diese Befehle dienen zur Kommunikation über Kommandokanäle (z.B. serielle Schnittstelle). Es existiert dazu eine gesonderte Dokumentation.


    Sowas dachte ich mir schon. (Nur hatte ich bei Praefix "C" auf "Console" getippt. "Command" macht aber eigentlich sogar noch mehr Sinn.) ;)


    Der SWRITE-Befehl erinnert mich sehr stark an das sprintf() aus der C-Standard-IO-Bibliothek. Ich nehme mal an, bei KUKA programmieren sie auch in C oder C++. Das hiesse dann, man kann die Verwendung des Format-Strings in jedem "gut-sortierten" C-Programmier-Handbuch nachlesen.


    Gruss, Dirk.


    P.S.: Dok. zu sprintf findet man im Internet, z.B. hier:
    http://www.gnu.org/software/li…put.html#Formatted-Output

    Hallo PorscheRobAdmin,


    helfen kann ich Dir leider auch nicht, aber ich haette noch ein paar weitere Funktionen/Befehle im Petto, mit denen ich auch nicht so recht was anfangen kann.
    Das Handbuch habe ich schon durchforstet. Entweder habe ich die richtigen Seiten ueberschlagen, oder es steht nicht drin. (Wahrscheinlich letzteres, denn im Index ist auch nichts zu finden...)


    CRWRITE
    CREAD
    COPEN
    CCLOSE
    SWRITE
    ERR_CLEAR
    ERR_RAISE
    SET_KRLMSG
    CLEAR_KRLMSG
    EK
    LK
    EB
    SYNCCMD
    REMOTECMD


    Gruss, Dirk.

    Hallo,


    voller Schrecken habe ich heute in einem Programm eine E3POS-Struktur entdeckt.
    Noch schlimmer, entspr. E3POS-Variablen werden dann auch z.B. in PTP-Befehlen verwendet. Laut meinem Handbuch gibt's die gar nicht, aber ich habe sie hier im Forum in Zusammenhang mit KRC32 gesehen.
    Es scheint, E3POS wird immer noch unterstuetzt, wenn auch nur heimlich...


    Gruss, Dirk.