Programmoptimierung - Verschachtelte State-Machine

Biiebs

Level-2
Beiträge
37
Reaktionspunkte
11
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Zusammen,

ich habe mal eine relativ simple Frage zu Programmieroptimierungen.
Mir scheint mein angestrebter Weg mit dem doppelten Aufruf der gleichen CASE-Anweisung (eSelectAxis) doch eher unschön (Meiner Meinung nach läuft es hier auf ein "Henne-Ei-Problem" zw. _eSeq und eSelectAxis hinaus...), es gibt hier sicherlich eine schönere / Alternativ-Lösung aus der Programmierpraxis. Hat jemand Tipps?

Annahme (Pseudo Programmauszug):
  • 2 verschiedene Typen von Achsen -> Achse 1 und Achse 2
    • Diese sollten, je nach Auswahl, entweder jeweils einzeln angesteuert oder beide zusammen angesteuert werden
  • Aufgerufen werden diese in einer Methode, die mit Execute aktiviert wird.
  • Die Ablaufsteuerung setzt sich wie folgt zusammen:
    • Schritt 0 - Setzt einen angestrebten Wert über SDO's
    • Schritt 1 - Aktiviert die Bewegung über PDO's

Code:
IF xExecute THEN

    CASE _eSeq OF
        (********************************************************************************************************)
        E_Seq.SetSDO:

            CASE eSelectAxis OF
                (********************************************************************************************************)
                E_Axis.None:
                    RETURN;
                    
                (********************************************************************************************************)
                E_Axis.Axis_1:
                    _Axis_1_SetCtrlDataExecute := TRUE;
                    _eAxis_1_CtrlDataTypes := EControlDataTypes.SetIntermediatePosition;
                    _rAxis_1_CtrlDataPosition := _stAxis.stConfig.rBasePosition;
                    
                    IF _Axis_1_SetCtrlDataDone THEN
                        _eSeq := E_Seq.SetPDO;
                    END_IF
                    
                (********************************************************************************************************)
                E_Axis.Axis_2:
                    _Axis_2_SetCtrlDataExecute := TRUE;
                    _eAxis_2_CtrlDataTypes := EControlDataTypes.SetIntermediatePosition;
                    _rAxis_2_CtrlDataPosition := _stAxis.stConfig.rBasePosition;
                    
                    IF _Axis_2_SetCtrlDataDone THEN
                        _eSeq := E_Seq.SetPDO;
                    END_IF
                    
                (********************************************************************************************************)
                E_Axis.Both_Axes:
                    _Axis_1_SetCtrlDataExecute := TRUE;
                    _eAxis_1_CtrlDataTypes := EControlDataTypes.SetIntermediatePosition;
                    _rAxis_1_CtrlDataPosition := _stAxis.stConfig.rBasePosition;
                
                    _Axis_2_SetCtrlDataExecute := TRUE;
                    _eAxis_2_CtrlDataTypes := EControlDataTypes.SetIntermediatePosition;
                    _rAxis_2_CtrlDataPosition := _stAxis.stConfig.rBasePosition;
                    
                    IF ( _Axis_1_SetCtrlDataDone AND _Axis_2_SetCtrlDataDone ) THEN
                        _eSeq := E_Seq.SetPDO;
                    END_IF   
            END_CASE
            
            
        (********************************************************************************************************)
        E_Seq.SetPDO: // Move to position

            CASE eSelectAxis OF
                (********************************************************************************************************)
                E_Axis.None:
                    RETURN;
                
                (********************************************************************************************************)
                E_Axis.Axis_1:
                    _stAxis_1.stPDO.xMoveToPosIntermediate := TRUE;
                    
                    IF _stAxis_1.stPDO.xIntermediatePosReached THEN
                        _stAxis_1.stPDO.xMoveToPosIntermediate := FALSE;
                        _eSeq := E_Seq.SetSDO;
                    END_IF
                
                (********************************************************************************************************)   
                E_Axis.Axis_2:
                    _stAxis_2.stPDO.xMoveToPosIntermediate := TRUE;
                    
                    IF _stAxis_2.stPDO.xIntermediatePosReached THEN
                        _stAxis_2.stPDO.xMoveToPosIntermediate := FALSE;
                        _eSeq := E_Seq.SetSDO;
                    END_IF
                
                (********************************************************************************************************)   
                E_Axis.Both_Axes:
                    _stAxis_1.stPDO.xMoveToPosIntermediate := TRUE;
                    _stAxis_2.stPDO.xMoveToPosIntermediate := TRUE;
                    
                    IF ( _stAxis_1.stPDO.xIntermediatePosReached AND _stAxis_2.stPDO.xIntermediatePosReached )  THEN
                        _stAxis_1.stPDO.xMoveToPosIntermediate := FALSE;
                        _stAxis_2.stPDO.xMoveToPosIntermediate := FALSE;
                        _eSeq := E_Seq.SetSDO;
                    END_IF           
            END_CASE
    END_CASE   
    
