{
    S7_Author := "ABH";
    S7_BlockComment := "MLC_3MT";
    S7_BlockNumber := "15151";
    S7_BlockTitle := "MLC_47N";
    S7_EditorMode := "SCL";
    S7_Family := "ZeusControl";
    S7_IECCheck := "TRUE";
    S7_Optimized := "TRUE";
    S7_Version := "1.0"
}
FUNCTION "FC15151_ZC_MARCHA_PARO_SEC" : Void
    VAR_INPUT
        { S7_MLC := "MLC_xg" }
        Pulso1Seg : Bool;
        { S7_MLC := "MLC_3UA" }
        Seguridad : Bool;
        { S7_MLC := "MLC_3g2" }
        Marcha : Bool;
    END_VAR
    VAR_IN_OUT
        MP_SEC : _.UDT_ZC_MARCHA_PARO_SEC;
    END_VAR
    VAR CONSTANT
        REPOSO : Int := 0;
        MARCHA_1 : Int := 10;
        MARCHA_2 : Int := 20;
        MARCHA_3 : Int := 30;
        MARCHA_4 : Int := 40;
        MARCHA_5 : Int := 50;
        MARCHA_6 : Int := 60;
        MARCHA_7 : Int := 70;
        MARCHA_8 : Int := 80;
    END_VAR

    { S7_Language := "SCL" }
    NETWORK
        REGION DESCRIPCION
        (*
        ###### (C)Copyright ZeusControl 2023 - 2025
        
        ---
        ### Información del Sistema
        | Hardware Compatible | Entorno de Ingeniería |
        |---------------------|-----------------------|
        | PLC serie 1200/1500 | TIA Portal 18         |
        
        ---
        > **Restricciones:** Ninguna.
        
        ---
        ### Descripción Funcional
        
        Función encargada de la gestión de secuencias de arranque y parada escalonada de hasta 8 dispositivos de forma temporizada.
        
            - Evaluar dinámicamente los parámetros de configuración, limitando el número de elementos de la secuencia a un rango válido entre 1 y 8 mediante la variable `NumElementos`.
            - Gestionar el traspaso del tiempo de espera entre etapas, aplicando de forma automática los parámetros `TiempoEntreMarcha` o `TiempoEntreParo` según el estado de la orden activa en la entrada `Marcha`.
            - Ejecutar una máquina de estados para la transición secuencial de las etapas de operación, controlando el tiempo de permanencia en cada fase mediante la señal base de tiempo `Pulso1Seg`.
            - Monitorizar de forma continua la señal de `Seguridad`, forzando el reinicio seguro de la máquina de estados a la etapa de reposo y limpiando los temporizadores en caso de pérdida.
            - Calcular y activar las señales de salida operativas, incluyendo los bits individuales de activación por dispositivo (`M[1]` a `M[8]`) y las confirmaciones de ciclo finalizado (`SecMarchaCompletada` y `SecParoCompletada`).
        
        ---
        ### Dependencias Requeridas
        | Tipo | Elementos |
        |------|-----------|
        | FC   | - |
        | FB   | - |
        | DB   | - |
        | UDT  | ´UDT_ZC_MARCHA_PARO_SEC´ |
        
        ---
        ### Historial de Cambios
        | Versión  | Fecha      | Técnico | Cambios |
        |----------|------------|---------|---------|
        | 01.00.00 | 24.05.2023 | (ABH)   | Primera version. |
        | 01.00.01 | 28.07.2023 | (ABH)   | Se añade traspaso de Set Point de tiempo de paso dentro del FC. |
        | 01.00.02 | 14.03.2025 | (ABH)   | Se separan los tiempos de arranque de marcha y paro. |
        *)
        END_REGION DESCRIPCION
        
        
        //  ==========================================================================================================
        REGION TRASPASO_PARAMETROS
            
            //  Limite de numero de elementos
            IF #MP_SEC.NumElementos < 1 THEN
                #MP_SEC.NumElementos := 1;
            END_IF;
            
            IF #MP_SEC.NumElementos > 8 THEN
                #MP_SEC.NumElementos := 8;
            END_IF;
            
            //  Traspaso de set point tiempo etapa
            IF #Marcha THEN
                #MP_SEC.Tiempo.SetPoint := #MP_SEC.TiempoEntreMarcha;
            ELSE
                #MP_SEC.Tiempo.SetPoint := #MP_SEC.TiempoEntreParo;
            END_IF;
            
            //  Seguridad
            IF NOT #Seguridad THEN
                #MP_SEC.Etapa := #MP_SEC.Tiempo.Actual := 0;
            END_IF;
            
        END_REGION TRASPASO_PARAMETROS
        
        
        //  ==========================================================================================================
        REGION SECUENCIA
            
            CASE #MP_SEC.Etapa OF
                    
                    //  ==========================================================================================================
                #REPOSO:
                    IF #Marcha AND #Seguridad THEN
                        #MP_SEC.Etapa := #MARCHA_1;
                        #MP_SEC.Tiempo.Actual := 0;
                    END_IF;
                    
                    //  ==========================================================================================================
                #MARCHA_1:
                    
                    //  Activacion tiempo de etapa
                    #MP_SEC.Tiempo.Activar := TRUE;
                    
                    //  Con tiempo de etapa cumplido
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
                        
                        //  Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
                        IF #Marcha THEN
                            
                            IF #MP_SEC.NumElementos > 1 THEN
                                #MP_SEC.Etapa := #MARCHA_2;
                                #MP_SEC.Tiempo.Actual := 0;
                            ELSE
                                #MP_SEC.Tiempo.Activar := FALSE;
                            END_IF;
                            
                        ELSE
                            #MP_SEC.Etapa := #REPOSO;
                            #MP_SEC.Tiempo.Actual := 0;
                        END_IF;
                        
                    END_IF;
                    
                    //  ==========================================================================================================
                #MARCHA_2:
                    
                    //  Activacion tiempo de etapa
                    #MP_SEC.Tiempo.Activar := TRUE;
                    
                    //  Con tiempo de etapa cumplido
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
                        
                        //  Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
                        IF #Marcha THEN
                            
                            IF #MP_SEC.NumElementos > 2 THEN
                                #MP_SEC.Etapa := #MARCHA_3;
                                #MP_SEC.Tiempo.Actual := 0;
                            ELSE
                                #MP_SEC.Tiempo.Activar := FALSE;
                            END_IF;
                            
                        ELSE
                            #MP_SEC.Etapa := #MARCHA_1;
                            #MP_SEC.Tiempo.Actual := 0;
                        END_IF;
                        
                    END_IF;
                    
                    //  ==========================================================================================================
                #MARCHA_3:
                    
                    //  Activacion tiempo de etapa
                    #MP_SEC.Tiempo.Activar := TRUE;
                    
                    //  Con tiempo de etapa cumplido
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
                        
                        //  Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
                        IF #Marcha THEN
                            
                            IF #MP_SEC.NumElementos > 3 THEN
                                #MP_SEC.Etapa := #MARCHA_4;
                                #MP_SEC.Tiempo.Actual := 0;
                            ELSE
                                #MP_SEC.Tiempo.Activar := FALSE;
                            END_IF;
                            
                        ELSE
                            #MP_SEC.Etapa := #MARCHA_2;
                            #MP_SEC.Tiempo.Actual := 0;
                        END_IF;
                        
                    END_IF;
                    
                    //  ==========================================================================================================
                #MARCHA_4:
                    
                    //  Activacion tiempo de etapa
                    #MP_SEC.Tiempo.Activar := TRUE;
                    
                    //  Con tiempo de etapa cumplido
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
                        
                        //  Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
                        IF #Marcha THEN
                            
                            IF #MP_SEC.NumElementos > 4 THEN
                                #MP_SEC.Etapa := #MARCHA_5;
                                #MP_SEC.Tiempo.Actual := 0;
                            ELSE
                                #MP_SEC.Tiempo.Activar := FALSE;
                            END_IF;
                            
                        ELSE
                            #MP_SEC.Etapa := #MARCHA_3;
                            #MP_SEC.Tiempo.Actual := 0;
                        END_IF;
                        
                    END_IF;
                    
                    //  ==========================================================================================================
                #MARCHA_5:
                    
                    //  Activacion tiempo de etapa
                    #MP_SEC.Tiempo.Activar := TRUE;
                    
                    //  Con tiempo de etapa cumplido
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
                        
                        //  Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
                        IF #Marcha THEN
                            
                            IF #MP_SEC.NumElementos > 5 THEN
                                #MP_SEC.Etapa := #MARCHA_6;
                                #MP_SEC.Tiempo.Actual := 0;
                            ELSE
                                #MP_SEC.Tiempo.Activar := FALSE;
                            END_IF;
                            
                        ELSE
                            #MP_SEC.Etapa := #MARCHA_4;
                            #MP_SEC.Tiempo.Actual := 0;
                        END_IF;
                        
                    END_IF;
                    
                    //  ==========================================================================================================
                #MARCHA_6:
                    
                    //  Activacion tiempo de etapa
                    #MP_SEC.Tiempo.Activar := TRUE;
                    
                    //  Con tiempo de etapa cumplido
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
                        
                        //  Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
                        IF #Marcha THEN
                            
                            IF #MP_SEC.NumElementos > 6 THEN
                                #MP_SEC.Etapa := #MARCHA_7;
                                #MP_SEC.Tiempo.Actual := 0;
                            ELSE
                                #MP_SEC.Tiempo.Activar := FALSE;
                            END_IF;
                            
                        ELSE
                            #MP_SEC.Etapa := #MARCHA_5;
                            #MP_SEC.Tiempo.Actual := 0;
                        END_IF;
                        
                    END_IF;
                    
                    //  ==========================================================================================================
                #MARCHA_7:
                    
                    //  Activacion tiempo de etapa
                    #MP_SEC.Tiempo.Activar := TRUE;
                    
                    //  Con tiempo de etapa cumplido
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
                        
                        //  Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
                        IF #Marcha THEN
                            
                            IF #MP_SEC.NumElementos > 7 THEN
                                #MP_SEC.Etapa := #MARCHA_8;
                                #MP_SEC.Tiempo.Actual := 0;
                            ELSE
                                #MP_SEC.Tiempo.Activar := FALSE;
                            END_IF;
                            
                        ELSE
                            #MP_SEC.Etapa := #MARCHA_6;
                            #MP_SEC.Tiempo.Actual := 0;
                        END_IF;
                        
                    END_IF;
                    
                    //  ==========================================================================================================
                #MARCHA_8:
                    
                    //  Activacion tiempo de etapa
                    #MP_SEC.Tiempo.Activar := TRUE;
                    
                    //  Con tiempo de etapa cumplido
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
                        
                        //  Estando en marcha, reseteamos el tiempo de etapa
                        IF #Marcha THEN
                            #MP_SEC.Tiempo.Activar := FALSE;
                        ELSE
                            #MP_SEC.Etapa := #MARCHA_7;
                            #MP_SEC.Tiempo.Actual := 0;
                        END_IF;
                        
                    END_IF;
                    
                ELSE
                    #MP_SEC.Etapa := #REPOSO;
            END_CASE;
            
            
        END_REGION SECUENCIA
        
        
        //  ==========================================================================================================
        REGION TIEMPO_DE_ETAPA
            
            IF #MP_SEC.Tiempo.Activar THEN
                
                IF #Pulso1Seg THEN
                    #MP_SEC.Tiempo.Actual += 1;
                END_IF;
                
                #MP_SEC.Tiempo.Restante := #MP_SEC.Tiempo.SetPoint - #MP_SEC.Tiempo.Actual;
                
                IF #MP_SEC.Tiempo.Restante <= 0 THEN
                    #MP_SEC.Tiempo.Restante := 0;
                END_IF;
                
                #MP_SEC.Tiempo.Activar := FALSE;
                
            END_IF;
            
        END_REGION TIEMPO_DE_ETAPA
        
        
        //  ==========================================================================================================
        REGION SALIDAS
            
            //  Secuencia paro completada
            #MP_SEC.SecParoCompletada := #MP_SEC.Etapa = 0;
            
            //  Secuencia Marcha completada
            #MP_SEC.SecMarchaCompletada := FALSE;
            CASE #MP_SEC.NumElementos OF
                1:
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 10 THEN
                        #MP_SEC.SecMarchaCompletada := TRUE;
                    END_IF;
                2:
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 20 THEN
                        #MP_SEC.SecMarchaCompletada := TRUE;
                    END_IF;
                3:
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 30 THEN
                        #MP_SEC.SecMarchaCompletada := TRUE;
                    END_IF;
                4:
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 40 THEN
                        #MP_SEC.SecMarchaCompletada := TRUE;
                    END_IF;
                5:
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 50 THEN
                        #MP_SEC.SecMarchaCompletada := TRUE;
                    END_IF;
                6:
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 60 THEN
                        #MP_SEC.SecMarchaCompletada := TRUE;
                    END_IF;
                7:
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 70 THEN
                        #MP_SEC.SecMarchaCompletada := TRUE;
                    END_IF;
                8:
                    IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 80 THEN
                        #MP_SEC.SecMarchaCompletada := TRUE;
                    END_IF;
            END_CASE;
            
            //  Bit marcha elementos
            #MP_SEC.M[1] := #MP_SEC.Etapa >= 10;
            #MP_SEC.M[2] := #MP_SEC.Etapa >= 20;
            #MP_SEC.M[3] := #MP_SEC.Etapa >= 30;
            #MP_SEC.M[4] := #MP_SEC.Etapa >= 40;
            #MP_SEC.M[5] := #MP_SEC.Etapa >= 50;
            #MP_SEC.M[6] := #MP_SEC.Etapa >= 60;
            #MP_SEC.M[7] := #MP_SEC.Etapa >= 70;
            #MP_SEC.M[8] := #MP_SEC.Etapa >= 80;
            
        END_REGION
        
        
    END_NETWORK
END_FUNCTION
