Primera version
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
FUNCTION_BLOCK "FB15050_ZC_CHEQUEO"
|
||||
TITLE = FB15050_ZC_CHEQUEO
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
VAR_INPUT
|
||||
GuardarRegistro : Bool; // Orden guardado registro nuevo
|
||||
ComprobarBajoChequeo : Bool; // Orden comprobacion Alarma bajo chequeo
|
||||
ResetBajoChequeo : Bool; // Reset alarma bajo chequeo
|
||||
TomarDatoChequeo : Bool; // Orden para visualizacion tomar datos en HMI
|
||||
PorcentajeBomba : Real; // Porcentaje bomba
|
||||
Temperatura : Real; // Temperatura
|
||||
Caudal : Real; // Caudal
|
||||
CaudalPermeado : Real; // Caudal permeado
|
||||
Conductividad : Real; // Conductividad
|
||||
Presion : Real; // Presion
|
||||
SP_Caudal_100por100 : Real; // Set Point caudal 100%
|
||||
SP_CaudalMinimoChequeo : Real; // Set Point caudal minimo
|
||||
FechaActual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
END_VAR
|
||||
|
||||
VAR_OUTPUT
|
||||
EstadoChequeoActual : Bool; // Estado chequeo actual
|
||||
AlarmaBajoChequeo : Bool; // Alarma bajo chequeo
|
||||
VisDatoChequeo : Bool; // Visibilidad tomar datos en HMI
|
||||
PorcentajeChequeoActual : Real; // Estado porcentaje actual
|
||||
END_VAR
|
||||
|
||||
VAR RETAIN
|
||||
s_PorcentajeChequeoOK { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Real := 80.0;
|
||||
END_VAR
|
||||
VAR
|
||||
s_OrdenGuardarRegistro { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
|
||||
s_OrdenBorrarRegistros { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
|
||||
s_NumeroBorrado { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // -1= Todos / Valor= Numero de registro
|
||||
s_OldGuardar { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
|
||||
END_VAR
|
||||
VAR RETAIN
|
||||
Registro { S7_SetPoint := 'False'} : Array[1..#N_REGISTROS] of "UDT_ZC_INF_CHEQUEO";
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_dummyInt : Int;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
N_REGISTROS : Int := 20;
|
||||
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 `FB15050_ZC_CHEQUEO` implementa la gestión de los datos de chequeo de un sistema de membranas, manteniendo un histórico circular de hasta `#N_REGISTROS` mediciones y evaluando el rendimiento de la instalación comparando el caudal de permeado real con un valor de referencia al 100% de la bomba.
|
||||
|
||||
Funcionalidades principales:
|
||||
- Detección de flanco ascendente en la orden de guardado: `#s_OrdenGuardarRegistro` se activa con un pulso de `#GuardarRegistro` mediante la variable estática `#s_P_Trig_Guardar`, evitando registros duplicados por nivel alto mantenido.
|
||||
- Adquisición de datos: al recibir la orden de guardado, se desplazan los registros existentes una posición hacia abajo mediante `MOVE_BLK_VARIANT` y se almacena en `#Registro[1]` el conjunto de variables de proceso (`PorcentajeBomba`, `Temperatura`, `Caudal`, `CaudalPermeado`, `Conductividad`, `Presion`), junto con el `ResultadoChequeo` calculado como el porcentaje de caudal de permeado frente a `SP_Caudal_100por100`, y la fecha actual convertida con `FC15005_ZC_DTL_TO_ZC_FECHA` a la estructura `ZC_FECHA`.
|
||||
- Cálculo del porcentaje de chequeo en tiempo real: `PorcentajeChequeoActual` se obtiene como el cociente entre el `CaudalPermeado` actual y `SP_Caudal_100por100`, y `EstadoChequeoActual` se activa cuando dicho porcentaje alcanza o supera `#s_PorcentajeChequeoOK`.
|
||||
- Alarma de bajo chequeo: se activa `#AlarmaBajoChequeo` cuando `#ComprobarBajoChequeo` está habilitado y el `Caudal` cae por debajo de `#SP_CaudalMinimoChequeo`. Se desactiva con `#ResetBajoChequeo`.
|
||||
- Animación de resultados: para cada registro se evalúa `ResultadoAnimacion`, que se activa cuando el `ResultadoChequeo` del registro es igual o superior a 80.0%, permitiendo al HMI colorear el histórico de forma intuitiva.
|
||||
- Visibilidad de toma de dato en HMI: `VisDatoChequeo` refleja el estado de `#TomarDatoChequeo` para señalizar al operador que la fase de toma de datos está activa.
|
||||
- Borrado de registros selectivo: según el valor de `#s_NumeroBorrado` se distingue entre borrado total (`0` o `-1`), borrado de un registro intermedio (con desplazamiento hacia abajo para mantener la trazabilidad) y borrado del último registro. En todos los casos se inicializan a cero todos los campos del registro (analógicos y de fecha).
|
||||
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC15005_ZC_DTL_TO_ZC_FECHA` |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `ZC_FECHA`, `ZC_CHEQUEO` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 18.07.2023 | (ABH) | Primera versión. |
|
||||
| 01.00.01 | 21.07.2023 | (ABH) | Se eliminan entradas `Etapa actual` y `tiempo restante`. La gestión de guardado y comprobación de bajo chequeo se realiza mediante entradas BOOL. |
|
||||
| 01.00.02 | 11.10.2023 | (HCR) | Se añaden entradas `TomarDatoChequeo` y salida `VisDatoChequeo` para mostrar en HMI la toma de datos por parte del operador. |
|
||||
| 01.00.02 | 03.07.2026 | (ABH) | Cambio a SCL. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION ORDEN_GUARDAR
|
||||
|
||||
// Orden guardar registro
|
||||
#s_OrdenGuardarRegistro := #GuardarRegistro AND NOT #s_OldGuardar;
|
||||
|
||||
// Estado anterior
|
||||
#s_OldGuardar := #GuardarRegistro;
|
||||
|
||||
END_REGION ORDEN_GUARDAR
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION ADQUISICION_DE_DATOS
|
||||
|
||||
// Con flanco de guardar datos, desplazamos los registros y almacenamos los datos del chequeo en la poisicion 1
|
||||
IF #s_OrdenGuardarRegistro THEN
|
||||
|
||||
// Desplazamiento de datos
|
||||
#t_dummyInt := MOVE_BLK_VARIANT(SRC := #Registro, COUNT := INT_TO_UDINT(#N_REGISTROS - 1), SRC_INDEX := 0, DEST_INDEX := 1, DEST => #Registro);
|
||||
|
||||
// Adquisicion de datos
|
||||
#Registro[1].PorcentajeBomba := #PorcentajeBomba;
|
||||
#Registro[1].Temperatura := #Temperatura;
|
||||
#Registro[1].Caudal := #Caudal;
|
||||
#Registro[1].CaudalPermeado := #CaudalPermeado;
|
||||
#Registro[1].Conductividad := #Conductividad;
|
||||
#Registro[1].Presion := #Presion;
|
||||
#Registro[1].ResultadoChequeo := #CaudalPermeado / #SP_Caudal_100por100 * 100.0;
|
||||
|
||||
#Registro[1].Fecha := "FC15005_ZC_DTL_TO_ZC_FECHA"(#FechaActual);
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION ADQUISICION_DE_DATOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION CALCULO_%_CHEQUEO
|
||||
|
||||
// Calculo porcentaje del chequeo
|
||||
IF #SP_Caudal_100por100 > 0.0 THEN
|
||||
#PorcentajeChequeoActual := (#Registro[1].CaudalPermeado / #SP_Caudal_100por100) * 100.0;
|
||||
ELSE
|
||||
#PorcentajeChequeoActual := 0.0;
|
||||
END_IF;
|
||||
|
||||
// Estado del chequeo actual
|
||||
#EstadoChequeoActual := #PorcentajeChequeoActual >= #s_PorcentajeChequeoOK;
|
||||
|
||||
END_REGION CALCULO_%_CHEQUEO
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION VISIBILIDADES
|
||||
|
||||
// Visibilidad bajo chequeo
|
||||
IF #ComprobarBajoChequeo AND (#Caudal < #SP_CaudalMinimoChequeo) THEN
|
||||
#AlarmaBajoChequeo := TRUE;
|
||||
END_IF;
|
||||
IF #ResetBajoChequeo THEN
|
||||
#AlarmaBajoChequeo := FALSE;
|
||||
END_IF;
|
||||
|
||||
// Visibilidad Resultado Chequeo
|
||||
FOR #for_i := 1 TO #N_REGISTROS DO
|
||||
#Registro[#for_i].ResultadoAnimacion := (#Registro[#for_i].ResultadoChequeo >= 80.0);
|
||||
END_FOR;
|
||||
|
||||
// Visibilidad tomar dato chequeo en HMI
|
||||
#VisDatoChequeo := #TomarDatoChequeo;
|
||||
|
||||
END_REGION VISIBILIDADES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION BORRADO
|
||||
|
||||
// Borrado de todos los registros
|
||||
IF #s_OrdenBorrarRegistros THEN
|
||||
IF #s_NumeroBorrado = -1 OR #s_NumeroBorrado = 0 THEN
|
||||
// ==============================================================================
|
||||
// Borrado total
|
||||
FOR #for_i := 1 TO #N_REGISTROS DO
|
||||
#Registro[#for_i].PorcentajeBomba := 0.0;
|
||||
#Registro[#for_i].Temperatura := 0.0;
|
||||
#Registro[#for_i].Caudal := 0.0;
|
||||
#Registro[#for_i].CaudalPermeado := 0.0;
|
||||
#Registro[#for_i].Conductividad := 0.0;
|
||||
#Registro[#for_i].Presion := 0.0;
|
||||
#Registro[#for_i].ResultadoChequeo := 0.0;
|
||||
#Registro[#for_i].Fecha.Ano := 0;
|
||||
#Registro[#for_i].Fecha.Mes := 0;
|
||||
#Registro[#for_i].Fecha.Dia := 0;
|
||||
#Registro[#for_i].Fecha.DiaSemana := 0;
|
||||
#Registro[#for_i].Fecha.Hora := 0;
|
||||
#Registro[#for_i].Fecha.Minuto := 0;
|
||||
#Registro[#for_i].Fecha.Segundo := 0;
|
||||
#Registro[#for_i].Fecha.NanoSegundo := 0;
|
||||
END_FOR;
|
||||
ELSIF #s_NumeroBorrado >= 1 AND #s_NumeroBorrado < #N_REGISTROS THEN
|
||||
// ==============================================================================
|
||||
// Borrado registro especifico
|
||||
#Registro[#s_NumeroBorrado].PorcentajeBomba := 0.0;
|
||||
#Registro[#s_NumeroBorrado].Temperatura := 0.0;
|
||||
#Registro[#s_NumeroBorrado].Caudal := 0.0;
|
||||
#Registro[#s_NumeroBorrado].CaudalPermeado := 0.0;
|
||||
#Registro[#s_NumeroBorrado].Conductividad := 0.0;
|
||||
#Registro[#s_NumeroBorrado].Presion := 0.0;
|
||||
#Registro[#s_NumeroBorrado].ResultadoChequeo := 0.0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.Ano := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.Mes := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.Dia := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.DiaSemana := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.Hora := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.Minuto := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.Segundo := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.NanoSegundo := 0;
|
||||
// ==============================================================================
|
||||
// Desplazamiento de datos
|
||||
#t_dummyInt := MOVE_BLK_VARIANT(SRC := #Registro,
|
||||
COUNT := INT_TO_UDINT(#N_REGISTROS - #s_NumeroBorrado),
|
||||
SRC_INDEX := #s_NumeroBorrado,
|
||||
DEST_INDEX := #s_NumeroBorrado - 1,
|
||||
DEST => #Registro);
|
||||
// ==============================================================================
|
||||
// Borrado del ultimo registro
|
||||
#Registro[#N_REGISTROS].PorcentajeBomba := 0.0;
|
||||
#Registro[#N_REGISTROS].Temperatura := 0.0;
|
||||
#Registro[#N_REGISTROS].Caudal := 0.0;
|
||||
#Registro[#N_REGISTROS].CaudalPermeado := 0.0;
|
||||
#Registro[#N_REGISTROS].Conductividad := 0.0;
|
||||
#Registro[#N_REGISTROS].Presion := 0.0;
|
||||
#Registro[#N_REGISTROS].ResultadoChequeo := 0.0;
|
||||
#Registro[#N_REGISTROS].Fecha.Ano := 0;
|
||||
#Registro[#N_REGISTROS].Fecha.Mes := 0;
|
||||
#Registro[#N_REGISTROS].Fecha.Dia := 0;
|
||||
#Registro[#N_REGISTROS].Fecha.DiaSemana := 0;
|
||||
#Registro[#N_REGISTROS].Fecha.Hora := 0;
|
||||
#Registro[#N_REGISTROS].Fecha.Minuto := 0;
|
||||
#Registro[#N_REGISTROS].Fecha.Segundo := 0;
|
||||
#Registro[#N_REGISTROS].Fecha.NanoSegundo := 0;
|
||||
ELSIF #s_NumeroBorrado = #N_REGISTROS THEN
|
||||
// ==============================================================================
|
||||
// Borrado de ultimo registro
|
||||
#Registro[#s_NumeroBorrado].PorcentajeBomba := 0.0;
|
||||
#Registro[#s_NumeroBorrado].Temperatura := 0.0;
|
||||
#Registro[#s_NumeroBorrado].Caudal := 0.0;
|
||||
#Registro[#s_NumeroBorrado].CaudalPermeado := 0.0;
|
||||
#Registro[#s_NumeroBorrado].Conductividad := 0.0;
|
||||
#Registro[#s_NumeroBorrado].Presion := 0.0;
|
||||
#Registro[#s_NumeroBorrado].ResultadoChequeo := 0.0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.Ano := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.Mes := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.Dia := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.DiaSemana := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.Hora := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.Minuto := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.Segundo := 0;
|
||||
#Registro[#s_NumeroBorrado].Fecha.NanoSegundo := 0;
|
||||
END_IF;
|
||||
#s_OrdenBorrarRegistros := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION BORRADO
|
||||
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
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
|
||||
|
||||
+277
@@ -0,0 +1,277 @@
|
||||
FUNCTION_BLOCK "FB15056_ZC_SIVE_MEMBRANA_CARE"
|
||||
TITLE = FB15056_ZC_REGISTRO_MEMBRANAS
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : HCR
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Bloque de funcion para la gestion del registro de membranas
|
||||
VAR_INPUT
|
||||
Pulso1Seg : Bool; // Pulso 1 Segundo
|
||||
OrdenRegistroGeneral : Bool; // OrdenRegistroGeneral
|
||||
FechaHora {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
Iniciar : Bool; // Orden contador de tiempo
|
||||
END_VAR
|
||||
VAR_INPUT RETAIN
|
||||
Usuario : String[25]; // Usuario
|
||||
END_VAR
|
||||
VAR_INPUT
|
||||
TecnicoRegistroGeneral : String[20]; // Tecnico registro general
|
||||
END_VAR
|
||||
VAR_INPUT RETAIN
|
||||
TiempoAvisoOn : Int; // Tiempo indicación aviso On
|
||||
TiempoAvisoOff : Int; // Tiempo indicación aviso Off
|
||||
TiempoAlarmaOn : Int; // Tiempo indicación alarma On
|
||||
TiempoAlarmaOff : Int; // Tiempo indicación alarma Off
|
||||
HorasAviso : Int; // Horas para aviso
|
||||
HorasAlarma : Int; // Horas para alarma
|
||||
HorasAlarmaCritica : Int; // Horas para alarma critica
|
||||
END_VAR
|
||||
|
||||
VAR_OUTPUT
|
||||
Aviso : Bool; // Estado de aviso
|
||||
Alarma : Bool; // Estado de alarma
|
||||
AlarmaCritica : Bool; // Estado de alarma critica
|
||||
Estado : Int; // Estado
|
||||
TiempoMembranaRestante : UDInt; // Tiempo membrana restante
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
OrdenBorrar : Bool; // Ordrn borrar registros
|
||||
END_VAR
|
||||
|
||||
VAR RETAIN
|
||||
Registros { S7_SetPoint := 'False'} : Array[1..#N_REGISTROS] of "UDT_ZC_SIVE_MEMBRANA_CARE";
|
||||
END_VAR
|
||||
VAR
|
||||
Pulsador { S7_SetPoint := 'False'} : "UDT_ZC_PULSADOR"; // Pulsador nuevo registro
|
||||
END_VAR
|
||||
VAR RETAIN
|
||||
Tiempo { S7_SetPoint := 'False'} : "UDT_ZC_CONTADOR_TIEMPO"; // Tiempo actual membranas
|
||||
s_PuestaMarchaAno : UInt; // Fecha de puesta en marcha
|
||||
s_PuestaMarchaMes : Int; // Fecha de puesta en marcha
|
||||
s_PuestaMarchaDia : Int; // Fecha de puesta en marcha
|
||||
s_Indice : Int := 1; // Indice registro
|
||||
s_TecnicoNuevoRegistro : String[20]; // Nombre tecnico nuevo registro
|
||||
s_FlipFlopAviso { S7_SetPoint := 'False'} : "UDT_ZC_DISP_FF";
|
||||
s_FlipFlopAlarma { S7_SetPoint := 'False'} : "UDT_ZC_DISP_FF";
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int; // Bucle para recorrer los registros
|
||||
t_OrdenReset : Bool; // Orden Reset contador de horas
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
N_REGISTROS : Int := 10; // Número de registros
|
||||
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 `FB15056_ZC_REGISTRO_MEMBRANAS` implementa la gestión integral del registro y vida útil de las membranas. Mantiene un histórico circular de intervenciones (`Registros[i]`), controla el tiempo de uso acumulado y genera los avisos, alarmas y alarma crítica en función de las horas restantes, incluyendo la posibilidad de registrar cambios generales de forma masiva.
|
||||
|
||||
Funcionalidades principales:
|
||||
- Registro de intervención por pulsador: el bloque gestiona un pulsador (`FC15026_ZC_PULSADOR`) con permiso dependiente de que haya un técnico introducido en `#s_TecnicoNuevoRegistro`. Al confirmarse la pulsación (`Pulsador.Plc`), se almacena en `#Registros[#s_Indice]` la fecha/hora convertida con `FC15005_ZC_DTL_TO_ZC_FECHA`, el técnico y el tiempo de membrana (`#Tiempo.Hora`), se limpia el técnico y se dispara la orden interna `#t_OrdenReset` para reiniciar el contador de tiempo. El índice avanza de forma circular hasta `#N_REGISTROS`.
|
||||
- Registro general: la entrada `#OrdenRegistroGeneral` permite registrar un cambio de membrana sin pulsador físico, asociando el técnico definido en `#TecnicoRegistroGeneral` y siguiendo la misma lógica circular de índice.
|
||||
- Contador de tiempo de membrana: mediante `FC15025_ZC_CONTADOR_TIEMPO` se acumula el tiempo de uso en horas, con posibilidad de reset a través de `#t_OrdenReset`.
|
||||
- Cálculo de horas restantes: `#TiempoMembranaRestante` se calcula como la diferencia entre `#HorasAlarmaCritica` y `#Tiempo.Hora`, acotado a `0` para evitar desbordamientos cuando se supera el umbral crítico.
|
||||
- Borrado de registros: la entrada `#OrdenBorrar` limpia completamente el array de registros (fecha, hora, técnico y tiempo de membrana) y reinicia el índice de escritura a `1`.
|
||||
- Estado global por tramos: clasificación del estado en `#Estado` (0: Normal, 1: Aviso, 2: Alarma, 3: Alarma crítica) según el rango de horas acumulado frente a `#HorasAviso`, `#HorasAlarma` y `#HorasAlarmaCritica`.
|
||||
- Aviso y Alarma intermitentes: se generan mediante dos Flip-Flop (`FC2926_ZC_FF_INDV`) con tiempos de encendido/apagado configurables (`#TiempoAvisoOn/Off`, `#TiempoAlarmaOn/Off`) para producir señales parpadeantes. La alarma crítica (`AlarmaCritica`) es continua y se activa definitivamente al alcanzar `#HorasAlarmaCritica`.
|
||||
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC15026_ZC_PULSADOR`, `FC15025_ZC_CONTADOR_TIEMPO`, `FC2926_ZC_FF_INDV`, `FC15005_ZC_DTL_TO_ZC_FECHA` |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `ZC_FECHA`, `UDT_ZC_PULSADOR`, `UDT_ZC_CONTADOR_TIEMPO`. `UDT_ZC_SIVE_MEMBRANA_CARE` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 10.05.2023 | (HCR) | Primera versión. |
|
||||
| 01.00.01 | 02.10.2023 | (ABH) | Cambio nombre a SIVE MEMBRANA CARE. Se corrigen permisos variables estáticas. Se corrigen nombres de variables. Se crea UDT `registro membranas`. Se cambia tipo de dato fecha/hora string a `ZC_FECHA`. Se quitan temporizadores y se utiliza Flip-Flop individual. Se eliminan variables innecesarias. |
|
||||
| 01.00.02 | 16.01.2024 | (ABH) | Se limita el tiempo restante de las membranas para que no se desborde. |
|
||||
| 01.00.03 | 02.12.2025 | (ABH) | Se corrige cálculo tiempo horas restantes. |
|
||||
| 01.00.04 | 10.01.2026 | (CNR) | Se añade orden y gestión de registro general. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// =============================================================================
|
||||
REGION ORDEN_REGISTRO
|
||||
|
||||
#Pulsador.Permiso := (#s_TecnicoNuevoRegistro <> '');
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := #Pulso1Seg,
|
||||
SP_Tiempo := 2,
|
||||
TrazaCategoria:=0,
|
||||
TrazaIdProceso:=0,
|
||||
TrazaIdPulsador:=0,
|
||||
Usuario := #Usuario,
|
||||
FechaHoraActual := #FechaHora,
|
||||
Pulsador := #Pulsador);
|
||||
|
||||
// Orden pulsador
|
||||
IF #Pulsador.Plc THEN
|
||||
|
||||
#Registros[#s_Indice].FechaHora := "FC15005_ZC_DTL_TO_ZC_FECHA"( #FechaHora);
|
||||
#Registros[#s_Indice].Tecnico := #s_TecnicoNuevoRegistro;
|
||||
#Registros[#s_Indice].TiempoMembrana := #Tiempo.Hora;
|
||||
|
||||
// Reset valor técnico y orden reset tiempo
|
||||
#s_TecnicoNuevoRegistro := '';
|
||||
|
||||
#t_OrdenReset := TRUE;
|
||||
|
||||
// Incrementamos indice y si es mayor que el número máximo de registro lo ponemos en la posición inicial
|
||||
#s_Indice += 1;
|
||||
IF #s_Indice > #N_REGISTROS THEN
|
||||
#s_Indice := 1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// Orden registro general
|
||||
IF #OrdenRegistroGeneral THEN
|
||||
|
||||
#Registros[#s_Indice].FechaHora := "FC15005_ZC_DTL_TO_ZC_FECHA"(#FechaHora);
|
||||
#Registros[#s_Indice].Tecnico := #TecnicoRegistroGeneral;
|
||||
#Registros[#s_Indice].TiempoMembrana := #Tiempo.Hora;
|
||||
|
||||
// Reset valor técnico y orden reset tiempo
|
||||
#t_OrdenReset := TRUE;
|
||||
|
||||
// Incrementamos indice y si es mayor que el número máximo de registro lo ponemos en la posición inicial
|
||||
#s_Indice += 1;
|
||||
IF #s_Indice > #N_REGISTROS THEN
|
||||
#s_Indice := 1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
END_REGION ORDEN_REGISTRO
|
||||
|
||||
|
||||
// =============================================================================
|
||||
REGION TIEMPO_MEMBRANAS
|
||||
|
||||
// Contador de tiempo
|
||||
"FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg := #Pulso1Seg,
|
||||
Iniciar := #Iniciar,
|
||||
Contador := #Tiempo,
|
||||
Reset := #t_OrdenReset);
|
||||
|
||||
// Horas Restante
|
||||
IF INT_TO_UDINT(#HorasAlarmaCritica) > #Tiempo.Hora THEN
|
||||
#TiempoMembranaRestante := INT_TO_UDINT(#HorasAlarmaCritica) - #Tiempo.Hora;
|
||||
ELSE
|
||||
#TiempoMembranaRestante := 0;
|
||||
END_IF;
|
||||
|
||||
END_REGION TIEMPO_MEMBRANAS
|
||||
|
||||
|
||||
// =============================================================================
|
||||
REGION BORRAR_REGISTROS
|
||||
|
||||
IF #OrdenBorrar THEN
|
||||
|
||||
FOR #for_i := 1 TO #N_REGISTROS DO
|
||||
|
||||
#Registros[#for_i].FechaHora.Ano := 0;
|
||||
#Registros[#for_i].FechaHora.Mes := 0;
|
||||
#Registros[#for_i].FechaHora.Dia := 0;
|
||||
#Registros[#for_i].FechaHora.Hora := 0;
|
||||
#Registros[#for_i].FechaHora.Minuto := 0;
|
||||
#Registros[#for_i].FechaHora.Segundo := 0;
|
||||
#Registros[#for_i].FechaHora.NanoSegundo := 0;
|
||||
|
||||
#Registros[#for_i].Tecnico := '';
|
||||
#Registros[#for_i].TiempoMembrana := 0;
|
||||
#s_Indice := 1;
|
||||
|
||||
END_FOR;
|
||||
|
||||
#OrdenBorrar := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION BORRAR_REGISTROS
|
||||
|
||||
|
||||
// =============================================================================
|
||||
REGION ESTADO
|
||||
|
||||
#s_FlipFlopAviso.Orden_Activar := FALSE;
|
||||
#s_FlipFlopAviso.Config_SetPointTiempoFlip := #TiempoAvisoOn;
|
||||
#s_FlipFlopAviso.Config_SetPointTiempoFlop := #TiempoAvisoOff;
|
||||
#s_FlipFlopAlarma.Orden_Activar := FALSE;
|
||||
#s_FlipFlopAlarma.Config_SetPointTiempoFlip := #TiempoAlarmaOn;
|
||||
#s_FlipFlopAlarma.Config_SetPointTiempoFlop := #TiempoAlarmaOff;
|
||||
|
||||
// Estado Aviso
|
||||
#Estado := 0;
|
||||
|
||||
IF #Tiempo.Hora >= #HorasAviso AND #Tiempo.Hora < #HorasAlarma THEN
|
||||
#s_FlipFlopAviso.Orden_Activar := TRUE;
|
||||
#Aviso := #s_FlipFlopAviso.#Estado_Flip;
|
||||
#Estado := 1;
|
||||
ELSE
|
||||
#Aviso := FALSE;
|
||||
END_IF;
|
||||
|
||||
|
||||
// Estado Alarma
|
||||
IF #Tiempo.Hora >= #HorasAlarma AND #Tiempo.Hora < #HorasAlarmaCritica THEN
|
||||
#s_FlipFlopAlarma.Orden_Activar := TRUE;
|
||||
#Alarma := #s_FlipFlopAlarma.#Estado_Flip;
|
||||
#Estado := 2;
|
||||
ELSE
|
||||
#Alarma := FALSE;
|
||||
END_IF;
|
||||
|
||||
|
||||
// Estado Alarma Crítica
|
||||
IF #Tiempo.Hora >= #HorasAlarmaCritica THEN
|
||||
#AlarmaCritica := TRUE;
|
||||
#Estado := 3;
|
||||
ELSE
|
||||
#AlarmaCritica := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION ESTADO
|
||||
|
||||
|
||||
// =============================================================================
|
||||
REGION GESTION_FF
|
||||
|
||||
// =============================================================================
|
||||
// Flip Flop aviso
|
||||
"FC2926_ZC_FF_INDV"(Pulso1Seg := #Pulso1Seg,
|
||||
FF := #s_FlipFlopAviso);
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Flip Flop alarma
|
||||
"FC2926_ZC_FF_INDV"(Pulso1Seg := #Pulso1Seg,
|
||||
FF := #s_FlipFlopAlarma);
|
||||
|
||||
|
||||
END_REGION GESTION_FF
|
||||
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
FUNCTION_BLOCK "FB15057_ZC_CONT_PROD_MEM"
|
||||
TITLE = FB15057_ZC_CONT_PROD_MEM
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Bloque de funcion para gestion de contadores de produccion maquinas membranas
|
||||
VAR_INPUT
|
||||
InicioProduccion : Bool; // En etapa inicio produccion
|
||||
EnProduccion : Bool; // En etapas de produccion
|
||||
FinProduccion : Bool; // En etapa fin de produccion
|
||||
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : DTL; // Fecha y hora actual
|
||||
LitrosEntrada : LReal; // Totalizador litros entrada
|
||||
LitrosConcentrado : LReal; // Totalizador litros concentrado
|
||||
LitrosPermeado : LReal; // Totalizador litros permeado
|
||||
FCV : Real; // Factor de concentradion
|
||||
Brix : LReal; // Media de grados BRIX
|
||||
TempAlimentacion : LReal; // Temperatura alimentacion
|
||||
TempConcentrado : LReal; // Temperatura Concentrado
|
||||
TempPermeado : LReal; // Temperatura Permeado
|
||||
BorrarParcial : Bool; // Borrar datos parciales
|
||||
END_VAR
|
||||
|
||||
VAR RETAIN
|
||||
Ultima { S7_SetPoint := 'False'} : "UDT_ZC_CONT_PROD_MEM";
|
||||
Penultima { S7_SetPoint := 'False'} : "UDT_ZC_CONT_PROD_MEM";
|
||||
Parcial { S7_SetPoint := 'False'} : "UDT_ZC_CONT_PROD_MEM";
|
||||
Total { S7_SetPoint := 'False'} : "UDT_ZC_CONT_PROD_MEM";
|
||||
END_VAR
|
||||
VAR
|
||||
s_OldInicioProd { S7_SetPoint := 'True'} : Bool;
|
||||
s_OldFinProd { S7_SetPoint := 'True'} : Bool;
|
||||
s_InicioProduccion : Bool; // Orden inicio produccion
|
||||
s_FinProduccion : Bool; // Orden fin de produccion
|
||||
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 la gestión de los contadores y totalizadores de producción de una máquina de membranas, manteniendo la trazabilidad histórica de la última y penúltima producción, así como los acumulados parciales y totales, junto con el cálculo del factor de conversión volumétrica (FCV) asociado a cada periodo.
|
||||
|
||||
Funcionalidades principales:
|
||||
- Detección de flanco ascendente en las órdenes `#InicioProduccion` y `#FinProduccion` mediante las variables estáticas `#s_P_Trig_InicioProd` y `#s_P_Trig_FinProd`, generando los pulsos internos `#s_InicioProduccion` y `#s_FinProduccion` para evitar disparos múltiples por nivel mantenido.
|
||||
- Inicio de producción: al recibir `#s_InicioProduccion` se trasladan los datos de la última producción a la estructura `#Penultima`, se inicializan a cero los campos analíticos y de fecha de `#Ultima`, y se registra la fecha/hora de inicio en `#Ultima.FechaInicio` mediante la conversión realizada por `FC15005_ZC_DTL_TO_ZC_FECHA`.
|
||||
- Datos en curso: mientras `#EnProduccion` está activo, se copian en `#Ultima` las variables de proceso (`LitrosEntrada`, `LitrosConcentrado`, `Brix`, `TempAlimentacion`, `TempConcentrado`, `TempPermeado`), manteniendo actualizada la instantánea de la producción en marcha.
|
||||
- Fin de producción: al detectar `#s_FinProduccion` se registra la fecha/hora de fin en `#Ultima.FechaFin` y se acumulan los valores de la producción actual sobre los contadores `#Parcial` y `#Total`, tanto de litros de entrada como de concentrado.
|
||||
- Cálculo de litros de permeado por diferencia (`LitrosEntrada - LitrosConcentrado`) para las cuatro estructuras: `#Ultima`, `#Penultima`, `#Parcial` y `#Total`.
|
||||
- Cálculo del factor de conversión volumétrica (FCV) para cada estructura con protección frente a división por cero (cuando `#LitrosEntrada` o `#LitrosConcentrado` son menores o iguales a `0.0`, el resultado se fija en `0.0`).
|
||||
- Reset de la producción parcial: la entrada `#BorrarParcial` reinicia los litros del contador parcial y actualiza `#Parcial.FechaInicio` con la fecha/hora actual.
|
||||
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC15005_ZC_DTL_TO_ZC_FECHA` |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_CONTADORES_PRODUCCION` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 29.09.2023 | (ABH) | Primera versión. |
|
||||
| 01.00.01 | 04.03.2024 | (ABH) | Se corrige gestión de marca fin de producción. |
|
||||
| 01.00.02 | 03.07.2026 | (ABH) | Cambio a SCL. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_ORDENES
|
||||
|
||||
// Inicio de produccion
|
||||
#s_InicioProduccion := #InicioProduccion AND NOT #s_OldInicioProd;
|
||||
|
||||
// Fin de produccion
|
||||
#s_FinProduccion := #FinProduccion AND NOT #s_OldFinProd;
|
||||
|
||||
// Estados anteriores
|
||||
#s_OldInicioProd := #InicioProduccion;
|
||||
#s_OldFinProd := #FinProduccion;
|
||||
|
||||
END_REGION GESTION_ORDENES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION MOVIMIENTO_DE_DATOS
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION INICIO_PRODUCCION
|
||||
|
||||
IF #s_InicioProduccion THEN
|
||||
|
||||
// =================================================================================================
|
||||
// Traspaso de datos de ultima produccion a penultima produccion
|
||||
#Penultima.LitrosEntrada := #Ultima.LitrosEntrada;
|
||||
#Penultima.LitrosConcentrado := #Ultima.LitrosConcentrado;
|
||||
#Penultima.Brix := #Ultima.Brix;
|
||||
#Penultima.TempAlimentacion := #Ultima.TempAlimentacion;
|
||||
#Penultima.TempConcentrado := #Ultima.TempConcentrado;
|
||||
#Penultima.FechaInicio := #Ultima.FechaInicio;
|
||||
#Penultima.FechaFin := #Ultima.FechaFin;
|
||||
|
||||
|
||||
// =================================================================================================
|
||||
// Reset datos ultima produccion
|
||||
#Ultima.LitrosEntrada := 0.0;
|
||||
#Ultima.LitrosConcentrado := 0.0;
|
||||
#Ultima.Brix := 0.0;
|
||||
#Ultima.TempAlimentacion := 0.0;
|
||||
#Ultima.TempConcentrado := 0.0;
|
||||
#Ultima.FechaInicio.Ano := 0;
|
||||
#Ultima.FechaInicio.Mes := 0;
|
||||
#Ultima.FechaInicio.Dia := 0;
|
||||
#Ultima.FechaInicio.Hora := 0;
|
||||
#Ultima.FechaInicio.Minuto := 0;
|
||||
#Ultima.FechaInicio.Segundo := 0;
|
||||
#Ultima.FechaFin.Ano := 0;
|
||||
#Ultima.FechaFin.Mes := 0;
|
||||
#Ultima.FechaFin.Dia := 0;
|
||||
#Ultima.FechaFin.Hora := 0;
|
||||
#Ultima.FechaFin.Minuto := 0;
|
||||
#Ultima.FechaFin.Segundo := 0;
|
||||
|
||||
|
||||
// =================================================================================================
|
||||
// Guardamos la fecha y hora de inicio de la produccion
|
||||
#Ultima.FechaInicio := "FC15005_ZC_DTL_TO_ZC_FECHA"(#FechaHoraActual);
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION INICIO_PRODUCCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION DATOS_DURANTE_PRODUCCION
|
||||
|
||||
// Movimientos de datos durante la produccion
|
||||
IF #EnProduccion THEN
|
||||
|
||||
#Ultima.LitrosEntrada := #LitrosEntrada;
|
||||
#Ultima.LitrosConcentrado := #LitrosConcentrado;
|
||||
#Ultima.Brix := #Brix;
|
||||
#Ultima.TempAlimentacion := #TempAlimentacion;
|
||||
#Ultima.TempConcentrado := #TempConcentrado;
|
||||
#Ultima.TempPermeado := #TempPermeado;
|
||||
END_IF;
|
||||
|
||||
END_REGION DATOS_DURANTE_PRODUCCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION DATOS_AL_FIN_PRODUCCION
|
||||
|
||||
// Movimiento de datos al finalizar la produccion
|
||||
IF #s_FinProduccion THEN
|
||||
|
||||
// Fecha fin
|
||||
#Ultima.FechaFin := "FC15005_ZC_DTL_TO_ZC_FECHA"(#FechaHoraActual);
|
||||
|
||||
// Suma de datos parciales y totales
|
||||
#Parcial.LitrosEntrada := #Ultima.LitrosEntrada + #Parcial.LitrosEntrada;
|
||||
#Parcial.LitrosConcentrado := #Ultima.LitrosConcentrado + #Parcial.LitrosConcentrado;
|
||||
#Total.LitrosEntrada := #Ultima.LitrosEntrada + #Total.LitrosEntrada;
|
||||
#Total.LitrosConcentrado := #Ultima.LitrosConcentrado + #Total.LitrosConcentrado;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION DATOS_AL_FIN_PRODUCCION
|
||||
|
||||
|
||||
|
||||
END_REGION MOVIMIENTO_DE_DATOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION CALCULOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION TOTALIZADORES
|
||||
|
||||
// Ultima produccion
|
||||
#Ultima.LitrosPermeado := #Ultima.LitrosEntrada - #Ultima.LitrosConcentrado;
|
||||
|
||||
// Penultima produccion
|
||||
#Penultima.LitrosPermeado := #Penultima.LitrosEntrada - #Penultima.LitrosConcentrado;
|
||||
|
||||
// Produccion parcial
|
||||
#Parcial.LitrosPermeado := #Parcial.LitrosEntrada - #Parcial.LitrosConcentrado;
|
||||
|
||||
// Produccion total
|
||||
#Total.LitrosPermeado := #Total.LitrosEntrada - #Total.LitrosConcentrado;
|
||||
|
||||
END_REGION TOTALIZADORES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION FCV
|
||||
|
||||
// FCV Ultima produccion
|
||||
IF #Ultima.LitrosEntrada > 0.0 AND #Ultima.LitrosConcentrado > 0.0 THEN
|
||||
#Ultima.FCV := LREAL_TO_REAL(#Ultima.LitrosEntrada / #Ultima.LitrosConcentrado);
|
||||
ELSE
|
||||
#Ultima.FCV := 0.0;
|
||||
END_IF;
|
||||
|
||||
// FCV Penultima produccion
|
||||
IF #Penultima.LitrosEntrada > 0.0 AND #Penultima.LitrosConcentrado > 0.0 THEN
|
||||
#Penultima.FCV := LREAL_TO_REAL(#Penultima.LitrosEntrada / #Penultima.LitrosConcentrado);
|
||||
ELSE
|
||||
#Penultima.FCV := 0.0;
|
||||
END_IF;
|
||||
|
||||
// FCV Produccion parcial
|
||||
IF #Parcial.LitrosEntrada > 0.0 AND #Parcial.LitrosConcentrado > 0.0 THEN
|
||||
#Parcial.FCV := LREAL_TO_REAL(#Parcial.LitrosEntrada / #Parcial.LitrosConcentrado);
|
||||
ELSE
|
||||
#Parcial.FCV := 0.0;
|
||||
END_IF;
|
||||
|
||||
// FCV Produccion Total
|
||||
IF #Total.LitrosEntrada > 0.0 AND #Total.LitrosConcentrado > 0.0 THEN
|
||||
#Total.FCV := LREAL_TO_REAL(#Total.LitrosEntrada / #Total.LitrosConcentrado);
|
||||
ELSE
|
||||
#Total.FCV := 0.0;
|
||||
END_IF;
|
||||
|
||||
END_REGION FCV
|
||||
|
||||
END_REGION CALCULOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION RESET_DATOS
|
||||
|
||||
// Reset produccion parcial
|
||||
IF #BorrarParcial THEN
|
||||
#Parcial.LitrosEntrada := 0.0;
|
||||
#Parcial.LitrosConcentrado := 0.0;
|
||||
#Parcial.FechaInicio := "FC15005_ZC_DTL_TO_ZC_FECHA"(#FechaHoraActual);
|
||||
END_IF;
|
||||
|
||||
END_REGION RESET_DATOS
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
FUNCTION "FC15106_ZC_GESTION_LISTA" : Void
|
||||
TITLE = FC15106_ZC_GESTION_LISTA
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion listas
|
||||
VAR_IN_OUT
|
||||
Lista : Array[*] of "UDT_ZC_LISTA_ORIG_DEST";
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
for_j : Int;
|
||||
t_Index : Int;
|
||||
t_LowerBound : Int;
|
||||
t_UpperBound : Int;
|
||||
t_YaExiste : Bool;
|
||||
t_ListaTemporal : Array[0..100] of "UDT_ZC_LISTA_ORIG_DEST";
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2025 - 2025
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Límite de listas de tipo `UDT_ZC_LISTA_ORIG_DEST` con 100 posiciones.
|
||||
|
||||
Función encargada de gestionar, limpiar y compactar listas de valores enteros.
|
||||
|
||||
- Calcular dinámicamente los límites del array de entrada `#Lista` mediante las instrucciones `LOWER_BOUND` y `UPPER_BOUND`.
|
||||
- Inicializar a cero una lista temporal interna (`#t_ListaTemporal`) adaptada a la longitud del array procesado.
|
||||
- Analizar cíclicamente los elementos de la `#Lista` para filtrar y omitir de forma automática aquellos que posean valor cero.
|
||||
- Identificar y suprimir las entradas duplicadas para garantizar un conjunto final de datos compuesto exclusivamente por valores únicos.
|
||||
- Compactar los datos filtrados y transferirlos de vuelta a la `#Lista` original, reescribiendo los valores secuencialmente desde su límite inferior.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_LISTA_ORIG_DEST` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 27.06.2025 | (ABH) | Primera version. |
|
||||
| 01.00.00 | 03.07.2026 | (ABH) | Cambio en tipo de datos de INT a `UDT_ZC_LISTA_ORIG_DEST`. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION CALCULOS
|
||||
|
||||
// Obtener límites reales del array
|
||||
#t_LowerBound := DINT_TO_INT(LOWER_BOUND(ARR := #Lista, DIM := 1));
|
||||
#t_UpperBound := DINT_TO_INT(UPPER_BOUND(ARR := #Lista, DIM := 1));
|
||||
|
||||
// Inicializar lista temporal
|
||||
FOR #for_i := 1 TO DINT_TO_INT((#t_UpperBound - #t_LowerBound + 1)) DO
|
||||
#t_ListaTemporal[#for_i].Id := 0;
|
||||
#t_ListaTemporal[#for_i].Consigna := 0;
|
||||
END_FOR;
|
||||
|
||||
END_REGION CALCULOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_LISTA
|
||||
|
||||
// Compactar y eliminar duplicados
|
||||
#t_Index := 1;
|
||||
FOR #for_i := #t_LowerBound TO #t_UpperBound DO
|
||||
IF #Lista[#for_i].Id <> 0 THEN
|
||||
#t_YaExiste := FALSE;
|
||||
|
||||
FOR #for_j := 1 TO #t_Index - 1 DO
|
||||
IF #t_ListaTemporal[#for_j].Id = #Lista[#for_i].Id THEN
|
||||
#t_YaExiste := TRUE;
|
||||
EXIT;
|
||||
END_IF;
|
||||
END_FOR;
|
||||
|
||||
IF NOT #t_YaExiste THEN
|
||||
#t_ListaTemporal[#t_Index] := #Lista[#for_i];
|
||||
#t_Index := #t_Index + 1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_FOR;
|
||||
|
||||
// Copiar de vuelta a lista original
|
||||
FOR #for_i := #t_LowerBound TO #t_UpperBound DO
|
||||
#Lista[#for_i] := #t_ListaTemporal[#for_i - #t_LowerBound + 1];
|
||||
END_FOR;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
Reference in New Issue
Block a user