Regler als SPS.SUB während einer Bewegung

  • Hallo alle zusammen,


    habe wieder mal ein Problemchen!


    und zwar geht es um SPS.SUB, ich habe einen Regler programmiert, der während der Bewegung "CIRC" regeln soll(nicht die Bewegung selbst, sondern was anderes, aber während der Fahrt kontrolliern), vor der Bewegung stratre ich Regler.SUB, der startet auch(alles in LOOP eingesetzt), läuft aber nicht im hintergrund, sondern andauernd und macht die Bewegung nicht(kehrt nicht zurück zum programm)! Nach der Bewegung soll der Regler(Sub) wieder deaktiviert werden, wenn ich das richtig verstanden habe, so wurde dies genau für solche zwecke entwickelt, oder?


    mfg ___xyz___

  • Schritt für Schritt zum Roboterprofi!
  • REGLER.SUB
    ===============================================================
    DEF Regler( )
    DECLARATIONS
    USER DECL
    SIGNAL SENSOR1 $ANIN[1] ; TRIANGULATION SENSOR
    ;=========== Vorschub ===============
    SIGNAL INK_GEB_VORSCH_L $IN[433] TO $IN[440]; Unterer BIT
    SIGNAL INK_GEB_VORSCH_H $IN[425] TO $IN[432]; Oberer BIT
    ;=========== Antrieb ================
    SIGNAL INK_GEB_ANTR_L $IN[489] TO $IN[496]; Low BYTE
    SIGNAL INK_GEB_ANTR_H $IN[473] TO $IN[480]; High BYTE
    ;========== DEKLARATION =============
    DECL SIGINF VORSCHUB ; INFO UEBER VORSCHUBSPANNUNG
    DECL REAL ISTWERT, SOLLWERT, ABWEICHUNG, ABWEICHUNG_ALT, IST, SOLL
    DECL INT STARTWERT_ANTR, ENDWERT_ANTR
    DECL INT STARTWERT_VORSCH, ENDWERT_VORSCH
    DECL REAL SUMME, Ta, Kp, Ki, Kd ; PID_Regler Faktoren
    DECL REAL STELLGROESSE, GRUNDSTELLUNG;
    DECL REAL ANTR_MOTOR, POSITION_NEU
    DECL REAL SENSOR_WERT, ABSTAND, RADIUS, DURCHMESSR, UMFANG, VERHAELTNIS


    INI
    USER INIT
    VORSCHUB = GET_SIG_INF("$ANOUT[2]"); INFO ZUWEISEN
    SENSOR_WERT = SENSOR1 * 10
    POSITION_NEU = 0
    GRUNDSTELLUNG = 0.5
    ISTWERT = 0
    SOLLWERT = 0
    ABWEICHUNG_ALT = 0
    ABWEICHUNG = 0
    SUMME = 0
    Ta = 6; Abtastzeit
    Kp = 0.005;P-Anteil,Die Werte sind nicht angepasst
    Ki = 0.005; I-Anteil
    Kd = 0.005; D-Anteil, wird am anfang auf null gesetzt
    STELLGROESSE = 0


    LOOP
    USER PLC


    ;=========================================
    ;=========== REGELUNGSSCHLEIFE ===========
    ;=========================================
    $TIMER[4] = 0
    $TIMER[5] = 0
    ;=========== Wertermitlung Vorschub =====
    $TIMER_STOP[4] = FALSE
    STARTWERT_VORSCH = INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L
    ENDWERT_VORSCH = 100 + STARTWERT_VORSCH
    IF ENDWERT_VORSCH > 65535 THEN
    ENDWERT_VORSCH = ENDWERT_VORSCH - 65536
    ENDIF
    IF ENDWERT_VORSCH > INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L THEN
    WAIT FOR ENDWERT_VORSCH <= INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L
    ELSE
    IF ENDWERT_VORSCH < INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L THEN
    WAIT FOR ENDWERT_VORSCH > INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L
    WAIT FOR ENDWERT_VORSCH <= INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L
    ENDIF
    ENDIF
    $TIMER_STOP[4] = TRUE
    SOLL = $TIMER[4]; Sollwert kommt von der Vorschubrolle
    SOLLWERT = (100 / SOLL); * 100
    ;============ Wertermittlung Antrieb =====
    $TIMER_STOP[5] = FALSE
    STARTWERT_ANTR = INK_GEB_ANTR_H * 256 + INK_GEB_ANTR_L
    ENDWERT_ANTR = 100 + STARTWERT_ANTR
    IF ENDWERT_ANTR > 65535 THEN
    ENDWERT_ANTR = ENDWERT_ANTR - 65536; endwert wird neue gesetz
    ENDIF
    IF ENDWERT_ANTR > INK_GEB_ANTR_H * 256 + INK_GEB_ANTR_L THEN;
    WAIT FOR ENDWERT_ANTR <= INK_GEB_ANTR_H * 256 + INK_GEB_ANTR_L
    ELSE
    IF ENDWERT_ANTR < INK_GEB_ANTR_H * 256 + INK_GEB_ANTR_L THEN
    WAIT FOR ENDWERT_ANTR > INK_GEB_ANTR_H * 256 + INK_GEB_ANTR_L
    WAIT FOR ENDWERT_ANTR <= INK_GEB_ANTR_H * 256 + INK_GEB_ANTR_L
    ENDIF
    ENDIF
    $TIMER_STOP[5] = TRUE
    IST = $TIMER[5]; Istwert ist die Antriebsrolle
    ISTWERT = (100 / IST); * 100
    ;=========== DATEN ==================
    ABSTAND = (300/10*SENSOR_WERT)+50; in mm
    RADIUS = 299 - ABSTAND; 299mm ist der abstand zwisch. sensor und Mit.punkt der CFK-Rolle
    UMFANG = 2 * Radius * 3.1415
    VERHAELTNIS = UMFANG / 651.36 ; 651,36 = 195.41 * (10/3)
    ;=========== ABWEICHUNG BERECHNUNG =================
    ABWEICHUNG = SOLLWERT - (ISTWERT * VERHAELTNIS); Abweichung ermitteln
    ;=========== ITEGRALTEIL MIT BEGRENZUNG ====
    SUMME = SUMME + ABWEICHUNG; Integrieren(Aufsummieren)
    IF SUMME > 100 THEN
    SUMME = 100
    ENDIF
    IF SUMME < -100 THEN
    SUMME = -100
    ENDIF
    ;=========== PID-REGLER ================
    STELLGROESSE = (Kp * ABWEICHUNG + (Ki * Ta * SUMME) + Kd * ((ABWEICHUNG - ABWEICHUNG_ALT)/Ta))/1; PID-Regler
    ABWEICHUNG_ALT = ABWEICHUNG ; Abweichung merken
    ;=========== Motor ansteuern ============
    POSITION_NEU = GRUNDSTELLUNG + STELLGROESSE;
    ;=========== Begrenzung nach oben =======
    IF POSITION_NEU > 0.9 THEN
    POSITION_NEU = 0.9
    ENDIF
    ;=========== Begrenzung nach unten ======
    IF POSITION_NEU < 0.5 THEN
    POSITION_NEU = 0.5
    ENDIF
    $ANOUT[1] = POSITION_NEU


    ENDLOOP
    USER SUBROUTINE
    ===============================================================
    und in SPS.SUB steht eigentlich nichts besonderes, nur standards
    DEF SPS()
    DECLARATIONS
    INI
    LOOP
    WAIT FOR NOT($POWER_FAIL)


    USER PLC
    ENDLOOP
    ================================================================

  • ich glaube ich habes gefunden!
    ......kann man irgendwie die SPS.SUB aus dem Hauptprogramm heraus starten und auch im programm stoppen?...oder wird es nur beim roboter-start ausgeführt und läuft die ganze zeit?

  • Hi!
    Seh den Sinn nicht, das in einem gesonderten Sub zu schreiben...
    Schreib den Regler als "normale" Funktion und ruf diese Funktion einfach im
    SPS.Sub auf.
    Dann musst du natürlich auch die "wait for" Befehle entfernen, da ja der SPS
    zyklisch käuft...
    Würde auch eine Regler-Struktur erstellen, und diese Struktur an die
    Reglerfunktion übergeben, so kannst du den Regler mehrmals aufrufen.

  • eben das "wait" befehl zu entfernen kann ich nicht!...den sonst kann ich die regelung, so wie ich die programmiert habe nicht nutzen!...ich weiss das man auf "wait" in sps besser verzichten soll, leider habe ich nicht so viel zeit um das noch mal zu ändern jetzt....aber ew währe überlegung wert!...Danke hierfür!

  • 1. Wait Befehle im Submit ist echt abartig! Sollte man verbieten. :down:
    2. Du kannst doch regler.sub von sps.sub aufrufen, indem du z.B. im Hauptprogramm einen Merker setzt.


    Auszug aus SPS.SUB:

    Code
    IF $FLAG[1] THEN
    regler()
    ENDIF


    3. Schalte mal die Variable $INTERPRETER auf 0! Dann siehst du, ob regler.sub irgendwo bei diesen Wait for oder so hängt.
    4. Natürlich läuft deine Regler.sub dauerhaft durch. Hast ja ein LOOP...ENDLOOP und keine Aussprung-Bedingung.

    Greetings, Irrer Polterer!

    Wie poste ich falsch? Nachdem ich die Suche und die FAQ erfolgreich ignoriert habe, erstelle ich das gleiche Thema in mehreren Unterforen, benutze einen sehr kreativen Titel wie "Hilfe", am Besten noch mit mehreren Ausrufezeichen, und veröffentliche einen so eindeutigen Text, dass sich jeder etwas Anderes darunter vorstellt.


    Life is a beta version. Full of bugs and no Manual.

    Einmal editiert, zuletzt von IrrerPolterer ()

  • Die wait for kannste doch rausprogrammieren....
    im Schlimmsten Fall machste das ganze
    mit Switch case wenn das ganze "schrittmässig" abgearbeitet werden soll.
    Dann kannste das wenigstens zyklisch laufen lassen.

  • Hallo ___xyz___,


    zu den von hmi_visu und IrrerPolterer benannten Problemen gesellen sich leider noch ein paar hinzu:


    1. Du setzt für die Regelung einen zeitdiskreten PID-Regler ein. Dieser ist für eine korrekte Funktionsweise darauf angewiesen, dass es in einem äquidistanten Takt aufgerufen wird (d.h. dass der zeitliche Abstand von einem zum nächsten Durchlauf immer gleich ist). Selbst wenn es Dir gelingen sollte, die WAIT FOR-Anweisungen aus dem Reglerprogramm zu entfernen (was erst einmal Grundvoraussetzung wäre), ist der äquidistante Takt beim Aufruf aus der SPS.SUB nicht gegeben, da die SPS.SUB immer dann durchlaufen wird, wenn im System sonst nichts zu tun ist. Das kann dann zu Zeitabständen zwischen zwei Durchläufen von 1 ms bis zu mehreren 100 ms führen.
    Die einzige Möglichkeit, einen äquidistanten Takt beim KUKA zu erzeugen, wäre die Kombination eines Interrupts mit Auslösung durch ein zyklisches Flag, hierbei ergibt sich dann eine Taktzeit von 24 ms.


    2. Auch Deine Routinen zur Erfassung der Vorschub- bzw. Antriebsgeschwindigkeiten sind so nicht in allen Fällen funktionsfähig:
    In dem Fall, wenn z.B. vom Geber des Vorschubs zufällig die Position 65436 gelesen wird, ergibt sich als neuer Wert für die Variable ENDWERT_VORSCH genau 0. In diesem Fall hängt dein Programm endlos fest in der Zeile:


    WAIT FOR ENDWERT_VORSCH > INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L


    mfg Hinky

  • Hallo Hinky und alle andere,


    Regler, den ich programmiert habe sollte zuerst als interrupt eingesetzt werden, deswegen sind die "WAIT FOR" befehle drin sind, da aber es nicht möglich ist, während einer Bewegung durch Interrupt etwas zu regeln(?), habe ich es einfach in SUB gepackt damit es wenigstens so läuft!
    was den PID-Regler angeht, so ist es eigentlich ausreichend für diese Anwendung, da die Ansteuerung von Motoren(pneumatisch) elektro-pneumatisch geschieht! Eigentlich bezieht es sich immer noch auf die von mir früher angefangene Themen.
    Das mit der Routine zur Erfassung der Vorschub- bzw. Antriebsgeschwindikeiten habe ich nicht wirklich verstanden was du mir sagen wolltest, jedoch ist mir das paar mal aufgefallen, das es hängen bleibt..... Wie ich schon früher beschrieben habe, liefern die Inkrementalgeber "unsaubere" Werte, deswegen musste eine "Auffang-Funktion" geschrieben werden, damit wenigstens nach dem überschreiben von "ENDWERTen" ich ein Signal bekomme, das es soweit ist!.....


  • Das mit der Routine zur Erfassung der Vorschub- bzw. Antriebsgeschwindikeiten habe ich nicht wirklich verstanden was du mir sagen wolltest, jedoch ist mir das paar mal aufgefallen, das es hängen bleibt.....


    Ich beziehe mich auf den folgenden Teil deines Reglerprogramms, das ja offenbar den Überlauf der Geberposition bei 65536 (16 Bit) kompensieren soll:


    STARTWERT_VORSCH = INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L
    ENDWERT_VORSCH = 100 + STARTWERT_VORSCH
    IF ENDWERT_VORSCH > 65535 THEN
    ENDWERT_VORSCH = ENDWERT_VORSCH - 65536
    ENDIF
    IF ENDWERT_VORSCH > INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L THEN
    WAIT FOR ENDWERT_VORSCH <= INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L
    ELSE
    IF ENDWERT_VORSCH < INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L THEN
    WAIT FOR ENDWERT_VORSCH > INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L
    WAIT FOR ENDWERT_VORSCH <= INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L
    ENDIF
    ENDIF


    Der Wert von STARTWERT_VORSCH wird ja aus den Geberwerten errechnet. Wenn dieser Wert nun einmal zufällig 65436 sein sollte, würde der Wert von ENDWERT_VORSCH zunächst mit 65536 bestimmt (Addition von 100) und dann auf 0 korrigiert (Subtraktion von 65536). In diesem Fall bleibt das Programm beim ersten WAIT FOR... im letzten IF-Block hängen...


    Ich hoffe, dass meine Anmerkung damit etwas klarer geworden ist ? Falls nicht, bitte einfach noch mal melden.


    Gruß
    Hinky

  • Hallo Hinky,


    danke sehr für die bemerkung, nur leider ist die nicht korrekt, den, zwar hast du recht, es kommt auf "0" hin, jedoch läuft mein Inkrementalgebe "im Kreis", d.h. von 0-65535, dann aber wieder von vorne....somit bekomme ich den wert, trotz dem! das es bei "0" oder darüber ist, ist mir dann egal!

  • Hallo ___xyz___,
    für den beschriebenen Fall läuft Dein Programm in die folgende markierte Zeile:


    IF ENDWERT_VORSCH > INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L THEN
    WAIT FOR ENDWERT_VORSCH <= INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L
    ELSE
    IF ENDWERT_VORSCH < INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L THEN
    WAIT FOR ENDWERT_VORSCH > INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L <= hier gehts nicht mehr weiter...
    WAIT FOR ENDWERT_VORSCH <= INK_GEB_VORSCH_H * 256 + INK_GEB_VORSCH_L
    ENDIF
    ENDIF


    Das Programm wartet dort, bis die Bedingung erfüllt ist. Links vom 'größer' Zeichen steht eine Variable mit Wert 0, rechts der aktuelle Wert vom Geber. Dieser kann sich nun im Bereich von 0-65535 einstellen wie er will, die Bedingung '0 > [akt. Geberwert]' ist niemals erfüllt, so dass Dein Programmablauf an dieser WAIT FOR-Anweisung hängenbleibt...


    Gruß Hinky


  • so bleibt es doch nicht mehr hängen, oder?


    In der Praxis schon noch:
    Beim WAIT FOR-Befehl prüft die Steuerung, ob die angegebene Bedingung zum Weiterschalten des Programms erfüllt ist. Wenn nicht, wird diese Prüfung einmal pro Ipo-Takt wiederholt. Beim KUKA heißt das, dass die Bedingung beim WAIT FOR alle 12 ms überprüft wird. Je nach Geschwindigkeit deines Gebers heißt das, dass nicht jeder Inkrementwert vom KUKA gelesen wird, sondern dass mehr oder weniger große Lücken (eben das, was der Geber an Inkrementen in 12 ms zurücklegt) in der Zahlenfolge sind.
    Beim Zahlenwertüberlauf (Übergang von 65535 auf 0) des Gebers bedeutet das, dass der KUKA wiederum nur zufällig den exakten Wert 0 vom Geber liest, in der Regel den Wert 0 aber überspringt. Bei der von Dir vorgeschlagenen Korrektur würde die WAIT FOR-Anweisung nur beendet werden, wenn exakt der Wert 0 vom Geber gelesen wird.


    Gruß Hinky

  • es ist mir aufgefallen, das die werte nicht kontinuierlich geliefert werden, deine Erklärung macht es noch klarer(1) und deswegen musste ich auch eine Auffangfunktion schreiben!...
    jetzt habe ich versuch das reinzuschreibe, nur klappt es nicht! obwohl THEN steht, erwartet er von mir noch ein "THEN"....komisch...habe jetzt einfach anstatt 65536, 65534 genommen....hat doch die gleiche wirkung...das mit WAIT FOR.....muss ich irgendwie wegkriegen....
    und jetzt habe ich noch ein problem, irgendwie ist diese Regelung für die Pneumatik-Motoren(Radialkolbenmotoren) nicht geeignet, vielleicht liegt es auch an Motore, weil jetzt hat sich noch ein Motor verabschiedet....(kolbenfresser)....Sch....-Planung!!!....

Erstelle ein Benutzerkonto oder melde dich an um zu kommentieren

Du musst ein Benutzerkonto haben um einen Kommentar hinterlassen zu können

Benutzerkonto erstellen
Neues Benutzerkonto für unsere Community erstellen. Geht einfach!
Neues Benutzerkonto erstellen
Anmelden
Du hast bereits ein Benutzerkonto? Melde dich hier an.
Jetzt anmelden