END_IF


Vielen Dank schonmal!

Gruß,

Biiebs
 
Du könntest 2 parallele Schrittketten machen - aber ich sehe bei deiner Variante nun auch nicht, dass das nicht funktionieren würde ... außer du hättest den Fall, dass du die eine Achse zeitlich versetzt zu der anderen Achse ansteuern möchtest, die andere Achse aber noch nicht fertig ist - in dem Fall wären 2 sperate (parallele) Schrittketten besser ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Für jede Achse eine eigene Sequenz und dann übergeordnet noch eine Sequenz, so könntest du auch, wenn sich die beiden Achsen in nichts unterscheiden die Sequenzen multiinstanzieren und müsstest sie nur einmal zentral bearbeiten um etwas zu ändern
 
So wäre mein Verständnis für deinem Problem. Natürlich jetzt nicht 100% richtig
Dürfte so sein wie DCDCDC gemeint hat

Ablaufbaustein

Code:
IF xExecute THEN

    CASE eSelectAxis OF
         (********************************************************************************************************)
         E_Axis.None:
              _Axis1.xExecute := false;
              _Axis2.xExecute := false;
        
         (********************************************************************************************************)
         E_Axis.Axis_1:
                _Axis1.xExecute := true;
                _Axis2.xExecute := false;
        
         (********************************************************************************************************)   
         E_Axis.Axis_2:
                _Axis1.xExecute := false;
                _Axis2.xExecute := true;
        
         (********************************************************************************************************)   
         E_Axis.Both_Axes:
                _Axis1.xExecute := true;
                _Axis2.xExecute := true;     

    END_CASE

END_IF

Achsenbaustein (mehrfach instanzierbar)
der dann natürlich als Eingang und Ausgangsparameter entsprechende
Variablen benötigt.

Code:
IF xExecute THEN

    CASE _eSeq OF
    (********************************************************************************************************)
    E_Seq.SetSDO:

        SetCtrlDataExecute := TRUE;
        CtrlDataTypes          := EControlDataTypes.SetIntermediatePosition;
        rCtrlDataPosition     := _stAxis.stConfig.rBasePosition;

        IF SetCtrlDataDone THEN
            _eSeq := E_Seq.SetPDO;
        END_IF
            
            
    (********************************************************************************************************)
    E_Seq.SetPDO: // Move to position

        stPDO.xMoveToPosIntermediate := TRUE;

        IF stPDO.xIntermediatePosReached THEN
            stPDO.xMoveToPosIntermediate := FALSE;
            _eSeq := E_Seq.SetSDO;
        END_IF
                
END_IF
 
Ich mache das gerne noch mit einem Handshake.

Das Startsignal wartet auf ein Fertigsignal, dann wird Start zurückgesetzt

Mit Start = false wird dann die andere Sequenz wird in den Init state gesetzt

So kannst du dann auch noch Zeitüberlauf bewachen etc..
 
Zurück
Oben