Search code examples
plcst

How do you control the order of executing different blocks of ST code?


I have a process recipe with 8 steps, each of which I have defined in ST. The user should be able to however, select the order in which these 8 steps are executed. I'm trying to come up with flags or variables which could be used for this but drawing a blank so far. Does anyone have any thoughts on how this could be implemented?


Solution

  • My proposal is to let the user fill an array with the step numbers in the order how it should be executed. Then put your different blocks of ST code in a CASE statement. For the CASE-variable use the array. This way the order of execution is fully flexible.

    Here is an Sandwich Decorator as an example. The important part starts at E_SandwichDecoratorStep.RecipeExecution

    Enumerations:

    TYPE E_SandwichDecoratorStep :
    (
        UserSelecting := 1,
        RecipeExecution,
        Finished
    );
    END_TYPE
    

    TYPE E_SandwichDecoratorUserRecipe :
    (
        Pepperoni := 1,
        Ham,
        Cheese,
        Tomato,
        Salad,
        Sauce,
        Salt,
        Pepper
    );
    END_TYPE
    

    Program:

    PROGRAM SANDWICHDECORATOR
    VAR
        arrnStepOrder       : ARRAY[1..8] OF E_SandwichDecoratorStep;   (*User Recipe Configuration*)
    
        bRestart            : BOOL;
        bUserRecipeStart    : BOOL; (*Start the execution of the Recipe*)
        eCurStep            : E_SandwichDecoratorStep;
        nCurUserRecipeIndex : INT := 1;
    END_VAR
    

    CASE eCurStep OF
        E_SandwichDecoratorStep.UserSelecting:
            (*Example Order*)
            arrnStepOrder[1] := E_SandwichDecoratorUserRecipe.Ham;
            arrnStepOrder[2] := E_SandwichDecoratorUserRecipe.Tomato;
            arrnStepOrder[3] := E_SandwichDecoratorUserRecipe.Pepperoni;
            arrnStepOrder[4] := E_SandwichDecoratorUserRecipe.Cheese;
            arrnStepOrder[5] := E_SandwichDecoratorUserRecipe.Salt;
            arrnStepOrder[6] := E_SandwichDecoratorUserRecipe.Sauce;
            arrnStepOrder[7] := E_SandwichDecoratorUserRecipe.Pepper;
            arrnStepOrder[8] := E_SandwichDecoratorUserRecipe.Salad;
    
            IF bUserRecipeStart THEN
                bUserRecipeStart := FALSE;
                eCurStep := E_SandwichDecoratorStep.RecipeExecution;
            END_IF
    
        E_SandwichDecoratorStep.RecipeExecution:
            IF nCurUserRecipeIndex <= E_SandwichDecoratorUserRecipe.Pepper THEN
                CASE arrnStepOrder[nCurUserRecipeIndex] OF
                    E_SandwichDecoratorUserRecipe.Pepperoni:
                        nCurUserRecipeIndex := nCurUserRecipeIndex + 1;
    
                    E_SandwichDecoratorUserRecipe.Ham:
                        nCurUserRecipeIndex := nCurUserRecipeIndex + 1;
    
                    E_SandwichDecoratorUserRecipe.Cheese:
                        nCurUserRecipeIndex := nCurUserRecipeIndex + 1;
    
                    E_SandwichDecoratorUserRecipe.Tomato:
                        nCurUserRecipeIndex := nCurUserRecipeIndex + 1;
    
                    E_SandwichDecoratorUserRecipe.Salad:
                        nCurUserRecipeIndex := nCurUserRecipeIndex + 1;
    
                    E_SandwichDecoratorUserRecipe.Sauce:
                        nCurUserRecipeIndex := nCurUserRecipeIndex + 1;
    
                    E_SandwichDecoratorUserRecipe.Salt:
                        nCurUserRecipeIndex := nCurUserRecipeIndex + 1;
    
                    E_SandwichDecoratorUserRecipe.Pepper:
                        nCurUserRecipeIndex := nCurUserRecipeIndex + 1;
                END_CASE
            ELSE
                nCurUserRecipeIndex := 1;
                eCurStep := E_SandwichDecoratorStep.Finished;
            END_IF
    
        E_SandwichDecoratorStep.Finished:
            IF bRestart THEN
                bRestart := FALSE;
                eCurStep := E_SandwichDecoratorStep.UserSelecting;
            END_IF
    
    END_CASE