igus D1 über CANopen - Homing funktioniert - andere Modi nicht

LeFish

Level-1
Beiträge
60
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo allerseits,

ich hab eine igus D1 Motorsteuerung an einer Beckhoff CX9020 mit EL6751 als CANopen Master hängen.

igus D1 Handbuch: https://igus.widen.net/content/kda7...=Vo3t8rhefqmfyd0rbZhwfQ6lVO0ktmDGNsgAuKxI81o=

Die Kommunikation mit der D1 funktioniert, ich kann alle SDOs auslesen und beschreiben.

Als Start habe ich ein Homing-Programm erstellt:

Mittels Methode werden die SDOs dazu auf der D1 geschrieben und das Homing getriggert:

Code:
METHOD PUBLIC Start_Homing
VAR_INPUT
    Feed_constant_Feed                    : UDINT;        // Vorschub des Antriebs
    Feed_constant_Shaft_revolutions        : UDINT;        // Motorwellendrehzahl
    Switch_Search_VEL                    : UDINT;        // Endlagenschaltersuchgeschwindigkeit 
    Zero_Search_VEL                        : UDINT;        // Nullpunktsuchgeschwindigkeit
    Homing_ACC                            : UDINT;        // Beschleunigung/Verzögerung für die Referenzfahrt
END_VAR

IF NOT _Homing.x_inProgress THEN
    //Set parameters for Homing lt D1 Handbuch S 88
    _dict.Feed_constant_Feed_RWW := Feed_constant_Feed;
    _dict.Feed_constant_Shaft_revolutions_RWW := Feed_constant_Shaft_revolutions;
    _dict.Homing_speeds_Speed_during_search_for_switch_RWW := Switch_Search_VEL;
    _dict.Homing_speeds_Speed_during_search_for_zero_RWW := Zero_Search_VEL;
    _dict.Homing_acceleration_RWW := Homing_ACC;
    _dict.Modes_of_operation_RWW := 6;
    //Trigger FB_Homing
    _Homing.x_StartHoming := TRUE;
END_IF

Das Homing selbst habe ich als State-Machine in einem zyklisch (Zykluszeit 1ms) aufgerufenen Funktionsblock abgebildet:

Code:
FUNCTION_BLOCK FB_Homing
VAR_INPUT
    _p_statusword            : POINTER TO _D1_states;            // Pointer zum Statusword (_status    in FB_D1)
    _p_controlword            : POINTER TO _D1_controls;            // Pointer zum Controlword
    CAN_is_inSync            : BOOL;
END_VAR
VAR_OUTPUT
END_VAR
VAR
    state                    : BYTE := 0;
    _x_isHomed                : BOOL;
    _x_StartHoming            : BOOL;
    _x_inProgress            : BOOL;
    _fb_Delay                : TON;                // Verzögerung für 100ms
    _str_Status_User        : STRING;            // User-friendly status messages
    _fb_Toggle                : BLINK;
END_VAR

// External Trigger Homing Action
IF _x_StartHoming AND NOT _x_inProgress THEN
    _x_StartHoming := FALSE;
    _x_isHomed := FALSE;
    _x_inProgress := TRUE;
    state := 1; // Start Homing
END_IF

