Primera version

This commit is contained in:
2026-07-14 10:21:52 +02:00
parent 273e2be076
commit 430e3b4db0
222 changed files with 176320 additions and 0 deletions
@@ -0,0 +1,219 @@
FUNCTION_BLOCK "FB15152_ZC_PARO_SEC"
TITLE = FB15152_ZC_PARO_SEC
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de funcion para la gestion de paro secuencial de dispositivos
VAR_INPUT
Pulso1Seg : Bool; // Pulso de 1 segundo
MarchaSecuenciaParo : Bool; // Orden marcha secuencia de paro
NumeroDispositivos { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Int := 4; // Numero de dispositivos
TiempoEntreEtapas { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Int := 2; // Tiempo entre etapas
ConfirmacionDisp { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Array[1..#N_MAX] of Bool; // Confirmacion activado dispositivo
END_VAR
VAR_OUTPUT
SecParoFinalizada : Bool; // Secuencia de paro completada
SecReposo : Bool; // Secuencia en reposo
ParoDispositivo { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Array[1..#N_MAX] of Bool; // Orden paro dispositivo
END_VAR
VAR
s_NumeroDispositivos { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Numero de dispositivos
END_VAR
VAR RETAIN
s_EtapaActual { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Etapa actual
s_Indice { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Indice dispositivo actual
s_TiempoActual { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Tiempo actual
END_VAR
VAR_TEMP
for_i : Int;
END_VAR
VAR CONSTANT
N_MAX : Int := 8;
REPOSO : Int := 0;
PARANDO : Int := 10;
REARMANDO : Int := 20;
FINALIZADO : Int := 30;
END_VAR
BEGIN
REGION DESCRIPCION
//=======================================================================
// (C)Copyright ZeusControl 2023 - 2026
//=======================================================================
(*
### Información del Sistema
| Hardware Compatible | Entorno de Ingeniería |
|---------------------|-----------------------|
| PLC serie 1200/1500 | TIA Portal 18 |
---
### Descripción Funcional
El bloque `FB15051_PARO_SECUENCIAL` implementa un secuenciador bidireccional para el paro ordenado de un array de dispositivos. Permite detener los dispositivos uno a uno esperando una confirmación por etapa, y rearmar la secuencia en sentido inverso si se retira la orden de marcha, continuando desde la última etapa alcanzada en lugar de reiniciar desde el inicio.
Funcionalidades principales:
- Validación del número de dispositivos: `#NumeroDispositivos` se acota entre 1 y la constante de dimensionamiento `#N_MAX`.
- Estado `REPOSO`: bloque en espera. Al recibir `#MarchaSecuenciaParo := TRUE` se inicializa el índice y se transita a la etapa `PARANDO`.
- Estado `PARANDO`: avanza secuencialmente por los dispositivos de menor a mayor índice. Cada dispositivo se considera parado cuando se cumple `#ConfirmacionDisp[i] = TRUE` durante `#TiempoEntreEtapas` segundos. Al confirmar, se incrementa el índice hasta superar `#s_NumeroDispositivos`, momento en el que se transita a `FINALIZADO`. Si durante esta etapa se desactiva `#MarchaSecuenciaParo`, se invierte el sentido y se pasa a `REARMANDO` sin perder la posición alcanzada.
- Estado `REARMANDO`: retrocede secuencialmente por los dispositivos de mayor a menor índice. Cada dispositivo se considera rearmado cuando `#ConfirmacionDisp[i] = FALSE` durante `#TiempoEntreEtapas` segundos. Al rearmar, se decrementa el índice hasta alcanzar 1, momento en el que se transita a `REPOSO`. Si durante esta etapa se vuelve a activar `#MarchaSecuenciaParo`, se invierte nuevamente el sentido y se pasa a `PARANDO` desde la posición actual.
- Estado `FINALIZADO`: secuencia de paro completa. Al retirar `#MarchaSecuenciaParo`, se rearman los dispositivos en orden inverso empezando desde el último, transitando a `REARMANDO`.
- Mapeado dinámico de salidas: para cada dispositivo se activa `#ParoDispositivo[i] := TRUE` si su índice es menor o igual al puntero actual y la etapa es `PARANDO`; en el resto de casos se mantiene en `FALSE`. Esto garantiza que los dispositivos ya parados en la fase actual permanezcan parados durante el rearmado inverso de los posteriores.
- Señales de estado: `#SecReposo` indica que la secuencia está en `REPOSO` y `#SecParoFinalizada` que ha terminado (`FINALIZADO`).
- Contadores de tiempo por etapa del tipo `ZC_TIEMPO_ETAPA` con base de tiempo en segundos (`#Pulso1Seg`).
> **Restricciones:** PLC serie 1200/1500.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | `ZC_TIEMPO_ETAPA` |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 00.00.01 | 24.05.2023 | (ABH) | Primera versión. |
| 00.00.02 | 15.12.2023 | (HCR) | Se aumentan los dispositivos de 4 a 8. |
| 00.00.03 | 18.12.2023 | (ABH) | Se cambia UDT tiempo etapa a `ZC_TIEMPO_ETAPA`. Se añade salida `SecReposo` para indicar que está en reposo. Se añade gestión de etapas para que, en caso de estar con orden de paro y se dé marcha, siga la secuencia donde le toque evitando tener que pararla por completo y volverla a arrancar. |
| 01.00.00 | 03.07.2026 | (ABH) | Cambio a SCL. Se refactoriza logicas para estandarizar. Se utiliza constante N_MAX para redimensionar. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION LIMITES
#s_NumeroDispositivos := #NumeroDispositivos;
// Limite de seguridad
IF #s_NumeroDispositivos > #N_MAX THEN
#s_NumeroDispositivos := #N_MAX;
ELSIF #s_NumeroDispositivos < 1 THEN
#s_NumeroDispositivos := 1;
END_IF;
END_REGION LIMITES
// ==========================================================================================================
REGION SECUENCIADOR_BIDIRECCIONAL
CASE #s_EtapaActual OF
#REPOSO:
#s_Indice := 1;
#s_TiempoActual := 0;
IF #MarchaSecuenciaParo THEN
#s_EtapaActual := #PARANDO;
END_IF;
#PARANDO:
// Contador de tiempo con confirmacion de dispositivo
IF #ConfirmacionDisp[#s_Indice] AND #Pulso1Seg THEN
#s_TiempoActual += 1;
END_IF;
// Tiempo cumplido
IF (#s_TiempoActual >= #TiempoEntreEtapas) THEN
#s_TiempoActual := 0;
#s_Indice += 1; // Avanzamos al siguiente dispositivo
// Comprobación de fin de secuencia de paro
IF #s_Indice > #s_NumeroDispositivos THEN
#s_EtapaActual := #FINALIZADO;
END_IF;
END_IF;
// Si se desactiva la orden de marcha de la secuencia, comenzamos el rearme inverso
IF NOT #MarchaSecuenciaParo THEN
#s_TiempoActual := 0;
#s_EtapaActual := #REARMANDO;
END_IF;
#REARMANDO:
// Límite de seguridad inferior
IF #s_Indice < 1 THEN
#s_EtapaActual := #REPOSO;
RETURN;
END_IF;
// Contador de tiempo sin confirmacion de dispositivo
IF NOT #ConfirmacionDisp[#s_Indice] AND #Pulso1Seg THEN
#s_TiempoActual += 1;
END_IF;
// Tiempo cumplido
IF (#s_TiempoActual >= #TiempoEntreEtapas) THEN
#s_TiempoActual := 0;
#s_Indice -= 1; // Avanzamos al dispositivo anterior
IF #s_Indice < 1 THEN
#s_EtapaActual := #REPOSO;
END_IF;
END_IF;
// Si se vuelve a dar marcha, invertimos dirección nuevamente
IF #MarchaSecuenciaParo THEN
#s_TiempoActual := 0;
#s_EtapaActual := #PARANDO;
END_IF;
#FINALIZADO:
IF NOT #MarchaSecuenciaParo THEN
#s_TiempoActual := 0;
// Empezamos a rearmar desde el último dispositivo que se paro
#s_Indice := #s_NumeroDispositivos;
#s_EtapaActual := #REARMANDO;
END_IF;
ELSE
#s_EtapaActual := #REPOSO;
END_CASE;
END_REGION SECUENCIADOR_BIDIRECCIONAL
// ==========================================================================================================
REGION MAPEADO_DINAMICO_DE_SALIDAS
#SecReposo := (#s_EtapaActual = #REPOSO);
#SecParoFinalizada := (#s_EtapaActual = #FINALIZADO);
// Mapeo vectorial de comandos físicos
FOR #for_i := 1 TO #N_MAX DO
// Si el índice iterativo es menor que nuestro puntero de etapa actual,
// significa que ya hemos pasado por él en la secuencia de paro y debe estar detenido.
IF #for_i < #s_Indice THEN
#ParoDispositivo[#for_i] := TRUE;
// Si el índice coincide con el puntero y estamos parando, forzamos la salida a TRUE
ELSIF (#for_i = #s_Indice) AND (#s_EtapaActual = #PARANDO) THEN
#ParoDispositivo[#for_i] := TRUE;
// Para el resto de condiciones
ELSE
#ParoDispositivo[#for_i] := FALSE;
END_IF;
END_FOR;
END_REGION MAPEADO_DINAMICO_DE_SALIDAS
END_FUNCTION_BLOCK
@@ -0,0 +1,216 @@
FUNCTION_BLOCK "FB15153_ZC_MARCHA_SEC_B_MEM"
TITLE = FB15153_ZC_MARCHA_SEC_B_MEM
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de funcion para la gestion de activacion de las bombas de de una maquina de membranas
VAR_INPUT
Pulso1Seg : Bool; // Pulso de 1 segundo
MarchaSecuencia : Bool; // Orden de marcha secuencia
EstadoBombaPresionVF : Bool; // Estado bomba Presion (Variador)
EstadoBombaPresion : Bool; // Estado bomba Presion
TiempoEntreBombas : Int := 10; // SP Tiempo entre bombas
NumeroBombasPresion : Int := 2; // Numero de bombas presion (1 o 2)
NumeroModulos : Int := 6; // Numero de modulos
END_VAR
VAR_OUTPUT
MarchaBombaPresionVF : Bool; // Activacion bomba Presion (Variador)
MarchaBombaPresion : Bool; // Activacion bomba Presion
MarchaBombaModulo : Array[1..#N_MAX] of Bool; // Activacion bomba Modulo
END_VAR
VAR RETAIN
s_TonPresion { S7_SetPoint := 'False'} : Array[1..2] of "UDT_ZC_DISP_TON";
s_TonModulos { S7_SetPoint := 'False'} : Array[1..#N_MAX] of "UDT_ZC_DISP_TON";
END_VAR
VAR_TEMP
for_i : Int;
t_NumBombasPresion : Int; // Numero de bombas presion
t_NumModulos : Int; // Numero de modulos
t_BombasPresionOk : Bool; // Bombas presion arrancadas Ok
END_VAR
VAR CONSTANT
N_MAX : Int := 6;
END_VAR
BEGIN
REGION DESCRIPCION
(*
###### (C)Copyright ZeusControl 2023 - 2026
---
### Información del Sistema
| Hardware Compatible | Entorno de Ingeniería |
|---------------------|-----------------------|
| PLC serie 1200/1500 | TIA Portal 18 |
---
> **Restricciones:** Ninguna.
---
### Descripción Funcional
Bloque de gestión de marcha secuencial de bombas de una máquina de membranas. Implementa el arranque escalonado, en cascada y temporizado, de las bombas de presión y de las bombas de los módulos de la máquina, respetando el número de bombas y módulos configurados y utilizando temporizadores individuales no retentivos.
Acciones detalladas:
- Limita el número de bombas de presión activas (`t_NumBombasPresion`) al rango válido `1``2`, acotando la entrada `NumeroBombasPresion`.
- Limita el número de módulos activos (`t_NumModulos`) al rango válido `1``N_MAX`, acotando la entrada `NumeroModulos`.
- Traslada el setpoint de temporización `TiempoEntreBombas` a todos los temporizadores de bombas de presión (`s_TonPresion[1..2]`) y de módulos (`s_TonModulos[1..N_MAX]`).
- Gestiona el arranque de las bombas de presión mediante dos temporizadores en cascada: primero la bomba de variador (`s_TonPresion[1]`) y, tras su confirmación y solo si hay 2 bombas configuradas, la segunda bomba de presión (`s_TonPresion[2]`).
- Calcula el flag `t_BombasPresionOk`, que indica que el conjunto de bombas de presión requerido está en marcha: con 1 bomba exige confirmación del variador, con 2 bombas exige confirmación de ambas.
- Arranca el módulo 1 (`s_TonModulos[1]`) directamente cuando las bombas de presión están OK.
- Arranca los módulos `2` a `N_MAX` en cascada, de forma que cada módulo espera a la confirmación del módulo anterior y a las bombas de presión OK; los módulos no configurados se fuerzan a `FALSE` por seguridad.
- Ejecuta los temporizadores llamando a la `FC` de temporización individual, lo que permite disponer de un `SP`, una `IN`, una salida `Q` y un tiempo transcurrido independientes por instancia.
- Genera las salidas finales: `MarchaBombaPresionVF` (variador), `MarchaBombaPresion` (segunda bomba) y `MarchaBombaModulo[1..N_MAX]` a partir de las salidas `Q` de los temporizadores correspondientes.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | `FC2928_ZC_TON_INDV` |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 01.00.00 | 09.05.2023 | (ABH) | Primera version. |
| 01.00.01 | 19.05.2023 | (ABH) | Se añade parámetro de entrada para límite de número de bombas de presión. |
| 01.00.02 | 02.10.2023 | (ABH) | Se añade `FC22028_TON_INV` para gestión de temporizadores. |
| 01.00.03 | 02.11.2023 | (ABH) | Se añade gestión para 6 módulos. |
| 01.00.03 | 06.07.2026 | (ABH) | Cambio a SCL. Se refactoriza numero de modulos.|
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION LIMITES
// Limite numero de bombas presion
#t_NumBombasPresion := #NumeroBombasPresion;
IF #t_NumBombasPresion < 1 THEN
#t_NumBombasPresion := 1;
END_IF;
IF #t_NumBombasPresion > 2 THEN
#t_NumBombasPresion := 2;
END_IF;
// Limite numero de bombas modulos
#t_NumModulos := #NumeroModulos;
IF #t_NumModulos < 1 THEN
#t_NumModulos := 1;
END_IF;
IF #t_NumModulos > #N_MAX THEN
#t_NumModulos := #N_MAX;
END_IF;
END_REGION LIMITES
// ==========================================================================================================
REGION TRASPASO_DE_PARAMETROS
// Traspaso de tiempos bomba presion
FOR #for_i := 1 TO 2 DO
#s_TonPresion[#for_i].SP := #TiempoEntreBombas;
END_FOR;
// Traspaso de tiempos bomba modulos
FOR #for_i := 1 TO #N_MAX DO
#s_TonModulos[#for_i].SP := #TiempoEntreBombas;
END_FOR;
END_REGION TRASPASO_DE_PARAMETROS
// ==========================================================================================================
REGION GESTION_BOMBAS_PRESION
// Temporizador bomba Presion (Variador)
#s_TonPresion[1].IN := #MarchaSecuencia;
// Temporizador bomba Presion
#s_TonPresion[2].IN :=
(#t_NumBombasPresion = 2) AND
#EstadoBombaPresionVF AND
#s_TonPresion[1].Q;
// Bombas presion arrancadas Ok
IF #t_NumBombasPresion = 1 THEN
#t_BombasPresionOk := #EstadoBombaPresionVF AND #s_TonPresion[1].Q;
ELSE
#t_BombasPresionOk := #EstadoBombaPresion AND #s_TonPresion[2].Q;
END_IF;
END_REGION GESTION_BOMBAS_PRESION
// ==========================================================================================================
REGION GESTION_BOMBAS_MODULOS
// El modulo 1 arranca directamente si las bombas de presion estan OK
#s_TonModulos[1].IN := #t_BombasPresionOk;
// Los modulos 2 a N_MAX arrancan en cascada
FOR #for_i := 2 TO #N_MAX DO
IF #for_i <= #t_NumModulos THEN
// Si el módulo está dentro de la configuración, evalúa la cascada (Módulo anterior Q + bombas presion Ok)
#s_TonModulos[#for_i].IN := #s_TonModulos[#for_i - 1].Q AND #t_BombasPresionOk;
ELSE
// Forzado de seguridad a FALSE para módulos no instalados/configurados en esta máquina
#s_TonModulos[#for_i].IN := FALSE;
END_IF;
END_FOR;
END_REGION GESTION_BOMBAS_MODULOS
// ==========================================================================================================
REGION GESTION_TEMPORIZADORES
// Temporizadores bombas presion
FOR #for_i := 1 TO 2 DO
"FC2928_ZC_TON_INDV"(Pulso1seg := #Pulso1Seg,
TON := #s_TonPresion[#for_i]);
END_FOR;
// Temporizadores bombas modulos
FOR #for_i := 1 TO #N_MAX DO
"FC2928_ZC_TON_INDV"(Pulso1seg := #Pulso1Seg,
TON := #s_TonModulos[#for_i]);
END_FOR;
END_REGION GESTION_TEMPORIZADORES
// ==========================================================================================================
REGION SALIDAS
// Bombas presion
#MarchaBombaPresionVF := #s_TonPresion[1].Q;
#MarchaBombaPresion := #s_TonPresion[2].Q;
// Bombas modulos
FOR #for_i := 1 TO #N_MAX DO
#MarchaBombaModulo[#for_i] := #s_TonModulos[#for_i].Q;
END_FOR;
END_REGION SALIDAS
END_FUNCTION_BLOCK
@@ -0,0 +1,403 @@
FUNCTION "FC15151_ZC_MARCHA_PARO_SEC" : Void
TITLE = FC15151_ZC_MARCHA_PARO_SEC
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Funcion para la gestion de marcha/paro de dispositivos secuencialmente
VAR_INPUT
Pulso1Seg : Bool; // Pulso de 1 segundo
Seguridad : Bool; // Estado seguridades ok
Marcha : Bool; // Orden de marcha
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
BEGIN
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_FUNCTION