{
    S7_Author := "ABH";
    S7_BlockComment := "MLC_uc";
    S7_BlockNumber := "15104";
    S7_BlockTitle := "MLC_55Q";
    S7_EditorMode := "SCL";
    S7_Family := "ZeusControl";
    S7_IECCheck := "TRUE";
    S7_Optimized := "TRUE";
    S7_Version := "1.0"
}
FUNCTION_BLOCK "FB15104_ZC_CALCULO_LIMP_2_MOD"
    VAR_INPUT
        { S7_MLC := "MLC_4U2" }
        EtapaRecirculacion : Bool;
        { S7_MLC := "MLC_xv" }
        EtapaTiempoRestante : Int;
        { S7_MLC := "MLC_3Q4" }
        SP_TiempoRecirculacion : Int;
        { S7_MLC := "MLC_YU" }
        SP_Modulo1 : Real;
        { S7_MLC := "MLC_4MX" }
        SP_Modulo2 : Real;
    END_VAR
    VAR_OUTPUT
        { S7_MLC := "MLC_3Na" }
        LimpiarSoloModulo1 : Bool;
        { S7_MLC := "MLC_4Lz" }
        LimpiarSoloModulo2 : Bool;
        { S7_MLC := "MLC_3Cc" }
        LimpiarTodosLosModulos : Bool;
    END_VAR
    VAR RETAIN
        {
            S7_Access := "ReadOnly := External";
            S7_MLC := "MLC_cF";
            S7_Visibility := "Hidden := External"
        }
        s_PorcentajeMinimoTodosModulos : Real := 20.0;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_PorcentajeModulo1 : Real;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_PorcentajeModulo2 : Real;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_PorcentajeRestante : Real;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_CalculoTiempoModulo1 : Int;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_CalculoTiempoModulo2 : Int;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_CalculoTiempoRestante : Int;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_TiempoModulo1 : Int;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_TiempoModulo2 : Int;
    END_VAR

    { S7_Language := "SCL" }
    NETWORK
        REGION DESCRIPCION
        //=======================================================================
        // (C)Copyright ZeusControl 2024 - 2026
        //=======================================================================
        (*
        ### Información del Sistema
        | Hardware Compatible | Entorno de Ingeniería |
        |---------------------|-----------------------|
        | PLC serie 1200/1500 | TIA Portal 18         |
        
        ---
        ### Descripción Funcional
        Bloque de funcion que implementa el cálculo y la distribución temporal de la limpieza de 2 módulos de membranas, con soporte operativo para 3 módulos mediante la agrupación de los módulos 2 y 3 en una sola fase. Permite configurar, en porcentaje, el peso de cada módulo dentro del tiempo total de recirculación y reparte el tiempo restante a una fase conjunta de limpieza de todos los módulos.
        
        Funcionalidades principales:
        - Traspaso y validación de porcentajes: se leen los porcentajes de cada módulo (`SP_Modulo1`, `SP_Modulo2`) y se limitan para que la suma no supere el máximo disponible (`100 - s_PorcentajeMinimoTodosModulos`). Si la suma supera dicho umbral, ambos porcentajes se igualan al valor medio permitido, garantizando que siempre quede un mínimo reservado para la fase de limpieza conjunta. El porcentaje restante (`s_PorcentajeRestante`) se calcula como `100 - (s_PorcentajeModulo1 + s_PorcentajeModulo2)`.
        - Cálculo de tiempos: a partir del tiempo total de recirculación (`SP_TiempoRecirculacion`) y de los porcentajes validados, se obtienen los tiempos individuales de cada módulo (`s_CalculoTiempoModulo1`, `s_CalculoTiempoModulo2`) y el tiempo restante (`s_CalculoTiempoRestante`). Se calculan también los tiempos acumulados hasta el inicio de cada fase (`s_TiempoModulo1`, `s_TiempoModulo2`) para acotar la salida de la etapa en curso.
        - Activación de salidas de limpieza: durante la etapa de recirculación (`EtapaRecirculacion`), en función del valor de `EtapaTiempoRestante`, se activa la salida correspondiente:
            - `LimpiarSoloModulo1`: mientras el tiempo restante está comprendido entre `s_TiempoModulo1` y `SP_TiempoRecirculacion` y el porcentaje del módulo 1 es distinto de cero.
            - `LimpiarSoloModulo2`: mientras el tiempo restante está comprendido entre `s_TiempoModulo2` y `s_TiempoModulo1` y el porcentaje del módulo 2 es distinto de cero.
            - `LimpiarTodosLosModulos`: en el resto de casos, durante la fase final del tiempo de recirculación.
        - Las salidas son mutuamente excluyentes: en todo momento solo una de las tres se encuentra activa, inicializándose todas a `FALSE` al inicio de la región.
        
        > **Restricciones:** Ninguna.
        
        ---
        ### Dependencias Requeridas
        | Tipo | Elementos |
        |------|-----------|
        | FC   | - |
        | FB   | - |
        | DB   | - |
        | UDT  | - |
            
        ---
        ### Historial de Cambios
        | Versión  | Fecha      | Técnico | Cambios |
        |----------|------------|---------|---------|
        | 01.00.00 | 12.09.2023 | (ABH)   | Primera versión. |
        | 01.00.01 | 17.11.2023 | (HCR/ABH) | Cambio en nombre de parámetro de entrada `EtapaTiempoActual` por `EtapaTiempoRestante`. Se añade parámetro estático `s_PorcentajeMinimoTodosModulos` para límite de los SP de porcentaje de tiempo de cada módulo para no sobrepasar el 100% del tiempo. |
        *)
        END_REGION DESCRIPCION
        
        
        //  ==========================================================================================================
        REGION TRASPASO_PARAMETROS
            
            //  =====================================================================================
            //  TRASPASO DE PARAMETROS DE PORCENTAJE
            //  Se revisa los limites de los porcentajes metidos en pantalla
            IF (#SP_Modulo1 + #SP_Modulo2) > (100.0 - #s_PorcentajeMinimoTodosModulos) THEN
                #s_PorcentajeModulo1 := ((100.0 - #s_PorcentajeMinimoTodosModulos) / 2.0);
                #s_PorcentajeModulo2 := #s_PorcentajeModulo1;
            ELSE
                #s_PorcentajeModulo1 := #SP_Modulo1;
                #s_PorcentajeModulo2 := #SP_Modulo2;
            END_IF;
            #s_PorcentajeRestante := 100.0 - (#s_PorcentajeModulo1 + #s_PorcentajeModulo2);
            
        END_REGION
        
        
        //  ==========================================================================================================
        REGION CALCULOS
            
            //  =====================================================================================
            //  CALCULO DE TIEMPO DE PASO
            //  MODULO 1
            IF #s_PorcentajeModulo1 <> 0.0 THEN
                #s_CalculoTiempoModulo1 := REAL_TO_INT((#s_PorcentajeModulo1 * #SP_TiempoRecirculacion) / 100.0);
            END_IF;
            
            //  MODULO 2 y 3
            IF #s_PorcentajeModulo2 <> 0.0 THEN
                #s_CalculoTiempoModulo2 := REAL_TO_INT((#s_PorcentajeModulo2 * #SP_TiempoRecirculacion) / 100.0);
            END_IF;
            
            //  TIEMPO RESTANTE
            #s_CalculoTiempoRestante := #SP_TiempoRecirculacion - (#s_CalculoTiempoModulo1 + #s_CalculoTiempoModulo2);
            
            
            #s_TiempoModulo1 := #SP_TiempoRecirculacion - #s_CalculoTiempoModulo1;
            #s_TiempoModulo2 := #SP_TiempoRecirculacion - #s_CalculoTiempoModulo1 - #s_CalculoTiempoModulo2;
            
        END_REGION
        
        
        //  ==========================================================================================================
        REGION SALIDAS
            
            #LimpiarSoloModulo1 := #LimpiarSoloModulo2 := #LimpiarTodosLosModulos := FALSE;
            
            IF #EtapaRecirculacion THEN
                
                IF (#s_PorcentajeModulo1 <> 0.0) AND #EtapaTiempoRestante <= #SP_TiempoRecirculacion AND #EtapaTiempoRestante > #s_TiempoModulo1 THEN
                    #LimpiarSoloModulo1 := TRUE;
                    #LimpiarSoloModulo2 := #LimpiarTodosLosModulos := FALSE;
                ELSIF (#s_PorcentajeModulo2 <> 0.0) AND #EtapaTiempoRestante <= #s_TiempoModulo1 AND #EtapaTiempoRestante > #s_TiempoModulo2 THEN
                    #LimpiarSoloModulo2 := TRUE;
                    #LimpiarSoloModulo1 := #LimpiarTodosLosModulos := FALSE;
                ELSE
                    #LimpiarTodosLosModulos := TRUE;
                    #LimpiarSoloModulo1 := #LimpiarSoloModulo2 := FALSE;
                END_IF;
                
            END_IF;
            
        END_REGION
        
        
    END_NETWORK
END_FUNCTION_BLOCK