CASE state OF
    
    0:
        //do nothing - no Homing required
        
    1:
        IF CAN_is_inSync THEN
            state := state + 1;
        END_IF
        
    2: 
        // Rücksetzen von delay
        _fb_Delay(IN := FALSE);
        // Starte Homing durch setzen von Controlword bit 4
        _p_controlword^.x_04_Mode_specific := TRUE;
        state := state + 1;
        
    3:
        //Warte für 100 ms.
        _fb_Delay(IN := TRUE, PT := T#100MS);
        IF _fb_Delay.Q THEN
            state := state + 1;
            // Rücksetzen von delay
            _fb_Delay(IN := FALSE);
        END_IF
        
    4:
        //Failsafe: Toggle Bit 4 Controlword um zu starten
        _fb_Toggle(ENABLE := TRUE, TIMELOW := T#50MS, TIMEHIGH := T#50MS);
        _p_controlword^.x_04_Mode_specific := _fb_Toggle.OUT;
        // Überprüfe ob Referenzfahrt im Gange?
        // Lt. D1 Handbuch S 88
        IF     NOT _p_statusword^.x_12_Operation_mode_specific AND 
            NOT _p_statusword^.x_10_Target_reached THEN
                _str_Status_User := 'Das Homing wird ausgeführt.';
                state := state + 1;
        END_IF
        
    5:
        //Überprüfe ob Referenzfahrt beendet?
        IF         _p_statusword^.x_12_Operation_mode_specific AND 
                _p_statusword^.x_10_Target_reached THEN
                _str_Status_User := 'Das Homing wurde erfolgreich ausgeführt.';
                state := state + 1;
        END_IF
        
    6:
        //Beende Homing process
        _p_controlword^.x_04_Mode_specific := FALSE;
        _x_isHomed := TRUE;
        _x_inProgress := FALSE;
        state := 0; // Reset Statemachine
END_CASE

Wie schon gesagt, das Homing funktioniert!

Was nicht funktioniert, sind alle anderen Modi. Das sind in meinem Fall:

  • Profile Position Mode (absolut und relativ)
  • Profile Velocity Mode

z.B.: für den Profile Position Mode (relativ) habe ich eine ähnliche Routine:

Methode zum Triggern:

Code:
METHOD PUBLIC GoToPosition_Rel
VAR_INPUT
    Feed_constant_Feed                    : UDINT;        // Vorschub des Antriebs
    Feed_constant_Shaft_revolutions        : UDINT;        // Motorwellendrehzahl
    Target_Position                        : DINT;            // Angabe der neuen Zielposition
    Profile_Velocity                    : UDINT;         // Geschwindigkeit
    Profile_Acceleration                : UDINT;        // Beschleunigung
    Profile_Deceleration                : UDINT;        // Verzögerung
END_VAR


//Set parameters for Profile Position Mode lt D1 Handbuch S 89
_dict.Feed_constant_Feed_RWW := Feed_constant_Feed;
_dict.Feed_constant_Shaft_revolutions_RWW := Feed_constant_Shaft_revolutions;
_dict.Target_position_RWW := Target_Position;
_dict.Profile_velocity_RWW := Profile_Velocity;
_dict.Profile_acceleration_RWW := Profile_Acceleration;
_dict.Profile_deceleration_RWW := Profile_Deceleration;
_dict.Modes_of_operation_RWW := 1;
_control.x_06_Mode_specific := TRUE;    // Control Bit 6 true-> Relativpositionierung
//Trigger FB_GoToPos_Abs
_RelPos.x_StartPos := TRUE;

Und FB für die State-Machine:

Code:
FUNCTION_BLOCK FB_GoToPos_Rel
VAR_INPUT
    _p_statusword            : POINTER TO _D1_states;            // Pointer zum Statusword (_status    in FB_D1)
    _p_controlword            : POINTER TO _D1_controls;            // Pointer zum Controlword
    CAN_is_inSync            : BOOL;
END_VAR
VAR_OUTPUT
END_VAR
VAR
    state                        : BYTE := 0;
    _x_StartPos                    : BOOL;
    _x_inProgress                : BOOL;
    _fb_Delay                : TON;                // Verzögerung für 10ms
    _str_Status_User            : STRING;            // User-friendly status messages
    _fb_Toggle                    : BLINK;
END_VAR

// External Trigger Homing Action
IF _x_StartPos AND NOT _x_inProgress THEN
    _x_StartPos := FALSE;
    _x_inProgress := TRUE;
    state := 1; // Start
END_IF

CASE state OF
    
    0:
        //do nothing - no Positioning required
        
    1:
        IF CAN_is_inSync THEN
            state := state + 1;
        END_IF
        
    2: 
        //Failsafe: Toggle Bit 4 Controlword um zu starten
        _fb_Toggle(ENABLE := TRUE, TIMELOW := T#50MS, TIMEHIGH := T#50MS);
        _p_controlword^.x_04_Mode_specific := _fb_Toggle.OUT;
        
        IF NOT _p_statusword^.x_10_Target_reached THEN
            //Motor in Bewegung
            state := state + 1;
        END_IF
        
    3:
        //Warte für 100 ms.
        _fb_Delay(IN := TRUE, PT := T#100MS);
        IF _fb_Delay.Q THEN
            state := state + 1;
        END_IF
        
    4:
        // Rücksetzen von delay
        _fb_Delay(IN := FALSE);
        _p_controlword^.x_04_Mode_specific := FALSE;
        IF NOT _p_statusword^.x_10_Target_reached AND _p_statusword^.x_12_Operation_mode_specific THEN
            // Rücksetzen von Startbit
            _str_Status_User := 'Positionierung im Gange.';
        END_IF
        IF _p_statusword^.x_10_Target_reached THEN
            // Ziel erreicht
            _str_Status_User := 'Position erreicht.';
            state := state + 1;
        END_IF
        
    5:
        //Beende Positioning process
        _x_inProgress := FALSE;
        state := 0; // Reset Statemachine

END_CASE

Ich habe mich auf folgenden Ablauf lt. Handbuch für einen Positioniervorgang gehalten (S.89 im D1 Handbuch):
Anhang anzeigen 50960

Lt. der Beschreibung sollte nach Setzen des Startbefehls Bit4 das Bit 10 im Statusword (Target reached) auf FALSE gesetzt werden. Das passiert aber nicht. Sehrwohl wird jedoch Bit 12 (New Setpoint) auf TRUE gesetzt.

Das sind die SDOs auf der D1:
Anhang anzeigen 50961

Und das ist der Zustand nach setzen von Bit 4 (Startbefehl)
Anhang anzeigen 50962

Der Motor dreht sich nicht.

Hat jemand einen Rat, was ich falsch mache?

Danke!

Beste Grüße
LeFish
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was mir noch auffält, Du machst den klassischen Anfängerfehler. Du rufst Timer und ähnliche FBs innerhalb der CASE-Anweisung (Gilt auch für IF-Anweisungen und Schleifen) auf, anstatt nur die Eingänge zu setzen und die Ausgänge auszuwerten und den Aufruf außerhalb zu machen. Was gibt Dein _fb_Toggle denn als erstes aus, high oder low Signal?
 
Außerdem befolgst Du die Anweisung von igus nicht. Laut dem Ausschnitt des Handbuchs soll das Startbit erst zurückgesetzt werden, wenn der Controller eine Rückmeldung geschickt hat. Vielleicht reichen ihm 50ms nicht.
Wieso nutzt Du übrigens SDOs und machst das nicht über PDOs? Da sollte es eigentlich eine passende PDO Konfiguration für geben oder man kann sie erstellen (Weiß leider nicht was bei igus möglich ist).
Bei der Gelegenheit, wofür brauchst Du eine so schnelle Task?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich nehme mal an, dass Du irgendeinen ADS Write-FB benutzt, um die CoE-Einträge zu beschreiben. Das läuft ja asynchron zum PLC-Programm. Hast Du sichergestellt, dass alle Parameter geschrieben wurden, bevor du Bit 4 im Controlword setzt?

Wie du richtig geschrieben hast benutze ich ADSREAD und ADSWRITE.

Ich schreibe zyklisch veränderungen und lese zyklisch alle SDOs aus. Es wird verglichen, ob meine Änderungen auch tatsächlich von der igus D1 übernommen wurde. Erst wenn das der Fall ist wird die VAR_INPUT
Code:
CAN_is_inSync            : BOOL;

auf TRUE gesetzt.

Die wird im Schritt 1 überprüft.
 
Außerdem befolgst Du die Anweisung von igus nicht. Laut dem Ausschnitt des Handbuchs soll das Startbit erst zurückgesetzt werden, wenn der Controller eine Rückmeldung geschickt hat. Vielleicht reichen ihm 50ms nicht.

Beim testen der Homing funktion bin ich daufgekommen, dass die igus D1 manchmal "fehlzündungen" hat. Es sind also alle Register gesetzt, und das Startbit 4 auf TRUE, aber es rührt sich nix. Erst wenn ich es wieder auf FALSE und wieder auf TRUE setze beginnt die Bewegung. Daher der 50 ms Blinker.

Ich habe die Werte sogar schon mal händisch gesetzt und erst dann das Startbit gesetzt. Hat sich auch nix gerührt. Außer wie schon oben beschrieben, Bit 12 im Statusword ist auf TRUE gegangen.

Wieso nutzt Du übrigens SDOs und machst das nicht über PDOs? Da sollte es eigentlich eine passende PDO Konfiguration für geben oder man kann sie erstellen (Weiß leider nicht was bei igus möglich ist).

Die igus D1 bietet max. 4 TX und 4 RX PDOs mit je 4 Byte an. Das ist zu wenig, um alle Werte (BeschleunigungEN, GeschwindigkeitEN etc) für alle Modi zu übertragen. Die meisten Werte sind 32bit Werte.

Bei der Gelegenheit, wofür brauchst Du eine so schnelle Task?

Auf 1 ms Zykluszeit bin ich gegangen, damit das Lesen und Schreiben der SDOs über ADSREAD und ADSWRITE möglichst schnell geht. Ich lese ja zyklisch alle 25 Werte aus und damit da nicht zu viel Zeit verloren geht (ADS.busy == FALSE, aber Programm steht) bin ich auf 1 ms gegangen.
Mein gesamtes Programm braucht nämlich bis jetzt ca. 300 µs.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie StructuredTrash schon schrieb tust Du das nicht, die SDO Kommandos arbeiten immer azyklisch. Zyklisch geht es nur mit den SDOs.

Mit zyklisch meine ich, dass ADSREAD zyklisch aufgerufen wird. Und wenn ADSREAD einen Wert (ADSREAD nicht mehr busy) hat, wird er der entsprechenden Variable übergeben und der Wert der nächsten Adresse ausgelesen.

Das Auslesen aller SDOs dauert ca. 200 ms. Wenn alle ausgelsenen sind beginnt der Spaß von vorne. Vor jedem auslesen werden alle SDOs, bei denen sich ein Wert geändert hat beschrieben.
Mit dem Auslesen danach vergleiche ich, ob die D1 den Wert auch übernommen hat. Dann wird x_Sync auf TRUE gesetzt.

Ich hab lange gebraucht, um das stabil hinzubekommen. Ich bin mir jetzt aber sicher, dass das Beschreiben und Auslesen der SDOs stabil funktioniert.
 
Zuletzt bearbeitet:
Was ich noch anmerken wollte:
Das Controlword und das Statusword der D1 hab ich als PDOs mittels %I* bzw %Q* auf Variablen gelegt.
Damit ist sichergestellt, dass die beiden Werte in Echtzeit (-> zyklisch, synchron) über den Bus ausgetauscht werden.
 
Was ich noch anmerken wollte:
Das Controlword und das Statusword der D1 hab ich als PDOs mittels %I* bzw %Q* auf Variablen gelegt.
Damit ist sichergestellt, dass die beiden Werte in Echtzeit (-> zyklisch, synchron) über den Bus ausgetauscht werden.
Schade, das wäre meine nächste Idee gewesen.
Ich kenne mich mit dem CAN-Bus nicht so aus, daher kann das Folgende völliger Blödsinn sein. Du schreibst ja Daten auf mehrere SDOs und liest diese dann aus, um zu prüfen, ob diese geschrieben wurden. Die Frage wäre jetzt, ob der Controller diese dann auch schon verarbeitet hat. Nicht das Du alle Daten zwar geschrieben hast, der Controller diese aber noch nicht verarbeitet hatte und schon ein Startsignal bekommt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das Toggeln des Start-Bits könnte ein Problem sein. Der Befehl wird zwar nur beim High Trigger übernommen, aber danach solltest Du das Bit High lassen, bis das Bestätigungs-Bit im Status Word kommt.
Denkbar ist auch, dass der Antrieb Profilparameter nur akzeptiert, wenn der Operation Mode dazu passt. Übertrag den mal als erstes.

Ansonsten schliesse ich mich Oliver an. PDOs sind die bessere Wahl. Die Parameter für PP und PV kriegst Du doch in 32 Bytes unter. z. B.:
PDO 1:
Control Word
Operation mode
PDO2:
Target position
Profile velocity für PP
PDO3:
Profile acceleration
Profile deceleration
PDO4:
Target velocity für PV
Alles andere würde ich konstant im Antrieb einstellen.
 
Nicht das Du alle Daten zwar geschrieben hast, der Controller diese aber noch nicht verarbeitet hatte und schon ein Startsignal bekommt.

Das Toggeln des Start-Bits könnte ein Problem sein. Der Befehl wird zwar nur beim High Trigger übernommen, aber danach solltest Du das Bit High lassen, bis das Bestätigungs-Bit im Status Word kommt.
Denkbar ist auch, dass der Antrieb Profilparameter nur akzeptiert, wenn der Operation Mode dazu passt. Übertrag den mal als erstes.

Ich habe schon versucht alle Werte händisch zu setzen. Ich habe es genau in der Reihenfolge der Anleitung gemacht (zuerst Mode_of_Operation auf 1):Anhang anzeigen 50964

Danach habe ich händisch Bit 4 im Controlword gesetzt. Nicht getoggelt.

Es ging Bit 12 im Statusword auf TRUE, Bit 10 jedoch nicht wie in der Beschreibung steht auf FALSE. Der Motor drehte nicht.
Setzte ich danach Bit 4 im COntrolword wieder auf FALSE, ging auf Bit 12 im Statusword wieder auf FALSE.

Irgendeinen Trick gibt es noch, der nicht eindeutig im Handbuch beschrieben ist.

Das Homing funktioniert bei mir interessanterweise sowohl händisch als auch aus dem Programm heraus nach obigem Ablauf.

Ansonsten schliesse ich mich Oliver an. PDOs sind die bessere Wahl. Die Parameter für PP und PV kriegst Du doch in 32 Bytes unter.

Das alles mit PDOs zu lösen war auch mein erster Zugang. Hätte mir da viel Arbeit erspart...
Lt. igus Support habe ich nur 16 Byte Receive und 16 Byte Transmit PDOs. Das heißt ich hab noch 3 RxPDOs vollkommen frei. Das wären 3 32bit Werte. Um den PP-Mode vollständig zu parametrieren brauch ich aber mind. 4 32 bit Werte. Erst in einigen Wochen soll laut igus ein Update kommen, wo sie die PDOs aufreißen und dann auch zB den Motorstrom über den Bus verfügbar machen.
So lange kann ich aber nicht warten.
Generell: Warum zB die Beschleunigungen und Geschwindigkeiten unbedingt (U)DINTs sein müssen versteh ich nicht, muss ich aber glaub ich auch nicht verstehen...



Außerdem ist das parametrieren von PDOs mit der Beckhoff EL6751 soweit ich bis jetzt weiß eine Wissenschaft für sich...
https://download.beckhoff.com/download/document/io/ethercat-terminals/el6751de.pdf
Anhang anzeigen 50965


Von Seiten igus sagte man mir auch: Lösen Sie das doch mit SDOs.
 
Zuletzt bearbeitet:
Ich habe soeben einen Beitrag von Anfang 2020 gefunden. Scheinbar bin ich nicht der einzige mit dem Problem bei der igus D1.
https://www.sps-forum.de/feldbusse/...en-tia-portal-pn-link-igus-d1.html#post745842

VIELLEICHT
überschreibt das defaultmäßig gemappte "Target Position" PDO den Wert des Objekts, den ich mittels ADSWRITE setze.
-> solange ich das PDO nicht beschreibe bleibt der Wert auf 0 und mein mittels ADSWRITE gesetzter Wert wird von der D1 nicht übernommen.

Defaultmäßig sind foldende PDOs gemappt - ich habe das Mapping nicht verändert:

RxPDO1.1: 0x6040h Controlword
RxPDO2.1: 0x6040h Controlword
RxPDO2.2: 0x607Ah Target Position
RxPDO3.1: 0x6040h Controlword
RxPDO3.2: 0x60FFh Target Velocity
RxPDO4.1: 0x6040h Controlword

TxPDO1.1: 0x6041h Statusword
TxPDO2.1: 0x6041h Statusword
TxPDO2.2: 0x6064h Position Actual Value
TxPDO3.1: 0x6041h Statusword
TxPDO3.2: 0x606Ch Velocity Actual Value
TxPDO4.1: 0x6041h Statusword

Meine Hoffnung ist, dass die PDOs meine über ADSWRITE gesetzten Objekte überschreiben, obwohl ich die entsprechenden PDOs nicht in meinem Projekt verknüpft habe.
Das werde ich morgen testen und berichten.

Interessanterweise kommt aber auf der Adresse 0x6064h über mein SDO_Read ein Wert an, der während des Homings hinaufzählt. Also ADSREAD geht scheinbar...
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
VIELLEICHT
überschreibt das defaultmäßig gemappte "Target Position" PDO den Wert des Objekts, den ich mittels ADSWRITE setze.
-> solange ich das PDO nicht beschreibe bleibt der Wert auf 0 und mein mittels ADSWRITE gesetzter Wert wird von der D1 nicht übernommen.
Das wird es wohl sein. Werte, die Du nicht per PDO schreiben willst, dürfen dort auch nicht aufgeführt sein.
Du könntest auf der Beckhoff-Seite alle PDOs löschen, in der Hoffnung, dass der Antrieb damit auch sein Default Mapping verwirft.
Oder die Target Position doch per PDO schreiben.

PS: 16 Byte in/out sind natürlich mager. Damit ist der Antrieb für PP eigentlich ungeeignet.
 
Zuletzt bearbeitet:
Das wird es wohl sein. Werte, die Du nicht per PDO schreiben willst, dürfen dort auch nicht aufgeführt sein.

Ich hoffe auch, dass es das war.
Ich bin ein Neuling beim CAN Bus, darum die Frage: Zieht PDO immer vor SDO?

Wenn ich online auf die Register schaue, sehe ich ja, dass zB Target Position scheinbar durch ADSWRITE gesetzt wurde:
SDOs.jpg
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
PS: 16 Byte in/out sind natürlich mager. Damit ist der Antrieb für PP eigentlich ungeeignet.

Das finde ich auch. Vorallem, da igus viele Werte auf 4 Byte ausgedehnt hat. Welcher Motor schafft eine Beschleunigung von 4.294.967.295 ? Der Wert ist einheitenlos, da entweder mm/s^2 oder °/s^2 gelten... Aber wurscht für beide würden kA über den Controller fließen. Da sind die möglichen 21 A dann doch begrenzend.
 
Zuletzt bearbeitet:
Mittlerweile kann ich andrehen.

Mein Fehler war, dass ich den Vorschub (Feed_constant_Feed) mit 1 definiert habe. Nachdem ich hier die für die Rotation erforderlichen 360°/Umdrehung definiert habe geht es - mehr schlecht als recht jedoch.

Das Problem ist, dass das Target reached Bit 10 im Statusword nicht auf 0 wechselt nachdem ich ihm über Bit 4 den Startbefehl gegeben habe. Nach ca. 1,5 s (!!!) wird dann das New Setpoint Bit 12 im Statusword TRUE, der Motor fährt dann.

Es passt also nicht mit der im Handbuch beschriebenen Abfolge zusammen.

Die State-Machine für die relativ-positionierung lautet folgendermaßen, wobei CANComm_SYNC bei jedem erfolgreichen Sync der PDOs (Zykluszeit 10ms) zwischen TRUE und FALSE toggelt (macht die EL6751).

Code:
// External Trigger Position Action
IF _x_StartPos AND NOT _x_inProgress THEN
    _x_StartPos := FALSE;
    _x_inProgress := TRUE;
    _x_PosReached := FALSE;
    state := 1; // Start
END_IF

_r_trig(CLK := CANComm_SYNC);
_f_trig(CLK := CANComm_SYNC);

CASE state OF
    
    0:
        //do nothing - no Positioning required
        
    1:
        IF CAN_is_inSync THEN
            // Rücksetzen von Startbit
            _p_controlword^.x_04_Mode_specific := FALSE;
            state := state + 1;
        END_IF
        
    2:
        //Einen vollen CAN-Update Zyklus warten
        IF _r_trig.Q THEN
            state := state + 1;
        END_IF
        
    3: 
        //Einen vollen CAN-Update Zyklus warten
        IF _f_trig.Q THEN
            state := state + 1;
        END_IF
        
    4:
        //Starte Bewegung
        _p_controlword^.x_04_Mode_specific := TRUE;
        state := state + 1;
        
    5:
        IF NOT _p_statusword^.x_10_Target_reached OR _p_statusword^.x_12_Operation_mode_specific THEN    // Bit 10 wird nicht immer zuverlässig FALSE, daher die verorderung.
            //Motor in Bewegung
            _str_Status_User := 'Positionierung im Gange.';
            state := state + 1;
        END_IF
        
    6:
        _p_controlword^.x_04_Mode_specific := FALSE;

        IF _p_statusword^.x_10_Target_reached THEN
            // Ziel erreicht
            _str_Status_User := 'Position erreicht.';
            state := state + 1;
        END_IF
        
    7:
        //Beende Positioning process
        _x_inProgress := FALSE;
        _x_PosReached := TRUE;
        state := 0; // Reset Statemachine

END_CASE

Ich hab Echtzeit Traces von dem Bewegungsvorgang gemacht:

Parameter:

Code:
Feed_constant_Feed : UDINT := 360;                                // Vorschub des Antriebs
Feed_constant_Shaft_revolutions : UDINT := 1;                  // Motorwellendrehzahl
Velocity          : UDINT := 3000;
Acceleration    : UDINT := 10000;
Deceleration    : UDINT := 10000;
                                           
Target_Position      : DINT := 100000;

X_StartPos Triggert die Statemachine für die Relativpositionierung.

Trace 1.jpg

Was auffällig ist, dass Zustand 5 ca. 1,5 s dauert. Hier warte ich entweder dass Bit 10 FALSE wird oder Bit 12 TRUE, da Bit 10 nicht immer FALSE wird.

Trace 2.jpg

Das Bit 4 im Controlword (Startbefehl) wird sofort nach Start der State-Machine auf TRUE gesetzt.

Trace 3.jpg

Bei dieser längeren Positionierfahrt wird Bit 10 auf FALSE gesetzt, wenn Bit 12 auf TRUE gesetzt wird. (Lt. Handbuch). Bei kürzeren Fahrten (Targetposition 1000 Statt 100000) wird Target reached gar nie auf FALSE gesetzt.
Interessant bleibt das Delay von ca. 1,5 s.

Trace 4.jpg

Das Verhalten ist unabhängig davon, ob ich SDOs zyklisch, asynchron auslese ( ca. 3% Buslast) oder überhaupt keine nennenswerte Buslast außer PDOs verursache.

Hat jemand ein solches Verhalten bei der igus schonmal beobachten können?
 
Zuletzt bearbeitet:
Zurück
Oben