FUNCTION "FC2926_ZC_FF_INDV" : Void
TITLE = FC2926_ZC_FF
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Funcion para gestion de flip flop
   VAR_INPUT 
      Pulso1Seg : Bool;   // Pulso de 1 segundo
   END_VAR

   VAR_IN_OUT 
      FF : "UDT_ZC_DISP_FF";
   END_VAR

   VAR CONSTANT 
      REPOSO : SInt := 0;
      FLOP : SInt := 10;
      PARO1 : SInt := 20;
      FLIP : SInt := 30;
      PARO2 : SInt := 40;
   END_VAR


BEGIN
	REGION DESCRIPCION
	    (*
	    ###### (C)Copyright ZeusControl 2026 - 2026
	    
	    ---
	    ### 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 gestionar un dispositivo flip flop con funcion de paro entre cambios.
	    
	    Las tareas que realiza son las siguientes:
	    
	    - Gestionar la activacion y calculos de tiempo de cambio entre ordenes Flip, Flop y paro.
	    - Adicionalmente, se gestiona tambien la posibilidad de pausar el contaje del tiempo, para evitar su reinicializacion en caso de pausa.
	    - En los cambios entre ´flip´ <--> ´flop´, se activa tambien la marca ´paro´ para poder gestionar los cambios y evitar golpes de ariete.
	    ---
	    ### Dependencias Requeridas
	    | Tipo | Elementos |
	    |------|-----------|
	    | FC   | - |
	    | FB   | - |
	    | DB   | - |
	    | UDT  | `UDT_ZC_DISP_FF_PARO` |
	    
	    ---
	    ### Historial de Cambios
	    | Versión  | Fecha      | Técnico | Cambios |
	    |----------|------------|---------|---------|
	    | 01.00.00 | 02.06.2026 | (ABH)   | Primera version. |
	*)
	END_REGION DESCRIPCION
	
	
	//  ==========================================================================================================
	REGION GESTION_DISPOSITIVO
	    
	    // ==========================================================================================================
	    REGION COMPROBACIONES_INICIALES
	        
	        //  Si no hay orden o faltan tiempos, reseteamos valores y salimos de la funcion
	        IF NOT #FF.Orden_Activar OR (#FF.Config_SetPointTiempoFlip <= 0 AND #FF.Config_SetPointTiempoFlop <= 0) THEN
	            #FF.Estado_Flip := FALSE;
	            #FF.Estado_Flop := FALSE;
	            #FF.Estado_Paro1 := FALSE;
	            #FF.Estado_Paro2 := FALSE;
	            
	            #FF.Aux_Tiempo := 0;
	            #FF.Estado_Etapa := #REPOSO;
	
	            #FF.Aux_Inicializado := FALSE;
	            RETURN;
	        END_IF;
	        
	    END_REGION COMPROBACIONES_INICIALES
	
	
	    // ==========================================================================================================
	    REGION INICIALIZACION
	        
	        //  Arranque inicial forzado a Flop si no hay estado activo
	        IF NOT #FF.Aux_Inicializado THEN
	            #FF.Estado_Etapa := #FLOP;
	            #FF.Aux_Inicializado := TRUE;
	        END_IF;
	        
	    END_REGION INICIALIZACION
	    
	    
	    // ==========================================================================================================
	    REGION LOGICA_DE_ESTADOS        
	        
	        CASE #FF.Estado_Etapa OF
	
	            #FLOP:
	                //  Salidas
	                #FF.Estado_Flip := FALSE;
	                #FF.Estado_Flop := TRUE;
	                #FF.Estado_Paro1 := FALSE;
	                #FF.Estado_Paro2 := FALSE;
	                
	                //  Conteo de tiempo
	                IF #Pulso1Seg AND NOT #FF.Orden_Pausa THEN
	                    #FF.Aux_Tiempo += 1;
	                END_IF;
	                
	                //  Transición
	                IF #FF.Aux_Tiempo >= #FF.Config_SetPointTiempoFlop THEN
	                    #FF.Aux_Tiempo := 0;
	                    //  Si no tenemos tiempo de paro configurado, saltamos a FLIP
	                    IF #FF.Config_SetPointTiempoParo <= 0 THEN
	                        #FF.Estado_Etapa := #FLIP;
	                    ELSE
	                        #FF.Estado_Etapa := #PARO1;
	                    END_IF;
	                END_IF;
	                
	            #PARO1:
	                //  Salidas
	                #FF.Estado_Flip := FALSE;
	                #FF.Estado_Flop := FALSE;
	                #FF.Estado_Paro1 := TRUE;
	                #FF.Estado_Paro2 := FALSE;
	                
	                //  Conteo de tiempo
	                IF #Pulso1Seg AND NOT #FF.Orden_Pausa THEN
	                    #FF.Aux_Tiempo += 1;
	                END_IF;
	                
	                //  Transición
	                IF #FF.Aux_Tiempo >= #FF.Config_SetPointTiempoParo THEN
	                    #FF.Aux_Tiempo := 0;
	                    #FF.Estado_Etapa := #FLIP;
	                END_IF;
	                
	                
	            #FLIP:
	                //  Salidas
	                #FF.Estado_Flip := TRUE;
	                #FF.Estado_Flop := FALSE;
	                #FF.Estado_Paro1 := FALSE;
	                #FF.Estado_Paro2 := FALSE;
	                
	                //  Conteo de tiempo
	                IF #Pulso1Seg AND NOT #FF.Orden_Pausa THEN
	                    #FF.Aux_Tiempo += 1;
	                END_IF;
	                
	                //  Transición
	                IF #FF.Aux_Tiempo >= #FF.Config_SetPointTiempoFlip THEN
	                    #FF.Aux_Tiempo := 0;
	                    //  Si no tenemos tiempo de paro configurado, saltamos a FLOP
	                    IF #FF.Config_SetPointTiempoParo <= 0 THEN
	                        #FF.Estado_Etapa := #FLOP;
	                    ELSE
	                        #FF.Estado_Etapa := #PARO2;
	                    END_IF;
	                END_IF;
	                
	                
	            #PARO2:
	                //  Salidas
	                #FF.Estado_Flip := FALSE;
	                #FF.Estado_Flop := FALSE;
	                #FF.Estado_Paro1 := FALSE;
	                #FF.Estado_Paro2 := TRUE;
	                
	                //  Conteo de tiempo
	                IF #Pulso1Seg AND NOT #FF.Orden_Pausa THEN
	                    #FF.Aux_Tiempo += 1;
	                END_IF;
	                
	                //  Transición
	                IF #FF.Aux_Tiempo >= #FF.Config_SetPointTiempoParo THEN
	                    #FF.Aux_Tiempo := 0;
	                    #FF.Estado_Etapa := #FLOP;
	                END_IF;
	                
	            ELSE  
	                #FF.Estado_Etapa := #REPOSO;
	        END_CASE;
	        
	    END_REGION LOGICA_DE_ESTADOS 
	    
	END_REGION GESTION_DISPOSITIVO
	
	
END_FUNCTION

