{
    S7_Author := "HCR";
    S7_BlockNumber := "15149";
    S7_BlockTitle := "MLC_3cn";
    S7_EditorMode := "SCL";
    S7_Family := "ZeusControl";
    S7_Optimized := "TRUE";
    S7_Version := "1.0"
}
FUNCTION_BLOCK "FB15049_ZC_AIRE_ESTERIL"
    VAR_INPUT
        { S7_MLC := "MLC_33z" }
        Pulso1Seg : Bool;
        { S7_MLC := "MLC_4GG" }
        HabilitarMantenimiento : Bool;
        { S7_MLC := "MLC_39V" }
        AlarmaFalloVapor : Bool;
        { S7_MLC := "MLC_Xw" }
        FechaHora : DTL;
        { S7_MLC := "MLC_4TG" }
        TempEsterilAlcanzada : Bool;
        { S7_MLC := "MLC_3r4" }
        SP_TiempoEsterilizacion : Int;
        { S7_MLC := "MLC_3XU" }
        SP_TiempoEnfriamiento : Int;
        { S7_MLC := "MLC_45q" }
        SP_NumeroMaximoEsterilizacion : Int;
        { S7_MLC := "MLC_zF" }
        SP_DiasMaximoFiltroEsteril : Int;
        { S7_MLC := "MLC_WZ" }
        ProcesoID : Int := 15049;
    END_VAR
    VAR_INPUT RETAIN
        { S7_MLC := "MLC_3cm" }
        Usuario : String[25];
    END_VAR
    VAR_INPUT
        { S7_MLC := "MLC_42q" }
        MinutoAlarma : USInt;
        { S7_MLC := "MLC_sZ" }
        SegundoAlarma : USInt;
    END_VAR
    VAR_IN_OUT
        { S7_MLC := "MLC_54s" }
        ParoMantenimiento : Bool;
        { S7_MLC := "MLC_3Du" }
        AvisoDiasEsterilizacion : Bool;
        { S7_MLC := "MLC_52S" }
        AlarmaDiasEsterilizacion : Bool;
    END_VAR
    VAR
        { S7_MLC := "MLC_4jQ" }
        s_Habilitar : Bool;
        { S7_MLC := "MLC_ZU" }
        s_FiltroEsteril : Bool;
    END_VAR
    VAR RETAIN
        { S7_MLC := "MLC_3qw" }
        s_Etapa : Int;
        { S7_MLC := "MLC_m7" }
        s_NumeroEsterilizaciones : Int;
    END_VAR
    VAR
        { S7_MLC := "MLC_3gR" }
        S_NumeroDiasEsterilizacion : Int;
    END_VAR
    VAR RETAIN
        {
            S7_MLC := "MLC_4hW";
            S7_Setpoint := "False"
        }
        s_TiempoEtapa : _.UDT_ZC_PRO_TIEMPO_ETAPA;
    END_VAR
    VAR
        { S7_MLC := "MLC_4vd" }
        Pulsadores : STRUCT
            {
                S7_MLC := "MLC_3jq";
                S7_Setpoint := "False"
            }
            Habilitar : _.UDT_ZC_PULSADOR;
            {
                S7_MLC := "MLC_3im";
                S7_Setpoint := "False"
            }
            Deshabilitar : _.UDT_ZC_PULSADOR;
            {
                S7_MLC := "MLC_49T";
                S7_Setpoint := "False"
            }
            Mantenimiento : _.UDT_ZC_PULSADOR;
        END_STRUCT;
    END_VAR
    VAR RETAIN
        { S7_MLC := "MLC_4jg" }
        TiempoEsterelizado : _.UDT_ZC_CONTADOR_TIEMPO;
    END_VAR
    VAR
        {
            S7_Access := "ReadOnly := External";
            S7_MLC := "MLC_RL";
            S7_Visibility := "Hidden := External"
        }
        s_PasswordCalculado : UInt;
        { S7_MLC := "MLC_3mQ" }
        s_PasswordHMI : UInt;
        { S7_Setpoint := "True" }
        s_MostrarAlarmaMto : Bool;
        { S7_Setpoint := "True" }
        s_oldMostrarAlarmaMto : Bool;
    END_VAR
    VAR_TEMP
        t_ResetContador : Bool;
        t_DiasAvisos : Int;
    END_VAR
    VAR CONSTANT
        ETAPA_0_REPOSO : Int := 0;
        ETAPA_10_ESTERILIZANDO : Int := 10;
        ETAPA_20_ESTERILIZADO : Int := 20;
        ETAPA_30_ENFRIAMIENTO : Int := 30;
    END_VAR

    { S7_Language := "SCL" }
    NETWORK
        REGION DESCRIPCION
        //=======================================================================
        // (C)Copyright ZeusControl 2024 - 202
        //=======================================================================
        (*
        ### Información del Sistema
        | Hardware Compatible | Entorno de Ingeniería |
        |---------------------|-----------------------|
        | PLC serie 1200/1500 | TIA Portal 18         |
        
        ---
        ### Descripción Funcional
        Función principal para la gestión integral y secuencial del dispositivo del tanque de aire estéril.
        
        > **Restricciones:** Ninguna.
        
        - Evaluar y gestionar las órdenes temporizadas provenientes de los pulsadores del HMI (`Habilitar`, `Deshabilitar`, `Mantenimiento`) mediante la invocación de `FC15026_ZC_PULSADOR`.
        - Ejecutar la máquina de estados principal para controlar el ciclo de vida y las fases operativas del sistema: `REPOSO`, `ESTERILIZANDO`, `ENFRIAMIENTO` y `ESTERILIZADO`.
        - Contabilizar el tiempo de permanencia en estado estéril utilizando `FC15025_ZC_CONTADOR_TIEMPO`, llevando el registro acumulado de días de operación del filtro.
        - Monitorizar dinámicamente los tiempos de cada etapa (`s_TiempoEtapa`) y validar las transiciones de estado en función de la temperatura (`TempEsterilAlcanzada`) o la detección de fallos (`AlarmaFalloVapor`).
        - Revocar automáticamente el estado de filtro estéril (`s_FiltroEsteril`) al superar el límite máximo de días configurado en `SP_DiasMaximoFiltroEsteril`.
        - Procesar las rutinas de parada por mantenimiento preventivo, exigiendo validación de seguridad mediante contraseña (`s_PasswordHMI` vs `s_PasswordCalculado`) una vez alcanzado el límite de esterilizaciones (`SP_NumeroMaximoEsterilizacion`).
        - Calcular y emitir señales preventivas de aviso (`AvisoDiasEsterilizacion`) y alarma crítica (`AlarmaDiasEsterilizacion`) según la caducidad operativa del filtro estéril.
        
        ---
        ### Dependencias Requeridas
        | Tipo | Elementos |
        |------|-----------|
        | FC   | `FC15025_ZC_CONTADOR_TIEMPO`, `FC15026_ZC_PULSADOR` |
        | FB   | - |
        | DB   | - |
        | UDT  | `UDT_ZC_CONTADOR_TIEMPO`, `UDT_ZC_PRO_TIEMPO_ETAPA`, `UDT_ZC_PULSADOR` |
            
        ---
        ### Historial de Cambios
        | Versión  | Fecha      | Técnico | Cambios |
        |----------|------------|---------|---------|
        | 01.00.00 | 15.10.2024 | (HCR) | Primera version. |
        | 01.00.01 | 28.01.2025 | (ABH) | Se cambia organizacion de variables y nombres para estandarizacion. |
        *)
        END_REGION DESCRIPCION
        
        
        //  ==========================================================================================================
        REGION PULSADORES
            
            //  Permiso pulsadores
            #Pulsadores.Habilitar.Permiso := NOT #s_Habilitar;
            #Pulsadores.Deshabilitar.Permiso := #s_Habilitar;
            #Pulsadores.Mantenimiento.Permiso := #ParoMantenimiento;
            
            //  Gestion pulsadores
            "FC15026_ZC_PULSADOR"(Pulso1Seg := #Pulso1Seg,
                                  SP_Tiempo := 2,
                                  TrazaCategoria:="TRZ_CAT_4_PRO_PUL",
                                  TrazaIdProceso:=#ProcesoID,
                                  TrazaIdPulsador:="TRZ_SYS_PUL_AE_HAB",
                                  Usuario := #Usuario,
                                  FechaHoraActual := #FechaHora,
                                  Pulsador := #Pulsadores.Habilitar);
            "FC15026_ZC_PULSADOR"(Pulso1Seg := #Pulso1Seg,
                                  SP_Tiempo := 2,
                                  TrazaCategoria:="TRZ_CAT_4_PRO_PUL",
                                  TrazaIdProceso:=#ProcesoID,
                                  TrazaIdPulsador:="TRZ_SYS_PUL_AE_DES",
                                  Usuario := #Usuario,
                                  FechaHoraActual := #FechaHora,
                                  Pulsador := #Pulsadores.Deshabilitar);
            "FC15026_ZC_PULSADOR"(Pulso1Seg := #Pulso1Seg,
                                  SP_Tiempo := 2,
                                  TrazaCategoria:="TRZ_CAT_4_PRO_PUL",
                                  TrazaIdProceso:=#ProcesoID,
                                  TrazaIdPulsador:="TRZ_SYS_PUL_AE_MNT",
                                  Usuario := #Usuario,
                                  FechaHoraActual := #FechaHora,
                                  Pulsador := #Pulsadores.Mantenimiento);
            
            //  Orden habilitar aire esteril
            IF #Pulsadores.Habilitar.Plc THEN
                #s_Habilitar := TRUE;
            ELSIF #Pulsadores.Deshabilitar.Plc THEN
                #s_Habilitar := FALSE;
            END_IF;
            
        END_REGION PULSADORES
        
        
        //  ==========================================================================================================
        REGION SECUENCIA_FILTRO  
            
            CASE #s_Etapa OF
                    
                    // =============================================================================    
                #ETAPA_0_REPOSO:
                    IF #s_Habilitar THEN
                        #s_Etapa := #ETAPA_20_ESTERILIZADO;
                        #s_TiempoEtapa.Actual := 0;
                    END_IF;
                    
                    // =============================================================================    
                #ETAPA_10_ESTERILIZANDO:
                    #s_TiempoEtapa.SP := #SP_TiempoEsterilizacion;
                    
                    IF NOT #s_Habilitar THEN
                        #s_Etapa := #ETAPA_0_REPOSO;
                    END_IF;
                    IF #AlarmaFalloVapor THEN
                        #s_Etapa := #ETAPA_0_REPOSO;
                    END_IF;
                    IF #s_TiempoEtapa.Cumplido THEN
                        #s_Etapa := #ETAPA_30_ENFRIAMIENTO;
                        #s_TiempoEtapa.Actual := 0;
                        #S_NumeroDiasEsterilizacion := 0;
                        #s_NumeroEsterilizaciones += 1;
                        #s_FiltroEsteril := TRUE;
                       
                    END_IF;
                    IF #TempEsterilAlcanzada THEN
                        #s_TiempoEtapa.Activar := TRUE;
                    ELSE
                        #s_TiempoEtapa.Activar := FALSE;
                        #s_TiempoEtapa.Actual := 0;
                    END_IF;
                    // =============================================================================              
                #ETAPA_30_ENFRIAMIENTO:
                    #s_TiempoEtapa.SP := #SP_TiempoEnfriamiento;
                    #s_TiempoEtapa.Activar := TRUE;
                    
                    IF NOT #s_Habilitar THEN
                        #s_Etapa := #ETAPA_0_REPOSO;
                    END_IF;
                    IF #s_TiempoEtapa.Cumplido THEN
                        #s_Etapa := #ETAPA_20_ESTERILIZADO;
                        #s_TiempoEtapa.Actual := 0;
                    END_IF;
                    // ============================================================================= 
                #ETAPA_20_ESTERILIZADO:
                    #s_TiempoEtapa.SP := 5;
                    IF NOT #s_Habilitar THEN
                        #s_Etapa := #ETAPA_0_REPOSO;
                    END_IF;
                    IF #s_TiempoEtapa.Cumplido THEN
                        #s_Etapa := #ETAPA_10_ESTERILIZANDO;
                        #s_TiempoEtapa.Actual := 0;
                    END_IF;
                    IF #TempEsterilAlcanzada AND NOT #s_FiltroEsteril THEN
                        #s_TiempoEtapa.Activar := TRUE;
                    ELSE
                        #s_TiempoEtapa.Activar := FALSE;
                        #s_TiempoEtapa.Actual := 0;
                    END_IF;
                ELSE
                    #s_Etapa := #ETAPA_0_REPOSO;
            END_CASE;
            
        END_REGION SECUENCIA_FILTRO  
        
        
        //  ==========================================================================================================
        REGION TIEMPO_ESTERILIZADO
            
            //  Incrementar dias de filtro #ESTERILIZADO
            IF #TiempoEsterelizado.Hora >= 24 THEN
                #t_ResetContador := TRUE;
                #S_NumeroDiasEsterilizacion += 1;
            END_IF;
            
            "FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg:=#Pulso1Seg,
                                         Iniciar:=#Pulso1Seg AND (#s_Etapa = #ETAPA_20_ESTERILIZADO),
                                         Reset:=#t_ResetContador,
                                         Contador:=#TiempoEsterelizado);
            
            //  Quitar estado filtro esteril
            IF #S_NumeroDiasEsterilizacion >= #SP_DiasMaximoFiltroEsteril THEN
                #s_FiltroEsteril := FALSE;
            END_IF;
            
        END_REGION TIEMPO_ESTERILIZADO
        
        
        //  ==========================================================================================================
        REGION TIEMPO_ETAPA
            
            //  Proceso en estado parado
            IF #s_Etapa = #ETAPA_0_REPOSO THEN
                #s_TiempoEtapa.Actual := 0;
                #s_TiempoEtapa.Activar := FALSE;
            END_IF;
            
            //  Temporizador activo
            IF #s_TiempoEtapa.Activar THEN
                IF #Pulso1Seg
                    AND
                    (#s_TiempoEtapa.Actual < #s_TiempoEtapa.SP)
                THEN
                    #s_TiempoEtapa.Actual += 1;
                END_IF;
                
                //  Reiniciar tiempo paso cumplido para esperar condicion
                #s_TiempoEtapa.Cumplido := FALSE;
                
                //  Tiempo paso cumplido 
                IF #s_TiempoEtapa.Actual >= #s_TiempoEtapa.SP AND #s_TiempoEtapa.Activar THEN
                    #s_TiempoEtapa.Cumplido := TRUE;
                END_IF;
                
                //  Tiempo restante
                #s_TiempoEtapa.Restante := #s_TiempoEtapa.SP - #s_TiempoEtapa.Actual;
            END_IF;
            
            //  Tiempo restante
            #s_TiempoEtapa.Restante := #s_TiempoEtapa.SP - #s_TiempoEtapa.Actual;
            
        END_REGION TIEMPO_ETAPA
        
        
        //  ==========================================================================================================
        REGION MANTENIMIENTO
            
            //  Flanco mostrar cartel de mantenieminto
            IF #HabilitarMantenimiento THEN
                
                #s_MostrarAlarmaMto := (#FechaHora.MINUTE = #MinutoAlarma) AND (#FechaHora.SECOND = #SegundoAlarma) AND (#s_NumeroEsterilizaciones >= #SP_NumeroMaximoEsterilizacion);
                
                IF #s_MostrarAlarmaMto AND NOT #s_oldMostrarAlarmaMto THEN
                    #ParoMantenimiento := TRUE;
                    #s_PasswordCalculado :=
                    #s_PasswordHMI := 0;
                END_IF;
                
                //  Pulsador chequear contraseña de mantenimiento
                IF #Pulsadores.Mantenimiento.Plc THEN
                    #s_PasswordCalculado := #FechaHora.YEAR + #FechaHora.MONTH + #FechaHora.DAY;
                    IF #s_PasswordCalculado = #s_PasswordHMI THEN
                        #s_NumeroEsterilizaciones := 0;
                        #S_NumeroDiasEsterilizacion := 0;
                    END_IF;
                    #s_PasswordCalculado :=
                    #s_PasswordHMI := 0;
                    #ParoMantenimiento := FALSE;
                END_IF;
            ELSE
                #ParoMantenimiento := FALSE;
            END_IF;
            
            #s_oldMostrarAlarmaMto := #s_MostrarAlarmaMto;
            
        END_REGION MANTENIMIENTO
        
        
        //  ==========================================================================================================
        REGION ALARMAS
            
            //  Aviso un dia antes  
            #t_DiasAvisos := #SP_DiasMaximoFiltroEsteril - 1;
            IF #t_DiasAvisos < 0 THEN
                #t_DiasAvisos := 0;
            END_IF;
            
            //  Alarmas por dia de esterilizacion
            #AlarmaDiasEsterilizacion := (#S_NumeroDiasEsterilizacion >= #SP_DiasMaximoFiltroEsteril);
            #AvisoDiasEsterilizacion := (#S_NumeroDiasEsterilizacion >= #t_DiasAvisos AND NOT #AlarmaDiasEsterilizacion);
            
        END_REGION ALARMAS
        
        
        //  ==========================================================================================================
        REGION NUMERO_ESTERILIZACIONES
            
            IF #s_NumeroEsterilizaciones = 0 THEN
                #s_NumeroEsterilizaciones += 1;
            END_IF;
            
        END_REGION NUMERO_ESTERILIZACIONES
        
    END_NETWORK
END_FUNCTION_BLOCK
