FUNCTION_BLOCK "FB15055_ZC_HORAS_MAQUINA"
TITLE = FB15055_ZC_HORAS_MAQUINA
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de funcion para la gestion de horas de funcionamiento
   VAR_INPUT 
      Pulso1Seg : Bool;   // Pulso 1 Segundo
      FechaHora {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // Fecha y hora actual
      IniciarTiempoMaquina : Bool;   // Orden Contar tiempo maquina
      IniciarTiempoProd : Bool;   // Orden contar tiempo produccion
      IniciarTiempoRecirc : Bool;   // Orden contar tiempo recirculacion
      IniciarTiempoEnzim : Bool;   // Orden contar tiempo planta con enzimatico
      IniciarTiempoCIP : Bool;
      IniciarTiempoPausa : Bool;
      ResetTiempoEnzim : Bool;   // Orden reset tiempo planta con enzimatico
   END_VAR
   VAR_INPUT RETAIN
      HabilitarMant : Bool;   // Habilitar gestion mantenimiento
      SP_HorasAlarma : UDInt;   // Numero de Horas para alarmas
      SP_MinutosAlarma : USInt;   // Numero de Minutos para alarmas
   END_VAR
   VAR_INPUT 
      ProcesoID : Int;   // ID Proceso para trazabilidad
   END_VAR
   VAR_INPUT RETAIN
      Usuario : String[25];   // Usuario actual
   END_VAR

   VAR_OUTPUT 
      ParoMantenimiento : Bool;   // Paro maquina por horas de mantenimiento
      VisTiempoRecirculacion : Bool;   // Visibilidad tiempo recirculacion
   END_VAR

   VAR RETAIN
      TiempoMaquina { S7_SetPoint := 'False'} : "UDT_ZC_CONTADOR_TIEMPO";   // Horas totales de la maquina
      TiempoMantenimiento { S7_SetPoint := 'False'} : "UDT_ZC_CONTADOR_TIEMPO";   // Horas totales mantenimiento
      TiempoProduccionActual : "UDT_ZC_CONTADOR_TIEMPO";
      TiempoProduccionTotal : "UDT_ZC_CONTADOR_TIEMPO";
      TiempoRecirculacion : "UDT_ZC_CONTADOR_TIEMPO";
      TiempoEnzimatica : "UDT_ZC_CONTADOR_TIEMPO";
      TiempoLimpieza : "UDT_ZC_CONTADOR_TIEMPO";
      TiempoPausa : "UDT_ZC_CONTADOR_TIEMPO";
   END_VAR
   VAR 
      Pulsador : "UDT_ZC_PULSADOR";   // Pulsador reset mantenimiento
      PasswordHMI : UInt;   // Contraseña HMI
      s_OldAvisoHoras { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Pulso alarma horas
      s_OldInicioProduccion : Bool;   // Pulso inicio produccion
      s_OldInicioCIP : Bool;
      s_OldInicioPausa : Bool;
      s_OldCondicionParo { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
      s_PasswordCalculado { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UInt;   // Contraseña calculada de mantenimiento
   END_VAR

   VAR_TEMP 
      t_OrdenReset : Bool;   // Orden Reset contador de horas
      t_CondicionParo : Bool;
      t_ResetProdActual : Bool;
      t_ResetLimpieza : Bool;
      t_ResetPausa : Bool;
   END_VAR


BEGIN
	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
	El bloque `FB15055_ZC_HORAS_MAQUINA` implementa la gestión integral de las horas de funcionamiento de la máquina, llevando el conteo de tiempo acumulado de operación, tiempos de producción (actual y total), mantenimiento, recirculación, limpieza, pausa y tiempo de planta parada con enzimático. Incluye además la gestión del pulsador de reset de mantenimiento protegido por contraseña HMI y la gestión de los avisos por horas alcanzadas.
	
	Funcionalidades principales:
	- Conteo de horas de funcionamiento de la máquina (`TiempoMaquina`) mediante el bloque `FC15025_ZC_CONTADOR_TIEMPO` con estructura `UDT_ZC_CONTADOR_TIEMPO`.
	- Conteo diferenciado de tiempo de producción actual (`TiempoProduccionActual`), producción total (`TiempoProduccionTotal`), tiempo de mantenimiento (`TiempoMantenimiento`), tiempo de recirculación (`TiempoRecirculacion`), tiempo de enzimática (`TiempoEnzimatica`), tiempo de limpieza (`TiempoLimpieza`) y tiempo de pausa (`TiempoPausa`), todos basados en `UDT_ZC_CONTADOR_TIEMPO`.
	- Gestión del pulsador de reset de mantenimiento (`Pulsador` tipo `UDT_ZC_PULSADOR`) con cálculo y verificación de contraseña HMI (`PasswordHMI` / `PasswordCalculado`).
	- Gestión de los flancos de inicio de producción, inicio de CIP e inicio de pausa mediante variables estáticas `s_P_Trig_*` para detección de pulsos de activación.
	- Activación de la alarma y el paro de mantenimiento (`OutputParoMantenimiento`) por horas acumuladas, con flag de aviso (`s_Trig_AvisoHoras`).
	- Señales de visibilidad HMI para los distintos tiempos (`VisTiempoRecirculacion`, etc.) y para el paro de mantenimiento.
	- Orden interna de reset de tiempos (`t_OrdenReset`) que se activa tras la pulsación autorizada del reset de mantenimiento, reinicializando los contadores pertinentes.
	
	> **Restricciones:** Ninguna.
	
	---
	### Dependencias Requeridas
	| Tipo | Elementos |
	|------|-----------|
	| FC   | `FC15025_ZC_CONTADOR_TIEMPO` |
	| FB   | - |
	| DB   | - |
	| UDT  | `UDT_ZC_CONTADOR_TIEMPO`, `UDT_ZC_PULSADOR` |
	    
	---
	### Historial de Cambios
	| Versión  | Fecha      | Técnico | Cambios |
	|----------|------------|---------|---------|
	| 01.00.00 | 28.07.2023 | (HCR/ABH) | Primera versión. Cambio en lógica funcionamiento del bloque. Además de la gestión de alarma mantenimiento, se añade gestión de horas de funcionamiento totales de la máquina. Se añade tiempo de planta parada con enzimático de la máquina. |
	| 01.00.01 | 04.03.2024 | (ABH)   | Se corrige gestión de tiempo total de producción. |
	| 01.00.02 | 23.05.2024 | (HCR)   | Se añade salida visibilidad para tiempo de recirculación. |
	| 01.00.03 | 29.10.2025 | (ABH)   | Se corrige gestión de reset tiempo enzimática. |
	| 01.00.04 | 03.12.2025 | (ABH)   | Se añade tiempo de limpieza y tiempo de pausa. |
	| 01.01.00 | 03.07.2026 | (ABH)   | Cambio a SCL. |
	*)
	END_REGION DESCRIPCION
	
	
	//  ==========================================================================================================
	REGION PULSADORES
	    
	    //  Pulsador comprobacion contraseña
	    "FC15026_ZC_PULSADOR"(Pulso1Seg:=#Pulso1Seg,
	                          SP_Tiempo:=2,
	                          TrazaCategoria:="TRZ_CAT_4_PRO_PUL",
	                          TrazaIdProceso:=#ProcesoID,
	                          TrazaIdPulsador:="TRZ_SYS_PUL_HOR_MAQ_RST",
	                          Usuario:=#Usuario,
	                          FechaHoraActual:=#FechaHora,
	                          Pulsador:=#Pulsador);
	    
	END_REGION PULSADORES
	
	
	//  ==========================================================================================================
	REGION PARO_MANTENIMIENTO
	    
	    //  Condicion de paro por mantenimiento
	    #t_CondicionParo :=
	    #HabilitarMant AND
	    (#TiempoMantenimiento.Hora = #SP_HorasAlarma) AND
	    (#FechaHora.MINUTE = #SP_MinutosAlarma);
	    
	    //  Con paro por mantenimiento, activamos la marca de paro
	    IF #t_CondicionParo AND NOT #s_OldCondicionParo THEN
	        #s_PasswordCalculado := 0;
	        #ParoMantenimiento := TRUE;
	    END_IF;
	    
	    //  Estado anterior condicion paro por mantenimiento
	    #s_OldCondicionParo := #t_CondicionParo;
	    
	    
	    //  Ligica de paro y calculo de contraseña
	    IF #ParoMantenimiento THEN
	        
	        //  Calculo de contraseña
	        #s_PasswordCalculado := #FechaHora.YEAR + #FechaHora.MONTH + #FechaHora.DAY;
	        #Pulsador.Permiso := TRUE;
	        #Pulsador.Visibilidad := TRUE;
	
	        //  Comprobacion de contraseñas desde HMI
	        IF #Pulsador.Plc THEN
	            
	            //  Contraseña correcta, reseteamos todo
	            IF #s_PasswordCalculado = #PasswordHMI THEN
	                #s_PasswordCalculado := 0;
	                #PasswordHMI := 0;
	                #ParoMantenimiento := FALSE;
	                #t_OrdenReset := TRUE;
	                
	            ELSE
	                //  Contraseña incorrecta
	                #PasswordHMI := 0;
	                #t_OrdenReset := FALSE;
	            END_IF;
	            
	        ELSE
	            #t_OrdenReset := FALSE;
	        END_IF;
	
	    ELSE
	        //  Reset de estados si no tenemos la señal de paro por mantenimiento
	        #Pulsador.Permiso := FALSE;
	        #Pulsador.Visibilidad := FALSE;
	        #t_OrdenReset := FALSE;
	        
	    END_IF;
	    
	    //  Si no esta habilitado el paro por mantenimiento, reseteamos
	    IF NOT #HabilitarMant THEN
	        #ParoMantenimiento := FALSE;
	    END_IF;
	    
	END_REGION PARO_MANTENIMIENTO
	
	
	//  ==========================================================================================================
	REGION CONTADORES
	    
	    // Resolución de flancos en memoria temporal para Clean Code
	    #t_ResetProdActual := #IniciarTiempoProd AND NOT #s_OldInicioProduccion;
	    #s_OldInicioProduccion := #IniciarTiempoProd;
	    
	    #t_ResetLimpieza := #IniciarTiempoCIP AND NOT #s_OldInicioCIP;
	    #s_OldInicioCIP := #IniciarTiempoCIP;
	    
	    #t_ResetPausa := #IniciarTiempoPausa AND NOT #s_OldInicioPausa;
	    #s_OldInicioPausa := #IniciarTiempoPausa;
	    
	    
	    //  ==========================================================================================================
	    //  Contador de tiempo de mantenimiento
	    "FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg:=#Pulso1Seg,
	                                 Iniciar:=#HabilitarMant AND #IniciarTiempoMaquina,
	                                 Reset:=#t_OrdenReset OR NOT #HabilitarMant,
	                                 Contador:=#TiempoMantenimiento);
	    
	    //  ==========================================================================================================
	    //  Contador de tiempo total Maquina
	    "FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg := #Pulso1Seg,
	                                 Iniciar := #IniciarTiempoMaquina,
	                                 Reset := FALSE,
	                                 Contador := #TiempoMaquina);
	
	    //  ==========================================================================================================
	    //  Contador de tiempo de produccion actual
	    "FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg := #Pulso1Seg,
	                                 Iniciar := #IniciarTiempoProd,
	                                 Reset := #t_ResetProdActual,
	                                 Contador := #TiempoProduccionActual);
	    
	    //  ==========================================================================================================
	    //  Contador de tiempo de produccion total
	    "FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg := #Pulso1Seg,
	                                 Iniciar := #IniciarTiempoProd,
	                                 Reset := FALSE,
	                                 Contador := #TiempoProduccionTotal);
	    
	    //  ==========================================================================================================
	    //  Contador de tiempo de recirculacion
	    "FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg := #Pulso1Seg,
	                                 Iniciar := #IniciarTiempoRecirc,
	                                 Reset := NOT #IniciarTiempoRecirc,
	                                 Contador := #TiempoRecirculacion);
	    //  Visibilidad tiempo recirculacion
	    #VisTiempoRecirculacion := #IniciarTiempoRecirc;
	    
	    //  ==========================================================================================================
	    //  Contador de tiempo de planta con enzimatico
	    "FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg := #Pulso1Seg,
	                                 Iniciar := #IniciarTiempoEnzim,
	                                 Reset := #ResetTiempoEnzim,
	                                 Contador := #TiempoEnzimatica);
	    
	    //  ==========================================================================================================
	    //  Contador de tiempo de limpieza
	    "FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg := #Pulso1Seg,
	                                 Iniciar := #IniciarTiempoCIP,
	                                 Reset := #t_ResetLimpieza,
	                                 Contador := #TiempoLimpieza);
	    
	    //  ==========================================================================================================
	    //  Contador de tiempo en pausa
	    "FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg := #Pulso1Seg,
	                                 Iniciar := #IniciarTiempoPausa,
	                                 Reset := #t_ResetPausa,
	                                 Contador := #TiempoPausa);
	    
	END_REGION CONTADORES
	
	
END_FUNCTION_BLOCK

