Reorganizacion de libreria.

This commit is contained in:
2026-07-20 08:15:06 +02:00
parent e0b9f4a206
commit 2b9dbc1f27
280 changed files with 9799 additions and 9398 deletions
@@ -0,0 +1,314 @@
FUNCTION_BLOCK "FB15102_ZC_CALCULO_FCV_UF"
TITLE = FB15102_ZC_CALCULO_FCV_UF
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : HCR
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de funcion para la gestion del cálculo de FCV según consignas de caudal de concentrado y consigna de FCV, para máquinas de membranas
VAR_INPUT
Pulso1Seg : Bool; // Pulso de 1 segundo
ActivarCalculosCaudal : Bool; // Activar calculos caudal
ActivarControlPresion : Bool; // Activar control presion
Marcha : Bool; // Estado marcha
EtapaRecircProd : Bool; // Etapa recirculacion produccion
CaudalTotalPermeado : Real; // CaudalInstantáneo de permeado
SP_FCV : Real; // Consigna FCV
SP_CaudalMaximoEntrada : Real; // Consigna máxima caudal de entrada
SP_PorcientoPermeadoTotal : Real; // Diferencia entre consigna de permeado y permeado total
SP_BajoCaudalPermeado : Real; // Consigna de caudal para corregir
SP_PresionInicial : Real; // Consigna de presión inicial
SP_IncrementosPresion : Real; // Consigna de incrementos de presión
SP_PresionMaxima : Real; // Consigna máxima de presión
SP_TiempoMuestreoPresion : Int; // Consigna tiempo de mustreo incremento de presión
SP_PorcentajeDecremento : Real; // % de decremento caudal concentrado
SP_CaudalMinConcentrado : Real; // Caudal minimo de concentrado en decrementos
SP_TiempoDecrementos : Int; // Consigna tiempo entre decrementos
BotonReset : Bool; // Orden pulsador reset presión
END_VAR
VAR_OUTPUT
SP_CaudalTeoricoEntrada : Real; // Consigna teorica caudal de entrada
SP_CaudalPermeado : Real; // Consigna caudal total permeado
SP_Presion : Real; // Consigna de presión
ErrorDiferenciaPermeado : Bool; // Error porcentaje caudal permeado total fuera de rango
VisibilidadConsignasCaudal : Bool; // Visibilidad de consignas calculadas de caudal
VisibilidadConsignasPresion : Bool; // Visibilidad de consignas calculadas de presion
VisibilidadConsignaCaudalDec : Bool; // Visibilidad de consignas caudal decremento
PermisoReset : Bool; // Permiso Reset Pulsador de presión
AjusteSP_CaudalConcentrado : Bool; // Orden de ajuste set point caudal concentrado
MaxPresionAlcanzada : Bool; // Maxima presion alcanzada
END_VAR
VAR_IN_OUT
SP_CaudalConcentrado : Real; // Consigna caudal de concentrado
SP_CaudalPermeadoTotal : Real; // Consigna de permeado total
ForzarIncrementos : Bool; // Forzar incrementos de presión
END_VAR
VAR RETAIN
s_SP_Presion : Real; // Calculo interno set point presion
s_old_SP_CaudalConcentrado : Real; // Estado anterior set point caudal concentrado
s_old_SP_FCV : Real; // Estado anterior set point FCV
END_VAR
VAR
s_DiferenciaCaudalPermeado : Real; // Diferencia caudal permeado
s_BajoCaudalPermeado : Bool; // Bajo caudal permeado activo
s_MaxPresionAlcanzada : Bool; // Maxima presion alcanzada
s_SP_CaudalConcentrado : Real; // Calculo interno set point caudal concentrado
s_TON { S7_SetPoint := 'False'} : Array[0..1] of "UDT_ZC_DISP_TON";
END_VAR
VAR_TEMP
t_CaudalTeoricoEntrada : Real; // Calculo caudal teorico entrada
END_VAR
VAR CONSTANT
LIM_MIN_CAUDAL_PERMEADO_TOTAL : Real; // Porciento mínimo diferencia caudal total de permeado
LIM_MAX_CAUDAL_PERMEADO_TOTAL : Real := 100.0; // Porciento máximo diferencia caudal total de permeado
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 `FB15102_ZC_CALCULO_FCV_UF` implementa el cálculo de la consigna de FCV (factor de conversión volumétrica) para máquinas de membranas de ultrafiltración, a partir de las consignas de caudal de concentrado y de FCV. Gestiona además el control de presión por incrementos/decrementos para mantener el caudal de permeado total dentro de los objetivos del proceso.
Funcionalidades principales:
- Validación de entradas: se detecta error (`ErrorDiferenciaPermeado`) cuando la consigna `SP_PorcientoPermeadoTotal` está fuera del rango definido por `LIM_MIN_CAUDAL_PERMEADO_TOTAL` y `LIM_MAX_CAUDAL_PERMEADO_TOTAL`. En caso de error, el cálculo del caudal teórico de permeado total se realiza con un valor de seguridad del 1%.
- Cálculo de caudales teóricos: a partir de `SP_CaudalConcentrado` y `SP_FCV` se obtiene el caudal teórico de entrada (`SP_CaudalTeoricoEntrada`) y, por diferencia, el caudal teórico de permeado (`SP_CaudalPermeado`). Si el caudal teórico de entrada supera el `SP_CaudalMaximoEntrada`, la consigna de concentrado se reduce automáticamente, activando el flag `AjusteSP_CaudalConcentrado` para señalizar el reescalado al exterior.
- Cálculo de caudal de permeado total: `SP_CaudalPermeadoTotal` se obtiene aplicando el porcentaje de permeado total al caudal de permeado teórico.
- Detección de bajo caudal de permeado: se calcula la diferencia entre el caudal teórico y el real (`CaudalTotalPermeado`). El flag `s_BajoCaudalPermeado` se activa cuando la diferencia es positiva pero inferior al umbral `SP_BajoCaudalPermeado`, o cuando el teórico es superior al real.
- Control de presión por incrementos: mediante un temporizador (`FC2928_ZC_TON_INDV` con estructura `ZC_TON`) se incrementa progresivamente la consigna `s_SP_Presion` en pasos `SP_IncrementosPresion` cuando se detecta bajo caudal de permeado, hasta alcanzar `SP_PresionMaxima`. Se permite reset a `SP_PresionInicial` mediante la entrada `BotonReset`, así como el disparo manual de un incremento con `ForzarIncrementos`.
- Lógica de decrementos de caudal: cuando se alcanza la presión máxima (`s_MaxPresionAlcanzada`) y el caudal real sigue por debajo del teórico, un segundo temporizador (`s_TON[1]`) reduce progresivamente la consigna de concentrado aplicando un porcentaje `SP_PorcentajeDecremento`, acotado inferiormente por `SP_CaudalMinConcentrado`. Cada ajuste activa `AjusteSP_CaudalConcentrado`.
- Modo no activo: cuando `ActivarCalculosCaudal` o `ActivarControlPresion` están desactivados, todas las salidas y variables internas se resetean a sus valores neutros, manteniendo únicamente la presión inicial si el proceso no se encuentra en recirculación de producto (`EtapaRecircProd`).
- Salidas de visibilidad HMI: `VisibilidadConsignasCaudal`, `VisibilidadConsignasPresion` y `VisibilidadConsignaCaudalDec` se exponen para que el sistema de supervisión muestre u oculte las pantallas de consignas según la etapa activa del bloque.
- Memoria de consignas anteriores: al final del bloque se actualizan `s_old_SP_CaudalConcentrado` y `s_old_SP_FCV` para la detección de cambios en el siguiente ciclo.
> **Restricciones:** Ninguna.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | `FC2928_ZC_TON_INDV` |
| FB | - |
| DB | - |
| UDT | `ZC_TON` |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 01.00.00 | 24.05.2023 | (HCR) | Primera versión. |
| 01.00.01 | 04.03.2024 | (HCR) | Se corrige gestión de `SP_Presion`. Se añade variable estática para su gestión. |
| 01.00.02 | 10.11.2025 | (ABH) | Se añade salida `AjusteSP_CaudalConcentrado` para poder realizar escritura de parámetros fuera del bloque. |
| 01.00.03 | 20.11.2025 | (CNR) | Se añade lógica de funcionamiento por decrementos. |
| 01.00.04 | 28.11.2025 | (ABH) | Se elimina la parte de la diafiltración. Se añade gestión con temporizadores ZC. Se eliminan variables externas al bloque. Se estandariza el nombre de variables. |
*)
END_REGION DESCRIPCION
REGION ERROR
// ====================================================
// SP_PorcientoPermeadoTotal fuera de rango
#ErrorDiferenciaPermeado := (#SP_PorcientoPermeadoTotal < #LIM_MIN_CAUDAL_PERMEADO_TOTAL OR #SP_PorcientoPermeadoTotal > #LIM_MAX_CAUDAL_PERMEADO_TOTAL);
END_REGION
REGION CALCULO_FCV
// Reinicializacion de valores
#AjusteSP_CaudalConcentrado := FALSE;
// ====================================================
// Modo activo
IF #ActivarCalculosCaudal THEN
#s_SP_CaudalConcentrado := #SP_CaudalConcentrado;
// ====================================================
// Cambio de consigna caudal de concentrado
IF #s_SP_CaudalConcentrado <> #s_old_SP_CaudalConcentrado OR #SP_FCV <> #s_old_SP_FCV THEN
// Cálculo temporal de caudal teórico de entrada
#t_CaudalTeoricoEntrada := #s_SP_CaudalConcentrado * #SP_FCV;
// Comparación con el caudal máximo de entrada
IF #t_CaudalTeoricoEntrada > #SP_CaudalMaximoEntrada THEN
// Recalcular caudal de concentrado
#s_SP_CaudalConcentrado := #SP_CaudalMaximoEntrada / #SP_FCV;
#AjusteSP_CaudalConcentrado := TRUE;
END_IF;
END_IF;
// Cálculo caudal teórico de entrada
#SP_CaudalTeoricoEntrada := #s_SP_CaudalConcentrado * #SP_FCV;
// Cálculo caudal teórico de permeado
#SP_CaudalPermeado := #SP_CaudalTeoricoEntrada - #s_SP_CaudalConcentrado;
// Cálculo caudal teórico de permeado total
IF NOT #ErrorDiferenciaPermeado THEN
#SP_CaudalPermeadoTotal := #SP_CaudalPermeado * ((#SP_PorcientoPermeadoTotal / 100) + 1);
ELSE
#SP_CaudalPermeadoTotal := #SP_CaudalPermeado * ((1 / 100) + 1);
END_IF;
// Comprobación bajo caudal de permeado total para incremento de presión
IF #SP_CaudalPermeadoTotal > #CaudalTotalPermeado THEN
#s_DiferenciaCaudalPermeado := #SP_CaudalPermeadoTotal - #CaudalTotalPermeado;
ELSE
#s_DiferenciaCaudalPermeado := 0.0;
END_IF;
#s_BajoCaudalPermeado := (#s_DiferenciaCaudalPermeado < #SP_BajoCaudalPermeado AND #s_DiferenciaCaudalPermeado > 0.0 ) OR (#SP_CaudalPermeadoTotal > #CaudalTotalPermeado);
ELSE
// ====================================================
// Modo no activo
#SP_CaudalTeoricoEntrada := 0.0;
#SP_CaudalPermeado := 0.0;
#SP_CaudalPermeadoTotal := 0.0;
#s_DiferenciaCaudalPermeado := 0.0;
#s_BajoCaudalPermeado := FALSE;
#s_MaxPresionAlcanzada := FALSE;
END_IF;
END_REGION
REGION PRESION
REGION TEMPORIZADOR
// ====================================================
// Temporizador para incrementos de presión
// Configuración temporizador
#s_TON[0].SP := #SP_TiempoMuestreoPresion;
#s_TON[0].IN := NOT #s_TON[0].Q AND #ActivarControlPresion AND #Marcha AND #s_BajoCaudalPermeado AND NOT #BotonReset AND (#s_SP_Presion < #SP_PresionMaxima);
"FC2928_ZC_TON_INDV"(Pulso1seg:=#Pulso1Seg,
TON:=#s_TON[0]);
END_REGION
IF #ActivarControlPresion THEN
#PermisoReset := TRUE;
// ====================================================
// Incrementos de presión
IF #s_TON[0].Q OR #ForzarIncrementos AND (#s_SP_Presion < #SP_PresionMaxima) THEN
#ForzarIncrementos := FALSE;
#s_SP_Presion += #SP_IncrementosPresion;
// Si el valor de presión calculado es mayor a la presión máxima, movemos la consigna máxima de presión
IF #s_SP_Presion > #SP_PresionMaxima THEN
#s_SP_Presion := #SP_PresionMaxima;
END_IF;
END_IF;
// Reset valor de presión a presión inicial
IF #BotonReset THEN
#s_SP_Presion := #SP_PresionInicial;
END_IF;
ELSE
IF NOT #EtapaRecircProd THEN
#s_SP_Presion := #SP_PresionInicial;
END_IF;
#ForzarIncrementos := FALSE;
#PermisoReset := FALSE;
END_IF;
// ====================================================
// Limite presion
IF #s_SP_Presion < #SP_PresionInicial THEN
#s_SP_Presion := #SP_PresionInicial;
END_IF;
END_REGION
REGION DECREMENTOS_CAUDAL
REGION TEMPORIZADOR
// ====================================================
// Temporizador para decrementos de caudal
// Configuración temporizador
#s_TON[1].SP := #SP_TiempoDecrementos;
#s_TON[1].IN := NOT #s_TON[1].Q AND #ActivarControlPresion AND #Marcha AND #s_MaxPresionAlcanzada AND (#CaudalTotalPermeado < #SP_CaudalPermeadoTotal);
"FC2928_ZC_TON_INDV"(Pulso1seg:=#Pulso1Seg,
TON:=#s_TON[1]);
END_REGION
IF #ActivarControlPresion THEN
// Presion máxima alcanzada
IF #s_SP_Presion >= #SP_PresionMaxima THEN
#s_MaxPresionAlcanzada := TRUE;
ELSE
#s_MaxPresionAlcanzada := FALSE;
END_IF;
// ====================================================
// Decrementos de caudal
IF #s_TON[1].Q AND (#s_SP_CaudalConcentrado > #SP_CaudalMinConcentrado) THEN
#s_SP_CaudalConcentrado := #s_SP_CaudalConcentrado * (1 - (#SP_PorcentajeDecremento / 100.0));
// Si el valor de caudal calculado es menor al caudal minimo, movemos la consigna minima de caudal
IF #s_SP_CaudalConcentrado < #SP_CaudalMinConcentrado THEN
#s_SP_CaudalConcentrado := #SP_CaudalMinConcentrado;
END_IF;
#AjusteSP_CaudalConcentrado := TRUE;
END_IF;
END_IF;
END_REGION
REGION SALIDAS
// ====================================================
// Salida de presion
#SP_Presion := #s_SP_Presion;
// ====================================================
// Maxima presion alcanzada
#MaxPresionAlcanzada := #s_MaxPresionAlcanzada;
// ====================================================
// Visibilidad en HMI
#VisibilidadConsignasCaudal := #ActivarCalculosCaudal;
#VisibilidadConsignasPresion := #ActivarControlPresion;
#VisibilidadConsignaCaudalDec := #ActivarControlPresion AND #s_MaxPresionAlcanzada;
#SP_CaudalConcentrado := #s_SP_CaudalConcentrado;
END_REGION ;
// Estados anteriores
#s_old_SP_CaudalConcentrado := #s_SP_CaudalConcentrado;
#s_old_SP_FCV := #SP_FCV;
END_FUNCTION_BLOCK
@@ -0,0 +1,147 @@
FUNCTION_BLOCK "FB15104_ZC_CALCULO_LIMP_2_MOD"
TITLE = FB15104_ZC_CALCULO_LIMP_2_MOD
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de funcion para el calculo de limpiezas modulos (2 modulos).
VAR_INPUT
EtapaRecirculacion : Bool; // En etapa de recirculacion
EtapaTiempoRestante : Int; // Tiempo de etapa restante
SP_TiempoRecirculacion : Int; // Set Point tiempo de recirculacion
SP_Modulo1 : Real; // Set Point (%) tiempo limpieza modulo 1
SP_Modulo2 : Real; // Set Point (%) tiempo limpieza modulo 2
END_VAR
VAR_OUTPUT
LimpiarSoloModulo1 : Bool; // Orden limpiar solo modulo 1
LimpiarSoloModulo2 : Bool; // Orden limpiar solo modulo 2
LimpiarTodosLosModulos : Bool; // Orden limpiar todos los modulos.
END_VAR
VAR RETAIN
s_PorcentajeMinimoTodosModulos { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Real := 20.0; // Set Point (%) minimo para limpieza de todos los modulos
s_PorcentajeModulo1 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Real;
s_PorcentajeModulo2 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Real;
s_PorcentajeRestante { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Real;
s_CalculoTiempoModulo1 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
s_CalculoTiempoModulo2 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
s_CalculoTiempoRestante { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
s_TiempoModulo1 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
s_TiempoModulo2 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
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
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_FUNCTION_BLOCK
@@ -0,0 +1,163 @@
FUNCTION_BLOCK "FB15105_ZC_CALCULO_CURVA"
TITLE = FB15105_ZC_CALCULO_CURVA
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de funcion para calculo curva de 10 puntos maximo.
VAR_INPUT
ValorActual : Real; // Valor actual
NumeroPuntos : Int := 10; // Numero de puntos
END_VAR
VAR_OUTPUT
Valor : Real; // Valor resultante curva
END_VAR
VAR
s_ValorActual : Real;
s_Valor : Real;
s_NumeroPuntos : Int;
END_VAR
VAR RETAIN
s_PuntoX : Array[1..#MAX_PUNTOS] of Real := [10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0]; // Valor X
s_PuntoY : Array[1..#MAX_PUNTOS] of Real := [10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0]; // Valor Y
END_VAR
VAR_TEMP
for_i : Int;
dx : Real;
dy : Real;
END_VAR
VAR CONSTANT
MAX_PUNTOS : Int := 10; // Numero maximo de puntos
END_VAR
BEGIN
REGION DESCRIPCION
//=======================================================================
// (C)Copyright ZeusControl 2023 - 2023
//=======================================================================
(*
### Información del Sistema
| Hardware Compatible | Entorno de Ingeniería |
|---------------------|-----------------------|
| PLC serie 1200/1500 | TIA Portal 18 |
---
### Descripción Funcional
El bloque `FB15105_ZC_CALCULO_CURVA` implementa una función de interpolación lineal por tramos sobre una curva configurable de hasta `#MAX_PUNTOS` puntos `(X, Y)`. A partir de un valor de entrada `ValorActual`, devuelve el valor de salida interpolado `Valor`, permitiendo linealizar señales no lineales como sondas de nivel, curvas de bombas o perfiles de consigna.
Funcionalidades principales:
- Validación del número de puntos activos: `#NumeroPuntos` se acota entre 2 (mínimo necesario para definir un segmento) y la constante de dimensionamiento `#MAX_PUNTOS`.
- Relleno automático: los puntos no utilizados por encima de `#s_NumeroPuntos` se rellenan con el último valor válido, manteniendo la coherencia del array para los cálculos posteriores.
- Corrección de monotonía: se fuerza la coordenada `X` a ser monótona creciente o igual hacia adelante, evitando inversiones de tramo que producirían divisiones por `dx` negativas o nulas.
- Saturación de entrada: si `#ValorActual` está por debajo del primer punto, la salida toma directamente el primer `Y`; si está por encima del último, toma el último `Y`, abortando el resto del escaneo para optimizar el tiempo de ciclo.
- Búsqueda del segmento activo: recorre los `#MAX_PUNTOS - 1` segmentos y detecta aquel en el que se encuentra el valor de entrada.
- Interpolación lineal: calcula los deltas `dx` y `dy` del segmento y aplica la ecuación `Y = (X - X1) * (dY / dX) + Y1`. En caso de `dx` nulo (tramo vertical o degenerado) se asigna directamente el `Y` del extremo inferior para evitar división por cero.
- Publicación del resultado en la salida `#Valor` una vez finalizado el cálculo.
> **Restricciones:** Ninguna.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 01.00.00 | 02.10.2023 | (ABH) | Primera versión. |
*)
END_REGION DESCRIPCION
// ===============================================================================================================
REGION LIMITES_VALORES
#s_ValorActual := #ValorActual;
#s_NumeroPuntos := #NumeroPuntos;
// Límite en configuración de número de puntos activos
IF #s_NumeroPuntos < 2 THEN
#s_NumeroPuntos := 2; // Una curva necesita mínimo 2 puntos (X1, Y1) a (X2, Y2)
ELSIF #s_NumeroPuntos > #MAX_PUNTOS THEN
#s_NumeroPuntos := #MAX_PUNTOS;
END_IF;
// Relleno automático de los puntos no utilizados con el último valor válido
FOR #for_i := #s_NumeroPuntos TO #MAX_PUNTOS DO
#s_PuntoX[#for_i] := #s_PuntoX[#s_NumeroPuntos];
#s_PuntoY[#for_i] := #s_PuntoY[#s_NumeroPuntos];
END_FOR;
// Corrección de monotonía (Asegurar que X siempre sea creciente o igual)
FOR #for_i := #MAX_PUNTOS TO 2 BY -1 DO
IF #s_PuntoX[#for_i] < #s_PuntoX[#for_i - 1] THEN
#s_PuntoX[#for_i] := #s_PuntoX[#for_i - 1];
END_IF;
END_FOR;
// Saturación del valor de entrada a los extremos de la curva configurada
IF #s_ValorActual <= #s_PuntoX[1] THEN
#s_ValorActual := #s_PuntoX[1];
#s_Valor := #s_PuntoY[1];
#Valor := #s_Valor;
RETURN; // Si está por debajo, asignamos y abortamos scan (Optimización)
ELSIF #s_ValorActual >= #s_PuntoX[#MAX_PUNTOS] THEN
#s_ValorActual := #s_PuntoX[#MAX_PUNTOS];
#s_Valor := #s_PuntoY[#MAX_PUNTOS];
#Valor := #s_Valor;
RETURN; // Si está por encima, asignamos y abortamos scan
END_IF;
END_REGION LIMITES_VALORES
// ===============================================================================================================
REGION CALCULO_SALIDA
// Búsqueda del segmento activo e interpolación lineal
FOR #for_i := 1 TO (#MAX_PUNTOS - 1) DO
IF (#s_ValorActual >= #s_PuntoX[#for_i]) AND (#s_ValorActual <= #s_PuntoX[#for_i + 1]) THEN
// Cálculo de deltas
#dx := #s_PuntoX[#for_i + 1] - #s_PuntoX[#for_i];
#dy := #s_PuntoY[#for_i + 1] - #s_PuntoY[#for_i];
// Proteccion por división por Cero
IF #dx <= 0.0 THEN
#s_Valor := #s_PuntoY[#for_i]; // Tramo vertical o nulo
ELSE
// Ecuación de la recta: Y = (X - X1) * (dY / dX) + Y1
#s_Valor := ((#s_ValorActual - #s_PuntoX[#for_i]) * (#dy / #dx)) + #s_PuntoY[#for_i];
END_IF;
// Segmento encontrado y calculado. Cortamos el bucle inmediatamente.
EXIT;
END_IF;
END_FOR;
END_REGION CALCULO_SALIDA
// ===============================================================================================================
REGION SALIDA
#Valor := #s_Valor;
END_REGION SALIDA
END_FUNCTION_BLOCK
@@ -0,0 +1,251 @@
FUNCTION_BLOCK "FB15106_ZC_CALCULO_LIMP_4_MOD"
TITLE = FB15106_ZC_CALCULO_LIMP_4_MOD
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de funcion para el calculo de limpiezas modulos (4 modulos).
VAR_INPUT
Etapa : Bool; // En etapa de recirculacion
Pulso1Seg : Bool;
EnMarcha : Bool;
SP_Tiempo : Int; // Set Point tiempo de recirculacion
SP_Salida1 : Real; // Set Point (%) tiempo limpieza modulo 1
SP_Salida2 : Real; // Set Point (%) tiempo limpieza modulo 2
SP_Salida3 : Real; // Set Point (%) tiempo limpieza modulo 3
SP_Salida4 : Real; // Set Point (%) tiempo limpieza modulo 4
END_VAR
VAR_IN_OUT
EtapaTiempoRestante : Int; // Tiempo de etapa restante
Salida1 : Bool; // Orden limpiar solo modulo 1
Salida2 : Bool; // Orden limpiar solo modulo 2
Salida3 : Bool; // Orden limpiar solo modulo 3
Salida4 : Bool; // Orden limpiar solo modulo 4
END_VAR
VAR RETAIN
s_PorcentajeSalida1 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Real;
s_PorcentajeSalida2 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Real;
END_VAR
VAR
s_PorcentajeSalida3 : Real;
s_PorcentajeSalida4 : Real;
END_VAR
VAR RETAIN
s_PorcentajeRestante { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Real;
s_CalculoTiempoSalida1 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
s_CalculoTiempoSalida2 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
END_VAR
VAR
s_CalculoTiempoSalida3 : Int;
s_CalculoTiempoSalida4 : Int;
END_VAR
VAR RETAIN
s_CalculoTiempoRestante { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
s_TiempoSalida1 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
s_TiempoSalida2 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
END_VAR
VAR
s_TiempoSalida3 : Int;
s_TiempoSalida4 : Int;
S_TON { S7_SetPoint := 'False'} : "UDT_ZC_DISP_TON";
s_TiempoTotal { S7_SetPoint := 'True'} : Int;
s_ContadorTiempo : Int;
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
Bloque de funcion que implementa el cálculo y la distribución temporal de la limpieza de 4 módulos, asignando a cada uno un porcentaje configurable del tiempo total de la etapa. A partir de los porcentajes validados y del tiempo total, calcula los tiempos individuales de cada módulo y activa secuencialmente la salida correspondiente en función de un contador interno en segundos.
Funcionalidades principales:
- Traspaso y validación de porcentajes: se leen los porcentajes de cada uno de los 4 módulos (`SP_Salida1` a `SP_Salida4`) y se comprueba que su suma no supere `100.0`. Si la suma supera dicho umbral, se asigna por defecto un valor de seguridad de `10.0` a cada uno de los cuatro porcentajes, evitando estados incoherentes.
- Cálculo de tiempos individuales: para cada módulo, si su porcentaje es distinto de cero, se calcula el tiempo correspondiente como `Porcentaje * SP_Tiempo / 100`, truncado a entero mediante `REAL_TO_INT`.
- Cálculo del tiempo total: se obtiene como la suma de los cuatro tiempos calculados y se utiliza para acotar el contador interno.
- Contador de etapa: mientras `Etapa` está activa, `EnMarcha` esté activado y `Pulso1Seg` genere un pulso por segundo, se incrementa el contador `#s_ContadorTiempo` hasta alcanzar `#s_TiempoTotal`, momento en el que se reinicia a `0` para comenzar un nuevo ciclo.
- Activación secuencial de salidas: cada salida (`Salida1`, `Salida2`, `Salida3`, `Salida4`) se activa cuando el contador se encuentra en el intervalo de tiempo correspondiente a su módulo. `Salida4` se activa por descarte cuando ninguna de las tres anteriores está activa.
- Reset al salir de etapa: cuando `Etapa` se desactiva, el contador y todas las salidas se ponen a cero.
- Cálculo del tiempo restante de etapa (`EtapaTiempoRestante`): se calcula en función de la salida activa como la diferencia entre el tiempo acumulado del módulo y el contador actual. Si el resultado es negativo, se satura a `0`.
> **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 | (HCR) | Primera versión. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION TRASPASO_PARAMETROS
// =====================================================================================
// TRASPASO DE PARAMETROS DE PORCENTAJE
// Se revisa los limites de los porcentajes metidos en pantalla
IF (#SP_Salida1 + #SP_Salida2 + #SP_Salida3 + #SP_Salida4) > 100.0 THEN
#s_PorcentajeSalida1 := 10.0;
#s_PorcentajeSalida2 := 10.0;
#s_PorcentajeSalida3 := 10.0;
#s_PorcentajeSalida4 := 10.0;
ELSE
#s_PorcentajeSalida1 := #SP_Salida1;
#s_PorcentajeSalida2 := #SP_Salida2;
#s_PorcentajeSalida3 := #SP_Salida3;
#s_PorcentajeSalida4 := #SP_Salida4;
END_IF;
END_REGION
// ==========================================================================================================
REGION CALCULOS
// =====================================================================================
// CALCULO DE TIEMPO DE PASO
// MODULO 1
IF #s_PorcentajeSalida1 <> 0.0 THEN
#s_CalculoTiempoSalida1 := REAL_TO_INT((#s_PorcentajeSalida1 * #SP_Tiempo) / 100.0);
END_IF;
// MODULO 2
IF #s_PorcentajeSalida2 <> 0.0 THEN
#s_CalculoTiempoSalida2 := REAL_TO_INT((#s_PorcentajeSalida2 * #SP_Tiempo) / 100.0);
END_IF;
// MODULO 3
IF #s_PorcentajeSalida3 <> 0.0 THEN
#s_CalculoTiempoSalida3 := REAL_TO_INT((#s_PorcentajeSalida3 * #SP_Tiempo) / 100.0);
END_IF;
// MODULO 4
IF #s_PorcentajeSalida4 <> 0.0 THEN
#s_CalculoTiempoSalida4 := REAL_TO_INT((#s_PorcentajeSalida4 * #SP_Tiempo) / 100.0);
END_IF;
#s_TiempoTotal := #s_CalculoTiempoSalida1 + #s_CalculoTiempoSalida2 + #s_CalculoTiempoSalida3 + #s_CalculoTiempoSalida4;
END_REGION
// ==========================================================================================================
REGION SALIDAS
IF #Etapa THEN
IF #s_ContadorTiempo < #s_TiempoTotal THEN
IF #Pulso1Seg AND #EnMarcha THEN
#s_ContadorTiempo += 1;
END_IF;
ELSE
#s_ContadorTiempo := 0;
END_IF;
// ACTIVACION 1
IF #s_ContadorTiempo < #s_CalculoTiempoSalida1 AND #s_CalculoTiempoSalida1 <> 0 THEN
#Salida1 := TRUE;
ELSE
#Salida1 := FALSE;
END_IF;
// ACTIVACION 2
IF #s_ContadorTiempo >= #s_CalculoTiempoSalida1 AND #s_ContadorTiempo < (#s_CalculoTiempoSalida2 + #s_CalculoTiempoSalida1) AND #s_CalculoTiempoSalida2 <> 0 THEN
#Salida2 := TRUE;
ELSE
#Salida2 := FALSE;
END_IF;
// ACTIVACION FLIP 3
IF #s_ContadorTiempo >= (#s_CalculoTiempoSalida2 + #s_CalculoTiempoSalida1) AND #s_ContadorTiempo < (#s_CalculoTiempoSalida2 + #s_CalculoTiempoSalida1 + #s_CalculoTiempoSalida3) AND #s_ContadorTiempo <> 0 THEN
#Salida3 := TRUE;
ELSE
#Salida3 := FALSE;
END_IF;
// ACTIVACION FLIP 4
#Salida4 := NOT #Salida1 AND NOT #Salida2 AND NOT #Salida3;
ELSE
#s_ContadorTiempo := 0;
#Salida1 := FALSE;
#Salida2 := FALSE;
#Salida3 := FALSE;
#Salida4 := FALSE;
END_IF;
// ACTIVACION 1
IF #s_ContadorTiempo < #s_CalculoTiempoSalida1 AND #s_CalculoTiempoSalida1 <> 0 THEN
#Salida1 := TRUE;
ELSE
#Salida1 := FALSE;
END_IF;
// ACTIVACION 2
IF #s_ContadorTiempo >= #s_CalculoTiempoSalida1 AND #s_ContadorTiempo < (#s_CalculoTiempoSalida2 + #s_CalculoTiempoSalida1) AND #s_CalculoTiempoSalida2 <> 0 THEN
#Salida2 := TRUE;
ELSE
#Salida2 := FALSE;
END_IF;
// ACTIVACION FLIP 3
IF #s_ContadorTiempo >= (#s_CalculoTiempoSalida2 + #s_CalculoTiempoSalida1) AND #s_ContadorTiempo < (#s_CalculoTiempoSalida2 + #s_CalculoTiempoSalida1 + #s_CalculoTiempoSalida3) AND #s_ContadorTiempo <> 0 THEN
#Salida3 := TRUE;
ELSE
#Salida3 := FALSE;
END_IF;
// ACTIVACION FLIP 4
#Salida4 := NOT #Salida1 AND NOT #Salida2 AND NOT #Salida3;
IF NOT #Etapa THEN
#Salida1 := #Salida2 := #Salida3 := #Salida4 := FALSE;
END_IF;
END_REGION
// ==========================================================================================================
REGION TIEMPO RESTANTE
IF #Salida1 THEN
#EtapaTiempoRestante := #s_CalculoTiempoSalida1 - #s_ContadorTiempo;
END_IF;
IF #Salida2 THEN
#EtapaTiempoRestante := (#s_CalculoTiempoSalida1 + #s_CalculoTiempoSalida2) - #s_ContadorTiempo;
END_IF;
IF #Salida3 THEN
#EtapaTiempoRestante := (#s_CalculoTiempoSalida1 + #s_CalculoTiempoSalida2 + #s_CalculoTiempoSalida3) - #s_ContadorTiempo;
END_IF;
IF #Salida4 THEN
#EtapaTiempoRestante := #s_TiempoTotal - #s_ContadorTiempo;
END_IF;
IF #EtapaTiempoRestante < 0 THEN
#EtapaTiempoRestante := 0;
END_IF;
END_REGION
END_FUNCTION_BLOCK
@@ -0,0 +1,149 @@
FUNCTION "FC15103_ZC_CALCULO_RAMPA" : Void
TITLE = FC15103_ZC_CALCULO_RAMPA
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Funcion para calculo de rampa hasta valor objetivo.
VAR_INPUT
Pulso100ms : Bool; // Pulso 100 ms
HabilitarRampa : Bool; // Habilitar Rampa
ValorObjetivo : Real; // Valor a alcanzar
IncRespRapida : Real; // Incremento rapido en ud. ing. / segundo
DecRespRapida : Real; // Decremento Rapido ud. ing. / segundo
IncRespLenta : Real; // Incremento lento en ud. ing. / segundo
DecRespLenta : Real; // Decremento lento ud. ing. / segundo
HistRapidaLenta : Real; // Histeresis respuesta rapida-lenta rampa
END_VAR
VAR_IN_OUT
ValorActual : Real; // Valor actual de la rampa
END_VAR
VAR_TEMP
t_Diferencia : Real;
t_Incremento : Real;
END_VAR
BEGIN
REGION DESCRIPCION
(*
###### (C)Copyright ZeusControl 2023 - 2023
---
### 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 calcular rampas hasta alcanzar valor objetivo.
El bloque opera de la siguiente manera:
1. Si esta la rampa habilitada:
2. Realiza el calculo de la diferencia entre el valor actual y el valor objetivo.
3. En funcion de en que rango este, realiza los incrementos en el valor actual.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 01.00.00 | 05.09.2023 | (HCR) | Primera version. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION CALCULO_RAMPA
// Gestion de la rampa de Set Point al cambiar de valor
IF #HabilitarRampa THEN
// ==========================================================================================================
REGION CALCULOS
// Calculo diferencia entre Set Point y valor de la rampa
#t_Diferencia := ABS(#ValorObjetivo - #ValorActual);
// Calculo de incremento DOWN
IF #ValorObjetivo < #ValorActual THEN
IF #t_Diferencia > #HistRapidaLenta THEN
#t_Incremento := #DecRespRapida / 10;
ELSE
#t_Incremento := #DecRespLenta / 10;
END_IF;
END_IF;
// Calculo de incremento UP
IF #ValorObjetivo > #ValorActual THEN
IF #t_Diferencia > #HistRapidaLenta THEN
#t_Incremento := #IncRespRapida / 10;
ELSE
#t_Incremento := #IncRespLenta / 10;
END_IF;
END_IF;
END_REGION
// ==========================================================================================================
REGION GESTION_INCREMENTOS
// Gestion incremento UP
IF #ValorActual < #ValorObjetivo
AND
#t_Diferencia > #t_Incremento
AND
#Pulso100ms
THEN
#ValorActual := #ValorActual + #t_Incremento;
END_IF;
// Gestion incremento DOWN
IF #ValorActual > #ValorObjetivo
AND
#t_Diferencia > #t_Incremento
AND
#Pulso100ms
THEN
#ValorActual := #ValorActual - #t_Incremento;
END_IF;
// Gestion limite alcanzado o sin incremento configurado
IF #t_Diferencia <= #t_Incremento
OR
#t_Incremento = 0
THEN
#ValorActual := #ValorObjetivo;
END_IF;
END_REGION
ELSE
#ValorActual := #ValorObjetivo;
END_IF;
END_REGION CALCULO_RAMPA
END_FUNCTION
@@ -0,0 +1,94 @@
FUNCTION "FC15025_ZC_CONTADOR_TIEMPO" : Void
TITLE = FC15025_ZC_CONTADOR_TIEMPO
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : HCR
FAMILY : ZeusControl
VERSION : 1.0
//Funcion contador de tiempo
VAR_INPUT
Pulso1seg : Bool; // Pulso de 1 segundo
Iniciar : Bool; // Orden iniciar contador
Reset : Bool; // Reset contador
END_VAR
VAR_IN_OUT
Contador : "UDT_ZC_CONTADOR_TIEMPO";
END_VAR
VAR CONSTANT
MAX_HORAS : UDInt := 10000000; // Valor maximo de horas
END_VAR
BEGIN
REGION DESCRIPCION
(*
###### (C)Copyright ZeusControl 2023 - 2023
---
### 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 contar tiempo.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 01.00.00 | 16.03.2023 | (HCR) | Primera version. |
| 01.00.01 | 25.07.2023 | (HCR) | Se añade valor maximo DINT para limitar contador horas. En caso de alcanzar valor maximo, se resetea el contador de horas. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION GESTION_CONTADOR
// ==========================================================================================================
REGION RESET_CONTADOR
IF #Reset OR #Contador.Hora >= #MAX_HORAS THEN
#Contador.Hora := #Contador.Minuto := #Contador.Segundo := 0;
END_IF;
END_REGION RESET_CONTADOR
// ==========================================================================================================
REGION GESTION_CONTADOR
IF #Iniciar AND #Pulso1seg THEN
#Contador.#Segundo += 1;
IF #Contador.#Segundo >= 60 THEN
#Contador.#Segundo := 0;
#Contador.#Minuto += 1;
IF #Contador.#Minuto >= 60 THEN
#Contador.#Minuto := 0;
#Contador.Hora += 1;
END_IF;
END_IF;
END_IF;
END_REGION RESET_CONTADOR
END_REGION
END_FUNCTION
@@ -0,0 +1,90 @@
FUNCTION "FC15027_ZC_CONTADOR_MINUTOS" : Void
TITLE = FC15027_ZC_CONTADOR_MINUTOS
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Funcion contador de minutos
VAR_INPUT
Pulso1seg : Bool; // Pulso de 1 segundo
Iniciar : Bool; // Orden iniciar contador
Reset : Bool; // Reset contador
END_VAR
VAR_IN_OUT
Contador : "UDT_ZC_CONTADOR_MINUTOS";
END_VAR
VAR CONSTANT
MAX_MINUTOS : UDInt := 10000000; // Valor maximo de minutos
END_VAR
BEGIN
REGION DESCRIPCION
(*
###### (C)Copyright ZeusControl 2024 - 2024
---
### 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 contar tiempo en minutos.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 01.00.00 | 13.05.2024 | (ABH) | Primera version. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION GESTION_CONTADOR
// ==========================================================================================================
REGION RESET_CONTADOR
IF #Reset OR #Contador.Minuto >= #MAX_MINUTOS THEN
#Contador.Minuto := #Contador.Segundo := 0;
END_IF;
END_REGION RESET_CONTADOR
// ==========================================================================================================
REGION GESTION_CONTADOR
IF #Iniciar AND #Pulso1seg THEN
#Contador.#Segundo += 1;
IF #Contador.#Segundo >= 60 THEN
#Contador.#Segundo := 0;
#Contador.#Minuto += 1;
END_IF;
END_IF;
END_REGION GESTION_CONTADOR
END_REGION GESTION_CONTADOR
END_FUNCTION
@@ -0,0 +1,63 @@
FUNCTION "FC15000_ZC_INT_TO_TIME" : Time
TITLE = FC15000_ZC_INT_TO_TIME
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : HCR
FAMILY : ZeusControl
VERSION : 1.0
//Funcion para conversion INT a TIME
VAR_INPUT
Valor : Int; // Valor INT
END_VAR
VAR CONSTANT
BASE_TIEMPO : Int := 1000; // Base de tiempo para conversion
END_VAR
BEGIN
REGION DESCRIPCION
(*
###### (C)Copyright ZeusControl 2023 - 2023
---
### 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 convertir tipo de dato INT a TIME.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 01.00.00 | 10.05.2023 | (HCR) | Primera version. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION CALCULO
#FC15000_ZC_INT_TO_TIME := DINT_TO_TIME(IN := INT_TO_DINT(IN := #Valor)) * #BASE_TIEMPO;
END_REGION CALCULO
END_FUNCTION
@@ -0,0 +1,60 @@
FUNCTION "FC15001_ZC_INT_TO_STRING" : String
TITLE = FC15001_ZC_INT_TO_STRING
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Funcion para convertir INT a STRING
VAR_INPUT
Valor : Int; // Valor INT
END_VAR
BEGIN
REGION DESCRIPCION
(*
###### (C)Copyright ZeusControl 2023 - 2023
---
### 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 convertir tipo de dato INT a STRING.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 01.00.00 | 15.03.2023 | (ABH) | Primera version. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION CALCULO
#FC15001_ZC_INT_TO_STRING := DELETE(IN := INT_TO_STRING(#Valor), L := 1, P := 1);
END_REGION CALCULO
END_FUNCTION
@@ -0,0 +1,83 @@
FUNCTION "FC15003_ZC_REAL_TO_STRING" : String
TITLE = FC15003_ZC_REAL_TO_STRING
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : HCR
FAMILY : ZeusControl
VERSION : 1.1
//Funcion para convertir REAL a TRING
VAR_INPUT
Valor : Real; // Valor REAL
END_VAR
VAR_TEMP
t_String : String;
t_Posición : Int;
END_VAR
BEGIN
REGION DESCRIPCION
(*
###### (C)Copyright ZeusControl 2022 - 2023
---
### 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 convertir tipo de dato REAL a STRING.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 01.00.00 | 15.10.2022 | (HCR) | Primera version. |
| 01.00.00 | 25.07.2023 | (ABH) | Cambio FC de Void a Funcion. Cambio en nombre de variables para estandarizacion. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION CALCULO
// Conversion de real a string
VAL_STRG(IN := #Valor,
SIZE := 10,
PREC := 1,
FORMAT := 16#0004,
P := 16,
OUT => #t_String);
// Se añade signo en base a valor
IF #Valor >= 0.0 THEN
#t_Posición := FIND(IN1 := #t_String, IN2 := '+');
END_IF;
IF #Valor < 0.0 THEN
#t_Posición := FIND(IN1 := #t_String, IN2 := '-');
END_IF;
// Borrado de caracteres antes del signo
#FC15003_ZC_REAL_TO_STRING := DELETE(IN := #t_String, L := #t_Posición - 1, P := 1);
END_REGION CALCULO
END_FUNCTION
@@ -0,0 +1,66 @@
FUNCTION "FC15005_ZC_DTL_TO_ZC_FECHA" : "UDT_ZC_FECHA"
TITLE = FC15005_ZC_DTL_TO_ZC_FECHA
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Funcion para convertir tipo de datos DTL a tipo de datos ZC_FECHA
VAR_INPUT
FechaDTL {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha DTL a convertir
END_VAR
BEGIN
REGION DESCRIPCION
(*
###### (C)Copyright ZeusControl 2023 - 2023
---
### Información del Sistema
| Hardware Compatible | Entorno de Ingeniería |
|---------------------|-----------------------|
| PLC serie 1200/1500 | TIA Portal 18 |
---
> **Restricciones:** Ninguna.
---
### Descripción Funcional
Función para traspaso de datos en DTL a tipo de dato ZC_FECHA
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 01.00.00 | 03.11.2022 | (ABH) | Primera version. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION CALCULO
#FC15005_ZC_DTL_TO_ZC_FECHA.Ano := #FechaDTL.YEAR;
#FC15005_ZC_DTL_TO_ZC_FECHA.Mes := #FechaDTL.MONTH;
#FC15005_ZC_DTL_TO_ZC_FECHA.Dia := #FechaDTL.DAY;
#FC15005_ZC_DTL_TO_ZC_FECHA.Hora := #FechaDTL.HOUR;
#FC15005_ZC_DTL_TO_ZC_FECHA.Minuto := #FechaDTL.MINUTE;
#FC15005_ZC_DTL_TO_ZC_FECHA.Segundo := #FechaDTL.SECOND;
#FC15005_ZC_DTL_TO_ZC_FECHA.NanoSegundo := #FechaDTL.NANOSECOND;
#FC15005_ZC_DTL_TO_ZC_FECHA.DiaSemana := #FechaDTL.WEEKDAY;
END_REGION CALCULO
END_FUNCTION
@@ -0,0 +1,187 @@
FUNCTION "FC15006_ZC_DTL_TO_STRING" : String
TITLE = FC15006_ZC_DTL_TO_STRING
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.1
//Funcion para convertir DTL a STRING
VAR_INPUT
FechaDTL {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;
Formato : USInt; // 0= Fecha y hora / 1= Fecha / 2= hORA
END_VAR
VAR_TEMP
t_Ano : String[5];
t_Mes : String[3];
t_Dia : String[3];
t_Hora : String[3];
t_Minuto : String[3];
t_Segundo : String[3];
t_Nanosegundo : String[50];
END_VAR
BEGIN
REGION DESCRIPCION
(*
###### (C)Copyright ZeusControl 2019 - 2023
---
### 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 convertir tipo de dato DTL a String
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 01.00.00 | 10.09.2019 | (ABH) | Primera version. |
| 01.00.00 | 25.07.2023 | (ABH) | Se eliminan las variables temporales STRING, para concatenar directamente en el return de la funcion el texto deseado. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION CALCULO
REGION GESTION_STRING
// Genero un String por cada elemento
#t_Ano := UINT_TO_STRING(#FechaDTL.YEAR);
#t_Mes := USINT_TO_STRING(#FechaDTL.MONTH);
#t_Dia := USINT_TO_STRING(#FechaDTL.DAY);
#t_Hora := USINT_TO_STRING(#FechaDTL.HOUR);
#t_Minuto := USINT_TO_STRING(#FechaDTL.MINUTE);
#t_Segundo := USINT_TO_STRING(#FechaDTL.SECOND);
#t_Nanosegundo := UDINT_TO_STRING(#FechaDTL.NANOSECOND);
// TRATAMIENTO DE LA FECHA
// Año
#t_Ano := DELETE(IN := #t_Ano, L := 1, P := 1);// Le borro el signo
// Mes
IF #FechaDTL.MONTH < 10 THEN
#t_Mes := DELETE(IN := #t_Mes, L := 1, P := 1);// Le borro el signo
#t_Mes := CONCAT(IN1 := '0', IN2 := #t_Mes);// Le añado un cero
ELSE
#t_Mes := DELETE(IN := #t_Mes, L := 1, P := 1);// Le borro el signo
END_IF;
// Dia
IF #FechaDTL.DAY < 10 THEN
#t_Dia := DELETE(IN := #t_Dia, L := 1, P := 1);// Le borro el signo
#t_Dia := CONCAT(IN1 := '0', IN2 := #t_Dia);// Le añado un cero
ELSE
#t_Dia := DELETE(IN := #t_Dia, L := 1, P := 1);// Le borro el signo
END_IF;
// TRATAMIENTO DE LA HORA
// Horas
IF #FechaDTL.HOUR < 10 THEN
#t_Hora := DELETE(IN := #t_Hora, L := 1, P := 1);// Le borro el signo
#t_Hora := CONCAT(IN1 := '0', IN2 := #t_Hora);// Le añado un cero
ELSE
#t_Hora := DELETE(IN := #t_Hora, L := 1, P := 1);// Le borro el signo
END_IF;
// Minutos
IF #FechaDTL.MINUTE < 10 THEN
#t_Minuto := DELETE(IN := #t_Minuto, L := 1, P := 1);// Le borro el signo
#t_Minuto := CONCAT(IN1 := '0', IN2 := #t_Minuto);// Le añado un cero
ELSE
#t_Minuto := DELETE(IN := #t_Minuto, L := 1, P := 1);// Le borro el signo
END_IF;
// Segundos
IF #FechaDTL.SECOND < 10 THEN
#t_Segundo := DELETE(IN := #t_Segundo, L := 1, P := 1);// Le borro el signo
#t_Segundo := CONCAT(IN1 := '0', IN2 := #t_Segundo);// Le añado un cero
ELSE
#t_Segundo := DELETE(IN := #t_Segundo, L := 1, P := 1);// Le borro el signo
END_IF;
// Nanosegundos
IF #FechaDTL.NANOSECOND < 10 THEN
#t_Nanosegundo := DELETE(IN := #t_Nanosegundo, L := 1, P := 1);// Le borro el signo
#t_Nanosegundo := LEFT(IN := CONCAT(IN1 := '0', IN2 := #t_Nanosegundo), L := 5);// Le añado un cero
ELSE
#t_Nanosegundo := LEFT(IN := DELETE(IN := #t_Nanosegundo, L := 1, P := 1), L := 5);// Le borro el signo
END_IF;
END_REGION GESTION_STRING
REGION SALIDAS
CASE #Formato OF
0: // Fecha y hora
#FC15006_ZC_DTL_TO_STRING := CONCAT(IN1 := #t_Dia,
IN2 := '/',
IN3 := #t_Mes,
IN4 := '/',
IN5 := #t_Ano,
IN6 := ' ',
IN7 := #t_Hora,
IN8 := ':',
IN9 := #t_Minuto,
IN10 := ':',
IN11 := #t_Segundo);
1: // Fecha
#FC15006_ZC_DTL_TO_STRING := CONCAT(IN1 := #t_Dia,
IN2 := '/',
IN3 := #t_Mes,
IN4 := '/',
IN5 := #t_Ano);
2: // Hora
#FC15006_ZC_DTL_TO_STRING := CONCAT(IN1 := #t_Hora,
IN2 := ':',
IN3 := #t_Minuto,
IN4 := ':',
IN5 := #t_Segundo);
3: // Fecha y hora (nanosegundo)
#FC15006_ZC_DTL_TO_STRING := CONCAT(IN1 := #t_Ano,
IN2 := #t_Mes,
IN3 := #t_Dia,
IN4 := #t_Hora,
IN5 := #t_Minuto,
IN6 := #t_Segundo,
IN7 := #t_Nanosegundo);
ELSE
#FC15006_ZC_DTL_TO_STRING := CONCAT(IN1 := #t_Dia,
IN2 := '/',
IN3 := #t_Mes,
IN4 := '/',
IN5 := #t_Ano,
IN6 := ' ',
IN7 := #t_Hora,
IN8 := ':',
IN9 := #t_Minuto,
IN10 := ':',
IN11 := #t_Segundo);
END_CASE;
END_REGION SALIDAS
END_REGION CALCULO
END_FUNCTION
@@ -0,0 +1,122 @@
FUNCTION "FC15026_ZC_PULSADOR" : Void
TITLE = FC15026_ZC_PULSADOR
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Funcion para gestion de pulsadores
VAR_INPUT
Pulso1Seg : Bool; // Pulso 1 segundo
SP_Tiempo : Int; // Tiempo retardo pulsador
TrazaCategoria : Int; // Categoria de la traza
TrazaIdProceso : Int; // ID Proceso para trazabilidad
TrazaIdPulsador : Int; // ID Pulsador para trazabilidad
Usuario : String; // Usuario actual
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
END_VAR
VAR_IN_OUT
Pulsador : "UDT_ZC_PULSADOR"; // Pulsador
END_VAR
BEGIN
REGION DESCRIPCION
(*
###### (C)Copyright ZeusControl 2025 - 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 la gestión temporizada de los pulsadores virtuales provenientes del sistema HMI o sistema externo, integrando el registro automático de cada acción en el sistema de trazabilidad.
En ella se realizan las siguientes acciones:
- Evalúa continuamente si existe una orden activa desde el HMI o desde sistema externo y si el pulsador dispone del permiso de ejecución necesario.
- Incrementa un temporizador interno auxiliar mediante un pulso de un segundo hasta alcanzar el tiempo de retardo configurado.
- Una vez superado el tiempo de retardo:
- Registra el evento en el buffer invocando la función FC8_ZC_TRAZA_REGISTRO, asignando la categoría específica de pulsadores, el identificador, el usuario y la marca de tiempo.
- Activa la señal de confirmación de orden hacia la lógica del PLC.
- Resetea automáticamente la marca de activación del HMI.
- Reinicia a cero el tiempo acumulado del pulsador en caso de perder el permiso de ejecución o si la orden del HMI se cancela antes de finalizar el temporizador.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | `FC8_ZC_TRAZA_REGISTRO` |
| FB | - |
| DB | - |
| UDT | `UDT_ZC_PULSADOR` |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 01.00.00 | 14.03.2025 | (ABH) | Primera version. |
| 01.01.00 | 08.07.2026 | (ABH) | Se implementa orden externa. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION GESTION_PULSADOR
// Reset orden PLC
#Pulsador.Plc := FALSE;
// Con permiso y con la orden desde HMI, contamos el tiempo para activar la orden de PLC
IF (#Pulsador.Hmi OR #Pulsador.Remoto) AND #Pulsador.Permiso THEN
IF #Pulso1Seg AND #Pulsador.AuxTiempo < #SP_Tiempo THEN
#Pulsador.AuxTiempo += 1;
END_IF;
IF #Pulsador.AuxTiempo >= #SP_Tiempo THEN
// Registramos la trazabilidad de la pulsacion del boton
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
Registrar := 1,
Categoria := #TrazaCategoria,
User := #Usuario,
CodInt_1 := #TrazaIdProceso,
CodInt_2 := #TrazaIdPulsador,
CodInt_3 := 0,
CodInt_4:= 0,
CodInt_5:= 0,
CodReal_1 := 0.0,
CodReal_2 := 0.0);
// Activacion de orden PLC y reset orden HMI
#Pulsador.Plc := TRUE;
#Pulsador.Hmi :=
#Pulsador.Remoto := FALSE;
END_IF;
END_IF;
END_REGION GESTION_PULSADOR
// ==========================================================================================================
REGION RESET_DATOS
// Sin orden desde HMI o si no tenemos permiso, reseteamos el tiempo del pulsador
IF (NOT #Pulsador.Hmi AND NOT #Pulsador.Remoto) OR NOT #Pulsador.Permiso THEN
#Pulsador.AuxTiempo := 0;
END_IF;
END_REGION RESET_DATOS
END_FUNCTION