Primera version
This commit is contained in:
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -0,0 +1,204 @@
|
||||
DATA_BLOCK "DB1_SYS"
|
||||
TITLE = Datos de sistema
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
VERSION : 0.1
|
||||
NON_RETAIN
|
||||
VAR
|
||||
ON : Bool; // Siempre a 1
|
||||
OFF : Bool; // Siempre a 0
|
||||
SIM : Bool; // Sistema en simulacion
|
||||
ACK : Bool; // Acuse general de errores
|
||||
ARRANQUE : Bool; // Marca de primer arranque del sistema
|
||||
Pulso100ms : Bool; // Pulso 100 ms
|
||||
Pulso1seg : Bool; // Pulso 1 segundo
|
||||
Pulso2seg : Bool; // Pulso 2 segundo
|
||||
Pulso5seg : Bool; // Pulso 5 segundos
|
||||
Pulso1min : Bool; // Pulso 1 minuto
|
||||
Pulso1h : Bool; // Pulso 1 hora
|
||||
FlipFlop1seg : Bool; // Flip flop 1 seg ON - 1 seg OFF
|
||||
FlipFlop2seg : Bool; // Flip flop 2 seg ON - 2 seg OFF
|
||||
FlipFlop5seg : Bool; // Flip flop 5 seg ON - 5 seg OFF
|
||||
ResetEntidades { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // Reset todas las entidades
|
||||
SincronizarFecha : Bool; // Orden sincronizacion fecha desde sistema superior
|
||||
WatchDog : Int; // Watchdog para comunicaciones
|
||||
Pulsador : Struct
|
||||
EscribirFechaHora { S7_SetPoint := 'False'} : "UDT_ZC_PULSADOR"; // Pulsador cambio de fecha y hora desde hmi
|
||||
Ack { S7_SetPoint := 'False'} : Array[0..9] of "UDT_ZC_PULSADOR"; // Pulsador acuse general de errores
|
||||
END_STRUCT;
|
||||
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual del sistema
|
||||
END_VAR
|
||||
VAR RETAIN
|
||||
FechaHoraNuevaManual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora nueva escrita manualmente desde HMI
|
||||
FechaHoraNuevaAuto {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora nueva escrita automaticamente
|
||||
END_VAR
|
||||
VAR
|
||||
TiempoCiclo : Real; // Tiempo de ciclo del PLC
|
||||
END_VAR
|
||||
VAR RETAIN
|
||||
Usuario : Struct
|
||||
Seleccion : Array[0..9] of Struct
|
||||
Orden : Bool;
|
||||
Usuario : String[25];
|
||||
END_STRUCT;
|
||||
Actual : String[25]; // Usuario actual
|
||||
END_STRUCT;
|
||||
END_VAR
|
||||
VAR
|
||||
RedProfinet : Array[0..1023] of Bool;
|
||||
END_VAR
|
||||
VAR RETAIN
|
||||
Aux : Struct
|
||||
P_Trig_Pulso100ms : Bool; // P_TRIG Pulso 100 ms
|
||||
P_Trig_Pulso1Seg : Bool; // P_TRIG Pulso 1 segundo
|
||||
Contador2seg : USInt; // Aux. Contador 2 segundos
|
||||
Contador5seg : USInt; // Aux. Contador 5 segundos
|
||||
Contador1min : USInt; // Aux. Contador 1 minuto
|
||||
Contador1h : UInt; // Aux. Contador 1 hora
|
||||
auxRuntime : LReal; // Aux. Runtime
|
||||
END_STRUCT;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
ON := TRUE;
|
||||
OFF := FALSE;
|
||||
SIM := FALSE;
|
||||
ACK := FALSE;
|
||||
ARRANQUE := FALSE;
|
||||
Pulso100ms := FALSE;
|
||||
Pulso1seg := FALSE;
|
||||
Pulso2seg := FALSE;
|
||||
Pulso5seg := FALSE;
|
||||
Pulso1min := FALSE;
|
||||
Pulso1h := FALSE;
|
||||
FlipFlop1seg := TRUE;
|
||||
FlipFlop2seg := TRUE;
|
||||
FlipFlop5seg := TRUE;
|
||||
ResetEntidades := FALSE;
|
||||
SincronizarFecha := FALSE;
|
||||
Pulsador.EscribirFechaHora.Hmi := FALSE;
|
||||
Pulsador.EscribirFechaHora.Plc := FALSE;
|
||||
Pulsador.EscribirFechaHora.Permiso := TRUE;
|
||||
Pulsador.EscribirFechaHora.Visibilidad := TRUE;
|
||||
Pulsador.EscribirFechaHora.AuxPulso := FALSE;
|
||||
Pulsador.EscribirFechaHora.AuxTiempo := 0;
|
||||
Pulsador.Ack[0].Hmi := FALSE;
|
||||
Pulsador.Ack[0].Plc := FALSE;
|
||||
Pulsador.Ack[0].Permiso := TRUE;
|
||||
Pulsador.Ack[0].Visibilidad := FALSE;
|
||||
Pulsador.Ack[0].AuxPulso := FALSE;
|
||||
Pulsador.Ack[0].AuxTiempo := 0;
|
||||
Pulsador.Ack[1].Hmi := FALSE;
|
||||
Pulsador.Ack[1].Plc := FALSE;
|
||||
Pulsador.Ack[1].Permiso := TRUE;
|
||||
Pulsador.Ack[1].Visibilidad := FALSE;
|
||||
Pulsador.Ack[1].AuxPulso := FALSE;
|
||||
Pulsador.Ack[1].AuxTiempo := 0;
|
||||
Pulsador.Ack[2].Hmi := FALSE;
|
||||
Pulsador.Ack[2].Plc := FALSE;
|
||||
Pulsador.Ack[2].Permiso := TRUE;
|
||||
Pulsador.Ack[2].Visibilidad := FALSE;
|
||||
Pulsador.Ack[2].AuxPulso := FALSE;
|
||||
Pulsador.Ack[2].AuxTiempo := 0;
|
||||
Pulsador.Ack[3].Hmi := FALSE;
|
||||
Pulsador.Ack[3].Plc := FALSE;
|
||||
Pulsador.Ack[3].Permiso := TRUE;
|
||||
Pulsador.Ack[3].Visibilidad := FALSE;
|
||||
Pulsador.Ack[3].AuxPulso := FALSE;
|
||||
Pulsador.Ack[3].AuxTiempo := 0;
|
||||
Pulsador.Ack[4].Hmi := FALSE;
|
||||
Pulsador.Ack[4].Plc := FALSE;
|
||||
Pulsador.Ack[4].Permiso := TRUE;
|
||||
Pulsador.Ack[4].Visibilidad := FALSE;
|
||||
Pulsador.Ack[4].AuxPulso := FALSE;
|
||||
Pulsador.Ack[4].AuxTiempo := 0;
|
||||
Pulsador.Ack[5].Hmi := FALSE;
|
||||
Pulsador.Ack[5].Plc := FALSE;
|
||||
Pulsador.Ack[5].Permiso := TRUE;
|
||||
Pulsador.Ack[5].Visibilidad := FALSE;
|
||||
Pulsador.Ack[5].AuxPulso := FALSE;
|
||||
Pulsador.Ack[5].AuxTiempo := 0;
|
||||
Pulsador.Ack[6].Hmi := FALSE;
|
||||
Pulsador.Ack[6].Plc := FALSE;
|
||||
Pulsador.Ack[6].Permiso := TRUE;
|
||||
Pulsador.Ack[6].Visibilidad := FALSE;
|
||||
Pulsador.Ack[6].AuxPulso := FALSE;
|
||||
Pulsador.Ack[6].AuxTiempo := 0;
|
||||
Pulsador.Ack[7].Hmi := FALSE;
|
||||
Pulsador.Ack[7].Plc := FALSE;
|
||||
Pulsador.Ack[7].Permiso := TRUE;
|
||||
Pulsador.Ack[7].Visibilidad := FALSE;
|
||||
Pulsador.Ack[7].AuxPulso := FALSE;
|
||||
Pulsador.Ack[7].AuxTiempo := 0;
|
||||
Pulsador.Ack[8].Hmi := FALSE;
|
||||
Pulsador.Ack[8].Plc := FALSE;
|
||||
Pulsador.Ack[8].Permiso := TRUE;
|
||||
Pulsador.Ack[8].Visibilidad := FALSE;
|
||||
Pulsador.Ack[8].AuxPulso := FALSE;
|
||||
Pulsador.Ack[8].AuxTiempo := 0;
|
||||
Pulsador.Ack[9].Hmi := FALSE;
|
||||
Pulsador.Ack[9].Plc := FALSE;
|
||||
Pulsador.Ack[9].Permiso := TRUE;
|
||||
Pulsador.Ack[9].Visibilidad := FALSE;
|
||||
Pulsador.Ack[9].AuxPulso := FALSE;
|
||||
Pulsador.Ack[9].AuxTiempo := 0;
|
||||
FechaHoraActual.YEAR := 2025;
|
||||
FechaHoraActual.MONTH := 9;
|
||||
FechaHoraActual.DAY := 18;
|
||||
FechaHoraActual.WEEKDAY := 5;
|
||||
FechaHoraActual.HOUR := 19;
|
||||
FechaHoraActual.MINUTE := 1;
|
||||
FechaHoraActual.SECOND := 56;
|
||||
FechaHoraActual.NANOSECOND := 550304800;
|
||||
FechaHoraActual := DTL#2025-09-18-19:01:56.550304800;
|
||||
FechaHoraNuevaManual.YEAR := 2026;
|
||||
FechaHoraNuevaManual.MONTH := 3;
|
||||
FechaHoraNuevaManual.DAY := 26;
|
||||
FechaHoraNuevaManual.WEEKDAY := 5;
|
||||
FechaHoraNuevaManual.HOUR := 11;
|
||||
FechaHoraNuevaManual.MINUTE := 31;
|
||||
FechaHoraNuevaManual.SECOND := 44;
|
||||
FechaHoraNuevaManual.NANOSECOND := 10900982;
|
||||
FechaHoraNuevaManual := DTL#2026-03-26-11:31:44.010900982;
|
||||
FechaHoraNuevaAuto.YEAR := 2026;
|
||||
FechaHoraNuevaAuto.MONTH := 3;
|
||||
FechaHoraNuevaAuto.DAY := 26;
|
||||
FechaHoraNuevaAuto.WEEKDAY := 5;
|
||||
FechaHoraNuevaAuto.HOUR := 11;
|
||||
FechaHoraNuevaAuto.MINUTE := 31;
|
||||
FechaHoraNuevaAuto.SECOND := 44;
|
||||
FechaHoraNuevaAuto.NANOSECOND := 10900982;
|
||||
FechaHoraNuevaAuto := DTL#2026-03-26-11:31:44.010900982;
|
||||
TiempoCiclo := 28.34702;
|
||||
Usuario.Seleccion[0].Orden := FALSE;
|
||||
Usuario.Seleccion[0].Usuario := 'sive';
|
||||
Usuario.Seleccion[1].Orden := FALSE;
|
||||
Usuario.Seleccion[1].Usuario := '';
|
||||
Usuario.Seleccion[2].Orden := FALSE;
|
||||
Usuario.Seleccion[2].Usuario := '';
|
||||
Usuario.Seleccion[3].Orden := FALSE;
|
||||
Usuario.Seleccion[3].Usuario := '';
|
||||
Usuario.Seleccion[4].Orden := FALSE;
|
||||
Usuario.Seleccion[4].Usuario := '';
|
||||
Usuario.Seleccion[5].Orden := FALSE;
|
||||
Usuario.Seleccion[5].Usuario := 's';
|
||||
Usuario.Seleccion[6].Orden := FALSE;
|
||||
Usuario.Seleccion[6].Usuario := '';
|
||||
Usuario.Seleccion[7].Orden := FALSE;
|
||||
Usuario.Seleccion[7].Usuario := '';
|
||||
Usuario.Seleccion[8].Orden := FALSE;
|
||||
Usuario.Seleccion[8].Usuario := '';
|
||||
Usuario.Seleccion[9].Orden := FALSE;
|
||||
Usuario.Seleccion[9].Usuario := '';
|
||||
Usuario.Actual := 's';
|
||||
Aux.P_Trig_Pulso100ms := TRUE;
|
||||
Aux.P_Trig_Pulso1Seg := TRUE;
|
||||
Aux.Contador2seg := 0;
|
||||
Aux.Contador5seg := 0;
|
||||
Aux.Contador1min := 33;
|
||||
Aux.Contador1h := 573;
|
||||
Aux.auxRuntime := 3.12728340475131E-308;
|
||||
|
||||
END_DATA_BLOCK
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
DATA_BLOCK "DB3_CHECKSUM"
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
VERSION : 0.1
|
||||
NON_RETAIN
|
||||
"FB3_ZC_CHECKSUM"
|
||||
|
||||
BEGIN
|
||||
|
||||
END_DATA_BLOCK
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
FUNCTION_BLOCK "FB3_ZC_CHECKSUM"
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
VERSION : 0.1
|
||||
VAR_INPUT
|
||||
Comprobar : Bool;
|
||||
Copiar : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_OUTPUT
|
||||
CheckSumOK : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR
|
||||
s_GetCheckSum {InstructionName := 'GetChecksum'; LibVersion := '1.0'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'; S7_SetPoint := 'False'} : GetChecksum;
|
||||
END_VAR
|
||||
VAR RETAIN
|
||||
s_EstadoCheckSum { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[0..7] of Byte;
|
||||
s_CheckSumFabrica { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[0..7] of Byte;
|
||||
END_VAR
|
||||
VAR
|
||||
s_Comprobar { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
|
||||
s_OldComprobar { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
//=======================================================================
|
||||
// (C)Copyright ZeusControl 2020 - 2026
|
||||
//=======================================================================
|
||||
(*
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
El bloque `FB3_CHECKSUM` implementa la lectura del checksum del programa actual del PLC y su comparación con el checksum de fábrica, permitiendo detectar modificaciones no autorizadas en el proyecto.
|
||||
|
||||
Funcionalidades principales:
|
||||
- Detección de flanco ascendente en la entrada `#Comprobar` para ejecutar la comprobación bajo demanda (modo "pulso"), mediante la variable interna `#s_OldComprobar`.
|
||||
- Lectura del checksum del bloque `Scope:=1` (objeto PLC) con `Range:=0` y `Subrange:=0` (rango completo), invocando la función de sistema `GetChecksum` a través del FB `GetChecksum` y depositando el resultado en `#s_EstadoCheckSum`.
|
||||
- Captura del checksum de fábrica: cuando se activa la entrada `#Copiar`, se copia el checksum actual al valor de referencia `#s_CheckSumFabrica`, operación que se realiza una sola vez durante la puesta en marcha para fijar la línea base.
|
||||
- Comparación continua entre el checksum actual y el de fábrica, exponiendo el resultado en la salida `#CheckSumOK` (TRUE cuando coinciden).
|
||||
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | `GetChecksum` |
|
||||
| DB | - |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 28.09.2020 | (ABH) | Primera versión. |
|
||||
| 01.00.01 | 02.07.2026 | (ABH) | Cambio a SCL. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION ORDEN_COMPROBACION
|
||||
|
||||
// Comprobacion mediante un pulso
|
||||
#s_Comprobar := #Comprobar AND NOT #s_OldComprobar;
|
||||
|
||||
// Estado anterior
|
||||
#s_OldComprobar := #Comprobar;
|
||||
|
||||
END_REGION ORDEN_COMPROBACION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION LECTURA_CHECKSUM
|
||||
|
||||
// Comprobacion mediante un pulso
|
||||
#s_GetCheckSum(Scope:=1,
|
||||
Range:=0,
|
||||
Subrange:=0,
|
||||
Checksum:=#s_EstadoCheckSum);
|
||||
|
||||
// Copia de checksum a valor de fabrica
|
||||
IF #Copiar THEN
|
||||
#s_CheckSumFabrica := #s_EstadoCheckSum;
|
||||
END_IF;
|
||||
|
||||
END_REGION LECTURA_CHECKSUM
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION SALIDAS
|
||||
|
||||
// Checksum OK
|
||||
#CheckSumOK := #s_EstadoCheckSum = #s_CheckSumFabrica;
|
||||
|
||||
END_REGION SALIDAS
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
@@ -0,0 +1,410 @@
|
||||
FUNCTION "FC1_ZC_SISTEMA" : Void
|
||||
TITLE = FC1_ZC_SISTEMA
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : HCR
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 2.0
|
||||
//Funcion para gestion de marcas de sistema
|
||||
VAR_INPUT
|
||||
CPU_MarcasCiclo : Byte; // Byte Marca de ciclo CPU
|
||||
CPU_MarcasSistema : Byte; // Byte Marcas de sistema
|
||||
RedProfinet : HW_IOSYSTEM; // ID Profinet IO System
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int; // Variable para bucles FOR
|
||||
t_RetVal : Int; // Variable temporal para su uso en programa
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 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 central para la gestión de marcas de sistema, temporizaciones generales, usuarios y resets del sistema.
|
||||
|
||||
En ella se realizan las siguientes acciones:
|
||||
|
||||
- Cálculo dinámico del tiempo de ciclo del OB1 (en milisegundos) evaluando la variable auxiliar con la instrucción RUNTIME.
|
||||
- Tratamiento y registro de trazabilidad de los 10 pulsadores de acuse de alarmas y del pulsador de modificación de fecha/hora mediante la función FC15026_ZC_PULSADOR.
|
||||
- Consolidación del acuse general (ACK), agrupando las activaciones del PLC de todos los pulsadores de reconocimiento en una única marca.
|
||||
- Generación de marcas estáticas (ON fijo y OFF fijo) y captura del primer ciclo de escáner tras el arranque.
|
||||
- Creación de pulsos temporizados (100 ms, 1 s, 2 s, 5 s, 1 min, 1 h) y señales Flip-Flop a partir de las marcas de ciclo del hardware de la CPU.
|
||||
- Lectura constante de la fecha y hora local (RD_LOC_T) y ejecución de la escritura en el sistema (WR_SYS_T) ante una orden del HMI.
|
||||
- Escaneo continuo de las órdenes de selección para determinar y fijar el usuario actualmente activo en el sistema.
|
||||
- Ejecución bajo demanda del reset general del array de entidades (solo aplicable con procesos parados), reinicializando sus variables a estados de disponibilidad, limpieza y vacío.
|
||||
- Llamada a la rutina DB3_CHECKSUM para la validación y gestión de la suma de comprobación del programa.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC15026_ZC_PULSADOR` |
|
||||
| FB | `FB3_ZC_CHECKSUM` |
|
||||
| DB | `DB1_SYS`, `DB3_CHECKSUM`, `DB6_ENTIDAD` |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 03.11.2022 | (HCR) | Primera version. |
|
||||
| 01.00.01 | 02.06.2023 | (ABH) | Optimizacion de bloque para integrar en libreria. Se eliminan marcas no utilizadas. Se reorganizan las variables y se ponen bien los comentarios. |
|
||||
| 01.00.02 | 24.04.2025 | (HCR) | Se añade gestion de idioma. |
|
||||
| 01.00.03 | 11.09.2025 | (ABH) | Se eliminan las constantes de idioma dentro del FC. Se utilizan constantes globales para facilitar su traduccion. |
|
||||
| 02.00.00 | 25.03.2026 | (ABH) | Se cambia lenguaje a SCL. Se eliminan idiomas. Se añade watchdog para comunicaciones. Se integra estado red profinet. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION TIEMPO_DE_CICLO
|
||||
|
||||
// Se almacena el tiempo de ciclo del OB1
|
||||
"DB1_SYS".TiempoCiclo := LREAL_TO_REAL(RUNTIME("DB1_SYS".Aux.auxRuntime));
|
||||
"DB1_SYS".TiempoCiclo := ("DB1_SYS".TiempoCiclo * 1000.0);
|
||||
|
||||
END_REGION TIEMPO_DE_CICLO
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_PULSADORES
|
||||
|
||||
// Gestion pulsadores de ack
|
||||
"DB1_SYS".Pulsador.Ack[0].Permiso := TRUE;
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := "DB1_SYS".Pulso1seg,
|
||||
SP_Tiempo := 0,
|
||||
TrazaCategoria := "TRZ_CAT_1_SYS",
|
||||
TrazaIdProceso := 0,
|
||||
TrazaIdPulsador := "TRZ_SYS_PUL_ACK_01",
|
||||
Usuario := "DB1_SYS".Usuario.Actual,
|
||||
FechaHoraActual := "DB1_SYS".FechaHoraActual,
|
||||
Pulsador := "DB1_SYS".Pulsador.Ack[0]);
|
||||
|
||||
"DB1_SYS".Pulsador.Ack[1].Permiso := TRUE;
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := "DB1_SYS".Pulso1seg,
|
||||
SP_Tiempo := 0,
|
||||
TrazaCategoria := "TRZ_CAT_1_SYS",
|
||||
TrazaIdProceso := 0,
|
||||
TrazaIdPulsador := "TRZ_SYS_PUL_ACK_02",
|
||||
Usuario := "DB1_SYS".Usuario.Actual,
|
||||
FechaHoraActual := "DB1_SYS".FechaHoraActual,
|
||||
Pulsador := "DB1_SYS".Pulsador.Ack[1]);
|
||||
|
||||
"DB1_SYS".Pulsador.Ack[2].Permiso := TRUE;
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := "DB1_SYS".Pulso1seg,
|
||||
SP_Tiempo := 0,
|
||||
TrazaCategoria := "TRZ_CAT_1_SYS",
|
||||
TrazaIdProceso := 0,
|
||||
TrazaIdPulsador := "TRZ_SYS_PUL_ACK_03",
|
||||
Usuario := "DB1_SYS".Usuario.Actual,
|
||||
FechaHoraActual := "DB1_SYS".FechaHoraActual,
|
||||
Pulsador := "DB1_SYS".Pulsador.Ack[2]);
|
||||
|
||||
"DB1_SYS".Pulsador.Ack[3].Permiso := TRUE;
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := "DB1_SYS".Pulso1seg,
|
||||
SP_Tiempo := 0,
|
||||
TrazaCategoria := "TRZ_CAT_1_SYS",
|
||||
TrazaIdProceso := 0,
|
||||
TrazaIdPulsador := "TRZ_SYS_PUL_ACK_04",
|
||||
Usuario := "DB1_SYS".Usuario.Actual,
|
||||
FechaHoraActual := "DB1_SYS".FechaHoraActual,
|
||||
Pulsador := "DB1_SYS".Pulsador.Ack[3]);
|
||||
|
||||
"DB1_SYS".Pulsador.Ack[4].Permiso := TRUE;
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := "DB1_SYS".Pulso1seg,
|
||||
SP_Tiempo := 0,
|
||||
TrazaCategoria := "TRZ_CAT_1_SYS",
|
||||
TrazaIdProceso := 0,
|
||||
TrazaIdPulsador := "TRZ_SYS_PUL_ACK_05",
|
||||
Usuario := "DB1_SYS".Usuario.Actual,
|
||||
FechaHoraActual := "DB1_SYS".FechaHoraActual,
|
||||
Pulsador := "DB1_SYS".Pulsador.Ack[4]);
|
||||
|
||||
"DB1_SYS".Pulsador.Ack[5].Permiso := TRUE;
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := "DB1_SYS".Pulso1seg,
|
||||
SP_Tiempo := 0,
|
||||
TrazaCategoria := "TRZ_CAT_1_SYS",
|
||||
TrazaIdProceso := 0,
|
||||
TrazaIdPulsador := "TRZ_SYS_PUL_ACK_06",
|
||||
Usuario := "DB1_SYS".Usuario.Actual,
|
||||
FechaHoraActual := "DB1_SYS".FechaHoraActual,
|
||||
Pulsador := "DB1_SYS".Pulsador.Ack[5]);
|
||||
|
||||
"DB1_SYS".Pulsador.Ack[6].Permiso := TRUE;
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := "DB1_SYS".Pulso1seg,
|
||||
SP_Tiempo := 0,
|
||||
TrazaCategoria := "TRZ_CAT_1_SYS",
|
||||
TrazaIdProceso := 0,
|
||||
TrazaIdPulsador := "TRZ_SYS_PUL_ACK_07",
|
||||
Usuario := "DB1_SYS".Usuario.Actual,
|
||||
FechaHoraActual := "DB1_SYS".FechaHoraActual,
|
||||
Pulsador := "DB1_SYS".Pulsador.Ack[6]);
|
||||
|
||||
"DB1_SYS".Pulsador.Ack[7].Permiso := TRUE;
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := "DB1_SYS".Pulso1seg,
|
||||
SP_Tiempo := 0,
|
||||
TrazaCategoria := "TRZ_CAT_1_SYS",
|
||||
TrazaIdProceso := 0,
|
||||
TrazaIdPulsador := "TRZ_SYS_PUL_ACK_08",
|
||||
Usuario := "DB1_SYS".Usuario.Actual,
|
||||
FechaHoraActual := "DB1_SYS".FechaHoraActual,
|
||||
Pulsador := "DB1_SYS".Pulsador.Ack[7]);
|
||||
|
||||
"DB1_SYS".Pulsador.Ack[8].Permiso := TRUE;
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := "DB1_SYS".Pulso1seg,
|
||||
SP_Tiempo := 0,
|
||||
TrazaCategoria := "TRZ_CAT_1_SYS",
|
||||
TrazaIdProceso := 0,
|
||||
TrazaIdPulsador := "TRZ_SYS_PUL_ACK_09",
|
||||
Usuario := "DB1_SYS".Usuario.Actual,
|
||||
FechaHoraActual := "DB1_SYS".FechaHoraActual,
|
||||
Pulsador := "DB1_SYS".Pulsador.Ack[8]);
|
||||
|
||||
"DB1_SYS".Pulsador.Ack[9].Permiso := TRUE;
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := "DB1_SYS".Pulso1seg,
|
||||
SP_Tiempo := 0,
|
||||
TrazaCategoria := "TRZ_CAT_1_SYS",
|
||||
TrazaIdProceso := 0,
|
||||
TrazaIdPulsador := "TRZ_SYS_PUL_ACK_10",
|
||||
Usuario := "DB1_SYS".Usuario.Actual,
|
||||
FechaHoraActual := "DB1_SYS".FechaHoraActual,
|
||||
Pulsador := "DB1_SYS".Pulsador.Ack[9]);
|
||||
|
||||
// Gestion pulsador cambio de fecha y hora
|
||||
"DB1_SYS".Pulsador.EscribirFechaHora.Permiso := TRUE;
|
||||
"DB1_SYS".Pulsador.EscribirFechaHora.Visibilidad := TRUE;
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := "DB1_SYS".Pulso1seg,
|
||||
SP_Tiempo := 0,
|
||||
TrazaCategoria := "TRZ_CAT_1_SYS",
|
||||
TrazaIdProceso := 0,
|
||||
TrazaIdPulsador := "TRZ_SYS_PUL_FECHA",
|
||||
Usuario := "DB1_SYS".Usuario.Actual,
|
||||
FechaHoraActual := "DB1_SYS".FechaHoraActual,
|
||||
Pulsador := "DB1_SYS".Pulsador.EscribirFechaHora);
|
||||
|
||||
END_REGION GESTION_PULSADORES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_ACUSE_GENERAL
|
||||
|
||||
// Activacion de marca de acuse general
|
||||
"DB1_SYS".ACK :=
|
||||
"DB1_SYS".Pulsador.Ack[0].Plc OR
|
||||
"DB1_SYS".Pulsador.Ack[1].Plc OR
|
||||
"DB1_SYS".Pulsador.Ack[2].Plc OR
|
||||
"DB1_SYS".Pulsador.Ack[3].Plc OR
|
||||
"DB1_SYS".Pulsador.Ack[4].Plc OR
|
||||
"DB1_SYS".Pulsador.Ack[5].Plc OR
|
||||
"DB1_SYS".Pulsador.Ack[6].Plc OR
|
||||
"DB1_SYS".Pulsador.Ack[7].Plc OR
|
||||
"DB1_SYS".Pulsador.Ack[8].Plc OR
|
||||
"DB1_SYS".Pulsador.Ack[9].Plc;
|
||||
|
||||
END_REGION GESTION_ACUSE_GENERAL
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_MARCAS_GENERALES_Y_FLANCOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
// Marca siempre a ON
|
||||
"DB1_SYS".OFF := FALSE;
|
||||
|
||||
// Marca siempre a OFF
|
||||
"DB1_SYS".ON := TRUE;
|
||||
|
||||
// Marca primer arranque
|
||||
"DB1_SYS".ARRANQUE := #CPU_MarcasSistema.%X0;
|
||||
|
||||
// ==========================================================================================================
|
||||
// Pulso por 100 ms
|
||||
"DB1_SYS".Pulso100ms := #CPU_MarcasCiclo.%X0 AND NOT "DB1_SYS".Aux.P_Trig_Pulso100ms;
|
||||
|
||||
// Pulso por 1 segundo
|
||||
"DB1_SYS".Pulso1seg := #CPU_MarcasCiclo.%X5 AND NOT "DB1_SYS".Aux.P_Trig_Pulso1Seg;
|
||||
|
||||
// Pulso por 2 segundos
|
||||
"DB1_SYS".Pulso2seg := FALSE;
|
||||
IF "DB1_SYS".Pulso1seg THEN
|
||||
"DB1_SYS".Aux.Contador2seg += 1;
|
||||
IF "DB1_SYS".Aux.Contador2seg >= 2 THEN
|
||||
"DB1_SYS".Pulso2seg := TRUE;
|
||||
"DB1_SYS".Aux.Contador2seg := 0;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// Pulso por 5 segundos
|
||||
"DB1_SYS".Pulso5seg := FALSE;
|
||||
IF "DB1_SYS".Pulso1seg THEN
|
||||
"DB1_SYS".Aux.Contador5seg += 1;
|
||||
IF "DB1_SYS".Aux.Contador5seg >= 5 THEN
|
||||
"DB1_SYS".Pulso5seg := TRUE;
|
||||
"DB1_SYS".Aux.Contador5seg := 0;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// Pulso por 1 minuto
|
||||
"DB1_SYS".Pulso1min := FALSE;
|
||||
IF "DB1_SYS".Pulso1seg THEN
|
||||
"DB1_SYS".Aux.Contador1min += 1;
|
||||
IF "DB1_SYS".Aux.Contador1min >= 60 THEN
|
||||
"DB1_SYS".Pulso1min := TRUE;
|
||||
"DB1_SYS".Aux.Contador1min := 0;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// Pulso por 1 hora
|
||||
"DB1_SYS".Pulso1h := FALSE;
|
||||
IF "DB1_SYS".Pulso1seg THEN
|
||||
"DB1_SYS".Aux.Contador1h += 1;
|
||||
IF "DB1_SYS".Aux.Contador1h >= 3600 THEN
|
||||
"DB1_SYS".Pulso1h := TRUE;
|
||||
"DB1_SYS".Aux.Contador1h := 0;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// ==========================================================================================================
|
||||
// Flip Flop 1 segundo
|
||||
IF "DB1_SYS".Pulso1seg AND NOT "DB1_SYS".FlipFlop1seg THEN
|
||||
"DB1_SYS".FlipFlop1seg := TRUE;
|
||||
ELSIF "DB1_SYS".Pulso1seg AND "DB1_SYS".FlipFlop1seg THEN
|
||||
"DB1_SYS".FlipFlop1seg := FALSE;
|
||||
END_IF;
|
||||
|
||||
// Flip Flop 2 segundos
|
||||
IF "DB1_SYS".Pulso2seg AND NOT "DB1_SYS".FlipFlop2seg THEN
|
||||
"DB1_SYS".FlipFlop2seg := TRUE;
|
||||
ELSIF "DB1_SYS".Pulso2seg AND "DB1_SYS".FlipFlop2seg THEN
|
||||
"DB1_SYS".FlipFlop2seg := FALSE;
|
||||
END_IF;
|
||||
|
||||
// Flip Flop 5 segundos
|
||||
IF "DB1_SYS".Pulso5seg AND NOT "DB1_SYS".FlipFlop5seg THEN
|
||||
"DB1_SYS".FlipFlop5seg := TRUE;
|
||||
ELSIF "DB1_SYS".Pulso5seg AND "DB1_SYS".FlipFlop5seg THEN
|
||||
"DB1_SYS".FlipFlop5seg := FALSE;
|
||||
END_IF;
|
||||
|
||||
// ==========================================================================================================
|
||||
// Watchdog
|
||||
IF "DB1_SYS".Pulso100ms THEN
|
||||
"DB1_SYS".WatchDog += 1;
|
||||
IF "DB1_SYS".WatchDog > 20000 THEN
|
||||
"DB1_SYS".WatchDog := 0;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
// Estados anteriores
|
||||
"DB1_SYS".Aux.P_Trig_Pulso100ms := #CPU_MarcasCiclo.%X0;
|
||||
"DB1_SYS".Aux.P_Trig_Pulso1Seg := #CPU_MarcasCiclo.%X5;
|
||||
|
||||
END_REGION GESTION_MARCAS_GENERALES_Y_FLANCOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION FECHA_Y_HORA
|
||||
|
||||
// Lectura de fecha y hora actual
|
||||
#t_RetVal := RD_LOC_T("DB1_SYS".FechaHoraActual);
|
||||
|
||||
// Escritura de fecha y hora nueva escrita manualmente desde HMI
|
||||
IF "DB1_SYS".Pulsador.EscribirFechaHora.Plc THEN
|
||||
#t_RetVal := WR_SYS_T("DB1_SYS".FechaHoraNuevaManual);
|
||||
END_IF;
|
||||
|
||||
// Escritura de fecha y hora nueva escrita autoamticamente desde Script, Scada, etc...
|
||||
IF "DB1_SYS".SincronizarFecha THEN
|
||||
#t_RetVal := WR_SYS_T("DB1_SYS".FechaHoraNuevaAuto);
|
||||
END_IF;
|
||||
|
||||
END_REGION FECHA_Y_HORA
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION USUARIOS
|
||||
|
||||
// Gestion de usuario actual para trazas
|
||||
FOR #for_i := 0 TO 9 DO
|
||||
IF "DB1_SYS".Usuario.Seleccion[#for_i].Orden THEN
|
||||
"DB1_SYS".Usuario.Actual := "DB1_SYS".Usuario.Seleccion[#for_i].Usuario;
|
||||
"DB1_SYS".Usuario.Seleccion[#for_i].Orden := FALSE;
|
||||
EXIT;
|
||||
END_IF;
|
||||
END_FOR;
|
||||
|
||||
END_REGION USUARIOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION RESET_ENTIDADES
|
||||
|
||||
// Reset todas las entidades
|
||||
// CUIDADO!!!!!!!!
|
||||
// TIENEN QUE ESTAR TODOS LOS PROCESOS PARADOS!!!!!!
|
||||
IF "DB1_SYS".ResetEntidades THEN
|
||||
FOR #for_i := 1 TO "N_MAX_ENTIDAD" DO
|
||||
|
||||
"DB6_ENTIDAD".ENT[#for_i].Estado.EnProduccion :=
|
||||
"DB6_ENTIDAD".ENT[#for_i].Estado.EnCIP :=
|
||||
"DB6_ENTIDAD".ENT[#for_i].Estado.EnSIP :=
|
||||
"DB6_ENTIDAD".ENT[#for_i].Estado.ConProducto :=
|
||||
"DB6_ENTIDAD".ENT[#for_i].Estado.ConAgua :=
|
||||
"DB6_ENTIDAD".ENT[#for_i].Estado.Vacia :=
|
||||
"DB6_ENTIDAD".ENT[#for_i].Estado.Sucia := FALSE;
|
||||
|
||||
"DB6_ENTIDAD".ENT[#for_i].Habilitar :=
|
||||
"DB6_ENTIDAD".ENT[#for_i].Estado.Disponible :=
|
||||
"DB6_ENTIDAD".ENT[#for_i].Estado.Limpia := TRUE;
|
||||
|
||||
"DB6_ENTIDAD".ENT[#for_i].Estado.CodEstado := 0;
|
||||
"DB6_ENTIDAD".ENT[#for_i].Asignacion := 0;
|
||||
|
||||
"DB6_ENTIDAD".ENT[#for_i].ID := #for_i;
|
||||
|
||||
END_FOR;
|
||||
|
||||
"DB1_SYS".ResetEntidades := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION RESET_ENTIDADES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION CHECKSUM
|
||||
|
||||
// Gestion de checksum del programa
|
||||
"DB3_CHECKSUM"();
|
||||
|
||||
END_REGION CHECKSUM
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION RED_PROFINET
|
||||
|
||||
// Comprobacion de red profinet
|
||||
#t_RetVal := DeviceStates(LADDR := #RedProfinet, MODE := 4, STATE := "DB1_SYS".RedProfinet);
|
||||
|
||||
END_REGION RED_PROFINET
|
||||
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Document>
|
||||
<Engineering version="V18" />
|
||||
<SW.Blocks.OB ID="0">
|
||||
<AttributeList>
|
||||
<HeaderAuthor>ABH</HeaderAuthor>
|
||||
<HeaderFamily>ZeusControl</HeaderFamily>
|
||||
<HeaderVersion>1.0</HeaderVersion>
|
||||
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
|
||||
<Section Name="Input">
|
||||
<Member Name="LostRetentive" Datatype="Bool" Informative="true" />
|
||||
<Member Name="LostRTC" Datatype="Bool" Informative="true" />
|
||||
</Section>
|
||||
<Section Name="Temp">
|
||||
<Member Name="t_DummyInt" Datatype="Int" />
|
||||
</Section>
|
||||
<Section Name="Constant" />
|
||||
</Sections></Interface>
|
||||
<IsIECCheckEnabled>true</IsIECCheckEnabled>
|
||||
<MemoryLayout>Optimized</MemoryLayout>
|
||||
<Name>OB100_Startup</Name>
|
||||
<Namespace />
|
||||
<Number>100</Number>
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
<SecondaryType>Startup</SecondaryType>
|
||||
<SetENOAutomatically>false</SetENOAutomatically>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="1" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="2" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
|
||||
<AttributeList>
|
||||
<NetworkSource><FlgNet xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v4">
|
||||
<Parts>
|
||||
<Access Scope="LocalVariable" UId="21">
|
||||
<Symbol>
|
||||
<Component Name="t_DummyInt" />
|
||||
</Symbol>
|
||||
</Access>
|
||||
<Access Scope="GlobalVariable" UId="22">
|
||||
<Symbol>
|
||||
<Component Name="DB1_SYS" />
|
||||
<Component Name="FechaHoraNuevaManual" />
|
||||
</Symbol>
|
||||
</Access>
|
||||
<Part Name="RD_LOC_T" Version="1.0" UId="23">
|
||||
<TemplateValue Name="date_type" Type="Type">DTL</TemplateValue>
|
||||
</Part>
|
||||
</Parts>
|
||||
<Wires>
|
||||
<Wire UId="24">
|
||||
<Powerrail />
|
||||
<NameCon UId="23" Name="en" />
|
||||
</Wire>
|
||||
<Wire UId="25">
|
||||
<NameCon UId="23" Name="RET_VAL" />
|
||||
<IdentCon UId="21" />
|
||||
</Wire>
|
||||
<Wire UId="26">
|
||||
<NameCon UId="23" Name="OUT" />
|
||||
<IdentCon UId="22" />
|
||||
</Wire>
|
||||
</Wires>
|
||||
</FlgNet></NetworkSource>
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="4" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="5" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<MultilingualText ID="6" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="7" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text>Al arrancar, actualizamos la fecha y hora nueva para editar desde HMI/SCADA</Text>
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.CompileUnit>
|
||||
<SW.Blocks.CompileUnit ID="8" CompositionName="CompileUnits">
|
||||
<AttributeList>
|
||||
<NetworkSource />
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="9" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="A" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<MultilingualText ID="B" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="C" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.CompileUnit>
|
||||
<MultilingualText ID="D" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="E" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text>OB100_Startup</Text>
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.OB>
|
||||
</Document>
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Document>
|
||||
<Engineering version="V18" />
|
||||
<SW.Blocks.OB ID="0">
|
||||
<AttributeList>
|
||||
<HeaderAuthor>ABH</HeaderAuthor>
|
||||
<HeaderFamily>ZeusControl</HeaderFamily>
|
||||
<HeaderVersion>1.0</HeaderVersion>
|
||||
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
|
||||
<Section Name="Input">
|
||||
<Member Name="BlockNr" Datatype="UInt" Informative="true" />
|
||||
<Member Name="Reaction" Datatype="USInt" Informative="true" />
|
||||
<Member Name="Fault_ID" Datatype="Byte" Informative="true" />
|
||||
<Member Name="BlockType" Datatype="USInt" Informative="true" />
|
||||
<Member Name="Area" Datatype="USInt" Informative="true" />
|
||||
<Member Name="DBNr" Datatype="DB_ANY" Informative="true" />
|
||||
<Member Name="Csg_OBNr" Datatype="OB_ANY" Informative="true" />
|
||||
<Member Name="Csg_Prio" Datatype="USInt" Informative="true" />
|
||||
<Member Name="Width" Datatype="USInt" Informative="true" />
|
||||
</Section>
|
||||
<Section Name="Temp" />
|
||||
<Section Name="Constant" />
|
||||
</Sections></Interface>
|
||||
<IsIECCheckEnabled>true</IsIECCheckEnabled>
|
||||
<MemoryLayout>Optimized</MemoryLayout>
|
||||
<Name>OB121_ProgrammingError</Name>
|
||||
<Namespace />
|
||||
<Number>121</Number>
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
<SecondaryType>ProgrammingError</SecondaryType>
|
||||
<SetENOAutomatically>false</SetENOAutomatically>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="1" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="2" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
|
||||
<AttributeList>
|
||||
<NetworkSource />
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="4" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="5" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<MultilingualText ID="6" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="7" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.CompileUnit>
|
||||
<MultilingualText ID="8" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="9" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text>OB121_ProgrammingError</Text>
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.OB>
|
||||
</Document>
|
||||
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Document>
|
||||
<Engineering version="V18" />
|
||||
<SW.Blocks.OB ID="0">
|
||||
<AttributeList>
|
||||
<HeaderAuthor>ABH</HeaderAuthor>
|
||||
<HeaderFamily>ZeusControl</HeaderFamily>
|
||||
<HeaderVersion>1.0</HeaderVersion>
|
||||
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
|
||||
<Section Name="Input">
|
||||
<Member Name="BlockNr" Datatype="UInt" Informative="true" />
|
||||
<Member Name="Reaction" Datatype="USInt" Informative="true" />
|
||||
<Member Name="Fault_ID" Datatype="Byte" Informative="true" />
|
||||
<Member Name="BlockType" Datatype="USInt" Informative="true" />
|
||||
<Member Name="Area" Datatype="USInt" Informative="true" />
|
||||
<Member Name="DBNr" Datatype="DB_ANY" Informative="true" />
|
||||
<Member Name="Csg_OBNr" Datatype="OB_ANY" Informative="true" />
|
||||
<Member Name="Csg_Prio" Datatype="USInt" Informative="true" />
|
||||
<Member Name="Width" Datatype="USInt" Informative="true" />
|
||||
</Section>
|
||||
<Section Name="Temp" />
|
||||
<Section Name="Constant" />
|
||||
</Sections></Interface>
|
||||
<IsIECCheckEnabled>true</IsIECCheckEnabled>
|
||||
<MemoryLayout>Optimized</MemoryLayout>
|
||||
<Name>OB122_IOAccessError</Name>
|
||||
<Namespace />
|
||||
<Number>122</Number>
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
<SecondaryType>IOAccessError</SecondaryType>
|
||||
<SetENOAutomatically>false</SetENOAutomatically>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="1" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="2" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
|
||||
<AttributeList>
|
||||
<NetworkSource />
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="4" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="5" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<MultilingualText ID="6" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="7" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.CompileUnit>
|
||||
<MultilingualText ID="8" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="9" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text>OB122_IOAccessError</Text>
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.OB>
|
||||
</Document>
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Document>
|
||||
<Engineering version="V18" />
|
||||
<SW.Blocks.OB ID="0">
|
||||
<AttributeList>
|
||||
<HeaderAuthor>ABH</HeaderAuthor>
|
||||
<HeaderFamily>ZeusControl</HeaderFamily>
|
||||
<HeaderVersion>1.0</HeaderVersion>
|
||||
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
|
||||
<Section Name="Input">
|
||||
<Member Name="LADDR" Datatype="HW_IO" Informative="true" />
|
||||
<Member Name="USI" Datatype="Word" Informative="true" />
|
||||
<Member Name="IChannel" Datatype="USInt" Informative="true" />
|
||||
<Member Name="EventType" Datatype="Byte" Informative="true" />
|
||||
<Member Name="PointAddr" Datatype="DWord" Informative="true" />
|
||||
</Section>
|
||||
<Section Name="Temp" />
|
||||
<Section Name="Constant" />
|
||||
</Sections></Interface>
|
||||
<IsIECCheckEnabled>true</IsIECCheckEnabled>
|
||||
<MemoryLayout>Optimized</MemoryLayout>
|
||||
<Name>OB40_HardwareInterrupt</Name>
|
||||
<Namespace />
|
||||
<Number>40</Number>
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
<SecondaryType>HardwareInterrupt</SecondaryType>
|
||||
<SetENOAutomatically>false</SetENOAutomatically>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="1" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="2" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
|
||||
<AttributeList>
|
||||
<NetworkSource />
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="4" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="5" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<MultilingualText ID="6" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="7" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.CompileUnit>
|
||||
<MultilingualText ID="8" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="9" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text>OB40_HardwareInterrupt</Text>
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.OB>
|
||||
</Document>
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Document>
|
||||
<Engineering version="V18" />
|
||||
<SW.Blocks.OB ID="0">
|
||||
<AttributeList>
|
||||
<HeaderAuthor>ABH</HeaderAuthor>
|
||||
<HeaderFamily>ZeusControl</HeaderFamily>
|
||||
<HeaderVersion>1.0</HeaderVersion>
|
||||
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
|
||||
<Section Name="Input">
|
||||
<Member Name="Fault_ID" Datatype="Byte" Informative="true" />
|
||||
<Member Name="Csg_OBnr" Datatype="OB_ANY" Informative="true" />
|
||||
<Member Name="Csg_Prio" Datatype="UInt" Informative="true" />
|
||||
</Section>
|
||||
<Section Name="Temp" />
|
||||
<Section Name="Constant" />
|
||||
</Sections></Interface>
|
||||
<IsIECCheckEnabled>true</IsIECCheckEnabled>
|
||||
<MemoryLayout>Optimized</MemoryLayout>
|
||||
<Name>OB80_TimeErrorInterrupt</Name>
|
||||
<Namespace />
|
||||
<Number>80</Number>
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
<SecondaryType>TimeErrorInterrupt</SecondaryType>
|
||||
<SetENOAutomatically>false</SetENOAutomatically>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="1" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="2" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
|
||||
<AttributeList>
|
||||
<NetworkSource />
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="4" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="5" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<MultilingualText ID="6" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="7" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.CompileUnit>
|
||||
<MultilingualText ID="8" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="9" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text>OB80_TimeErrorInterrupt</Text>
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.OB>
|
||||
</Document>
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Document>
|
||||
<Engineering version="V18" />
|
||||
<SW.Blocks.OB ID="0">
|
||||
<AttributeList>
|
||||
<HeaderAuthor>ABH</HeaderAuthor>
|
||||
<HeaderFamily>ZeusControl</HeaderFamily>
|
||||
<HeaderVersion>1.0</HeaderVersion>
|
||||
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
|
||||
<Section Name="Input">
|
||||
<Member Name="IO_State" Datatype="Word" Informative="true" />
|
||||
<Member Name="LADDR" Datatype="HW_ANY" Informative="true" />
|
||||
<Member Name="Channel" Datatype="UInt" Informative="true" />
|
||||
<Member Name="MultiError" Datatype="Bool" Informative="true" />
|
||||
</Section>
|
||||
<Section Name="Temp" />
|
||||
<Section Name="Constant" />
|
||||
</Sections></Interface>
|
||||
<IsIECCheckEnabled>true</IsIECCheckEnabled>
|
||||
<MemoryLayout>Optimized</MemoryLayout>
|
||||
<Name>OB82_DiagnosticErrorInterrupt</Name>
|
||||
<Namespace />
|
||||
<Number>82</Number>
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
<SecondaryType>DiagnosticErrorInterrupt</SecondaryType>
|
||||
<SetENOAutomatically>false</SetENOAutomatically>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="1" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="2" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
|
||||
<AttributeList>
|
||||
<NetworkSource />
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="4" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="5" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<MultilingualText ID="6" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="7" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.CompileUnit>
|
||||
<MultilingualText ID="8" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="9" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text>OB82_DiagnosticErrorInterrupt</Text>
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.OB>
|
||||
</Document>
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Document>
|
||||
<Engineering version="V18" />
|
||||
<SW.Blocks.OB ID="0">
|
||||
<AttributeList>
|
||||
<HeaderAuthor>ABH</HeaderAuthor>
|
||||
<HeaderFamily>ZeusControl</HeaderFamily>
|
||||
<HeaderVersion>1.0</HeaderVersion>
|
||||
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
|
||||
<Section Name="Input">
|
||||
<Member Name="LADDR" Datatype="HW_IO" Informative="true" />
|
||||
<Member Name="Event_Class" Datatype="Byte" Informative="true" />
|
||||
<Member Name="Fault_ID" Datatype="Byte" Informative="true" />
|
||||
</Section>
|
||||
<Section Name="Temp" />
|
||||
<Section Name="Constant" />
|
||||
</Sections></Interface>
|
||||
<IsIECCheckEnabled>true</IsIECCheckEnabled>
|
||||
<MemoryLayout>Optimized</MemoryLayout>
|
||||
<Name>OB83_PullOrPlugOfModules</Name>
|
||||
<Namespace />
|
||||
<Number>83</Number>
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
<SecondaryType>PullOrPlugOfModules</SecondaryType>
|
||||
<SetENOAutomatically>false</SetENOAutomatically>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="1" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="2" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
|
||||
<AttributeList>
|
||||
<NetworkSource />
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="4" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="5" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<MultilingualText ID="6" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="7" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.CompileUnit>
|
||||
<MultilingualText ID="8" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="9" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text>OB83_PullOrPlugOfModules</Text>
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.OB>
|
||||
</Document>
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Document>
|
||||
<Engineering version="V18" />
|
||||
<SW.Blocks.OB ID="0">
|
||||
<AttributeList>
|
||||
<HeaderAuthor>ABH</HeaderAuthor>
|
||||
<HeaderFamily>ZeusControl</HeaderFamily>
|
||||
<HeaderVersion>1.0</HeaderVersion>
|
||||
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
|
||||
<Section Name="Input">
|
||||
<Member Name="LADDR" Datatype="HW_DEVICE" Informative="true" />
|
||||
<Member Name="Event_Class" Datatype="Byte" Informative="true" />
|
||||
<Member Name="Fault_ID" Datatype="Byte" Informative="true" />
|
||||
</Section>
|
||||
<Section Name="Temp" />
|
||||
<Section Name="Constant" />
|
||||
</Sections></Interface>
|
||||
<IsIECCheckEnabled>true</IsIECCheckEnabled>
|
||||
<MemoryLayout>Optimized</MemoryLayout>
|
||||
<Name>OB86_RackOrStationFailure</Name>
|
||||
<Namespace />
|
||||
<Number>86</Number>
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
<SecondaryType>RackOrStationFailure</SecondaryType>
|
||||
<SetENOAutomatically>false</SetENOAutomatically>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="1" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="2" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
|
||||
<AttributeList>
|
||||
<NetworkSource />
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<MultilingualText ID="4" CompositionName="Comment">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="5" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
<MultilingualText ID="6" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="7" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text />
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.CompileUnit>
|
||||
<MultilingualText ID="8" CompositionName="Title">
|
||||
<ObjectList>
|
||||
<MultilingualTextItem ID="9" CompositionName="Items">
|
||||
<AttributeList>
|
||||
<Culture>es-ES</Culture>
|
||||
<Text>OB86_RackOrStationFailure</Text>
|
||||
</AttributeList>
|
||||
</MultilingualTextItem>
|
||||
</ObjectList>
|
||||
</MultilingualText>
|
||||
</ObjectList>
|
||||
</SW.Blocks.OB>
|
||||
</Document>
|
||||
@@ -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
|
||||
|
||||
+147
@@ -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
|
||||
|
||||
+251
@@ -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
|
||||
|
||||
+66
@@ -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
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
FUNCTION_BLOCK "FB15049_ZC_AIRE_ESTERIL"
|
||||
TITLE = FB15049_ZC_AIRE_ESTERIL
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : HCR
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
VAR_INPUT
|
||||
Pulso1Seg : Bool; // Pulso 1 Segundo
|
||||
HabilitarMantenimiento : Bool;
|
||||
AlarmaFalloVapor : Bool;
|
||||
FechaHora {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
TempEsterilAlcanzada : Bool; // Estado temperatura de esterilizacion alcanzada
|
||||
SP_TiempoEsterilizacion : Int; // SP_Tiempo de esterilizacion
|
||||
SP_TiempoEnfriamiento : Int; // SP_Tiempo de enfriamiento
|
||||
SP_NumeroMaximoEsterilizacion : Int;
|
||||
SP_DiasMaximoFiltroEsteril : Int; // SP_Dias Maximo Filtro Esteril
|
||||
ProcesoID : Int; // ID Proceso para trazabilidad
|
||||
END_VAR
|
||||
VAR_INPUT RETAIN
|
||||
Usuario : String[25]; // Usuario actual
|
||||
END_VAR
|
||||
VAR_INPUT
|
||||
MinutoAlarma : USInt;
|
||||
SegundoAlarma : USInt;
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
ParoMantenimiento : Bool;
|
||||
AvisoDiasEsterilizacion : Bool;
|
||||
AlarmaDiasEsterilizacion : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR
|
||||
s_Habilitar : Bool; // Estado habilitado
|
||||
s_FiltroEsteril : Bool; // Estado filtro esteril
|
||||
END_VAR
|
||||
VAR RETAIN
|
||||
s_Etapa : Int; // Etapa actual
|
||||
s_NumeroEsterilizaciones : Int; // Numero de esterilizaciones
|
||||
END_VAR
|
||||
VAR
|
||||
S_NumeroDiasEsterilizacion : Int; // Numerpo de dias con filtro esterilizado
|
||||
END_VAR
|
||||
VAR RETAIN
|
||||
s_TiempoEtapa { S7_SetPoint := 'False'} : "UDT_ZC_PRO_TIEMPO_ETAPA"; // Tiempo de etapa
|
||||
END_VAR
|
||||
VAR
|
||||
Pulsadores : Struct
|
||||
Habilitar { S7_SetPoint := 'False'} : "UDT_ZC_PULSADOR";
|
||||
Deshabilitar { S7_SetPoint := 'False'} : "UDT_ZC_PULSADOR";
|
||||
Mantenimiento { S7_SetPoint := 'False'} : "UDT_ZC_PULSADOR";
|
||||
END_STRUCT;
|
||||
END_VAR
|
||||
VAR RETAIN
|
||||
TiempoEsterelizado : "UDT_ZC_CONTADOR_TIEMPO";
|
||||
END_VAR
|
||||
VAR
|
||||
s_PasswordCalculado { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UInt; // Contraseña calculada de mantenimiento
|
||||
s_PasswordHMI : UInt; // Contraseña calculada de mantenimiento
|
||||
s_MostrarAlarmaMto { S7_SetPoint := 'True'} : Bool;
|
||||
s_oldMostrarAlarmaMto { S7_SetPoint := 'True'} : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
t_ResetContador : Bool; // Tempoeral reset contador de horas
|
||||
t_DiasAvisos : Int;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
REPOSO : Int := 0;
|
||||
ESTERILIZANDO : Int := 10;
|
||||
ESTERILIZADO : Int := 20;
|
||||
ENFRIAMIENTO : Int := 30;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
//=======================================================================
|
||||
// (C)Copyright ZeusControl 2024 - 202
|
||||
//=======================================================================
|
||||
(*
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
Función principal para la gestión integral y secuencial del dispositivo del tanque de aire estéril.
|
||||
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- Evaluar y gestionar las órdenes temporizadas provenientes de los pulsadores del HMI (`Habilitar`, `Deshabilitar`, `Mantenimiento`) mediante la invocación de `FC15026_ZC_PULSADOR`.
|
||||
- Ejecutar la máquina de estados principal para controlar el ciclo de vida y las fases operativas del sistema: `REPOSO`, `ESTERILIZANDO`, `ENFRIAMIENTO` y `ESTERILIZADO`.
|
||||
- Contabilizar el tiempo de permanencia en estado estéril utilizando `FC15025_ZC_CONTADOR_TIEMPO`, llevando el registro acumulado de días de operación del filtro.
|
||||
- Monitorizar dinámicamente los tiempos de cada etapa (`s_TiempoEtapa`) y validar las transiciones de estado en función de la temperatura (`TempEsterilAlcanzada`) o la detección de fallos (`AlarmaFalloVapor`).
|
||||
- Revocar automáticamente el estado de filtro estéril (`s_FiltroEsteril`) al superar el límite máximo de días configurado en `SP_DiasMaximoFiltroEsteril`.
|
||||
- Procesar las rutinas de parada por mantenimiento preventivo, exigiendo validación de seguridad mediante contraseña (`s_PasswordHMI` vs `s_PasswordCalculado`) una vez alcanzado el límite de esterilizaciones (`SP_NumeroMaximoEsterilizacion`).
|
||||
- Calcular y emitir señales preventivas de aviso (`AvisoDiasEsterilizacion`) y alarma crítica (`AlarmaDiasEsterilizacion`) según la caducidad operativa del filtro estéril.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC15025_ZC_CONTADOR_TIEMPO`, `FC15026_ZC_PULSADOR` |
|
||||
| FB | - |
|
||||
| DB | `DB1_SYS` |
|
||||
| UDT | `UDT_ZC_CONTADOR_TIEMPO`, `UDT_ZC_PRO_TIEMPO_ETAPA`, `UDT_ZC_PULSADOR` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 15.10.2024 | (HCR) | Primera version. |
|
||||
| 01.00.01 | 28.01.2025 | (ABH) | Se cambia organizacion de variables y nombres para estandarizacion. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION PULSADORES
|
||||
|
||||
// Permiso pulsadores
|
||||
#Pulsadores.Habilitar.Permiso := NOT #s_Habilitar;
|
||||
#Pulsadores.Deshabilitar.Permiso := #s_Habilitar;
|
||||
#Pulsadores.Mantenimiento.Permiso := #ParoMantenimiento;
|
||||
|
||||
// Gestion pulsadores
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := #Pulso1Seg,
|
||||
SP_Tiempo := 2,
|
||||
TrazaCategoria:="TRZ_CAT_4_PRO_PUL",
|
||||
TrazaIdProceso:=#ProcesoID,
|
||||
TrazaIdPulsador:="TRZ_SYS_PUL_AE_HAB",
|
||||
Usuario := #Usuario,
|
||||
FechaHoraActual := #FechaHora,
|
||||
Pulsador := #Pulsadores.Habilitar);
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := #Pulso1Seg,
|
||||
SP_Tiempo := 2,
|
||||
TrazaCategoria:="TRZ_CAT_4_PRO_PUL",
|
||||
TrazaIdProceso:=#ProcesoID,
|
||||
TrazaIdPulsador:="TRZ_SYS_PUL_AE_DES",
|
||||
Usuario := #Usuario,
|
||||
FechaHoraActual := #FechaHora,
|
||||
Pulsador := #Pulsadores.Deshabilitar);
|
||||
"FC15026_ZC_PULSADOR"(Pulso1Seg := #Pulso1Seg,
|
||||
SP_Tiempo := 2,
|
||||
TrazaCategoria:="TRZ_CAT_4_PRO_PUL",
|
||||
TrazaIdProceso:=#ProcesoID,
|
||||
TrazaIdPulsador:="TRZ_SYS_PUL_AE_MNT",
|
||||
Usuario := #Usuario,
|
||||
FechaHoraActual := #FechaHora,
|
||||
Pulsador := #Pulsadores.Mantenimiento);
|
||||
|
||||
// Orden habilitar aire esteril
|
||||
IF #Pulsadores.Habilitar.Plc THEN
|
||||
#s_Habilitar := TRUE;
|
||||
ELSIF #Pulsadores.Deshabilitar.Plc THEN
|
||||
#s_Habilitar := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION PULSADORES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION SECUENCIA_FILTRO
|
||||
|
||||
CASE #s_Etapa OF
|
||||
|
||||
// =============================================================================
|
||||
#REPOSO:
|
||||
IF #s_Habilitar THEN
|
||||
#s_Etapa := #ESTERILIZADO;
|
||||
#s_TiempoEtapa.Actual := 0;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
#ESTERILIZANDO:
|
||||
#s_TiempoEtapa.SP := #SP_TiempoEsterilizacion;
|
||||
|
||||
IF NOT #s_Habilitar THEN
|
||||
#s_Etapa := #REPOSO;
|
||||
END_IF;
|
||||
IF #AlarmaFalloVapor THEN
|
||||
#s_Etapa := #REPOSO;
|
||||
END_IF;
|
||||
IF #s_TiempoEtapa.Cumplido THEN
|
||||
#s_Etapa := #ENFRIAMIENTO;
|
||||
#s_TiempoEtapa.Actual := 0;
|
||||
#S_NumeroDiasEsterilizacion := 0;
|
||||
#s_NumeroEsterilizaciones += 1;
|
||||
#s_FiltroEsteril := TRUE;
|
||||
|
||||
END_IF;
|
||||
IF #TempEsterilAlcanzada THEN
|
||||
#s_TiempoEtapa.Activar := TRUE;
|
||||
ELSE
|
||||
#s_TiempoEtapa.Activar := FALSE;
|
||||
#s_TiempoEtapa.Actual := 0;
|
||||
END_IF;
|
||||
// =============================================================================
|
||||
#ENFRIAMIENTO:
|
||||
#s_TiempoEtapa.SP := #SP_TiempoEnfriamiento;
|
||||
#s_TiempoEtapa.Activar := TRUE;
|
||||
|
||||
IF NOT #s_Habilitar THEN
|
||||
#s_Etapa := #REPOSO;
|
||||
END_IF;
|
||||
IF #s_TiempoEtapa.Cumplido THEN
|
||||
#s_Etapa := #ESTERILIZADO;
|
||||
#s_TiempoEtapa.Actual := 0;
|
||||
END_IF;
|
||||
// =============================================================================
|
||||
#ESTERILIZADO:
|
||||
#s_TiempoEtapa.SP := 5;
|
||||
IF NOT #s_Habilitar THEN
|
||||
#s_Etapa := #REPOSO;
|
||||
END_IF;
|
||||
IF #s_TiempoEtapa.Cumplido THEN
|
||||
#s_Etapa := #ESTERILIZANDO;
|
||||
#s_TiempoEtapa.Actual := 0;
|
||||
END_IF;
|
||||
IF #TempEsterilAlcanzada AND NOT #s_FiltroEsteril THEN
|
||||
#s_TiempoEtapa.Activar := TRUE;
|
||||
ELSE
|
||||
#s_TiempoEtapa.Activar := FALSE;
|
||||
#s_TiempoEtapa.Actual := 0;
|
||||
END_IF;
|
||||
ELSE
|
||||
#s_Etapa := #REPOSO;
|
||||
END_CASE;
|
||||
|
||||
END_REGION SECUENCIA_FILTRO
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION TIEMPO_ESTERILIZADO
|
||||
|
||||
// Incrementar dias de filtro #ESTERILIZADO
|
||||
IF #TiempoEsterelizado.Hora >= 24 THEN
|
||||
#t_ResetContador := TRUE;
|
||||
#S_NumeroDiasEsterilizacion += 1;
|
||||
END_IF;
|
||||
|
||||
"FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg:=#Pulso1Seg,
|
||||
Iniciar:=#Pulso1Seg AND (#s_Etapa = #ESTERILIZADO),
|
||||
Reset:=#t_ResetContador,
|
||||
Contador:=#TiempoEsterelizado);
|
||||
|
||||
// Quitar estado filtro esteril
|
||||
IF #S_NumeroDiasEsterilizacion >= #SP_DiasMaximoFiltroEsteril THEN
|
||||
#s_FiltroEsteril := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION TIEMPO_ESTERILIZADO
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION TIEMPO_ETAPA
|
||||
|
||||
// Proceso en estado parado
|
||||
IF #s_Etapa = #REPOSO THEN
|
||||
#s_TiempoEtapa.Actual := 0;
|
||||
#s_TiempoEtapa.Activar := FALSE;
|
||||
END_IF;
|
||||
|
||||
// Temporizador activo
|
||||
IF #s_TiempoEtapa.Activar THEN
|
||||
IF #Pulso1Seg
|
||||
AND
|
||||
(#s_TiempoEtapa.Actual < #s_TiempoEtapa.SP)
|
||||
THEN
|
||||
#s_TiempoEtapa.Actual += 1;
|
||||
END_IF;
|
||||
|
||||
// Reiniciar tiempo paso cumplido para esperar condicion
|
||||
#s_TiempoEtapa.Cumplido := FALSE;
|
||||
|
||||
// Tiempo paso cumplido
|
||||
IF #s_TiempoEtapa.Actual >= #s_TiempoEtapa.SP AND #s_TiempoEtapa.Activar THEN
|
||||
#s_TiempoEtapa.Cumplido := TRUE;
|
||||
END_IF;
|
||||
|
||||
// Tiempo restante
|
||||
#s_TiempoEtapa.Restante := #s_TiempoEtapa.SP - #s_TiempoEtapa.Actual;
|
||||
END_IF;
|
||||
|
||||
// Tiempo restante
|
||||
#s_TiempoEtapa.Restante := #s_TiempoEtapa.SP - #s_TiempoEtapa.Actual;
|
||||
|
||||
END_REGION TIEMPO_ETAPA
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION MANTENIMIENTO
|
||||
|
||||
// Flanco mostrar cartel de mantenieminto
|
||||
IF #HabilitarMantenimiento THEN
|
||||
|
||||
#s_MostrarAlarmaMto := (#FechaHora.MINUTE = #MinutoAlarma) AND (#FechaHora.SECOND = #SegundoAlarma) AND (#s_NumeroEsterilizaciones >= #SP_NumeroMaximoEsterilizacion);
|
||||
|
||||
IF #s_MostrarAlarmaMto AND NOT #s_oldMostrarAlarmaMto THEN
|
||||
#ParoMantenimiento := TRUE;
|
||||
#s_PasswordCalculado :=
|
||||
#s_PasswordHMI := 0;
|
||||
END_IF;
|
||||
|
||||
// Pulsador chequear contraseña de mantenimiento
|
||||
IF #Pulsadores.Mantenimiento.Plc THEN
|
||||
#s_PasswordCalculado := #FechaHora.YEAR + #FechaHora.MONTH + #FechaHora.DAY;
|
||||
IF #s_PasswordCalculado = #s_PasswordHMI THEN
|
||||
#s_NumeroEsterilizaciones := 0;
|
||||
#S_NumeroDiasEsterilizacion := 0;
|
||||
END_IF;
|
||||
#s_PasswordCalculado :=
|
||||
#s_PasswordHMI := 0;
|
||||
#ParoMantenimiento := FALSE;
|
||||
END_IF;
|
||||
ELSE
|
||||
#ParoMantenimiento := FALSE;
|
||||
END_IF;
|
||||
|
||||
#s_oldMostrarAlarmaMto := #s_MostrarAlarmaMto;
|
||||
|
||||
END_REGION MANTENIMIENTO
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION ALARMAS
|
||||
|
||||
// Aviso un dia antes
|
||||
#t_DiasAvisos := #SP_DiasMaximoFiltroEsteril - 1;
|
||||
IF #t_DiasAvisos < 0 THEN
|
||||
#t_DiasAvisos := 0;
|
||||
END_IF;
|
||||
|
||||
// Alarmas por dia de esterilizacion
|
||||
#AlarmaDiasEsterilizacion := (#S_NumeroDiasEsterilizacion >= #SP_DiasMaximoFiltroEsteril);
|
||||
#AvisoDiasEsterilizacion := (#S_NumeroDiasEsterilizacion >= #t_DiasAvisos AND NOT #AlarmaDiasEsterilizacion);
|
||||
|
||||
END_REGION ALARMAS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION NUMERO_ESTERILIZACIONES
|
||||
|
||||
IF #s_NumeroEsterilizaciones = 0 THEN
|
||||
#s_NumeroEsterilizaciones += 1;
|
||||
END_IF;
|
||||
|
||||
END_REGION NUMERO_ESTERILIZACIONES
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
@@ -0,0 +1,614 @@
|
||||
FUNCTION_BLOCK "FB2017_ZC_M_SINA"
|
||||
TITLE = FB2017_M_SINA
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Bloque de funcion para gestion de dispositivo motor sinamics
|
||||
VAR_INPUT
|
||||
Pulso1seg { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // Pulso de 1 segundo
|
||||
Simulacion { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // Simulacion
|
||||
Arranque { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // Primer arranque
|
||||
Ack { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // Acuse general
|
||||
SeguridadesOK { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // Seguridades OK
|
||||
UsuarioActual { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : String; // Usuario actual
|
||||
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : DTL; // Fecha y hora actual
|
||||
END_VAR
|
||||
|
||||
VAR
|
||||
HWIDSTW : Array[0.."N_MAX_DISP_M_SINA"] of HW_IO; // Hardware Identifer set point slot
|
||||
HWIDZSW : Array[0.."N_MAX_DISP_M_SINA"] of HW_IO; // Hardware Identifer actual value slot
|
||||
SinaSpeed {InstructionName := 'SinaSpeed'; LibVersion := '1.0'} : Array[0.."N_MAX_DISP_M_SINA"] of SinaSpeed;
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
t_Activar : Bool;
|
||||
t_Frecuencia : Real;
|
||||
t_ErrorSinaSpeed : Bool;
|
||||
t_ErrorTermico : Bool;
|
||||
t_ConfigAxis : Word;
|
||||
t_ZSW1 : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
SOLO_DIRECTO : USInt := 0;
|
||||
DIRECTO_INVERSO : USInt := 1;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
(*
|
||||
ZEUS CONTROL, S.A.
|
||||
(c)Copyright (2025) All Rights Reserved
|
||||
--------------------------------------------------------------------------------------
|
||||
|
||||
Software: TIA Portal 18
|
||||
Restricciones: PLC serie 1200/1500
|
||||
|
||||
Nombre: DISPOSITIVO SINAMICS
|
||||
Descripcion: Modelo de dispositivo sinamics (comunicado)
|
||||
|
||||
Dependencias:
|
||||
FC: FC8_ZC_TRAZA_REGISTRO
|
||||
FB: -
|
||||
DB: DB2017_DISP_M_SINA
|
||||
DB2018_INST_M_SINA
|
||||
DB1_SYS
|
||||
UDT: ZC_DISP_M_SINA
|
||||
ZC_DISP_MUX_M_SINA
|
||||
|
||||
Change log:
|
||||
|
||||
Version Fecha Tecnico a cargo Descripcion
|
||||
|
||||
01.00.00 27.04.2020 (ABH) Primera version.
|
||||
01.00.01 26.05.2020 (ABH) Se añade logica como dispositivo motor VF.
|
||||
01.00.02 22.09.2022 (HCR) Cambio lógica SinaSpeed
|
||||
Se añade trazabilidad manualizaciones
|
||||
Se añade trazabilidad de activación manual
|
||||
01.00.03 08.11.2022 (HCR) Cambio lógica enclavamiento
|
||||
01.00.04 18.09.2023 (ABH) Cambio en tipo de dato de horas de alarma. Se utiliza el tipo de dato ZC_CONTADOR_TIEMPO y el FC15025_ZC_CONTADOR_TIEMPO
|
||||
01.00.05 28.02.2024 (ABH) Se añade gestion multiplexado para Scada (no indexado)
|
||||
01.00.06 26.03.2025 (ABH) Se añade variable grupo de alarma para separar los nuevos avisos por cuadro.
|
||||
01.00.07 07.10.2025 (ABH) Se modifica la logica del multiplexado, la asignacion de oldindex se cambia de sitio ya que de vez en cuando (dependiendo de cuando el HMI
|
||||
realiza la comunicacion asincrona con el PLC) no detectaba el cambio y se machacaban valores.
|
||||
02.00.00 17.12.2025 (ABH) Se eliminan los idiomas. Se utiliza codigos para trazabilidad. Se elimina entrada "Idioma". Se elimina nombre de UDT. Se añade indexHMI para lista de
|
||||
texto en sistemas de supervision.
|
||||
|
||||
//=====================================================================================
|
||||
*)
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Funcion para la gestion de dispositivo de tipo Motor con variador de frecuencia SINAMICS.
|
||||
|
||||
En ella se realizan las siguientes acciones:
|
||||
|
||||
- Se gestiona el multiplexado de los dispositivos para su uso en sistemas HMI/SCADA.
|
||||
- Se gestiona el estado del dispositivo
|
||||
- Se gestiona el tiempo en marcha
|
||||
- Se gestiona la orden de escritura
|
||||
- Se gestiona la trazabilidad de las manualizaciones del dispositivo
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC8_ZC_TRAZA_REGISTRO`, `FC15025_ZC_CONTADOR_TIEMPO` |
|
||||
| FB | - |
|
||||
| DB | `DB2017_DISP_M_SINA` |
|
||||
| UDT | `ZC_DISP_M_SINA`, `ZC_DISP_MUX_M_SINA`, `ZC_CONTADOR_TIEMPO` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 27.04.2020 | (ABH) | Primera version. |
|
||||
| 00.00.02 | 26.05.2020 | (ABH) | Se añade logica como dispositivo motor VF. |
|
||||
| 00.00.03 | 22.09.2022 | (ABH) | Cambio lógica SinaSpeed, Se añade trazabilidad manualizaciones, Se añade trazabilidad de activación manual |
|
||||
| 00.00.04 | 08.11.2022 | (HCR) | Cambio lógica enclavamiento. |
|
||||
| 00.00.05 | 18.09.2023 | (ABH) | Cambio en tipo de dato de horas de alarma. Se utiliza el tipo de dato ZC_CONTADOR_TIEMPO y el FC15025_ZC_CONTADOR_TIEMPO. |
|
||||
| 00.00.06 | 28.02.2024 | (ABH) | Se añade gestion multiplexado para Scada (no indexado). |
|
||||
| 00.00.07 | 26.03.2025 | (ABH) | Se añade variable grupo de alarma para separar los nuevos avisos por cuadro. |
|
||||
| 00.00.08 | 07.10.2025 | (HCR) | Se modifica la logica del multiplexado, la asignacion de oldindex se cambia de sitio ya que de vez en cuando (dependiendo de cuando el HMI realiza la comunicacion asincrona con el PLC) no detectaba el cambio y se machacaban valores. |
|
||||
| 00.00.09 | 08.11.2022 | (HCR) | Cambio lógica enclavamiento |
|
||||
| 00.00.10 | 18.09.2023 | (ABH) | Cambio en tipo de dato de horas de alarma. Se utiliza el tipo de dato ZC_CONTADOR_TIEMPO y el FC15025_ZC_CONTADOR_TIEMPO |
|
||||
| 00.00.11 | 22.02.2024 | (ABH) | Se añade gestion multiplexado para Scada (no indexado) |
|
||||
| 00.00.12 | 08.01.2025 | (ABH) | Se añade entrada de primer arranque del PLC para resetear indices de multiplexado Se añade movimiento de M[0] a multiplexado en caso de que el indice sea 0. |
|
||||
| 00.00.13 | 17.12.2025 | (ABH) | Se eliminan los idiomas. Se utiliza codigos para trazabilidad. Se elimina entrada "Idioma". Se elimina nombre de UDT. Se elimina nombre de UDT. Se añade indexHMI para lista de texto en sistemas de supervision. |
|
||||
| 00.00.14 | 18.05.2026 | (ABH) | Se añade variable `Config_TipoAcceso` para uso de direccionamiento indirecto o uso directo en PLC. |
|
||||
| 01.00.00 | 08.07.2026 | (ABH) | Se extrae el multiplexado a FC independiente. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// Resetear todas las alarmas para que se vuelvan a generar
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2017_M_SINA".Agrup[#for_i].AlgunaAlarma := FALSE;
|
||||
"DB2017_M_SINA".Agrup[#for_i].AlgunaEnManual := FALSE;
|
||||
END_FOR;
|
||||
|
||||
// Numero maximo de dispositivos para limitar en HMI/Scada
|
||||
"DB2017_M_SINA".Mux.NumDispositivos := "N_MAX_DISP_M_SINA";
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_M_SINA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_M_SINA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
|
||||
REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Config_GrupoAlarma < 0 THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Config_GrupoAlarma := 0;
|
||||
END_IF;
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Config_GrupoAlarma > "N_MAX_DISP_AGRUP" THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Config_GrupoAlarma := "N_MAX_DISP_AGRUP";
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO HABILITADO
|
||||
// =============================================================================
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Config_Habilitar THEN
|
||||
|
||||
// =============================================================================
|
||||
// PUESTA A CERO DE LA SALIDA
|
||||
#t_Activar := FALSE;
|
||||
#t_Frecuencia := 0.0;
|
||||
|
||||
// =============================================================================
|
||||
// INICIALIZACION DE VALORES QUE SIEMPRE TIENEN QUE ESTAR A 1 EN LA PALABRA DE MANDO
|
||||
#t_ConfigAxis := 16#003F;
|
||||
|
||||
|
||||
REGION LECTURA_VALORES_DE_LA_TARJETA
|
||||
|
||||
// =============================================================================
|
||||
// RETORNO TERMICO
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Config_DireccionRetTermicoByte >= 0 THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_RetornoTermico := PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2017_M_SINA".M_SINA[#for_i].Config_DireccionRetTermicoByte,
|
||||
bitOffset := "DB2017_M_SINA".M_SINA[#for_i].Config_DireccionRetTermicoBit);
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Config_HabilitarInvertirTermico THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_RetornoTermico := NOT (PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2017_M_SINA".M_SINA[#for_i].Config_DireccionRetTermicoByte,
|
||||
bitOffset := "DB2017_M_SINA".M_SINA[#for_i].Config_DireccionRetTermicoBit));
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION MODOS_DE_TRABAJO
|
||||
|
||||
// =============================================================================
|
||||
// RESET CON LOCKOUT
|
||||
IF #SinaSpeed[#for_i].Lockout AND NOT #Simulacion THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Orden_ActivarManual := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Orden_ActivarAuto := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MODO MANUAL
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Estado_AutoMan THEN
|
||||
"DB2017_M_SINA".Agrup["DB2017_M_SINA".M_SINA[#for_i].Config_GrupoAlarma].AlgunaEnManual := TRUE;
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Orden_ActivarManual AND NOT "DB2017_M_SINA".M_SINA[#for_i].Estado_Enclavado AND #SeguridadesOK AND "DB2017_M_SINA".M_SINA[#for_i].Estado_SeguridadOk AND NOT "DB2017_M_SINA".M_SINA[#for_i].Alarmas_Termico THEN
|
||||
#t_Activar := TRUE;
|
||||
#t_Frecuencia := "DB2017_M_SINA".M_SINA[#for_i].Orden_ConsignaManual;
|
||||
ELSE
|
||||
#t_Activar := FALSE;
|
||||
#t_Frecuencia := 0.0;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MODO AUTO
|
||||
IF NOT "DB2017_M_SINA".M_SINA[#for_i].Estado_AutoMan THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_VelocidadSalida := "DB2017_M_SINA".M_SINA[#for_i].Orden_ConsignaAuto;
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Orden_ActivarAuto AND NOT "DB2017_M_SINA".M_SINA[#for_i].Estado_Enclavado AND #SeguridadesOK AND "DB2017_M_SINA".M_SINA[#for_i].Estado_SeguridadOk AND NOT "DB2017_M_SINA".M_SINA[#for_i].Alarmas_Termico THEN
|
||||
#t_Activar := TRUE;
|
||||
#t_Frecuencia := "DB2017_M_SINA".M_SINA[#for_i].Orden_ConsignaAuto;
|
||||
ELSE
|
||||
#t_Activar := FALSE;
|
||||
#t_Frecuencia := 0.0;
|
||||
END_IF;
|
||||
|
||||
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Orden_ActivarManual := "DB2017_M_SINA".M_SINA[#for_i].Estado_Activado;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Orden_ConsignaManual := "DB2017_M_SINA".M_SINA[#for_i].Orden_ConsignaAuto;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION ESTADO_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// MOTOR SIMULADO Y NO SIMULADO
|
||||
IF #Simulacion THEN
|
||||
|
||||
IF #t_Activar THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_ValorActual := #t_Frecuencia;
|
||||
|
||||
ELSE
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Estado_EjeHabilitado THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
IF #SinaSpeed[#for_i].ActVelocity > 0.0 THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_ValorActual := #SinaSpeed[#for_i].ActVelocity * "DB2017_M_SINA".M_SINA[#for_i].Config_VelocidadMax / "DB2017_M_SINA".M_SINA[#for_i].Config_K_Velocidad;
|
||||
ELSE
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_ValorActual := #SinaSpeed[#for_i].ActVelocity;
|
||||
END_IF;
|
||||
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION ERRORES
|
||||
|
||||
// =============================================================================
|
||||
// CHEQUEO RETORNO TERMICO
|
||||
IF NOT #Simulacion AND "DB2017_M_SINA".M_SINA[#for_i].Config_HabilitarRetornoTermico
|
||||
AND "DB2017_M_SINA".M_SINA[#for_i].Estado_RetornoTermico THEN
|
||||
#t_ErrorTermico := TRUE;
|
||||
ELSE
|
||||
#t_ErrorTermico := FALSE;
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// CHEQUEO ERROR DESDE EL BLOQUE SINA SPEED
|
||||
IF NOT #Simulacion AND #SinaSpeed[#for_i].Error AND (#SinaSpeed[#for_i].Status <> 16#8402) THEN
|
||||
#t_ErrorSinaSpeed := TRUE;
|
||||
ELSE
|
||||
#t_ErrorSinaSpeed := FALSE;
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// TEMPORIZADO DE ERRORES
|
||||
IF #t_ErrorSinaSpeed
|
||||
AND NOT "DB2017_M_SINA".M_SINA[#for_i].Alarmas_SinaSpeed
|
||||
AND NOT "DB2017_M_SINA".M_SINA[#for_i].Alarmas_Termico
|
||||
THEN
|
||||
IF NOT #Simulacion AND #Pulso1seg THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Tiempos_Alarma += 1;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Tiempos_Alarma := 0;
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ERROR TERMICO
|
||||
IF #t_ErrorTermico THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Alarmas_Termico := TRUE;
|
||||
END_IF;
|
||||
IF NOT #t_ErrorTermico THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Alarmas_Termico := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ERROR DESDE EL BLOQUE SINA SPEED
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Tiempos_Alarma >= "DB2017_M_SINA".M_SINA[#for_i].Tiempos_SetPointTiempoAlarma AND #t_ErrorSinaSpeed THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Alarmas_SinaSpeed := TRUE;
|
||||
END_IF;
|
||||
IF NOT #t_ErrorSinaSpeed THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Alarmas_SinaSpeed := FALSE;
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ERROR GLOBAL
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Alarmas_General := "DB2017_M_SINA".M_SINA[#for_i].Alarmas_Termico OR "DB2017_M_SINA".M_SINA[#for_i].Alarmas_SinaSpeed;
|
||||
|
||||
// =============================================================================
|
||||
// SI TENEMOS UN ERROR DESACTIVAMOS LA SALIDA
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Alarmas_General THEN
|
||||
"DB2017_M_SINA".Agrup["DB2017_M_SINA".M_SINA[#for_i].Config_GrupoAlarma].AlgunaAlarma := TRUE;
|
||||
#t_Activar := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION DIAGNOSIS
|
||||
|
||||
// =============================================================================
|
||||
// CONTADOR DE HORAS DE FUNCIONAMIENTO
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Orden_ResetHoras THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Orden_ResetHoras := FALSE;
|
||||
END_IF;
|
||||
IF NOT #Simulacion AND #Pulso1seg AND "DB2017_M_SINA".M_SINA[#for_i].Estado_Activado THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Tiempos_Mantenimiento += 0.00027778;
|
||||
END_IF;
|
||||
// =============================================================================
|
||||
// ALARMA HORAS PARA MANTENIMIENTO ALCANZADOS
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Alarmas_Mantenimiento := FALSE;
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Config_HabilitarMantenimiento
|
||||
AND
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Tiempos_Mantenimiento > "DB2017_M_SINA".M_SINA[#for_i].Tiempos_SetPointMantenimiento
|
||||
THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Alarmas_Mantenimiento := TRUE;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION ESCRITURA_SALIDA
|
||||
|
||||
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_VelocidadSalida := #t_Frecuencia;
|
||||
|
||||
// =============================================================================
|
||||
// LIMITAR SALIDA A LOS VALORES ESTABLECIDOS EN EL ELEMENTO
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Estado_VelocidadSalida > "DB2017_M_SINA".M_SINA[#for_i].Config_VelocidadMax THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_VelocidadSalida := "DB2017_M_SINA".M_SINA[#for_i].Config_VelocidadMax;
|
||||
END_IF;
|
||||
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Estado_VelocidadSalida < "DB2017_M_SINA".M_SINA[#for_i].Config_VelocidadMin THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_VelocidadSalida := "DB2017_M_SINA".M_SINA[#for_i].Config_VelocidadMin;
|
||||
END_IF;
|
||||
|
||||
|
||||
(*
|
||||
// =============================================================================
|
||||
// PERMISO PARA INVERTIR EL SENTIDO DE GIRO
|
||||
"DB52_DISP_M_SINA".SINA[#i].Estado_PermisoInvertirSentido := NOT #tempActivar;
|
||||
|
||||
// =============================================================================
|
||||
// REINICIALIZO LA PALABRA DE SALIDAS EN CASO DE QUE HAYAMOS INVERTIDO EL SENTIDO DE GIRO
|
||||
IF "DB52_DISP_M_SINA".SINA[#i].Orden_SeleccionInverso THEN
|
||||
#tempConfigAxis := 16#00FE;
|
||||
END_IF;
|
||||
*)
|
||||
|
||||
// =============================================================================
|
||||
// ESCRITURA SALIDA SI NO ESTA LA ORDEN DE ACTIVAR
|
||||
IF NOT #t_Activar THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_VelocidadSalida := 0.0;
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// CONVERSION DE Hz A VALOR EN RPM
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Estado_VelocidadSalida > 0.0 THEN
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_VelocidadSalida := ("DB2017_M_SINA".M_SINA[#for_i].Estado_VelocidadSalida * "DB2017_M_SINA".M_SINA[#for_i].Config_K_Velocidad) / "DB2017_M_SINA".M_SINA[#for_i].Config_VelocidadMax;
|
||||
ELSE
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_VelocidadSalida := 0.0;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// RESET ORDEN ACTIVAR EN AUTO
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Orden_ActivarAuto := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_Enclavado := FALSE;
|
||||
|
||||
REGION TRAZABILIDAD_MANUALIZACION
|
||||
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Estado_AutoMan AND NOT "DB2017_M_SINA".M_SINA[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_17_DISP_M_SINA",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_M_SINA",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF NOT "DB2017_M_SINA".M_SINA[#for_i].Estado_AutoMan AND "DB2017_M_SINA".M_SINA[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_17_DISP_M_SINA",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_M_SINA",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_AUTO",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Estado_AutoMan AND "DB2017_M_SINA".M_SINA[#for_i].Estado_Activado AND NOT "DB2017_M_SINA".M_SINA[#for_i].Aux_oldActivado THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_17_DISP_M_SINA",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_M_SINA",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_ON",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Estado_AutoMan AND NOT "DB2017_M_SINA".M_SINA[#for_i].Estado_Activado AND "DB2017_M_SINA".M_SINA[#for_i].Aux_oldActivado THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_17_DISP_M_SINA",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_M_SINA",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_OFF",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
// =============================================================================
|
||||
// Estado anterior manual/automatico
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Aux_oldAutoMan := "DB2017_M_SINA".M_SINA[#for_i].Estado_AutoMan;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Aux_oldActivado := "DB2017_M_SINA".M_SINA[#for_i].Estado_Activado;
|
||||
|
||||
ELSE
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO NO HABILITADO
|
||||
// =============================================================================
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Alarmas_General := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Alarmas_Termico := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Alarmas_Mantenimiento := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Alarmas_SinaSpeed := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_RetornoTermico := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_Enclavado := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Orden_ActivarAuto := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Orden_ActivarManual := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_Activado := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Estado_ValorActual := 0.0;
|
||||
|
||||
END_IF;
|
||||
|
||||
|
||||
REGION GESTION_HMI
|
||||
|
||||
// =============================================================================
|
||||
// GESTION BITS PARA VISUALIZACION
|
||||
// Bit 0 Habilitacion
|
||||
// Bit 1 ManualAutomatico
|
||||
// Bit 2 Enclavado
|
||||
// Bit 3 Activado 1
|
||||
// Bit 4 Activado 2
|
||||
// Bit 5 Reserva
|
||||
// Bit 6 Reserva
|
||||
// Bit 7 Reserva
|
||||
// Bit 8 Alarma General
|
||||
// Bit 9 Alarma 1
|
||||
// Bit 10 Alarma 2
|
||||
// Bit 11 Alarma 3
|
||||
// Bit 12 Alarma 4
|
||||
// Bit 13 Alarma Mantenimiento
|
||||
// Bit 14 Reserva
|
||||
// Bit 15 Reserva
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X0 := "DB2017_M_SINA".M_SINA[#for_i].Config_Habilitar;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X1 := "DB2017_M_SINA".M_SINA[#for_i].Estado_AutoMan;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X2 := "DB2017_M_SINA".M_SINA[#for_i].Estado_Enclavado;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X3 := "DB2017_M_SINA".M_SINA[#for_i].Estado_Activado;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X4 := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X5 := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X6 := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X7 := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X8 :="DB2017_M_SINA".M_SINA[#for_i].Alarmas_Termico;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X9 := "DB2017_M_SINA".M_SINA[#for_i].Alarmas_SinaSpeed;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X10 := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X11 := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X12 := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X13 := "DB2017_M_SINA".M_SINA[#for_i].Alarmas_Mantenimiento;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X14 := FALSE;
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Hmi_Estado.%X15 := FALSE;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION GESTION_NUEVA_ALARMA
|
||||
|
||||
// =============================================================================
|
||||
// DETECCION DE NUEVA ALARMA
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Alarmas_General AND NOT "DB2017_M_SINA".M_SINA[#for_i].Aux_oldAlarma THEN
|
||||
"DB2017_M_SINA".Agrup["DB2017_M_SINA".M_SINA[#for_i].Config_GrupoAlarma].NuevaAlarma := TRUE;
|
||||
END_IF;
|
||||
|
||||
// Estado anterior de las alarmas
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Aux_oldAlarma := "DB2017_M_SINA".M_SINA[#for_i].Alarmas_General;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION SINASPEED
|
||||
|
||||
|
||||
IF #HWIDSTW[#for_i] <> 0 AND #HWIDZSW[#for_i] <> 0 THEN
|
||||
#SinaSpeed[#for_i](EnableAxis := #t_Activar,
|
||||
AckError := "DB2017_M_SINA".M_SINA[#for_i].Orden_ResetFallos OR #Ack,
|
||||
SpeedSp := "DB2017_M_SINA".M_SINA[#for_i].Estado_VelocidadSalida,
|
||||
RefSpeed := "DB2017_M_SINA".M_SINA[#for_i].Config_K_Velocidad,
|
||||
ConfigAxis := #t_ConfigAxis,
|
||||
HWIDSTW := #HWIDSTW[#for_i],
|
||||
HWIDZSW := #HWIDZSW[#for_i],
|
||||
AxisEnabled => "DB2017_M_SINA".M_SINA[#for_i].Estado_EjeHabilitado,
|
||||
Lockout => "DB2017_M_SINA".M_SINA[#for_i].Estado_EjeBloqueado,
|
||||
Status => "DB2017_M_SINA".M_SINA[#for_i].Estado_Estado,
|
||||
DiagId => "DB2017_M_SINA".M_SINA[#for_i].Estado_CodigoFallo);
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ESCRITURA RESET FALLOS
|
||||
IF "DB2017_M_SINA".M_SINA[#for_i].Orden_ResetFallos AND #Pulso1seg THEN // Reset de este BIT cada segundo (es suficiente para resetear el Variador)
|
||||
"DB2017_M_SINA".M_SINA[#for_i].Orden_ResetFallos := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
END_FOR;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ACUSE DE NUEVAS ALARMAS
|
||||
IF #Ack THEN
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2017_M_SINA".Agrup[#for_i].NuevaAlarma := FALSE;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
@@ -0,0 +1,371 @@
|
||||
FUNCTION "FC2000_ZC_ED" : Void
|
||||
TITLE = FC2000_ED
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : HCR
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Modelo de dispositivo Entrada digital
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool; // Pulso de 1 segundo
|
||||
Simulacion : Bool; // Simulacion
|
||||
UsuarioActual : String; // Usuario actual
|
||||
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
t_ValorEntrada : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
TIPO_ACCESO_INDIRECTO : SInt := 0;
|
||||
TIPO_ACCESO_PLC : SInt := 1;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Funcion para la gestion de dispositivo de tipo Entrada Digital.
|
||||
|
||||
En ella se realizan las siguientes acciones:
|
||||
|
||||
- Se gestiona el multiplexado de los dispositivos para su uso en sistemas HMI/SCADA.
|
||||
- Se realiza la lectura de la entrada de manera indirecta si esta habilitada.
|
||||
- Se gestiona el estado del dispositivo
|
||||
- Se gestiona la trazabilidad de las manualizaciones del dispositivo
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC8_ZC_TRAZA_REGISTRO` |
|
||||
| FB | - |
|
||||
| DB | `DB2000_ED` |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 15.10.2020 | (ABH) | Primera version. |
|
||||
| 00.01.00 | 26.04.2022 | (HCR) | Cambio en la organizacion del UDT. Se organiza en estructuras en base al tipo de funcion que realizan los datos. |
|
||||
| 00.02.00 | 27.04.2022 | (ABH) | Se añaden auxiliares de estado anterior del modo manual y automatico para poder registrar las trazas. |
|
||||
| 00.00.03 | 22.02.2024 | (ABH) | Se añade gestion multiplexado para Scada (no indexado) |
|
||||
| 00.00.04 | 08.01.2025 | (ABH) | Se añade entrada de primer arranque del PLC para resetear indices de multiplexado. Se añade movimiento de SD[0] a multiplexado en caso de que el indice sea 0. |
|
||||
| 00.00.05 | 24.01.2025 | (ABH) | Se modifica la logica del multiplexado, la asignacion de oldindex se cambia de sitio ya que de vez en cuando (dependiendo de cuando el HMI realiza la comunicacion asincrona con el PLC) no detectaba el cambio y se machacaban valores. |
|
||||
| 00.00.06 | 26.03.2025 | (ABH) | Se añade variable grupo de alarma para separar los nuevos avisos por cuadro. |
|
||||
| 00.00.07 | 24.04.2025 | (HCR) | Se añade gestion de idioma |
|
||||
| 00.00.08 | 11.09.2025 | (ABH) | Se eliminan las constantes de idioma dentro del FC. Se utilizan constantes globales para facilitar su traduccion. |
|
||||
| 00.00.09 | 17.12.2025 | (ABH) | Se eliminan los idiomas. Se utiliza codigos para trazabilidad. Se elimina entrada "Idioma". Se elimina nombre de UDT. Se elimina nombre de UDT. Se añade indexHMI para lista de texto en sistemas de supervision. |
|
||||
| 00.00.00 | 18.05.2026 | (ABH) | Se añade variable `Config_TipoAcceso` para uso de direccionamiento indirecto o uso directo en PLC. |
|
||||
| 01.00.00 | 08.07.2026 | (ABH) | Se extrae el multiplexado a FC independiente. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// Resetear todas las alarmas para que se vuelvan a generar
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2000_ED".Agrup[#for_i].AlgunaAlarma := FALSE;
|
||||
"DB2000_ED".Agrup[#for_i].AlgunaEnManual := FALSE;
|
||||
END_FOR;
|
||||
|
||||
// Numero maximo de dispositivos para limitar en HMI/Scada
|
||||
"DB2000_ED".Mux.NumDispositivos := "N_MAX_DISP_ED";
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_ED" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_ED";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO HABILITADO
|
||||
// =============================================================================
|
||||
IF "DB2000_ED".ED[#for_i].Config_Habilitar THEN
|
||||
|
||||
REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
IF "DB2000_ED".ED[#for_i].Config_GrupoAlarma < 0 THEN
|
||||
"DB2000_ED".ED[#for_i].Config_GrupoAlarma := 0;
|
||||
END_IF;
|
||||
IF "DB2000_ED".ED[#for_i].Config_GrupoAlarma > "N_MAX_DISP_AGRUP" THEN
|
||||
"DB2000_ED".ED[#for_i].Config_GrupoAlarma := "N_MAX_DISP_AGRUP";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
|
||||
REGION LECTURA_VALORES
|
||||
|
||||
CASE "DB2000_ED".ED[#for_i].Config_TipoAcceso OF
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO:
|
||||
IF "DB2000_ED".ED[#for_i].Config_DirEntradaByte >= 0 THEN
|
||||
(*
|
||||
AREA: Pueden seleccionarse las siguientes áreas:
|
||||
16#81: Input,
|
||||
16#82: Output,
|
||||
16#83: Marcas,
|
||||
16#84: DB,
|
||||
16#1: Entrada de periferia (solo S7-1500)
|
||||
DBNUMBER: Número del bloque de datos si AREA = DB, de lo contrario "0"
|
||||
BYTEOFFSET: Dirección en la que se lee. Solo se utilizan los 16 bits menos significativos.*)
|
||||
#t_ValorEntrada := PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2000_ED".ED[#for_i].Config_DirEntradaByte,
|
||||
bitOffset := "DB2000_ED".ED[#for_i].Config_DirEntradaBit);
|
||||
|
||||
IF NOT "DB2000_ED".ED[#for_i].Config_HabilitarInvertir THEN
|
||||
"DB2000_ED".ED[#for_i].Estado_EntradaCanal := NOT #t_ValorEntrada;
|
||||
ELSE
|
||||
"DB2000_ED".ED[#for_i].Estado_EntradaCanal := #t_ValorEntrada;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
#TIPO_ACCESO_PLC:
|
||||
;
|
||||
|
||||
END_CASE;
|
||||
|
||||
END_REGION LECTURA_VALORES
|
||||
|
||||
|
||||
REGION MODOS_DE_TRABAJO
|
||||
|
||||
// =============================================================================
|
||||
// MODO MANUAL
|
||||
IF "DB2000_ED".ED[#for_i].Estado_AutoMan THEN
|
||||
|
||||
"DB2000_ED".Agrup["DB2000_ED".ED[#for_i].Config_GrupoAlarma].AlgunaEnManual := TRUE;
|
||||
|
||||
IF "DB2000_ED".ED[#for_i].Orden_ActivarManual THEN
|
||||
"DB2000_ED".ED[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2000_ED".ED[#for_i].Estado_Activado := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
"DB2000_ED".ED[#for_i].Orden_ActivarManual := "DB2000_ED".ED[#for_i].Estado_Activado;
|
||||
END_IF;
|
||||
|
||||
END_REGION MODOS_DE_TRABAJO
|
||||
|
||||
|
||||
REGION ESTADO_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// DETECTOR SIMULADO
|
||||
IF #Simulacion THEN
|
||||
|
||||
IF "DB2000_ED".ED[#for_i].Orden_ActivarManual THEN
|
||||
"DB2000_ED".ED[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2000_ED".ED[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
|
||||
IF NOT "DB2000_ED".ED[#for_i].Estado_AutoMan AND NOT #Simulacion THEN
|
||||
|
||||
// =============================================================================
|
||||
// RETARDO A LA ACTIVACIÓN AUTOMÁTICO
|
||||
IF "DB2000_ED".ED[#for_i].Estado_EntradaCanal AND "DB2000_ED".ED[#for_i].Config_HabilitarRetardoAct THEN
|
||||
|
||||
IF #Pulso1seg AND "DB2000_ED".ED[#for_i].Tiempos_TiempoAct < "DB2000_ED".ED[#for_i].Tiempos_SPTiempoAct THEN
|
||||
"DB2000_ED".ED[#for_i].Tiempos_TiempoAct += 1;
|
||||
END_IF;
|
||||
|
||||
IF "DB2000_ED".ED[#for_i].Tiempos_TiempoAct >= "DB2000_ED".ED[#for_i].Tiempos_SPTiempoAct THEN
|
||||
"DB2000_ED".ED[#for_i].Estado_Activado := TRUE;
|
||||
END_IF;
|
||||
|
||||
ELSIF "DB2000_ED".ED[#for_i].Estado_EntradaCanal THEN
|
||||
|
||||
"DB2000_ED".ED[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2000_ED".ED[#for_i].Tiempos_TiempoAct := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// RETARDO A LA DESACTIVACIÓN AUTOMÁTICO
|
||||
IF NOT "DB2000_ED".ED[#for_i].Estado_EntradaCanal AND "DB2000_ED".ED[#for_i].Config_HabilitarRetardoDes THEN
|
||||
|
||||
IF #Pulso1seg AND "DB2000_ED".ED[#for_i].Tiempos_TiempoDes < "DB2000_ED".ED[#for_i].Tiempos_SPTiempoDes THEN
|
||||
"DB2000_ED".ED[#for_i].Tiempos_TiempoDes += 1;
|
||||
END_IF;
|
||||
|
||||
IF "DB2000_ED".ED[#for_i].Tiempos_TiempoDes >= "DB2000_ED".ED[#for_i].Tiempos_SPTiempoDes THEN
|
||||
"DB2000_ED".ED[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSIF NOT "DB2000_ED".ED[#for_i].Estado_EntradaCanal THEN
|
||||
|
||||
"DB2000_ED".ED[#for_i].Estado_Activado := FALSE;
|
||||
|
||||
ELSE
|
||||
|
||||
"DB2000_ED".ED[#for_i].Tiempos_TiempoDes := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION ESTADO_DEL_DISPOSITIVO
|
||||
|
||||
|
||||
REGION TRAZABILIDAD_MANUALIZACION
|
||||
|
||||
IF "DB2000_ED".ED[#for_i].Estado_AutoMan AND NOT "DB2000_ED".ED[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_10_DISP_ED",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_ED",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF NOT "DB2000_ED".ED[#for_i].Estado_AutoMan AND "DB2000_ED".ED[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_10_DISP_ED",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_ED",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_AUTO",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2000_ED".ED[#for_i].Estado_AutoMan AND "DB2000_ED".ED[#for_i].Estado_Activado AND NOT "DB2000_ED".ED[#for_i].Aux_oldActivado THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_10_DISP_ED",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_ED",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_ON",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2000_ED".ED[#for_i].Estado_AutoMan AND NOT "DB2000_ED".ED[#for_i].Estado_Activado AND "DB2000_ED".ED[#for_i].Aux_oldActivado THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_10_DISP_ED",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_ED",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_OFF",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
|
||||
|
||||
END_REGION TRAZABILIDAD_MANUALIZACION
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ESTADO ANTERIOR MANUAL/AUTOMÁTICO
|
||||
"DB2000_ED".ED[#for_i].Aux_oldAutoMan := "DB2000_ED".ED[#for_i].Estado_AutoMan;
|
||||
"DB2000_ED".ED[#for_i].Aux_oldActivado := "DB2000_ED".ED[#for_i].Estado_Activado;
|
||||
|
||||
ELSE
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO NO HABILITADO
|
||||
// =============================================================================
|
||||
"DB2000_ED".ED[#for_i].Estado_EntradaCanal := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Estado_Activado := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Tiempos_TiempoAct := 0;
|
||||
"DB2000_ED".ED[#for_i].Tiempos_TiempoDes := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
REGION ESTADO_HMI
|
||||
|
||||
// =============================================================================
|
||||
// ESTADO BITS PARA VISUALIZACION
|
||||
// Bit 0 Habilitacion
|
||||
// Bit 1 ManualAutomatico
|
||||
// Bit 2 Enclavado
|
||||
// Bit 3 Activado 1
|
||||
// Bit 4 Activado 2
|
||||
// Bit 5 Reserva
|
||||
// Bit 6 Reserva
|
||||
// Bit 7 Reserva
|
||||
// Bit 8 Alarma General
|
||||
// Bit 9 Alarma 1
|
||||
// Bit 10 Alarma 2
|
||||
// Bit 11 Alarma 3
|
||||
// Bit 12 Alarma 4
|
||||
// Bit 13 Alarma Mantenimiento
|
||||
// Bit 14 Reserva
|
||||
// Bit 15 Reserva
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X0 := "DB2000_ED".ED[#for_i].Config_Habilitar;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X1 := "DB2000_ED".ED[#for_i].Estado_AutoMan;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X2 := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X3 := "DB2000_ED".ED[#for_i].Estado_Activado;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X4 := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X5 := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X6 := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X7 := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X8 := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X9 := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X10 := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X11 := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X12 := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X13 := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X14 := FALSE;
|
||||
"DB2000_ED".ED[#for_i].Hmi_Estado.%X15 := FALSE;
|
||||
|
||||
|
||||
END_REGION ESTADO_HMI
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,568 @@
|
||||
FUNCTION "FC2001_ZC_EA" : Void
|
||||
TITLE = FC2001_EA
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Modelo de dispositivo entrada analogica
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool; // Pulso de 1 segundo
|
||||
Simulacion : Bool; // Simulacion
|
||||
Arranque : Bool; // Primer arranque
|
||||
Ack : Bool; // Acuse general
|
||||
UsuarioActual : String; // Usuario actual
|
||||
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
t_x0 : Real;
|
||||
t_x1 : Real;
|
||||
t_y0 : Real;
|
||||
t_y1 : Real;
|
||||
t_x : Real;
|
||||
t_ErrorGeneral : Bool;
|
||||
t_LecturaRealizada : Bool;
|
||||
t_SubError : Real;
|
||||
t_ValorTarjeta : Int;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
TIPO_ACCESO_INDIRECTO_ESCALADO : SInt := 0;
|
||||
TIPO_ACCESO_PLC : SInt := 1;
|
||||
TIPO_ACCESO_INDIRECTO_WORD_SIN_ESCALADO : SInt := 2;
|
||||
TIPO_ACCESO_INDIRECTO_DWORD_SIN_ESCALADO : SInt := 3;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Funcion para la gestion de dispositivo de tipo Entrada Analogica.
|
||||
|
||||
En ella se realizan las siguientes acciones:
|
||||
|
||||
- Se gestiona el multiplexado de los dispositivos para su uso en sistemas HMI/SCADA.
|
||||
- Se realiza la lectura de la entrada de manera indirecta si esta habilitada.
|
||||
- Se gestiona el escalado si esta habilitado.
|
||||
- Se gestiona el estado del dispositivo
|
||||
- Se gestiona la trazabilidad de las manualizaciones del dispositivo
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC8_ZC_TRAZA_REGISTRO` |
|
||||
| FB | - |
|
||||
| DB | `DB2001_EA` |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.00 | 15.10.2020 | (ABH) | Primera versión. |
|
||||
| 00.00.01 | 26.04.2022 | (HCR) | Cambio en la organizacion del UDT en base al tipo de funcion.Se añade seguridad en el escalado. |
|
||||
| 00.00.02 | 27.04.2022 | (ABH) | Se añaden auxiliares de estado anterior del modo manual y automatico para poder registrar las trazas. |
|
||||
| 00.00.06 | 29.04.2022 | (HCR) | Cambio del estado de la señal, se agrega señal estado por prioridades. Cambio de las condiciones de para error de configuración. Cambio en la programaciíon de alarmas. Cambio en los límites de la señal |
|
||||
| 00.00.07 | 08.11.2022 | (ABH) | Se añade trazabilidad manualizaciones |
|
||||
| 00.00.08 | 20.12.2022 | (HCR) | Se añade trazabilidad de escalado y offset |
|
||||
| 00.00.09 | 22.02.2024 | (ABH) | Se añade gestion multiplexado para Scada (no indexado) |
|
||||
| 00.00.10 | 08.01.2025 | (ABH) | Se añade entrada de primer arranque del PLC para resetear indices de multiplexado.nSe añade movimiento de EA[0] a multiplexado en caso de que el indice sea 0. |
|
||||
| 00.00.11 | 24.01.2025 | (ABH) | Se modifica la logica del multiplexado, la asignacion de oldindex se cambia de sitio ya que de vez en cuando (dependiendo de cuando el HMI realiza la comunicacion asincrona con el PLC) no detectaba el cambio y se machacaban valores. |
|
||||
| 00.00.12 | 26.03.2025 | (ABH) | Se añade variable grupo de alarma para separar los nuevos avisos por cuadro. |
|
||||
| 00.00.13 | 24.04.2025 | (HCR) | Se añade gestion de idioma |
|
||||
| 00.00.14 | 11.09.2025 | (ABH) | Se eliminan las constantes de idioma dentro del FC. Se utilizan constantes globales para facilitar su traduccion. |
|
||||
| 00.00.15 | 17.12.2025 | (ABH) | Se eliminan los idiomas. Se utiliza codigos para trazabilidad. Se elimina entrada "Idioma". Se elimina nombre de UDT. Se añade indexHMI para lista de texto en sistemas de supervision. |
|
||||
| 00.00.16 | 14.05.2026 | (ABH) | Se modifica UDT para añadir tipo de lectura. |
|
||||
| 01.00.00 | 18.05.2026 | (ABH) | Se añade variable `Config_TipoAcceso` para uso de direccionamiento indirecto o uso directo en PLC. |
|
||||
| 01.01.00 | 08.07.2026 | (ABH) | Se extrae el multiplexado a FC independiente. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// Resetear todas las alarmas para que se vuelvan a generar
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2001_EA".Agrup[#for_i].AlgunaAlarma := FALSE;
|
||||
"DB2001_EA".Agrup[#for_i].AlgunaEnManual := FALSE;
|
||||
END_FOR;
|
||||
|
||||
// Numero maximo de dispositivos para limitar en HMI/Scada
|
||||
"DB2001_EA".Mux.NumDispositivos := "N_MAX_DISP_EA";
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_EA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_EA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
|
||||
REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
IF "DB2001_EA".EA[#for_i].Config_GrupoAlarma < 0 THEN
|
||||
"DB2001_EA".EA[#for_i].Config_GrupoAlarma := 0;
|
||||
END_IF;
|
||||
IF "DB2001_EA".EA[#for_i].Config_GrupoAlarma > "N_MAX_DISP_AGRUP" THEN
|
||||
"DB2001_EA".EA[#for_i].Config_GrupoAlarma := "N_MAX_DISP_AGRUP";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
#t_LecturaRealizada := FALSE;
|
||||
#t_ErrorGeneral := FALSE;
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO HABILITADO
|
||||
// =============================================================================
|
||||
IF "DB2001_EA".EA[#for_i].Config_Habilitar THEN
|
||||
|
||||
REGION LECTURA
|
||||
|
||||
CASE "DB2001_EA".EA[#for_i].Config_TipoAcceso OF
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO_ESCALADO:
|
||||
REGION LECTURA_VALORES_DE_LA_TARJETA
|
||||
|
||||
IF "DB2001_EA".EA[#for_i].Config_DireccionEntradaByte > 0 THEN
|
||||
|
||||
// =============================================================================
|
||||
// LECTURA DE LA SEÑAL DE ENTRADA - PEEK_WORD (area) 16#1 para CPU 1500; 16#81 para CPU 1200
|
||||
#t_ValorTarjeta := WORD_TO_INT(PEEK_WORD(area := 16#81, dbNumber := 0, byteOffset := "DB2001_EA".EA[#for_i].Config_DireccionEntradaByte));
|
||||
// =============================================================================
|
||||
// COMPROBAMOS LOCALARMASENTE LA LECTURA CORRECTA DE LA ENTRADA ANALOGICA
|
||||
REGION DESCRIPCION_GET_ERR_ID()
|
||||
// La instrucción "Consultar ID de error locALARMASente" consulta si se han producido errores en un bloque. Suele tratarse de un error de acceso.
|
||||
// si al ejecutar el bloque el sistema notifica errores de ejecución desde que se ejecutó La instrucción por última vez, la instrucción emite la ID del primer error ocurrido.
|
||||
// La ID de error solo se puede guardar en operandos del tipo de datos WORD. Si se producen varios errores en el bloque, la instrucción soluciona el primer error ocurrido,
|
||||
// y solo entonces la instrucción emite la ID de error del siguiente error ocurrido.
|
||||
// 0 0 Ningún error
|
||||
// 2503 9475 Puntero no válido
|
||||
// 2520 9504 STRING no válido
|
||||
// 2522 9506 Error de lectura: operando fuera del rango válido
|
||||
// 2523 9507 Error de escritura: operando fuera del rango válido
|
||||
// 2524 9508 Error de lectura: operando no válido
|
||||
// 2525 9509 Error de escritura: operando no válido
|
||||
// 2528 9512 Error de lectura: alineación de datos
|
||||
// 2529 9513 Error de escritura: alineación de datos
|
||||
// 252C 9516 Puntero no válido
|
||||
// 2530 9520 Error de escritura: Bloque de datos
|
||||
// 2533 9523 Referencia usada no válida
|
||||
// 2538 9528 Error de acceso: el DB no existe
|
||||
// 2539 9529 Error de acceso: se ha utilizado un DB incorrecto
|
||||
// 253A 9530 El bloque de datos global no existe
|
||||
// 253C 9532 Indicación errónea o la función no existe
|
||||
// 253D 9533 La función de sistema no existe
|
||||
// 253E 9534 Indicación errónea o el bloque de función no existe
|
||||
// 253F 9535 El bloque de sistema no existe
|
||||
// 2550 9552 Error de acceso: el DB no existe
|
||||
// 2551 9553 Error de acceso: se ha utilizado un DB incorrecto
|
||||
// 2575 9589 Error en la profundidad de anidamiento del programa
|
||||
// 2576 9590 Error en la distribución de datos locales
|
||||
// 2577 9591 La propiedad de bloque "Alimentación de parámetros a través de registros" no está activada.
|
||||
// 25A0 9632 Error interno en TP
|
||||
// 25A1 9633 Variable protegida contra escritura
|
||||
// 25A2 9634 Valor numérico no válido de la variable
|
||||
// 2942 10562 Error de lectura: entrada
|
||||
// 2943 10563 Error de escritura: salida
|
||||
END_REGION
|
||||
|
||||
"DB2001_EA".EA[#for_i].Estado_Lectura := GET_ERR_ID();
|
||||
#t_LecturaRealizada := ("DB2001_EA".EA[#for_i].Estado_Lectura = 0);
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorTarjeta := #t_ValorTarjeta;
|
||||
ELSE
|
||||
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorTarjeta := 0;
|
||||
#t_LecturaRealizada := TRUE;
|
||||
END_IF;
|
||||
|
||||
END_REGION LECTURA_VALORES_DE_LA_TARJETA
|
||||
|
||||
|
||||
REGION CALCULO_VALOR
|
||||
|
||||
IF "DB2001_EA".EA[#for_i].Config_DireccionEntradaByte > 0 THEN
|
||||
|
||||
IF "DB2001_EA".EA[#for_i].Config_EscaladoMaxIngenieria > "DB2001_EA".EA[#for_i].Config_EscaladoMinIngenieria AND
|
||||
"DB2001_EA".EA[#for_i].Config_EscaladoMaxTarjeta > "DB2001_EA".EA[#for_i].Config_EscaladoMinTarjeta THEN
|
||||
|
||||
#t_x0 := INT_TO_REAL("DB2001_EA".EA[#for_i].Config_EscaladoMinTarjeta);
|
||||
#t_x1 := INT_TO_REAL("DB2001_EA".EA[#for_i].Config_EscaladoMaxTarjeta);
|
||||
#t_x := DINT_TO_REAL("DB2001_EA".EA[#for_i].Estado_ValorTarjeta);
|
||||
#t_y0 := "DB2001_EA".EA[#for_i].Config_EscaladoMinIngenieria;
|
||||
#t_y1 := "DB2001_EA".EA[#for_i].Config_EscaladoMaxIngenieria;
|
||||
|
||||
// =============================================================================
|
||||
// DETECCIÓN DE FALLO EN EL CANAL
|
||||
IF ("DB2001_EA".EA[#for_i].Estado_ValorTarjeta > -32768) AND ("DB2001_EA".EA[#for_i].Estado_ValorTarjeta < 32767) AND #t_LecturaRealizada THEN
|
||||
|
||||
IF ("DB2001_EA".EA[#for_i].Config_EscaladoMaxIngenieria <> "DB2001_EA".EA[#for_i].Config_EscaladoMinIngenieria)
|
||||
AND
|
||||
("DB2001_EA".EA[#for_i].Config_EscaladoMaxTarjeta <> "DB2001_EA".EA[#for_i].Config_EscaladoMinTarjeta)
|
||||
THEN
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := ((#t_x - #t_x0) * ((#t_y1 - #t_y0) / (#t_x1 - #t_x0))) + #t_y0;
|
||||
|
||||
// =============================================================================
|
||||
// LÍMITES
|
||||
IF "DB2001_EA".EA[#for_i].Estado_ValorIngenieria > "DB2001_EA".EA[#for_i].Config_EscaladoMaxIngenieria THEN
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := "DB2001_EA".EA[#for_i].Config_EscaladoMaxIngenieria;
|
||||
END_IF;
|
||||
IF "DB2001_EA".EA[#for_i].Estado_ValorIngenieria < "DB2001_EA".EA[#for_i].Config_EscaladoMinIngenieria THEN
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := "DB2001_EA".EA[#for_i].Config_EscaladoMinIngenieria;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// OFFSET
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := "DB2001_EA".EA[#for_i].Estado_ValorIngenieria + "DB2001_EA".EA[#for_i].Config_EscaladoOffset;
|
||||
ELSE
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := 0.0;
|
||||
END_IF;
|
||||
"DB2001_EA".EA[#for_i].Alarmas_HiloRoto := FALSE;
|
||||
ELSE
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := 0.0;
|
||||
"DB2001_EA".EA[#for_i].Alarmas_HiloRoto := TRUE; // Error del canal
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := 0.0;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION CALCULO_VALOR
|
||||
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO_WORD_SIN_ESCALADO:
|
||||
REGION LECTURA_VALORES_DE_LA_TARJETA
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorTarjeta := 0;
|
||||
|
||||
IF "DB2001_EA".EA[#for_i].Config_DireccionEntradaByte > 0 THEN
|
||||
|
||||
// =============================================================================
|
||||
// LECTURA DE LA SEÑAL DE ENTRADA - PEEK_WORD (area) 16#1 para CPU 1500; 16#81 para CPU 1200
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := DINT_TO_REAL(WORD_TO_DINT(PEEK_WORD(area := 16#81, dbNumber := 0, byteOffset := "DB2001_EA".EA[#for_i].Config_DireccionEntradaByte)));
|
||||
|
||||
// =============================================================================
|
||||
// COMPROBAMOS LOCALARMASENTE LA LECTURA CORRECTA DE LA ENTRADA ANALOGICA
|
||||
"DB2001_EA".EA[#for_i].Estado_Lectura := GET_ERR_ID();
|
||||
#t_LecturaRealizada := ("DB2001_EA".EA[#for_i].Estado_Lectura = 0);
|
||||
ELSE
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := 0;
|
||||
#t_LecturaRealizada := TRUE;
|
||||
END_IF;
|
||||
END_REGION LECTURA_VALORES_DE_LA_TARJETA
|
||||
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO_DWORD_SIN_ESCALADO:
|
||||
REGION LECTURA_VALORES_DE_LA_TARJETA
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorTarjeta := 0;
|
||||
|
||||
IF "DB2001_EA".EA[#for_i].Config_DireccionEntradaByte > 0 THEN
|
||||
|
||||
// =============================================================================
|
||||
// LECTURA DE LA SEÑAL DE ENTRADA - PEEK_WORD (area) 16#1 para CPU 1500; 16#81 para CPU 1200
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := DINT_TO_REAL(DWORD_TO_DINT(PEEK_DWORD(area := 16#81, dbNumber := 0, byteOffset := "DB2001_EA".EA[#for_i].Config_DireccionEntradaByte)));
|
||||
|
||||
// =============================================================================
|
||||
// COMPROBAMOS LOCALARMASENTE LA LECTURA CORRECTA DE LA ENTRADA ANALOGICA
|
||||
"DB2001_EA".EA[#for_i].Estado_Lectura := GET_ERR_ID();
|
||||
#t_LecturaRealizada := ("DB2001_EA".EA[#for_i].Estado_Lectura = 0);
|
||||
ELSE
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := 0;
|
||||
#t_LecturaRealizada := TRUE;
|
||||
END_IF;
|
||||
END_REGION LECTURA_VALORES_DE_LA_TARJETA
|
||||
|
||||
|
||||
#TIPO_ACCESO_PLC:
|
||||
#t_LecturaRealizada := TRUE;
|
||||
|
||||
END_CASE;
|
||||
|
||||
END_REGION LECTURA
|
||||
|
||||
|
||||
REGION MODOS_DE_TRABAJO
|
||||
|
||||
// =============================================================================
|
||||
// FORZADO DE LA SEÑAL
|
||||
IF "DB2001_EA".EA[#for_i].Estado_AutoMan THEN
|
||||
"DB2001_EA".Agrup["DB2001_EA".EA[#for_i].Config_GrupoAlarma].AlgunaEnManual := TRUE;
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := "DB2001_EA".EA[#for_i].Orden_ConsignaManual;
|
||||
ELSE
|
||||
"DB2001_EA".EA[#for_i].Orden_ConsignaManual := "DB2001_EA".EA[#for_i].Estado_ValorIngenieria;
|
||||
END_IF;
|
||||
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION ERRORES
|
||||
|
||||
#t_SubError := "DB2001_EA".EA[#for_i].Config_EscaladoMaxIngenieria - "DB2001_EA".EA[#for_i].Config_EscaladoMinIngenieria;
|
||||
// =============================================================================
|
||||
// ALARMA NIVEL MÍNIMO
|
||||
IF "DB2001_EA".EA[#for_i].Config_HabilitarAlarmaMin THEN
|
||||
IF "DB2001_EA".EA[#for_i].Estado_ValorIngenieria < "DB2001_EA".EA[#for_i].Config_ErrorMinIngenieria THEN
|
||||
"DB2001_EA".EA[#for_i].Alarmas_Min := TRUE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// RESET DE ALARMA CON HISTÉRESIS EN UNIDADES DE INGENIERÍA
|
||||
IF NOT ("DB2001_EA".EA[#for_i].Config_HisteresisTipo) AND ("DB2001_EA".EA[#for_i].Estado_ValorIngenieria >= ("DB2001_EA".EA[#for_i].Config_ErrorMinIngenieria + "DB2001_EA".EA[#for_i].Config_ErrorMinHisteresis)) THEN
|
||||
"DB2001_EA".EA[#for_i].Alarmas_Min := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// RESET DE ALARMA CON HISTÉRESIS EN %
|
||||
IF "DB2001_EA".EA[#for_i].Config_HisteresisTipo AND ("DB2001_EA".EA[#for_i].Estado_ValorIngenieria >= "DB2001_EA".EA[#for_i].Config_ErrorMinIngenieria + ("DB2001_EA".EA[#for_i].Config_ErrorMinHisteresis / 100.0) * #t_SubError) THEN
|
||||
"DB2001_EA".EA[#for_i].Alarmas_Min := FALSE;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2001_EA".EA[#for_i].Alarmas_Min := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ALARMA NIVEL MÁXIMO
|
||||
IF "DB2001_EA".EA[#for_i].Config_HabilitarAlarmaMax THEN
|
||||
IF "DB2001_EA".EA[#for_i].Estado_ValorIngenieria > "DB2001_EA".EA[#for_i].Config_ErrorMaxIngenieria THEN
|
||||
"DB2001_EA".EA[#for_i].Alarmas_Max := TRUE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// RESET DE ALARMA CON HISTÉRESIS EN UNIDADES DE INGENIERÍA
|
||||
IF NOT ("DB2001_EA".EA[#for_i].Config_HisteresisTipo) AND ("DB2001_EA".EA[#for_i].Estado_ValorIngenieria <= ("DB2001_EA".EA[#for_i].Config_ErrorMaxIngenieria - "DB2001_EA".EA[#for_i].Config_ErrorMaxHisteresis)) THEN
|
||||
"DB2001_EA".EA[#for_i].Alarmas_Max := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// RESET DE ALARMA CON HISTÉRESIS EN %
|
||||
IF "DB2001_EA".EA[#for_i].Config_HisteresisTipo AND ("DB2001_EA".EA[#for_i].Estado_ValorIngenieria <= "DB2001_EA".EA[#for_i].Config_ErrorMaxIngenieria - ("DB2001_EA".EA[#for_i].Config_ErrorMaxHisteresis / 100.0) * #t_SubError) THEN
|
||||
"DB2001_EA".EA[#for_i].Alarmas_Max := FALSE;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2001_EA".EA[#for_i].Alarmas_Max := FALSE;
|
||||
END_IF;
|
||||
|
||||
#t_ErrorGeneral := "DB2001_EA".EA[#for_i].Alarmas_HiloRoto OR "DB2001_EA".EA[#for_i].Alarmas_Max OR "DB2001_EA".EA[#for_i].Alarmas_Min;
|
||||
"DB2001_EA".EA[#for_i].Alarmas_General := #t_ErrorGeneral;
|
||||
|
||||
IF #t_ErrorGeneral THEN
|
||||
"DB2001_EA".Agrup["DB2001_EA".EA[#for_i].Config_GrupoAlarma].AlgunaAlarma := TRUE;
|
||||
END_IF;
|
||||
|
||||
|
||||
"DB2001_EA".EA[#for_i].Alarmas_Lectura := NOT #t_LecturaRealizada;
|
||||
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION ESTADO
|
||||
|
||||
// Estado normal
|
||||
"DB2001_EA".EA[#for_i].Aux_Estado := 1;
|
||||
|
||||
// Error de configuración
|
||||
IF ("DB2001_EA".EA[#for_i].Config_EscaladoMaxIngenieria = "DB2001_EA".EA[#for_i].Config_EscaladoMinIngenieria) OR
|
||||
("DB2001_EA".EA[#for_i].Config_EscaladoMaxTarjeta = "DB2001_EA".EA[#for_i].Config_EscaladoMinTarjeta)
|
||||
THEN
|
||||
"DB2001_EA".EA[#for_i].Aux_Estado := 6;
|
||||
END_IF;
|
||||
|
||||
// Error de configuración
|
||||
IF ("DB2001_EA".EA[#for_i].Config_EscaladoMaxIngenieria < "DB2001_EA".EA[#for_i].Config_EscaladoMinIngenieria) OR
|
||||
("DB2001_EA".EA[#for_i].Config_EscaladoMaxTarjeta < "DB2001_EA".EA[#for_i].Config_EscaladoMinTarjeta)
|
||||
THEN
|
||||
"DB2001_EA".EA[#for_i].Aux_Estado := 6;
|
||||
END_IF;
|
||||
|
||||
// Error del canal
|
||||
IF "DB2001_EA".EA[#for_i].Config_TipoAcceso = #TIPO_ACCESO_INDIRECTO_ESCALADO AND
|
||||
("DB2001_EA".EA[#for_i].Estado_ValorTarjeta <= -32766) OR
|
||||
("DB2001_EA".EA[#for_i].Estado_ValorTarjeta >= 32766)
|
||||
THEN
|
||||
"DB2001_EA".EA[#for_i].Aux_Estado := 3;
|
||||
END_IF;
|
||||
|
||||
// Señal en alarma
|
||||
IF "DB2001_EA".EA[#for_i].Config_HabilitarAlarmaMin THEN
|
||||
IF "DB2001_EA".EA[#for_i].Estado_ValorIngenieria < "DB2001_EA".EA[#for_i].Config_ErrorMinIngenieria
|
||||
THEN
|
||||
"DB2001_EA".EA[#for_i].Aux_Estado := 4;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// Señal en alarma
|
||||
IF "DB2001_EA".EA[#for_i].Config_HabilitarAlarmaMax THEN
|
||||
IF "DB2001_EA".EA[#for_i].Estado_ValorIngenieria > "DB2001_EA".EA[#for_i].Config_ErrorMaxIngenieria
|
||||
THEN
|
||||
"DB2001_EA".EA[#for_i].Aux_Estado := 5;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// Error de lectura
|
||||
IF NOT #t_LecturaRealizada THEN
|
||||
"DB2001_EA".EA[#for_i].Aux_Estado := 7;
|
||||
END_IF;
|
||||
|
||||
// EA no direccionada
|
||||
IF ("DB2001_EA".EA[#for_i].Config_TipoAcceso = #TIPO_ACCESO_INDIRECTO_ESCALADO OR "DB2001_EA".EA[#for_i].Config_TipoAcceso = #TIPO_ACCESO_INDIRECTO_ESCALADO)
|
||||
AND
|
||||
"DB2001_EA".EA[#for_i].Config_DireccionEntradaByte <= 0
|
||||
THEN
|
||||
"DB2001_EA".EA[#for_i].Aux_Estado := 8;
|
||||
END_IF;
|
||||
|
||||
// Señal forzada
|
||||
IF "DB2001_EA".EA[#for_i].Estado_AutoMan THEN
|
||||
"DB2001_EA".EA[#for_i].Aux_Estado := 2;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION TRAZABILIDAD
|
||||
|
||||
IF "DB2001_EA".EA[#for_i].Estado_AutoMan AND NOT "DB2001_EA".EA[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_11_DISP_EA",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_EA",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF NOT "DB2001_EA".EA[#for_i].Estado_AutoMan AND "DB2001_EA".EA[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_11_DISP_EA",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_EA",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_AUTO",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
// =============================================================================
|
||||
// Estado anterior manual/automatico
|
||||
"DB2001_EA".EA[#for_i].Aux_oldAutoMan := "DB2001_EA".EA[#for_i].Estado_AutoMan;
|
||||
|
||||
ELSE
|
||||
// =============================================================================
|
||||
// DISPOSITIVO NO HABILITADO
|
||||
// =============================================================================
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorTarjeta := 0;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado := 0; // Canal deshabilitado
|
||||
"DB2001_EA".EA[#for_i].Aux_Estado := 0; // Canal deshabilitado
|
||||
"DB2001_EA".EA[#for_i].Estado_ValorIngenieria := 0.0;
|
||||
"DB2001_EA".EA[#for_i].Alarmas_Max := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Alarmas_Min := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Alarmas_HiloRoto := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Alarmas_General := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Estado_AutoMan := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
REGION GESTION_HMI
|
||||
|
||||
// =============================================================================
|
||||
// GESTION BITS PARA VISUALIZACION
|
||||
// Bit 0 Habilitacion
|
||||
// Bit 1 ManualAutomatico
|
||||
// Bit 2 Reserva
|
||||
// Bit 3 Reserva
|
||||
// Bit 4 Reserva
|
||||
// Bit 5 Reserva
|
||||
// Bit 6 Reserva
|
||||
// Bit 7 Reserva
|
||||
// Bit 8 Alarma Hilo Roto
|
||||
// Bit 9 Alarma Alta
|
||||
// Bit 10 Alarma Baja
|
||||
// Bit 11 Alarma 3
|
||||
// Bit 12 Alarma 4
|
||||
// Bit 13 Alarma 5
|
||||
// Bit 14 Reserva
|
||||
// Bit 15 Reserva
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X0 := "DB2001_EA".EA[#for_i].Config_Habilitar;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X1 := "DB2001_EA".EA[#for_i].Estado_AutoMan;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X2 := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X3 := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X4 := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X5 := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X6 := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X7 := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X8 := "DB2001_EA".EA[#for_i].Alarmas_HiloRoto;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X9 := "DB2001_EA".EA[#for_i].Alarmas_Max;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X10 := "DB2001_EA".EA[#for_i].Alarmas_Min;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X11 := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X12 := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X13 := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X14 := FALSE;
|
||||
"DB2001_EA".EA[#for_i].Hmi_Estado.%X15 := FALSE;
|
||||
|
||||
END_REGION
|
||||
|
||||
REGION GESTION_NUEVA_ALARMA
|
||||
|
||||
// =============================================================================
|
||||
// DETECCION DE NUEVA ALARMA
|
||||
IF "DB2001_EA".EA[#for_i].Alarmas_General AND NOT "DB2001_EA".EA[#for_i].Aux_oldAlarma THEN
|
||||
"DB2001_EA".Agrup["DB2001_EA".EA[#for_i].Config_GrupoAlarma].NuevaAlarma := TRUE;
|
||||
END_IF;
|
||||
|
||||
// Estado anterior de las alarmas
|
||||
"DB2001_EA".EA[#for_i].Aux_oldAlarma := "DB2001_EA".EA[#for_i].Alarmas_General;
|
||||
|
||||
END_REGION
|
||||
|
||||
END_FOR;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ACUSE DE NUEVAS ALARMAS
|
||||
IF #Ack THEN
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2001_EA".Agrup[#for_i].NuevaAlarma := FALSE;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,411 @@
|
||||
FUNCTION "FC2005_ZC_SD" : Void
|
||||
TITLE = FC2005_SD
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Modelo de dispositivo salida digital
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool; // Pulso de 1 segundo
|
||||
Simulacion : Bool; // Simulacion
|
||||
Arranque : Bool; // Primer arranque
|
||||
Ack : Bool; // Acuse general
|
||||
SeguridadesOK : Bool; // Seguridades Ok
|
||||
UsuarioActual : String; // Usuario actual
|
||||
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
t_Activar : Bool;
|
||||
t_ActivarConRetardo : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
TIPO_ACCESO_INDIRECTO : SInt := 0;
|
||||
TIPO_ACCESO_PLC : SInt := 1;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Funcion para la gestion de dispositivo de tipo Salida Digital.
|
||||
|
||||
En ella se realizan las siguientes acciones:
|
||||
|
||||
- Se gestiona el multiplexado de los dispositivos para su uso en sistemas HMI/SCADA.
|
||||
- Se gestiona el estado del dispositivo
|
||||
- Se gestiona la orden de activacion y activacion retardada
|
||||
- Se gestiona la trazabilidad de las manualizaciones del dispositivo
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 26.04.2022 | (HCR) | Primera version. Cambio en la organizacion del UDT. Se organiza en estructuras en base al tipo de funcion que realizan los datos. |
|
||||
| 00.00.02 | 27.04.2022 | (ABH) | Se añaden auxiliares de estado anterior del modo manual y automatico para poder registrar las trazas. |
|
||||
| 00.00.03 | 08.11.2022 | (ABH) | Se añade trazabilidad manualizaciones |
|
||||
| 00.00.03 | 08.11.2022 | (HCR) | Se añade trazabilidad de activación manual |
|
||||
| 00.00.04 | 20.02.2024 | (ABH) | Se añade gestion multiplexado para Scada (no indexado) |
|
||||
| 00.00.05 | 08.01.2025 | (ABH) | Se añade entrada de primer arranque del PLC para resetear indices de multiplexado Se añade movimiento de ED[0] a multiplexado en caso de que el indice sea 0. |
|
||||
| 00.00.07 | 24.01.2025 | (ABH) | Se modifica la logica del multiplexado, la asignacion de oldindex se cambia de sitio ya que de vez en cuando (dependiendo de cuando el HMI realiza la comunicacion asincrona con el PLC) no detectaba el cambio y se machacaban valores. |
|
||||
| 00.00.08 | 26.03.2025 | (ABH) | Se añade variable grupo de alarma para separar los nuevos avisos por cuadro. |
|
||||
| 00.00.09 | 24.04.2025 | (HCR) | Se añade gestion de idioma |
|
||||
| 00.00.10 | 11.09.2025 | (ABH) | Se eliminan las constantes de idioma dentro del FC. Se utilizan constantes globales para facilitar su traduccion. |
|
||||
| 00.00.11 | 17.12.2025 | (ABH) | Se eliminan los idiomas. Se utiliza codigos para trazabilidad. Se elimina entrada "Idioma". Se elimina nombre de UDT. Se añade indexHMI para lista de texto en sistemas de supervision. |
|
||||
| 00.00.12 | 14.05.2026 | (ABH) | Se modifica UDT para añadir tipo de lectura. |
|
||||
| 01.00.00 | 18.05.2026 | (ABH) | Se añade variable `Config_TipoAcceso` para uso de direccionamiento indirecto o uso directo en PLC. |
|
||||
| 01.01.00 | 08.07.2026 | (ABH) | Se extrae el multiplexado a FC independiente. Se corrigen logicas de activacion y se añade variable "Estado_Salida". |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// Resetear todas las alarmas para que se vuelvan a generar
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2005_SD".Agrup[#for_i].AlgunaAlarma := FALSE;
|
||||
"DB2005_SD".Agrup[#for_i].AlgunaEnManual := FALSE;
|
||||
END_FOR;
|
||||
|
||||
// Numero maximo de dispositivos para limitar en HMI/Scada
|
||||
"DB2005_SD".Mux.NumDispositivos := "N_MAX_DISP_SD";
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_SD" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_SD";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO HABILITADO
|
||||
// =============================================================================
|
||||
IF "DB2005_SD".SD[#for_i].Config_Habilitar THEN
|
||||
|
||||
REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
IF "DB2005_SD".SD[#for_i].Config_GrupoAlarma < 0 THEN
|
||||
"DB2005_SD".SD[#for_i].Config_GrupoAlarma := 0;
|
||||
END_IF;
|
||||
IF "DB2005_SD".SD[#for_i].Config_GrupoAlarma > "N_MAX_DISP_AGRUP" THEN
|
||||
"DB2005_SD".SD[#for_i].Config_GrupoAlarma := "N_MAX_DISP_AGRUP";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
|
||||
REGION MODOS_DE_TRABAJO
|
||||
|
||||
// =============================================================================
|
||||
// MODO MANUAL
|
||||
IF "DB2005_SD".SD[#for_i].Estado_AutoMan THEN
|
||||
"DB2005_SD".Agrup["DB2005_SD".SD[#for_i].Config_GrupoAlarma].AlgunaEnManual := TRUE;
|
||||
IF "DB2005_SD".SD[#for_i].Orden_ActivarManual AND #SeguridadesOK AND "DB2005_SD".SD[#for_i].Estado_SeguridadOk THEN // En caso de enclavar válvula en manual AND NOT "DB2005_SD".SD[#for_i].Estado_Enclavado
|
||||
#t_Activar := TRUE;
|
||||
ELSE
|
||||
#t_Activar := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2005_SD".SD[#for_i].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MODO AUTO
|
||||
IF NOT "DB2005_SD".SD[#for_i].Estado_AutoMan THEN
|
||||
IF "DB2005_SD".SD[#for_i].Orden_ActivarAuto AND #SeguridadesOK AND "DB2005_SD".SD[#for_i].Estado_SeguridadOk AND NOT "DB2005_SD".SD[#for_i].Estado_Enclavado THEN
|
||||
#t_Activar := TRUE;
|
||||
ELSE
|
||||
#t_Activar := FALSE;
|
||||
END_IF;
|
||||
"DB2005_SD".SD[#for_i].Orden_ActivarManual := "DB2005_SD".SD[#for_i].Estado_Activado;
|
||||
END_IF;
|
||||
// Reset orden auto
|
||||
"DB2005_SD".SD[#for_i].Orden_ActivarAuto := FALSE;
|
||||
|
||||
END_REGION MODOS_DE_TRABAJO
|
||||
|
||||
|
||||
REGION ESTADO_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// SALIDA SIMULADA
|
||||
IF #Simulacion THEN
|
||||
|
||||
IF #t_Activar THEN
|
||||
"DB2005_SD".SD[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2005_SD".SD[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
|
||||
IF NOT "DB2005_SD".SD[#for_i].Estado_AutoMan AND NOT #Simulacion THEN
|
||||
|
||||
// =============================================================================
|
||||
// RETARDO A LA ACTIVACIÓN AUTOMÁTICO
|
||||
IF #t_Activar AND "DB2005_SD".SD[#for_i].Config_HabilitarRetardoAct THEN
|
||||
|
||||
IF #Pulso1seg AND "DB2005_SD".SD[#for_i].Tiempos_TiempoAct < "DB2005_SD".SD[#for_i].Tiempos_SetPointTiempoAct THEN
|
||||
"DB2005_SD".SD[#for_i].Tiempos_TiempoAct += 1;
|
||||
END_IF;
|
||||
|
||||
IF "DB2005_SD".SD[#for_i].Tiempos_TiempoAct >= "DB2005_SD".SD[#for_i].Tiempos_SetPointTiempoAct THEN
|
||||
#t_ActivarConRetardo := TRUE;
|
||||
ELSE
|
||||
#t_ActivarConRetardo := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSIF #t_Activar THEN
|
||||
#t_ActivarConRetardo := TRUE;
|
||||
ELSE
|
||||
"DB2005_SD".SD[#for_i].Tiempos_TiempoAct := 0;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// RETARDO A LA DESACTIVACIÓN AUTOMÁTICO
|
||||
IF NOT #t_Activar AND "DB2005_SD".SD[#for_i].Config_HabilitarRetardoDes THEN
|
||||
|
||||
IF #Pulso1seg AND "DB2005_SD".SD[#for_i].Tiempos_TiempoDes < "DB2005_SD".SD[#for_i].Tiempos_SetPointTiempoDes THEN
|
||||
"DB2005_SD".SD[#for_i].Tiempos_TiempoDes += 1;
|
||||
END_IF;
|
||||
|
||||
IF "DB2005_SD".SD[#for_i].Tiempos_TiempoDes >= "DB2005_SD".SD[#for_i].Tiempos_SetPointTiempoDes THEN
|
||||
#t_ActivarConRetardo := FALSE;
|
||||
ELSE
|
||||
#t_ActivarConRetardo := TRUE;
|
||||
END_IF;
|
||||
|
||||
ELSIF NOT #t_Activar THEN
|
||||
#t_ActivarConRetardo := FALSE;
|
||||
ELSE
|
||||
"DB2005_SD".SD[#for_i].Tiempos_TiempoDes := 0;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
#t_ActivarConRetardo := #t_Activar;
|
||||
|
||||
END_IF;
|
||||
|
||||
// Estado activado
|
||||
"DB2005_SD".SD[#for_i].Estado_Activado := #t_ActivarConRetardo;
|
||||
|
||||
END_REGION ESTADO_DEL_DISPOSITIVO
|
||||
|
||||
|
||||
REGION ESCRITURA_SALIDA
|
||||
|
||||
// =============================================================================
|
||||
// INVERSION DE LA SALIDA
|
||||
IF "DB2005_SD".SD[#for_i].Config_HabilitarInvertir THEN
|
||||
#t_ActivarConRetardo := NOT #t_ActivarConRetardo;
|
||||
END_IF;
|
||||
|
||||
|
||||
CASE "DB2005_SD".SD[#for_i].Config_TipoAcceso OF
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO:
|
||||
// =============================================================================
|
||||
// ESCRITURA VALORES DE LA TARJETA
|
||||
IF "DB2005_SD".SD[#for_i].Config_DireccionSalidaByte >= 0 THEN
|
||||
IF #t_ActivarConRetardo THEN
|
||||
|
||||
"DB2005_SD".SD[#for_i].Estado_Salida := TRUE;
|
||||
POKE_BOOL(area := 16#82,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2005_SD".SD[#for_i].Config_DireccionSalidaByte,
|
||||
bitOffset := "DB2005_SD".SD[#for_i].Config_DireccionSalidaBit,
|
||||
value := TRUE);
|
||||
ELSE
|
||||
"DB2005_SD".SD[#for_i].Estado_Salida := FALSE;
|
||||
POKE_BOOL(area := 16#82,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2005_SD".SD[#for_i].Config_DireccionSalidaByte,
|
||||
bitOffset := "DB2005_SD".SD[#for_i].Config_DireccionSalidaBit,
|
||||
value := FALSE);
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
#TIPO_ACCESO_PLC:
|
||||
IF #t_ActivarConRetardo THEN
|
||||
"DB2005_SD".SD[#for_i].Estado_Salida := TRUE;
|
||||
ELSE
|
||||
"DB2005_SD".SD[#for_i].Estado_Salida := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_CASE;
|
||||
|
||||
END_REGION ESCRITURA_SALIDA
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// RESET ORDEN ACTIVAR EN AUTO
|
||||
"DB2005_SD".SD[#for_i].Orden_ActivarAuto := FALSE;
|
||||
|
||||
|
||||
REGION TRAZABILIDAD_MANUALIZACION
|
||||
|
||||
IF "DB2005_SD".SD[#for_i].Estado_AutoMan AND NOT "DB2005_SD".SD[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_12_DISP_SD",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_SD",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF NOT "DB2005_SD".SD[#for_i].Estado_AutoMan AND "DB2005_SD".SD[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_12_DISP_SD",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_SD",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_AUTO",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2005_SD".SD[#for_i].Estado_AutoMan AND "DB2005_SD".SD[#for_i].Estado_Activado AND NOT "DB2005_SD".SD[#for_i].Aux_oldActivado THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_12_DISP_SD",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_SD",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_ON",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2005_SD".SD[#for_i].Estado_AutoMan AND NOT "DB2005_SD".SD[#for_i].Estado_Activado AND "DB2005_SD".SD[#for_i].Aux_oldActivado THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_12_DISP_SD",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_SD",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_OFF",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Estado anterior manual/automatico
|
||||
"DB2005_SD".SD[#for_i].Aux_oldAutoMan := "DB2005_SD".SD[#for_i].Estado_AutoMan;
|
||||
"DB2005_SD".SD[#for_i].Aux_oldActivado := "DB2005_SD".SD[#for_i].Estado_Activado;
|
||||
|
||||
ELSE
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO DESHABILITADO
|
||||
// =============================================================================
|
||||
"DB2005_SD".SD[#for_i].Estado_Activado := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Estado_AutoMan := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Estado_Enclavado := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Estado_Salida := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Tiempos_TiempoAct := 0;
|
||||
"DB2005_SD".SD[#for_i].Tiempos_TiempoDes := 0;
|
||||
"DB2005_SD".SD[#for_i].Orden_ActivarManual := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
|
||||
REGION GESTION_HMI
|
||||
|
||||
// =============================================================================
|
||||
// GESTION BITS PARA VISUALIZACION
|
||||
// Bit 0 Habilitacion
|
||||
// Bit 1 ManualAutomatico
|
||||
// Bit 2 Enclavado
|
||||
// Bit 3 Activado 1
|
||||
// Bit 4 Activado 2
|
||||
// Bit 5 Reserva
|
||||
// Bit 6 Reserva
|
||||
// Bit 7 Reserva
|
||||
// Bit 8 Alarma General
|
||||
// Bit 9 Alarma 1
|
||||
// Bit 10 Alarma 2
|
||||
// Bit 11 Alarma 3
|
||||
// Bit 12 Alarma 4
|
||||
// Bit 13 Alarma Mantenimiento
|
||||
// Bit 14 Reserva
|
||||
// Bit 15 Reserva
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X0 := "DB2005_SD".SD[#for_i].Config_Habilitar;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X1 := "DB2005_SD".SD[#for_i].Estado_AutoMan;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X2 := "DB2005_SD".SD[#for_i].Estado_Enclavado;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X3 := "DB2005_SD".SD[#for_i].Estado_Activado;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X4 := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X5 := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X6 := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X7 := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X8 := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X9 := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X10 := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X11 := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X12 := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X13 := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X14 := FALSE;
|
||||
"DB2005_SD".SD[#for_i].Hmi_Estado.%X15 := FALSE;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,477 @@
|
||||
FUNCTION "FC2006_ZC_SA" : Void
|
||||
TITLE = FC2006_SA
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Modelo de dispositivo salida analogica
|
||||
VAR_INPUT
|
||||
Ack : Bool; // Acuse general
|
||||
SeguridadesOK : Bool; // Seguridades Ok
|
||||
UsuarioActual : String; // Usuario actual
|
||||
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
t_X0 : Real;
|
||||
t_X1 : Real;
|
||||
t_Y0 : Real;
|
||||
t_Y1 : Real;
|
||||
X : Real;
|
||||
t_ValorSalida : Real;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
TIPO_ACCESO_INDIRECTO : SInt := 0;
|
||||
TIPO_ACCESO_PLC : SInt := 1;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Funcion para la gestion de dispositivo de tipo Salida Analogica.
|
||||
|
||||
En ella se realizan las siguientes acciones:
|
||||
|
||||
- Se gestiona el multiplexado de los dispositivos para su uso en sistemas HMI/SCADA.
|
||||
- Se gestiona el estado del dispositivo
|
||||
- Se gestiona la orden de escritura
|
||||
- Se gestiona la trazabilidad de las manualizaciones del dispositivo
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.00 | 15.10.2020 | (ABH) | Primera version. |
|
||||
| 00.00.01 | 06.05.2021 | (ABH) | Añadido bit de enclavamiento. Cuando Estado_Enclavado este a TRUE, la salida tiene el valor de Config_ConsignaEnclavado. |
|
||||
| 00.00.02 | 27.07.2021 | (ABH) | Se añade que si la direccion de salida es igual a 0, no realiza ningun calculo ni intenta escribir la salida para que no salten errores. Se añade variable aux para almacenar el mensaje de error, para que a la hora de generar las alarmas se generen adecuadamente. |
|
||||
| 00.00.03 | 26.04.2022 | (HCR) | Cambio en la organizacion del UDT. Se organiza en estructuras en base al tipo de funcion que realizan los datos. Se gestionan los BITs de visibilidad para Hmi. |
|
||||
| 00.00.04 | 27.04.2022 | (ABH) | Se añaden auxiliares de estado anterior del modo manual y automatico para poder registrar las trazas. |
|
||||
| 00.00.05 | 28.04.2022 | (HCR) | Se mantiene la salida al pasar a modo manual. |
|
||||
| 00.00.06 | 29.04.2022 | (HCR) | Cambio del estado de la señal por prioridades. Cambio de las condiciones de para error de configuración, poniendo parámetros de ingenería y de tarjeta. Cambio en Alarmas. |
|
||||
| 00.00.07 | 17.05.2022 | (BRM) | Cambio en escritura canal - Funcion POKE area: 16#82 para CPU 1200. |
|
||||
| 00.00.08 | 08.11.2022 | (ABH) | Se añade trazabilidad manualizaciones. |
|
||||
| 00.00.09 | 27.07.2023 | (ABH) | Se añade trazabilidad cambio parametros. |
|
||||
| 00.00.10 | 18.09.2023 | (ABH) | Se añade reset de valor SP auto al final de la gestion del dispositivo. |
|
||||
| 00.00.11 | 22.02.2024 | (ABH) | Se añade gestion multiplexado para Scada (no indexado) |
|
||||
| 00.00.12 | 08.01.2025 | (ABH) | Se añade entrada de primer arranque del PLC para resetear indices de multiplexado. Se añade movimiento de SA[0] a multiplexado en caso de que el indice sea 0. |
|
||||
| 00.00.12 | 24.01.2025 | (ABH) | Se modifica la logica del multiplexado, la asignacion de oldindex se cambia de sitio ya que de vez en cuando (dependiendo de cuando el HMI realiza la comunicacion asincrona con el PLC) no detectaba el cambio y se machacaban valores. |
|
||||
| 00.00.13 | 26.03.2025 | (ABH) | Se añade variable grupo de alarma para separar los nuevos avisos por cuadro. |
|
||||
| 00.00.14 | 24.04.2025 | (HCR) | Se añade gestion de idioma |
|
||||
| 00.00.15 | 11.09.2025 | (ABH) | Se eliminan las constantes de idioma dentro del FC. Se utilizan constantes globales para facilitar su traduccion. |
|
||||
| 00.00.16 | 17.12.2025 | (ABH) | Se eliminan los idiomas. Se utiliza codigos para trazabilidad. Se elimina entrada "Idioma". Se elimina nombre de UDT.Se elimina nombre de UDT. Se elimina nombre de UDT. Se añade indexHMI para lista de texto en sistemas de supervision. |
|
||||
| 01.00.00 | 18.05.2026 | (ABH) | Se añade variable `Config_TipoAcceso` para uso de direccionamiento indirecto o uso directo en PLC. |
|
||||
| 01.01.00 | 09.07.2026 | (ABH) | Se extrae el multiplexado a FC independiente. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// Resetear todas las alarmas para que se vuelvan a generar
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2006_SA".Agrup[#for_i].AlgunaAlarma := FALSE;
|
||||
"DB2006_SA".Agrup[#for_i].AlgunaEnManual := FALSE;
|
||||
END_FOR;
|
||||
|
||||
// Numero maximo de dispositivos para limitar en HMI/Scada
|
||||
"DB2006_SA".Mux.NumDispositivos := "N_MAX_DISP_SA";
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_SA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_SA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO HABILITADO
|
||||
// =============================================================================
|
||||
IF "DB2006_SA".SA[#for_i].Config_Habilitar THEN
|
||||
|
||||
REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
IF "DB2006_SA".SA[#for_i].Config_GrupoAlarma < 0 THEN
|
||||
"DB2006_SA".SA[#for_i].Config_GrupoAlarma := 0;
|
||||
END_IF;
|
||||
IF "DB2006_SA".SA[#for_i].Config_GrupoAlarma > "N_MAX_DISP_AGRUP" THEN
|
||||
"DB2006_SA".SA[#for_i].Config_GrupoAlarma := "N_MAX_DISP_AGRUP";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
|
||||
REGION MODOS_DE_TRABAJO
|
||||
|
||||
// =============================================================================
|
||||
// MODO MANUAL
|
||||
IF "DB2006_SA".SA[#for_i].Estado_AutoMan THEN
|
||||
"DB2006_SA".Agrup["DB2006_SA".SA[#for_i].Config_GrupoAlarma].AlgunaEnManual := TRUE;
|
||||
"DB2006_SA".SA[#for_i].Estado_ValorActual := "DB2006_SA".SA[#for_i].Orden_ConsignaManual;
|
||||
ELSE
|
||||
"DB2006_SA".SA[#for_i].Estado_ValorActual := "DB2006_SA".SA[#for_i].Orden_ConsignaAuto;
|
||||
"DB2006_SA".SA[#for_i].Orden_ConsignaManual := "DB2006_SA".SA[#for_i].Orden_ConsignaAuto;
|
||||
END_IF;
|
||||
|
||||
END_REGION MODOS_DE_TRABAJO
|
||||
|
||||
|
||||
REGION ERRORES
|
||||
|
||||
// =============================================================================
|
||||
// LIMITE INFERIOR
|
||||
IF "DB2006_SA".SA[#for_i].Estado_ValorActual <= "DB2006_SA".SA[#for_i].Config_EscaladoMinIngenieria THEN
|
||||
"DB2006_SA".SA[#for_i].Estado_ValorActual := "DB2006_SA".SA[#for_i].Config_EscaladoMinIngenieria;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// LIMITE SUPERIOR
|
||||
IF "DB2006_SA".SA[#for_i].Estado_ValorActual >= "DB2006_SA".SA[#for_i].Config_EscaladoMaxIngenieria THEN
|
||||
"DB2006_SA".SA[#for_i].Estado_ValorActual := "DB2006_SA".SA[#for_i].Config_EscaladoMaxIngenieria;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ERROR MÍNIMO
|
||||
IF "DB2006_SA".SA[#for_i].Config_HabilitarAlarmaMin AND
|
||||
"DB2006_SA".SA[#for_i].Estado_ValorActual < "DB2006_SA".SA[#for_i].Config_ErrorMinIngenieria THEN
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Min := TRUE;
|
||||
ELSE
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Min := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ERROR MÁXIMO
|
||||
IF "DB2006_SA".SA[#for_i].Config_HabilitarAlarmaMax AND
|
||||
"DB2006_SA".SA[#for_i].Estado_ValorActual > "DB2006_SA".SA[#for_i].Config_ErrorMaxIngenieria THEN
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Max := TRUE;
|
||||
ELSE
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Max := FALSE;
|
||||
END_IF;
|
||||
|
||||
|
||||
END_REGION ERRORES
|
||||
|
||||
|
||||
REGION SALIDA
|
||||
|
||||
IF NOT "DB2006_SA".SA[#for_i].Estado_Enclavado AND #SeguridadesOK AND "DB2006_SA".SA[#for_i].Estado_SeguridadOk THEN
|
||||
|
||||
// =============================================================================
|
||||
// CONVERSIÓN DE VALORES
|
||||
#t_Y0 := INT_TO_REAL("DB2006_SA".SA[#for_i].Config_EscaladoMinTarjeta);
|
||||
#t_Y1 := INT_TO_REAL("DB2006_SA".SA[#for_i].Config_EscaladoMaxTarjeta);
|
||||
#X := "DB2006_SA".SA[#for_i].Estado_ValorActual;
|
||||
#t_X0 := "DB2006_SA".SA[#for_i].Config_EscaladoMinIngenieria;
|
||||
#t_X1 := "DB2006_SA".SA[#for_i].Config_EscaladoMaxIngenieria;
|
||||
|
||||
// =============================================================================
|
||||
// ESCALADO Y = (X-x0)*((y1-y0)/(x1-x0)) + y0
|
||||
IF "DB2006_SA".SA[#for_i].Config_EscaladoMaxIngenieria > "DB2006_SA".SA[#for_i].Config_EscaladoMinIngenieria AND
|
||||
"DB2006_SA".SA[#for_i].Config_EscaladoMaxTarjeta > "DB2006_SA".SA[#for_i].Config_EscaladoMinTarjeta THEN
|
||||
|
||||
#t_ValorSalida := ((#X - #t_X0) * ((#t_Y1 - #t_Y0) / (#t_X1 - #t_X0))) + #t_Y0;
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Parametros := FALSE;
|
||||
#t_ValorSalida := #t_ValorSalida + "DB2006_SA".SA[#for_i].Config_EscaladoOffset;
|
||||
ELSE
|
||||
#t_ValorSalida := "DB2006_SA".SA[#for_i].Config_EscaladoMinIngenieria;
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Parametros := TRUE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// =============================================================================
|
||||
// AJUSTE LIMITES CONSIGNA ENCLAVADO
|
||||
IF "DB2006_SA".SA[#for_i].Orden_ConsignaEnclavado > "DB2006_SA".SA[#for_i].Config_EscaladoMaxIngenieria THEN
|
||||
"DB2006_SA".SA[#for_i].Orden_ConsignaEnclavado := "DB2006_SA".SA[#for_i].Config_EscaladoMaxIngenieria;
|
||||
END_IF;
|
||||
IF "DB2006_SA".SA[#for_i].Orden_ConsignaEnclavado < "DB2006_SA".SA[#for_i].Config_EscaladoMinIngenieria THEN
|
||||
"DB2006_SA".SA[#for_i].Orden_ConsignaEnclavado := "DB2006_SA".SA[#for_i].Config_EscaladoMinIngenieria;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ESCRITURA SALIDA ENCLAVADA
|
||||
|
||||
// =============================================================================
|
||||
// CONVERSIÓN DE VALORES
|
||||
#t_Y0 := INT_TO_REAL("DB2006_SA".SA[#for_i].Config_EscaladoMinTarjeta);
|
||||
#t_Y1 := INT_TO_REAL("DB2006_SA".SA[#for_i].Config_EscaladoMaxTarjeta);
|
||||
#X := "DB2006_SA".SA[#for_i].Orden_ConsignaEnclavado;
|
||||
#t_X0 := "DB2006_SA".SA[#for_i].Config_EscaladoMinIngenieria;
|
||||
#t_X1 := "DB2006_SA".SA[#for_i].Config_EscaladoMaxIngenieria;
|
||||
|
||||
// =============================================================================
|
||||
// ESCALADO Y = (X-x0)*((y1-y0)/(x1-x0)) + y0
|
||||
IF "DB2006_SA".SA[#for_i].Config_EscaladoMaxIngenieria > "DB2006_SA".SA[#for_i].Config_EscaladoMinIngenieria AND
|
||||
"DB2006_SA".SA[#for_i].Config_EscaladoMaxTarjeta > "DB2006_SA".SA[#for_i].Config_EscaladoMinTarjeta THEN
|
||||
|
||||
#t_ValorSalida := ((#X - #t_X0) * ((#t_Y1 - #t_Y0) / (#t_X1 - #t_X0))) + #t_Y0;
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Parametros := FALSE;
|
||||
ELSE
|
||||
#t_ValorSalida := "DB2006_SA".SA[#for_i].Config_EscaladoMinIngenieria;
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Parametros := TRUE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
REGION ESCRITURA_SALIDA
|
||||
|
||||
CASE "DB2006_SA".SA[#for_i].Config_TipoAcceso OF
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO:
|
||||
// =============================================================================
|
||||
// ESCRITURA DEL CANAL - POKE (area) 16#2 para CPU 1500 ; 16#82 para CPU 1200
|
||||
IF "DB2006_SA".SA[#for_i].Config_DireccionSalidaByte > 0 THEN
|
||||
|
||||
"DB2006_SA".SA[#for_i].Estado_ValorTarjeta := REAL_TO_INT(#t_ValorSalida);
|
||||
|
||||
POKE(area := 16#82,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2006_SA".SA[#for_i].Config_DireccionSalidaByte,
|
||||
value := INT_TO_WORD("DB2006_SA".SA[#for_i].Estado_ValorTarjeta));
|
||||
|
||||
"DB2006_SA".SA[#for_i].Estado_Escritura := GET_ERR_ID();
|
||||
IF "DB2006_SA".SA[#for_i].Estado_Escritura <> 0 THEN
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Escritura := TRUE;
|
||||
ELSE
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Escritura := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
"DB2006_SA".SA[#for_i].Estado_ValorTarjeta := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
#TIPO_ACCESO_PLC:
|
||||
// =============================================================================
|
||||
// ESCRITURA VALORES DE LA TARJETA
|
||||
"DB2006_SA".SA[#for_i].Estado_ValorTarjeta := REAL_TO_INT(#t_ValorSalida);
|
||||
|
||||
END_CASE;
|
||||
|
||||
END_REGION ESCRITURA_SALIDA
|
||||
|
||||
END_REGION SALIDA
|
||||
|
||||
|
||||
REGION ESTADO
|
||||
|
||||
// Señal normal
|
||||
"DB2006_SA".SA[#for_i].Aux_Estado := 1;
|
||||
|
||||
// Límites alcanzados
|
||||
IF "DB2006_SA".SA[#for_i].Estado_ValorActual < "DB2006_SA".SA[#for_i].Config_ErrorMinIngenieria AND
|
||||
"DB2006_SA".SA[#for_i].Config_HabilitarAlarmaMin THEN
|
||||
"DB2006_SA".SA[#for_i].Aux_Estado := 4;
|
||||
END_IF;
|
||||
|
||||
// Límites alcanzados
|
||||
IF "DB2006_SA".SA[#for_i].Estado_ValorActual >= "DB2006_SA".SA[#for_i].Config_ErrorMaxIngenieria AND
|
||||
"DB2006_SA".SA[#for_i].Config_HabilitarAlarmaMax THEN
|
||||
"DB2006_SA".SA[#for_i].Aux_Estado := 5;
|
||||
END_IF;
|
||||
|
||||
// Señal forzada
|
||||
IF "DB2006_SA".SA[#for_i].Estado_AutoMan THEN
|
||||
"DB2006_SA".SA[#for_i].Aux_Estado := 2;
|
||||
END_IF;
|
||||
|
||||
// Enclavado
|
||||
IF "DB2006_SA".SA[#for_i].Config_EscaladoMaxIngenieria > "DB2006_SA".SA[#for_i].Config_EscaladoMinIngenieria AND
|
||||
"DB2006_SA".SA[#for_i].Config_EscaladoMaxTarjeta > "DB2006_SA".SA[#for_i].Config_EscaladoMinTarjeta AND
|
||||
"DB2006_SA".SA[#for_i].Estado_Enclavado THEN
|
||||
"DB2006_SA".SA[#for_i].Aux_Estado := 9;
|
||||
END_IF;
|
||||
|
||||
// Error parametros
|
||||
IF "DB2006_SA".SA[#for_i].Config_EscaladoMaxIngenieria <= "DB2006_SA".SA[#for_i].Config_EscaladoMinIngenieria OR
|
||||
"DB2006_SA".SA[#for_i].Config_EscaladoMaxTarjeta <= "DB2006_SA".SA[#for_i].Config_EscaladoMinTarjeta THEN
|
||||
"DB2006_SA".SA[#for_i].Aux_Estado := 6;
|
||||
END_IF;
|
||||
|
||||
// Error de escritura
|
||||
IF "DB2006_SA".SA[#for_i].Estado_Escritura <> 0 THEN
|
||||
"DB2006_SA".SA[#for_i].Aux_Estado := 10;
|
||||
END_IF;
|
||||
|
||||
// SA no direccionada
|
||||
IF "DB2006_SA".SA[#for_i].Config_DireccionSalidaByte <= 0 THEN
|
||||
"DB2006_SA".SA[#for_i].Aux_Estado := 8;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
"DB2006_SA".SA[#for_i].Alarmas_General := FALSE;
|
||||
IF "DB2006_SA".SA[#for_i].Alarmas_Max OR
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Min OR
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Parametros OR
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Escritura
|
||||
THEN
|
||||
"DB2006_SA".Agrup["DB2006_SA".SA[#for_i].Config_GrupoAlarma].AlgunaAlarma := TRUE;
|
||||
"DB2006_SA".SA[#for_i].Alarmas_General := TRUE;
|
||||
END_IF;
|
||||
|
||||
|
||||
REGION TRAZABILIDAD
|
||||
|
||||
IF "DB2006_SA".SA[#for_i].Estado_AutoMan AND NOT "DB2006_SA".SA[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_13_DISP_SA",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_SA",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF NOT "DB2006_SA".SA[#for_i].Estado_AutoMan AND "DB2006_SA".SA[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_13_DISP_SA",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_SA",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_AUTO",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
// =============================================================================
|
||||
// Estado anterior manual/automatico
|
||||
"DB2006_SA".SA[#for_i].Aux_oldAutoMan := "DB2006_SA".SA[#for_i].Estado_AutoMan;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Reset de orden automatica
|
||||
"DB2006_SA".SA[#for_i].Orden_ConsignaAuto := 0.0;
|
||||
|
||||
ELSE
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO NO HABILITADO
|
||||
// =============================================================================
|
||||
"DB2006_SA".SA[#for_i].Estado_ValorTarjeta := 0;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado := 0; // Canal deshabilitado
|
||||
"DB2006_SA".SA[#for_i].Estado_ValorActual := 0.0;
|
||||
"DB2006_SA".SA[#for_i].Estado_ValorTarjeta := 0;
|
||||
"DB2006_SA".SA[#for_i].Orden_ConsignaAuto := 0.0;
|
||||
"DB2006_SA".SA[#for_i].Orden_ConsignaManual := 0.0;
|
||||
"DB2006_SA".SA[#for_i].Estado_AutoMan := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Alarmas_General := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Max := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Alarmas_Min := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
REGION GESTION_HMI
|
||||
|
||||
// =============================================================================
|
||||
// GESTION BITS PARA VISUALIZACION
|
||||
// Bit 0 Habilitacion
|
||||
// Bit 1 ManualAutomatico
|
||||
// Bit 2 Reserva
|
||||
// Bit 3 Reserva
|
||||
// Bit 4 Enclavado
|
||||
// Bit 5 Reserva
|
||||
// Bit 6 Reserva
|
||||
// Bit 7 Reserva
|
||||
// Bit 8 Alarma General
|
||||
// Bit 9 Alarma 1
|
||||
// Bit 10 Alarma 2
|
||||
// Bit 11 Alarma 3
|
||||
// Bit 12 Alarma 4
|
||||
// Bit 13 Alarma 5
|
||||
// Bit 14 Reserva
|
||||
// Bit 15 Reserva
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X0 := "DB2006_SA".SA[#for_i].Config_Habilitar;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X1 := "DB2006_SA".SA[#for_i].Estado_AutoMan;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X2 := "DB2006_SA".SA[#for_i].Estado_Enclavado;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X3 := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X4 := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X5 := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X6 := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X7 := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X8 := "DB2006_SA".SA[#for_i].Alarmas_General;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X9 := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X10 := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X11 := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X12 := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X13 := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X14 := FALSE;
|
||||
"DB2006_SA".SA[#for_i].Hmi_Estado.%X15 := FALSE;
|
||||
|
||||
END_REGION
|
||||
|
||||
REGION GESTION_NUEVA_ALARMA
|
||||
|
||||
// =============================================================================
|
||||
// DETECCION DE NUEVA ALARMA
|
||||
IF "DB2006_SA".SA[#for_i].Alarmas_General AND NOT "DB2006_SA".SA[#for_i].Aux_oldAlarma THEN
|
||||
"DB2006_SA".Agrup["DB2006_SA".SA[#for_i].Config_GrupoAlarma].NuevaAlarma := TRUE;
|
||||
END_IF;
|
||||
|
||||
// Estado anterior de las alarmas
|
||||
"DB2006_SA".SA[#for_i].Aux_oldAlarma := "DB2006_SA".SA[#for_i].Alarmas_General;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
END_FOR;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ACUSE DE NUEVAS ALARMAS
|
||||
IF #Ack THEN
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2006_SA".Agrup[#for_i].NuevaAlarma := FALSE;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,657 @@
|
||||
FUNCTION "FC2010_ZC_V" : Void
|
||||
TITLE = FC2010_V
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Modelo de dispositivo vlvula
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool; // Pulso de 1 segundo
|
||||
Simulacion : Bool; // Simulacion
|
||||
Arranque : Bool; // Primer arranque
|
||||
Ack : Bool; // Acuse general
|
||||
SeguridadesOK : Bool; // Seguridades OK
|
||||
UsuarioActual : String; // Usuario actual
|
||||
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
t_Activar : Bool;
|
||||
t_ErrorReposo : Bool;
|
||||
t_ErrorTrabajo : Bool;
|
||||
t_ErrorDoble : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
TIPO_ACCESO_INDIRECTO : SInt := 0;
|
||||
TIPO_ACCESO_PLC : SInt := 1;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Funcion para la gestion de dispositivo de tipo Valvula.
|
||||
|
||||
En ella se realizan las siguientes acciones:
|
||||
|
||||
- Se gestiona el multiplexado de los dispositivos para su uso en sistemas HMI/SCADA.
|
||||
- Se gestiona el estado del dispositivo
|
||||
- Se gestiona el numero de activaciones
|
||||
- Se gestiona la orden de escritura
|
||||
- Se gestiona la trazabilidad de las manualizaciones del dispositivo
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC8_ZC_TRAZA_REGISTRO` |
|
||||
| FB | - |
|
||||
| DB | `DB1_SYS`, `DB2010_V` |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 15.10.2020 | (ABH) | Primera version. |
|
||||
| 00.00.02 | 28.11.2020 | (ABH) | Añadidas alarmas mantenimiento |
|
||||
| 00.00.03 | 28.07.2021 | (ABH) | Añadidas alarmas en doble posicion / ninguna posicion |
|
||||
| 00.00.04 | 22.12.2021 | (ABH) | Añadido bit de visibilidad, a traves de variable CFG_Hmi_ |
|
||||
| 00.00.05 | 26.04.2022 | (HCR) | Cambio UDT |
|
||||
| 00.00.06 | 26.04.2022 | (HCR) | BITs de visibilidad para HMI, quitar enclavamiento para orden manual |
|
||||
| 00.00.07 | 27.04.2022 | (HCR) | Si no esta habilitado se quita orden manual y se quita el estado manual. Se agrega Ack para alarma de confirmación de marcha. Se mantiene el estado de válvula cuando se pasa a manual. Cambio en lógica de errores. Cambio en la escritura de la salida |
|
||||
| 00.00.08 | 08.11.2022 | (ABH) | Se añade trazabilidad manualizaciones |
|
||||
| 00.00.09 | 08.11.2022 | (HCR) | Se añade trazabilidad de activación manual |
|
||||
| 00.00.10 | 08.11.2022 | (HCR) | Cambio lógica enclavamiento |
|
||||
| 00.00.11 | 22.02.2024 | (ABH) | Se añade gestion multiplexado para Scada (no indexado) |
|
||||
| 00.00.12 | 08.01.2025 | (ABH) | Se añade entrada de primer arranque del PLC para resetear indices de multiplexado. Se añade movimiento de V[0] a multiplexado en caso de que el indice sea 0. |
|
||||
| 00.00.13 | 24.01.2025 | (ABH) | Se modifica la logica del multiplexado, la asignacion de oldindex se cambia de sitio ya que de vez en cuando (dependiendo de cuando el HMI realiza la comunicacion asincrona con el PLC) no detectaba el cambio y se machacaban valores. |
|
||||
| 00.00.14 | 26.03.2025 | (ABH) | Se añade variable grupo de alarma para separar los nuevos avisos por cuadro. |
|
||||
| 00.00.15 | 24.04.2025 | (HCR) | Se añade gestion de idioma |
|
||||
| 00.00.16 | 11.09.2025 | (ABH) | Se eliminan las constantes de idioma dentro del FC. Se utilizan constantes globales para facilitar su traduccion. |
|
||||
| 00.00.17 | 17.12.2025 | (ABH) | Se eliminan los idiomas. Se utiliza codigos para trazabilidad. Se elimina entrada "Idioma". Se elimina nombre de UDT. Se elimina nombre de UDT. Se añade indexHMI para lista de texto en sistemas de supervision. |
|
||||
| 01.00.00 | 18.05.2026 | (ABH) | Se añade variable `Config_TipoAcceso` para uso de direccionamiento indirecto o uso directo en PLC. |
|
||||
| 01.01.00 | 09.07.2026 | (ABH) | Se extrae el multiplexado a FC independiente. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// Resetear todas las alarmas para que se vuelvan a generar
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2010_V".Agrup[#for_i].AlgunaAlarma := FALSE;
|
||||
"DB2010_V".Agrup[#for_i].AlgunaEnManual := FALSE;
|
||||
END_FOR;
|
||||
|
||||
// Numero maximo de dispositivos para limitar en HMI/Scada
|
||||
"DB2010_V".Mux.NumDispositivos := "N_MAX_DISP_V";
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_V" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_V";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO HABILITADO
|
||||
// =============================================================================
|
||||
IF "DB2010_V".V[#for_i].Config_Habilitar THEN
|
||||
|
||||
REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
IF "DB2010_V".V[#for_i].Config_GrupoAlarma < 0 THEN
|
||||
"DB2010_V".V[#for_i].Config_GrupoAlarma := 0;
|
||||
END_IF;
|
||||
IF "DB2010_V".V[#for_i].Config_GrupoAlarma > "N_MAX_DISP_AGRUP" THEN
|
||||
"DB2010_V".V[#for_i].Config_GrupoAlarma := "N_MAX_DISP_AGRUP";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
// =============================================================================
|
||||
// PUESTA A CERO DE LA SALIDA
|
||||
#t_Activar := FALSE;
|
||||
|
||||
REGION LECTURA_VALORES
|
||||
|
||||
CASE "DB2010_V".V[#for_i].Config_TipoAcceso OF
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO:
|
||||
(* AREA: Pueden seleccionarse las siguientes áreas: 16#81: Input, 16#82: Output, 16#83: Marcas, 16#84: DB, 16#1: Entrada de periferia (solo S7-1500)
|
||||
DBNUMBER: Número del bloque de datos si AREA = DB, de lo contrario "0"
|
||||
BYTEOFFSET: Dirección en la que se lee. Solo se utilizan los 16 bits menos significativos.*)
|
||||
|
||||
// =============================================================================
|
||||
// RETORNO REPOSO
|
||||
IF "DB2010_V".V[#for_i].Config_DireccionRetReposoByte >= 0 THEN
|
||||
|
||||
"DB2010_V".V[#for_i].Estado_EntradaRetornoReposo := PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2010_V".V[#for_i].Config_DireccionRetReposoByte,
|
||||
bitOffset := "DB2010_V".V[#for_i].Config_DireccionRetReposoBit);
|
||||
|
||||
IF "DB2010_V".V[#for_i].Config_HabilitarInvertirReposo THEN
|
||||
"DB2010_V".V[#for_i].Estado_EntradaRetornoReposo := NOT (PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2010_V".V[#for_i].Config_DireccionRetReposoByte,
|
||||
bitOffset := "DB2010_V".V[#for_i].Config_DireccionRetReposoBit));
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// RETORNO TRABAJO
|
||||
IF "DB2010_V".V[#for_i].Config_DireccionRetTrabajoByte >= 0 THEN
|
||||
"DB2010_V".V[#for_i].Estado_EntradaRetornoTrabajo := PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2010_V".V[#for_i].Config_DireccionRetTrabajoByte,
|
||||
bitOffset := "DB2010_V".V[#for_i].Config_DireccionRetTrabajoBit);
|
||||
IF "DB2010_V".V[#for_i].Config_HabilitarInvertirTrabajo THEN
|
||||
"DB2010_V".V[#for_i].Estado_EntradaRetornoTrabajo := NOT (PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2010_V".V[#for_i].Config_DireccionRetTrabajoByte,
|
||||
bitOffset := "DB2010_V".V[#for_i].Config_DireccionRetTrabajoBit));
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
|
||||
#TIPO_ACCESO_PLC:
|
||||
;
|
||||
|
||||
END_CASE;
|
||||
|
||||
END_REGION LECTURA_VALORES
|
||||
|
||||
|
||||
REGION MODOS_DE_TRABAJO
|
||||
|
||||
// =============================================================================
|
||||
// MODO MANUAL
|
||||
IF "DB2010_V".V[#for_i].Estado_AutoMan THEN
|
||||
"DB2010_V".Agrup["DB2010_V".V[#for_i].Config_GrupoAlarma].AlgunaEnManual := TRUE;
|
||||
IF "DB2010_V".V[#for_i].Orden_ActivarManual AND #SeguridadesOK AND "DB2010_V".V[#for_i].Estado_SeguridadOk THEN // En caso de enclavar válvula en manual AND NOT "DB2035_TMF1_DISP_V".V[#i].Estado_Enclavado
|
||||
#t_Activar := TRUE;
|
||||
ELSE
|
||||
#t_Activar := FALSE;
|
||||
"DB2010_V".V[#for_i].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2010_V".V[#for_i].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MODO AUTO
|
||||
IF NOT "DB2010_V".V[#for_i].Estado_AutoMan THEN
|
||||
IF "DB2010_V".V[#for_i].Orden_ActivarAuto AND NOT "DB2010_V".V[#for_i].Estado_Enclavado AND #SeguridadesOK AND "DB2010_V".V[#for_i].Estado_SeguridadOk THEN
|
||||
#t_Activar := TRUE;
|
||||
ELSE
|
||||
#t_Activar := FALSE;
|
||||
END_IF;
|
||||
"DB2010_V".V[#for_i].Orden_ActivarManual := "DB2010_V".V[#for_i].Estado_Activado;
|
||||
END_IF;
|
||||
|
||||
END_REGION MODOS_DE_TRABAJO
|
||||
|
||||
|
||||
REGION ESTADO_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// VÁLVULA SIMULADA
|
||||
IF #Simulacion THEN
|
||||
|
||||
IF #t_Activar THEN
|
||||
"DB2010_V".V[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2010_V".V[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// VÁLVULA 2 RETORNOS (REPOSO + TRABAJO)
|
||||
IF NOT #Simulacion AND
|
||||
"DB2010_V".V[#for_i].Config_HabilitarRetornoReposo AND "DB2010_V".V[#for_i].Config_HabilitarRetornoTrabajo
|
||||
THEN
|
||||
|
||||
IF "DB2010_V".V[#for_i].Estado_EntradaRetornoTrabajo AND NOT "DB2010_V".V[#for_i].Estado_EntradaRetornoReposo AND #t_Activar THEN
|
||||
"DB2010_V".V[#for_i].Estado_Activado := TRUE;
|
||||
END_IF;
|
||||
|
||||
IF "DB2010_V".V[#for_i].Estado_EntradaRetornoReposo AND NOT "DB2010_V".V[#for_i].Estado_EntradaRetornoTrabajo AND NOT #t_Activar THEN
|
||||
"DB2010_V".V[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// VÁLVULA SOLO RETORNO REPOSO
|
||||
IF NOT #Simulacion AND
|
||||
"DB2010_V".V[#for_i].Config_HabilitarRetornoReposo AND NOT "DB2010_V".V[#for_i].Config_HabilitarRetornoTrabajo
|
||||
THEN
|
||||
|
||||
IF NOT "DB2010_V".V[#for_i].Estado_EntradaRetornoReposo THEN
|
||||
"DB2010_V".V[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2010_V".V[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// VÁLVULA SOLO RETORNO TRABAJO
|
||||
IF NOT #Simulacion AND
|
||||
NOT "DB2010_V".V[#for_i].Config_HabilitarRetornoReposo AND "DB2010_V".V[#for_i].Config_HabilitarRetornoTrabajo
|
||||
THEN
|
||||
|
||||
IF "DB2010_V".V[#for_i].Estado_EntradaRetornoTrabajo THEN
|
||||
"DB2010_V".V[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2010_V".V[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// VÁLVULA SIN RETORNOS
|
||||
IF NOT #Simulacion AND
|
||||
NOT "DB2010_V".V[#for_i].Config_HabilitarRetornoReposo AND NOT "DB2010_V".V[#for_i].Config_HabilitarRetornoTrabajo
|
||||
THEN
|
||||
|
||||
IF #t_Activar THEN
|
||||
"DB2010_V".V[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2010_V".V[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION ESTADO_DEL_DISPOSITIVO
|
||||
|
||||
|
||||
REGION ERRORES
|
||||
|
||||
// =============================================================================
|
||||
// CHEQUEO RETORNO REPOSO
|
||||
IF NOT #Simulacion AND
|
||||
"DB2010_V".V[#for_i].Config_HabilitarRetornoReposo AND
|
||||
(
|
||||
(#t_Activar AND "DB2010_V".V[#for_i].Estado_EntradaRetornoReposo)
|
||||
OR
|
||||
(NOT #t_Activar AND NOT "DB2010_V".V[#for_i].Estado_EntradaRetornoReposo)
|
||||
)
|
||||
THEN
|
||||
#t_ErrorReposo := TRUE;
|
||||
ELSE
|
||||
#t_ErrorReposo := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// CHEQUEO RETORNO TRABAJO
|
||||
IF NOT #Simulacion AND
|
||||
"DB2010_V".V[#for_i].Config_HabilitarRetornoTrabajo AND
|
||||
(
|
||||
(#t_Activar AND NOT "DB2010_V".V[#for_i].Estado_EntradaRetornoTrabajo)
|
||||
OR
|
||||
(NOT #t_Activar AND "DB2010_V".V[#for_i].Estado_EntradaRetornoTrabajo)
|
||||
)
|
||||
THEN
|
||||
#t_ErrorTrabajo := TRUE;
|
||||
ELSE
|
||||
#t_ErrorTrabajo := FALSE;
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// CHEQUEO DOBLE RETORNO EN DOS POSICIONES O EN NINGUNA POSICION
|
||||
IF NOT #Simulacion AND
|
||||
("DB2010_V".V[#for_i].Config_HabilitarRetornoReposo AND "DB2010_V".V[#for_i].Config_HabilitarRetornoTrabajo)
|
||||
AND
|
||||
(
|
||||
(NOT "DB2010_V".V[#for_i].Estado_EntradaRetornoReposo AND NOT "DB2010_V".V[#for_i].Estado_EntradaRetornoTrabajo)
|
||||
OR
|
||||
("DB2010_V".V[#for_i].Estado_EntradaRetornoReposo AND "DB2010_V".V[#for_i].Estado_EntradaRetornoTrabajo)
|
||||
)
|
||||
THEN
|
||||
#t_ErrorDoble := TRUE;
|
||||
ELSE
|
||||
#t_ErrorDoble := FALSE;
|
||||
END_IF;
|
||||
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// TEMPORIZADO DE ERRORES
|
||||
IF (
|
||||
("DB2010_V".V[#for_i].Config_HabilitarRetornoReposo AND #t_ErrorReposo AND NOT "DB2010_V".V[#for_i].Alarmas_Reposo)
|
||||
OR
|
||||
("DB2010_V".V[#for_i].Config_HabilitarRetornoTrabajo AND #t_ErrorTrabajo AND NOT "DB2010_V".V[#for_i].Alarmas_Trabajo)
|
||||
OR
|
||||
("DB2010_V".V[#for_i].Config_HabilitarRetornoReposo AND "DB2010_V".V[#for_i].Config_HabilitarRetornoTrabajo AND #t_ErrorDoble AND NOT "DB2010_V".V[#for_i].Alarmas_Doble)
|
||||
)
|
||||
THEN
|
||||
IF #Pulso1seg AND NOT #Simulacion THEN
|
||||
"DB2010_V".V[#for_i].Tiempos_Alarma += 1;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2010_V".V[#for_i].Tiempos_Alarma := 0;
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ERROR REPOSO
|
||||
IF "DB2010_V".V[#for_i].Tiempos_Alarma >= "DB2010_V".V[#for_i].Tiempos_SetPointTiempoAlarma AND #t_ErrorReposo THEN
|
||||
"DB2010_V".V[#for_i].Alarmas_Reposo := TRUE;
|
||||
END_IF;
|
||||
IF NOT #t_ErrorReposo THEN
|
||||
"DB2010_V".V[#for_i].Alarmas_Reposo := FALSE;
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ERROR TRABAJO
|
||||
IF "DB2010_V".V[#for_i].Tiempos_Alarma >= "DB2010_V".V[#for_i].Tiempos_SetPointTiempoAlarma AND #t_ErrorTrabajo THEN
|
||||
"DB2010_V".V[#for_i].Alarmas_Trabajo := TRUE;
|
||||
END_IF;
|
||||
IF NOT #t_ErrorTrabajo THEN
|
||||
"DB2010_V".V[#for_i].Alarmas_Trabajo := FALSE;
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ERROR DOBLE
|
||||
IF "DB2010_V".V[#for_i].Tiempos_Alarma >= "DB2010_V".V[#for_i].Tiempos_SetPointTiempoAlarma AND #t_ErrorDoble THEN
|
||||
"DB2010_V".V[#for_i].Alarmas_Doble := TRUE;
|
||||
END_IF;
|
||||
IF NOT #t_ErrorDoble THEN
|
||||
"DB2010_V".V[#for_i].Alarmas_Doble := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ERROR GLOBAL
|
||||
IF "DB2010_V".V[#for_i].Alarmas_Reposo OR
|
||||
"DB2010_V".V[#for_i].Alarmas_Trabajo OR
|
||||
"DB2010_V".V[#for_i].Alarmas_Doble
|
||||
THEN
|
||||
"DB2010_V".V[#for_i].Alarmas_General := TRUE;
|
||||
END_IF;
|
||||
IF #Ack AND
|
||||
NOT "DB2010_V".V[#for_i].Alarmas_Reposo AND
|
||||
NOT "DB2010_V".V[#for_i].Alarmas_Trabajo AND
|
||||
NOT "DB2010_V".V[#for_i].Alarmas_Doble
|
||||
THEN
|
||||
"DB2010_V".V[#for_i].Alarmas_General := FALSE;
|
||||
END_IF;
|
||||
|
||||
//"DB2010_V".V[#for_i].Alarmas_General := "DB2010_V".V[#for_i].Alarmas_Reposo OR "DB2010_V".V[#for_i].Alarmas_Trabajo OR "DB2010_V".V[#for_i].Alarmas_Doble;
|
||||
|
||||
IF "DB2010_V".V[#for_i].Alarmas_General THEN
|
||||
"DB2010_V".Agrup["DB2010_V".V[#for_i].Config_GrupoAlarma].AlgunaAlarma := TRUE;
|
||||
END_IF;
|
||||
|
||||
END_REGION ERRORES
|
||||
|
||||
|
||||
REGION DIAGNOSIS
|
||||
|
||||
// =============================================================================
|
||||
// CONTADOR DE CICLOS DE ACTIVACIÓN DE LA VÁLVULA
|
||||
IF ("DB2010_V".V[#for_i].Estado_Activado AND NOT "DB2010_V".V[#for_i].Aux_oldActivado)
|
||||
OR
|
||||
(NOT "DB2010_V".V[#for_i].Estado_Activado AND "DB2010_V".V[#for_i].Aux_oldActivado)
|
||||
THEN
|
||||
"DB2010_V".V[#for_i].Tiempos_Ciclos += 1;
|
||||
END_IF;
|
||||
|
||||
IF "DB2010_V".V[#for_i].Orden_ResetCiclos THEN
|
||||
"DB2010_V".V[#for_i].Tiempos_Ciclos := 0;
|
||||
"DB2010_V".V[#for_i].Orden_ResetCiclos := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ALARMA CICLOS PARA MANTENIMIENTO ALCANZADOS
|
||||
"DB2010_V".V[#for_i].Alarmas_Mantenimiento := FALSE;
|
||||
IF "DB2010_V".V[#for_i].Config_HabilitarMantenimiento AND ("DB2010_V".V[#for_i].Tiempos_Ciclos > "DB2010_V".V[#for_i].Tiempos_SetPointCiclos) THEN
|
||||
"DB2010_V".V[#for_i].Alarmas_Mantenimiento := TRUE;
|
||||
END_IF;
|
||||
|
||||
|
||||
|
||||
END_REGION DIAGNOSIS
|
||||
|
||||
|
||||
REGION ESCRITURA_SALIDA
|
||||
|
||||
CASE "DB2010_V".V[#for_i].Config_TipoAcceso OF
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO:
|
||||
// =============================================================================
|
||||
// ESCRITURA SALIDA
|
||||
(* AREA: Pueden seleccionarse las siguientes áreas:16#81: Input, 16#82: Output, 16#83: Marcas, 16#84: DB, 16#2: Salida de periferia (solo S7-1500)
|
||||
DBNUMBER: Número del bloque de datos si AREA = DB, de lo contrario "0"
|
||||
BYTEOFFSET: Dirección que se escribe, Solo se utilizan los 16 bits menos significativos.
|
||||
BITOFFSET: Bit que se escribe,
|
||||
VALUE: Valor que se escribe *)
|
||||
|
||||
IF "DB2010_V".V[#for_i].Config_DireccionSalidaByte >= 0 THEN
|
||||
|
||||
IF #t_Activar AND NOT "DB2010_V".V[#for_i].Alarmas_General THEN
|
||||
|
||||
"DB2010_V".V[#for_i].Estado_Salida := TRUE;
|
||||
POKE_BOOL(area := 16#82,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2010_V".V[#for_i].Config_DireccionSalidaByte,
|
||||
bitOffset := "DB2010_V".V[#for_i].Config_DireccionSalidaBit,
|
||||
value := TRUE);
|
||||
ELSE
|
||||
|
||||
"DB2010_V".V[#for_i].Estado_Salida := FALSE;
|
||||
POKE_BOOL(area := 16#82,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2010_V".V[#for_i].Config_DireccionSalidaByte,
|
||||
bitOffset := "DB2010_V".V[#for_i].Config_DireccionSalidaBit,
|
||||
value := FALSE);
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
#TIPO_ACCESO_PLC:
|
||||
IF #t_Activar AND NOT "DB2010_V".V[#for_i].Alarmas_General THEN
|
||||
"DB2010_V".V[#for_i].Estado_Salida := TRUE;
|
||||
ELSE
|
||||
"DB2010_V".V[#for_i].Estado_Salida := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_CASE;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// RESET ORDEN ACTIVAR EN AUTO
|
||||
"DB2010_V".V[#for_i].Orden_ActivarAuto := FALSE;
|
||||
"DB2010_V".V[#for_i].Estado_Enclavado := FALSE;
|
||||
|
||||
|
||||
REGION TRAZABILIDAD_MANUALIZACION
|
||||
|
||||
IF "DB2010_V".V[#for_i].Estado_AutoMan AND NOT "DB2010_V".V[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_14_DISP_V",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_V",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF NOT "DB2010_V".V[#for_i].Estado_AutoMan AND "DB2010_V".V[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_14_DISP_V",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_V",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_AUTO",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2010_V".V[#for_i].Estado_AutoMan AND "DB2010_V".V[#for_i].Estado_Activado AND NOT "DB2010_V".V[#for_i].Aux_oldActivado THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_14_DISP_V",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_V",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_ON",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2010_V".V[#for_i].Estado_AutoMan AND NOT "DB2010_V".V[#for_i].Estado_Activado AND "DB2010_V".V[#for_i].Aux_oldActivado THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_14_DISP_V",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_V",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_OFF",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
END_REGION TRAZABILIDAD_MANUALIZACION
|
||||
|
||||
// =============================================================================
|
||||
// Estado anterior manual/automatico
|
||||
"DB2010_V".V[#for_i].Aux_oldActivado := "DB2010_V".V[#for_i].Estado_Activado;
|
||||
"DB2010_V".V[#for_i].Aux_oldAutoMan := "DB2010_V".V[#for_i].Estado_AutoMan;
|
||||
|
||||
ELSE
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO NO HABILITADO
|
||||
// =============================================================================
|
||||
"DB2010_V".V[#for_i].Alarmas_General := FALSE;
|
||||
"DB2010_V".V[#for_i].Alarmas_Reposo := FALSE;
|
||||
"DB2010_V".V[#for_i].Alarmas_Trabajo := FALSE;
|
||||
"DB2010_V".V[#for_i].Alarmas_Doble := FALSE;
|
||||
"DB2010_V".V[#for_i].Alarmas_Mantenimiento := FALSE;
|
||||
"DB2010_V".V[#for_i].Estado_EntradaRetornoTrabajo := FALSE;
|
||||
"DB2010_V".V[#for_i].Estado_EntradaRetornoReposo := FALSE;
|
||||
"DB2010_V".V[#for_i].Estado_Enclavado := FALSE;
|
||||
"DB2010_V".V[#for_i].Estado_Salida := FALSE;
|
||||
"DB2010_V".V[#for_i].Orden_ActivarAuto := FALSE;
|
||||
"DB2010_V".V[#for_i].Estado_Activado := FALSE;
|
||||
"DB2010_V".V[#for_i].Tiempos_Alarma := 0;
|
||||
"DB2010_V".V[#for_i].Orden_ActivarManual := FALSE;
|
||||
"DB2010_V".V[#for_i].Estado_AutoMan := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
|
||||
REGION GESTION_HMI
|
||||
|
||||
// =============================================================================
|
||||
// GESTION BITS PARA VISUALIZACION
|
||||
// Bit 0 Habilitacion
|
||||
// Bit 1 ManualAutomatico
|
||||
// Bit 2 Enclavado
|
||||
// Bit 3 Activado 1
|
||||
// Bit 4 Activado 2
|
||||
// Bit 5 Reserva
|
||||
// Bit 6 Reserva
|
||||
// Bit 7 Reserva
|
||||
// Bit 8 Alarma General
|
||||
// Bit 9 Alarma 1
|
||||
// Bit 10 Alarma 2
|
||||
// Bit 11 Alarma 3
|
||||
// Bit 12 Alarma 4
|
||||
// Bit 13 Alarma Mantenimiento
|
||||
// Bit 14 Reserva
|
||||
// Bit 15 Reserva
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X0 := "DB2010_V".V[#for_i].Config_Habilitar;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X1 := "DB2010_V".V[#for_i].Estado_AutoMan;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X2 := "DB2010_V".V[#for_i].Estado_Enclavado;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X3 := "DB2010_V".V[#for_i].Estado_Activado;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X4 := FALSE;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X5 := FALSE;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X6 := FALSE;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X7 := FALSE;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X8 := "DB2010_V".V[#for_i].Alarmas_General;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X9 := FALSE;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X10 := FALSE;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X11 := FALSE;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X12 := FALSE;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X13 := "DB2010_V".V[#for_i].Alarmas_Mantenimiento;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X14 := FALSE;
|
||||
"DB2010_V".V[#for_i].Hmi_Estado.%X15 := FALSE;
|
||||
|
||||
END_REGION GESTION_HMI
|
||||
|
||||
REGION GESTION_NUEVA_ALARMA
|
||||
|
||||
// =============================================================================
|
||||
// DETECCION DE NUEVA ALARMA
|
||||
IF "DB2010_V".V[#for_i].Alarmas_General AND NOT "DB2010_V".V[#for_i].Aux_oldAlarma THEN
|
||||
"DB2010_V".Agrup["DB2010_V".V[#for_i].Config_GrupoAlarma].NuevaAlarma := TRUE;
|
||||
END_IF;
|
||||
|
||||
// Estado anterior de las alarmas
|
||||
"DB2010_V".V[#for_i].Aux_oldAlarma := "DB2010_V".V[#for_i].Alarmas_General;
|
||||
|
||||
END_REGION GESTION_NUEVA_ALARMA
|
||||
|
||||
|
||||
END_FOR;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ACUSE DE NUEVAS ALARMAS
|
||||
IF #Ack THEN
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2010_V".Agrup[#for_i].NuevaAlarma := FALSE;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
END_REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,594 @@
|
||||
FUNCTION "FC2015_ZC_M" : Void
|
||||
TITLE = FC2015_M
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Modelo de dispositivo motor
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool; // Pulso de 1 segundo
|
||||
Simulacion : Bool; // Simulacion
|
||||
Ack : Bool; // Acuse general
|
||||
SeguridadesOK : Bool; // Seguridades OK
|
||||
UsuarioActual : String; // Usuario actual
|
||||
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
t_Activar : Bool;
|
||||
t_ErrorTermico : Bool;
|
||||
t_ErrorConfMarcha : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
TIPO_ACCESO_INDIRECTO : SInt := 0;
|
||||
TIPO_ACCESO_PLC : SInt := 1;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Funcion para la gestion de dispositivo de tipo Motor arranque directo.
|
||||
|
||||
En ella se realizan las siguientes acciones:
|
||||
|
||||
- Se gestiona el multiplexado de los dispositivos para su uso en sistemas HMI/SCADA.
|
||||
- Se gestiona el estado del dispositivo
|
||||
- Se gestiona el tiempo en marcha
|
||||
- Se gestiona la orden de escritura
|
||||
- Se gestiona la trazabilidad de las manualizaciones del dispositivo
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC8_ZC_TRAZA_REGISTRO`, `FC15025_ZC_CONTADOR_TIEMPO` |
|
||||
| FB | - |
|
||||
| DB | `DB2015_DISP_M` |
|
||||
| UDT | `ZC_DISP_M`, `ZC_DISP_MUX_M`, `ZC_CONTADOR_TIEMPO` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 15.10.2020 | (ABH) | Primera version.
|
||||
| 00.00.02 | 28.11.2020 | (ABH) | Añadidas alarmas mantenimiento
|
||||
| 00.00.03 | 26.10.2021 | (ABH) | Se integra la gestion de directo/inverso
|
||||
| 00.00.04 | 26.04.2022 | (HCR) | Cambio en la organizacion del UDT. Se organiza en estructuras en base al tipo de funcion que realizan los datos. Se quita el enclavamiento para orden manual.
|
||||
| 00.00.05 | 27.04.2022 | (ABH) | Se añaden auxiliares de estado anterior del modo manual y automatico para poder registrar las trazas.
|
||||
| 00.00.06 | 27.04.2022 | (HCR) | Si no esta habilitado se quita orden manual y se quita el estado manual. Se agrega Ack para alarmas de confirmación de marcha. Se mantiene el estado cuando se pasa a manual. Cambio en lógica de errores. Cambio en la escritura de la salida. Cambio en laógica de modos
|
||||
| 00.00.07 | 08.11.2022 | (ABH) | Se añade trazabilidad manualizaciones
|
||||
| 00.00.08 | 08.11.2022 | (HCR) | Se añade trazabilidad de activación manual
|
||||
| 00.00.09 | 08.11.2022 | (HCR) | Cambio lógica enclavamiento
|
||||
| 00.00.10 | 18.09.2023 | (ABH) | Cambio en tipo de dato de horas de alarma. Se utiliza el tipo de dato ZC_CONTADOR_TIEMPO y el FC15025_ZC_CONTADOR_TIEMPO
|
||||
| 00.00.11 | 22.02.2024 | (ABH) | Se añade gestion multiplexado para Scada (no indexado)
|
||||
| 00.00.12 | 08.01.2025 | (ABH) | Se añade entrada de primer arranque del PLC para resetear indices de multiplexado Se añade movimiento de M[0] a multiplexado en caso de que el indice sea 0.
|
||||
| 00.00.13 | 24.01.2025 | (ABH) | Se modifica la logica del multiplexado, la asignacion de oldindex se cambia de sitio ya que de vez en cuando (dependiendo de cuando el HMI realiza la comunicacion asincrona con el PLC) no detectaba el cambio y se machacaban valores.
|
||||
| 00.00.14 | 26.03.2025 | (ABH) | Se añade variable grupo de alarma para separar los nuevos avisos por cuadro.
|
||||
| 00.00.15 | 24.04.2025 | (HCR) | Se añade gestion de idioma
|
||||
| 00.00.16 | 11.09.2025 | (ABH) | Se eliminan las constantes de idioma dentro del FC. Se utilizan constantes globales para facilitar su traduccion.
|
||||
| 00.00.17 | 17.12.2025 | (ABH) | Se eliminan los idiomas. Se utiliza codigos para trazabilidad. Se elimina entrada "Idioma". Se elimina nombre de UDT. Se elimina nombre de UDT. Se añade indexHMI para lista de texto en sistemas de supervision.
|
||||
| 01.00.00 | 18.05.2026 | (ABH) | Se añade variable `Config_TipoAcceso` para uso de direccionamiento indirecto o uso directo en PLC. |
|
||||
| 01.01.00 | 08.07.2026 | (ABH) | Se extrae el multiplexado a FC independiente. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// Resetear todas las alarmas para que se vuelvan a generar
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2015_M".Agrup[#for_i].AlgunaAlarma := FALSE;
|
||||
"DB2015_M".Agrup[#for_i].AlgunaEnManual := FALSE;
|
||||
END_FOR;
|
||||
|
||||
// Numero maximo de dispositivos para limitar en HMI/Scada
|
||||
"DB2015_M".Mux.NumDispositivos := "N_MAX_DISP_M";
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_M" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_M";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO HABILITADO
|
||||
// =============================================================================
|
||||
IF "DB2015_M".M[#for_i].Config_Habilitar THEN
|
||||
|
||||
REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
IF "DB2015_M".M[#for_i].Config_GrupoAlarma < 0 THEN
|
||||
"DB2015_M".M[#for_i].Config_GrupoAlarma := 0;
|
||||
END_IF;
|
||||
IF "DB2015_M".M[#for_i].Config_GrupoAlarma > "N_MAX_DISP_AGRUP" THEN
|
||||
"DB2015_M".M[#for_i].Config_GrupoAlarma := "N_MAX_DISP_AGRUP";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
// =============================================================================
|
||||
// PUESTA A CERO DE LA SALIDA
|
||||
#t_Activar := FALSE;
|
||||
|
||||
REGION LECTURA_VALORES
|
||||
|
||||
CASE "DB2015_M".M[#for_i].Config_TipoAcceso OF
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO:
|
||||
(* AREA: Pueden seleccionarse las siguientes áreas: 16#81: Input, 16#82: Output, 16#83: Marcas, 16#84: DB, 16#1: Entrada de periferia (solo S7-1500)
|
||||
DBNUMBER: Número del bloque de datos si AREA = DB, de lo contrario "0"
|
||||
BYTEOFFSET: Dirección en la que se lee. Solo se utilizan los 16 bits menos significativos.*)
|
||||
|
||||
// =============================================================================
|
||||
// RETORNO TERMICO
|
||||
IF "DB2015_M".M[#for_i].Config_DireccionRetTermicoByte >= 0 THEN
|
||||
"DB2015_M".M[#for_i].Estado_EntradaTermico := PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2015_M".M[#for_i].Config_DireccionRetTermicoByte,
|
||||
bitOffset := "DB2015_M".M[#for_i].Config_DireccionRetTermicoBit);
|
||||
IF "DB2015_M".M[#for_i].Config_HabilitarInvertirTermico THEN
|
||||
"DB2015_M".M[#for_i].Estado_EntradaTermico := NOT (PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2015_M".M[#for_i].Config_DireccionRetTermicoByte,
|
||||
bitOffset := "DB2015_M".M[#for_i].Config_DireccionRetTermicoBit));
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// RETORNO CONFIRMACION DE MARCHA
|
||||
IF "DB2015_M".M[#for_i].Config_DireccionRetConfMarchaByte >= 0 THEN
|
||||
"DB2015_M".M[#for_i].Estado_EntradaConfMarcha := PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2015_M".M[#for_i].Config_DireccionRetConfMarchaByte,
|
||||
bitOffset := "DB2015_M".M[#for_i].Config_DireccionRetConfMarchaBit);
|
||||
IF "DB2015_M".M[#for_i].Config_HabilitarInvertirConfMarcha THEN
|
||||
"DB2015_M".M[#for_i].Estado_EntradaConfMarcha := NOT (PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2015_M".M[#for_i].Config_DireccionRetConfMarchaByte,
|
||||
bitOffset := "DB2015_M".M[#for_i].Config_DireccionRetConfMarchaBit));
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
|
||||
#TIPO_ACCESO_PLC:
|
||||
;
|
||||
|
||||
END_CASE;
|
||||
|
||||
END_REGION LECTURA_VALORES
|
||||
|
||||
|
||||
REGION MODOS_DE_TRABAJO
|
||||
|
||||
// =============================================================================
|
||||
// MODO MANUAL
|
||||
IF "DB2015_M".M[#for_i].Estado_AutoMan THEN
|
||||
"DB2015_M".Agrup["DB2015_M".M[#for_i].Config_GrupoAlarma].AlgunaEnManual := TRUE;
|
||||
IF "DB2015_M".M[#for_i].Orden_ActivarManual = TRUE AND #SeguridadesOK AND "DB2015_M".M[#for_i].Estado_SeguridadOk AND NOT "DB2015_M".M[#for_i].Alarmas_Termico THEN // En caso de enclavar manual NOT "DB2036_TMF1_DISP_M".M[#i].Estado_Enclavado
|
||||
#t_Activar := TRUE;
|
||||
ELSE
|
||||
#t_Activar := FALSE;
|
||||
"DB2015_M".M[#for_i].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2015_M".M[#for_i].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MODO AUTO
|
||||
IF NOT "DB2015_M".M[#for_i].Estado_AutoMan THEN
|
||||
IF "DB2015_M".M[#for_i].Orden_ActivarAuto = TRUE AND NOT "DB2015_M".M[#for_i].Estado_Enclavado AND #SeguridadesOK AND "DB2015_M".M[#for_i].Estado_SeguridadOk AND NOT "DB2015_M".M[#for_i].Alarmas_Termico THEN
|
||||
#t_Activar := TRUE;
|
||||
ELSE
|
||||
#t_Activar := FALSE;
|
||||
END_IF;
|
||||
|
||||
"DB2015_M".M[#for_i].Orden_ActivarManual := "DB2015_M".M[#for_i].Estado_Activado;
|
||||
END_IF;
|
||||
|
||||
END_REGION MODOS_DE_TRABAJO
|
||||
|
||||
|
||||
REGION ESTADO_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// MOTOR SIMULADO
|
||||
IF #Simulacion THEN
|
||||
|
||||
IF #t_Activar THEN
|
||||
"DB2015_M".M[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2015_M".M[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MOTOR RETORNO TERMICO Y CONFIRMACION DE MARCHA
|
||||
IF NOT #Simulacion AND "DB2015_M".M[#for_i].Config_HabilitarRetornoTermico
|
||||
AND "DB2015_M".M[#for_i].Config_HabilitarRetornoConfMarcha
|
||||
THEN
|
||||
|
||||
IF NOT "DB2015_M".M[#for_i].Estado_EntradaTermico AND "DB2015_M".M[#for_i].Estado_EntradaConfMarcha THEN
|
||||
"DB2015_M".M[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2015_M".M[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MOTOR RETORNO SOLO TERMICO
|
||||
IF NOT #Simulacion AND "DB2015_M".M[#for_i].Config_HabilitarRetornoTermico
|
||||
AND NOT "DB2015_M".M[#for_i].Config_HabilitarRetornoConfMarcha THEN
|
||||
|
||||
IF NOT "DB2015_M".M[#for_i].Estado_EntradaTermico AND #t_Activar THEN
|
||||
"DB2015_M".M[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2015_M".M[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MOTOR RETORNO SOLO CONFIRMACION DE MARCHA
|
||||
IF NOT #Simulacion AND NOT "DB2015_M".M[#for_i].Config_HabilitarRetornoTermico
|
||||
AND "DB2015_M".M[#for_i].Config_HabilitarRetornoConfMarcha THEN
|
||||
|
||||
IF "DB2015_M".M[#for_i].Estado_EntradaConfMarcha THEN
|
||||
"DB2015_M".M[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2015_M".M[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MOTOR SIN RETORNOS
|
||||
IF NOT (#Simulacion) AND NOT ("DB2015_M".M[#for_i].Config_HabilitarRetornoTermico)
|
||||
AND NOT ("DB2015_M".M[#for_i].Config_HabilitarRetornoConfMarcha) THEN
|
||||
|
||||
IF #t_Activar THEN
|
||||
"DB2015_M".M[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2015_M".M[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION ESTADO_DEL_DISPOSITIVO
|
||||
|
||||
|
||||
REGION ERRORES
|
||||
|
||||
// =============================================================================
|
||||
// CHEQUEO RETORNO TERMICO
|
||||
IF NOT #Simulacion AND "DB2015_M".M[#for_i].Config_HabilitarRetornoTermico
|
||||
AND "DB2015_M".M[#for_i].Estado_EntradaTermico THEN
|
||||
#t_ErrorTermico := TRUE;
|
||||
ELSE
|
||||
#t_ErrorTermico := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// CHEQUEO RETORNO CONFIRMACION DE MARCHA
|
||||
IF NOT #Simulacion AND "DB2015_M".M[#for_i].Config_HabilitarRetornoConfMarcha AND
|
||||
(
|
||||
(#t_Activar AND NOT "DB2015_M".M[#for_i].Estado_EntradaConfMarcha)
|
||||
OR
|
||||
(NOT #t_Activar AND "DB2015_M".M[#for_i].Estado_EntradaConfMarcha)
|
||||
) THEN
|
||||
#t_ErrorConfMarcha := TRUE;
|
||||
ELSE
|
||||
#t_ErrorConfMarcha := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// TEMPORIZADO DE ERRORES
|
||||
IF "DB2015_M".M[#for_i].Config_HabilitarRetornoConfMarcha
|
||||
AND #t_ErrorConfMarcha
|
||||
AND NOT "DB2015_M".M[#for_i].Alarmas_ConfirmacionMarcha
|
||||
AND NOT "DB2015_M".M[#for_i].Alarmas_Termico
|
||||
THEN
|
||||
IF NOT #Simulacion AND #Pulso1seg THEN
|
||||
"DB2015_M".M[#for_i].Tiempos_Alarma += 1;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2015_M".M[#for_i].Tiempos_Alarma := 0;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ERROR TERMICO
|
||||
IF #t_ErrorTermico THEN
|
||||
"DB2015_M".M[#for_i].Alarmas_Termico := TRUE;
|
||||
END_IF;
|
||||
IF NOT #t_ErrorTermico THEN
|
||||
"DB2015_M".M[#for_i].Alarmas_Termico := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ERROR CONFIRMACION DE MARCHA
|
||||
IF "DB2015_M".M[#for_i].Tiempos_Alarma >= "DB2015_M".M[#for_i].Tiempos_SetPointTiempoAlarma AND #t_ErrorConfMarcha THEN
|
||||
"DB2015_M".M[#for_i].Alarmas_ConfirmacionMarcha := TRUE;
|
||||
END_IF;
|
||||
IF NOT #t_ErrorConfMarcha THEN
|
||||
"DB2015_M".M[#for_i].Alarmas_ConfirmacionMarcha := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ERROR GLOBAL
|
||||
IF "DB2015_M".M[#for_i].Alarmas_Termico OR
|
||||
"DB2015_M".M[#for_i].Alarmas_ConfirmacionMarcha
|
||||
THEN
|
||||
"DB2015_M".M[#for_i].Alarmas_General := TRUE;
|
||||
END_IF;
|
||||
IF #Ack AND
|
||||
NOT "DB2015_M".M[#for_i].Alarmas_Termico AND
|
||||
NOT "DB2015_M".M[#for_i].Alarmas_ConfirmacionMarcha
|
||||
THEN
|
||||
"DB2015_M".M[#for_i].Alarmas_General := FALSE;
|
||||
END_IF;
|
||||
//"DB2015_M".M[#for_i].Alarmas_General := "DB2015_M".M[#for_i].Alarmas_Termico OR "DB2015_M".M[#for_i].Alarmas_ConfirmacionMarcha;
|
||||
|
||||
IF "DB2015_M".M[#for_i].Alarmas_General THEN
|
||||
"DB2015_M".Agrup["DB2015_M".M[#for_i].Config_GrupoAlarma].AlgunaAlarma := TRUE;
|
||||
END_IF;
|
||||
|
||||
END_REGION ERRORES
|
||||
|
||||
|
||||
REGION DIAGNOSIS
|
||||
|
||||
// =============================================================================
|
||||
// CONTADOR DE HORAS DE FUNCIONAMIENTO
|
||||
IF "DB2015_M".M[#for_i].Orden_ResetHoras THEN
|
||||
"DB2015_M".M[#for_i].Tiempos_Mantenimiento := 0.0;
|
||||
"DB2015_M".M[#for_i].Orden_ResetHoras := FALSE;
|
||||
END_IF;
|
||||
IF NOT #Simulacion AND #Pulso1seg AND "DB2015_M".M[#for_i].Estado_Activado THEN
|
||||
"DB2015_M".M[#for_i].Tiempos_Mantenimiento += 0.00027778;
|
||||
END_IF;
|
||||
// =============================================================================
|
||||
// ALARMA HORAS PARA MANTENIMIENTO ALCANZADOS
|
||||
"DB2015_M".M[#for_i].Alarmas_Mantenimiento := FALSE;
|
||||
IF "DB2015_M".M[#for_i].Config_HabilitarMantenimiento
|
||||
AND
|
||||
"DB2015_M".M[#for_i].Tiempos_Mantenimiento > "DB2015_M".M[#for_i].Tiempos_SetPointMantenimiento
|
||||
THEN
|
||||
"DB2015_M".M[#for_i].Alarmas_Mantenimiento := TRUE;
|
||||
END_IF;
|
||||
|
||||
|
||||
END_REGION DIAGNOSIS
|
||||
|
||||
|
||||
REGION ESCRITURA_SALIDA
|
||||
|
||||
CASE "DB2015_M".M[#for_i].Config_TipoAcceso OF
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO:
|
||||
// =============================================================================
|
||||
// ESCRITURA SALIDA
|
||||
(* AREA: Pueden seleccionarse las siguientes áreas:16#81: Input, 16#82: Output, 16#83: Marcas, 16#84: DB, 16#2: Salida de periferia (solo S7-1500)
|
||||
DBNUMBER: Número del bloque de datos si AREA = DB, de lo contrario "0"
|
||||
BYTEOFFSET: Dirección que se escribe, Solo se utilizan los 16 bits menos significativos.
|
||||
BITOFFSET: Bit que se escribe,
|
||||
VALUE: Valor que se escribe *)
|
||||
|
||||
IF "DB2015_M".M[#for_i].Config_DireccionSalidaByte >= 0 THEN
|
||||
|
||||
IF #t_Activar AND NOT "DB2015_M".M[#for_i].Alarmas_General THEN
|
||||
|
||||
"DB2015_M".M[#for_i].Estado_Salida := TRUE;
|
||||
POKE_BOOL(area := 16#82,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2015_M".M[#for_i].Config_DireccionSalidaByte,
|
||||
bitOffset := "DB2015_M".M[#for_i].Config_DireccionSalidaBit,
|
||||
value := TRUE);
|
||||
ELSE
|
||||
"DB2015_M".M[#for_i].Estado_Salida := FALSE;
|
||||
POKE_BOOL(area := 16#82,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2015_M".M[#for_i].Config_DireccionSalidaByte,
|
||||
bitOffset := "DB2015_M".M[#for_i].Config_DireccionSalidaBit,
|
||||
value := FALSE);
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
#TIPO_ACCESO_PLC:
|
||||
IF #t_Activar AND NOT "DB2015_M".M[#for_i].Alarmas_General THEN
|
||||
"DB2015_M".M[#for_i].Estado_Salida := TRUE;
|
||||
ELSE
|
||||
"DB2015_M".M[#for_i].Estado_Salida := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_CASE;
|
||||
|
||||
END_REGION ESCRITURA_SALIDA
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// RESET ORDEN ACTIVAR EN AUTO
|
||||
"DB2015_M".M[#for_i].Orden_ActivarAuto := FALSE;
|
||||
"DB2015_M".M[#for_i].Estado_Enclavado := FALSE;
|
||||
|
||||
REGION TRAZABILIDAD_MANUALIZACION
|
||||
|
||||
IF "DB2015_M".M[#for_i].Estado_AutoMan AND NOT "DB2015_M".M[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_15_DISP_M",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_M",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF NOT "DB2015_M".M[#for_i].Estado_AutoMan AND "DB2015_M".M[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_15_DISP_M",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_M",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_AUTO",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2015_M".M[#for_i].Estado_AutoMan AND "DB2015_M".M[#for_i].Estado_Activado AND NOT "DB2015_M".M[#for_i].Aux_oldActivado THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_15_DISP_M",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_M",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_ON",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2015_M".M[#for_i].Estado_AutoMan AND NOT "DB2015_M".M[#for_i].Estado_Activado AND "DB2015_M".M[#for_i].Aux_oldActivado THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_15_DISP_M",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_M",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_OFF",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
END_REGION TRAZABILIDAD_MANUALIZACION
|
||||
|
||||
// =============================================================================
|
||||
// Estado anterior manual/automatico
|
||||
"DB2015_M".M[#for_i].Aux_oldAutoMan := "DB2015_M".M[#for_i].Estado_AutoMan;
|
||||
"DB2015_M".M[#for_i].Aux_oldActivado := "DB2015_M".M[#for_i].Estado_Activado;
|
||||
|
||||
ELSE
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO NO HABILITADO
|
||||
// =============================================================================
|
||||
"DB2015_M".M[#for_i].Alarmas_General := FALSE;
|
||||
"DB2015_M".M[#for_i].Alarmas_Termico := FALSE;
|
||||
"DB2015_M".M[#for_i].Alarmas_ConfirmacionMarcha := FALSE;
|
||||
"DB2015_M".M[#for_i].Alarmas_Mantenimiento := FALSE;
|
||||
"DB2015_M".M[#for_i].Estado_EntradaTermico := FALSE;
|
||||
"DB2015_M".M[#for_i].Estado_EntradaConfMarcha := FALSE;
|
||||
"DB2015_M".M[#for_i].Estado_Enclavado := FALSE;
|
||||
"DB2015_M".M[#for_i].Estado_Salida := FALSE;
|
||||
"DB2015_M".M[#for_i].Orden_ActivarAuto := FALSE;
|
||||
"DB2015_M".M[#for_i].Estado_Activado := FALSE;
|
||||
"DB2015_M".M[#for_i].Tiempos_Alarma := 0;
|
||||
"DB2015_M".M[#for_i].Orden_ActivarManual := FALSE;
|
||||
"DB2015_M".M[#for_i].Estado_AutoMan := FALSE;
|
||||
END_IF;
|
||||
|
||||
REGION GESTION_HMI
|
||||
|
||||
// =============================================================================
|
||||
// GESTION BITS PARA VISUALIZACION
|
||||
// Bit 0 Habilitacion
|
||||
// Bit 1 ManualAutomatico
|
||||
// Bit 2 Enclavado
|
||||
// Bit 3 Activado 1
|
||||
// Bit 4 Activado 2
|
||||
// Bit 5 Reserva
|
||||
// Bit 6 Reserva
|
||||
// Bit 7 Reserva
|
||||
// Bit 8 alarmas General
|
||||
// Bit 9 alarmas 1
|
||||
// Bit 10 alarmas 2
|
||||
// Bit 11 alarmas 3
|
||||
// Bit 12 alarmas 4
|
||||
// Bit 13 alarmas Mantenimiento
|
||||
// Bit 14 Reserva
|
||||
// Bit 15 Reserva
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X0 := "DB2015_M".M[#for_i].Config_Habilitar;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X1 := "DB2015_M".M[#for_i].Estado_AutoMan;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X2 := "DB2015_M".M[#for_i].Estado_Enclavado;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X3 := "DB2015_M".M[#for_i].Estado_Activado;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X4 := FALSE;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X5 := FALSE;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X6 := FALSE;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X7 := FALSE;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X8 := "DB2015_M".M[#for_i].Alarmas_General;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X9 := FALSE;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X10 := FALSE;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X11 := FALSE;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X12 := FALSE;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X13 := "DB2015_M".M[#for_i].Alarmas_Mantenimiento;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X14 := FALSE;
|
||||
"DB2015_M".M[#for_i].Hmi_Estado.%X15 := FALSE;
|
||||
|
||||
END_REGION GESTION_HMI
|
||||
|
||||
REGION GESTION_NUEVA_ALARMA
|
||||
|
||||
// =============================================================================
|
||||
// DETECCION DE NUEVA alarmas
|
||||
IF "DB2015_M".M[#for_i].Alarmas_General AND NOT "DB2015_M".M[#for_i].Aux_oldAlarma THEN
|
||||
"DB2015_M".Agrup["DB2015_M".M[#for_i].Config_GrupoAlarma].NuevaAlarma := TRUE;
|
||||
END_IF;
|
||||
|
||||
// Estado anterior de las alarmass
|
||||
"DB2015_M".M[#for_i].Aux_oldAlarma := "DB2015_M".M[#for_i].Alarmas_General;
|
||||
|
||||
END_REGION GESTION_NUEVA_ALARMA
|
||||
|
||||
|
||||
END_FOR;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ACUSE DE NUEVAS ALARMAS
|
||||
IF #Ack THEN
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2015_M".Agrup[#for_i].NuevaAlarma := FALSE;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
END_REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,695 @@
|
||||
FUNCTION "FC2016_ZC_M_VF" : Void
|
||||
TITLE = FC2016_M_VF
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Modelo de dispositivo motor variador
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool; // Pulso de 1 segundo
|
||||
Simulacion : Bool; // Simulacion
|
||||
Arranque : Bool; // Primer arranque
|
||||
Ack : Bool; // Acuse general
|
||||
SeguridadesOK : Bool; // Seguridades OK
|
||||
UsuarioActual : String; // Usuario actual
|
||||
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
t_Activar : Bool;
|
||||
t_ErrorTermico : Bool;
|
||||
t_ErrorConfirmacionMarcha : Bool;
|
||||
t_Frecuencia : Real;
|
||||
t_x : Real;
|
||||
t_x0 : Real;
|
||||
t_x1 : Real;
|
||||
t_y0 : Real;
|
||||
t_y1 : Real;
|
||||
t_ValorSalida : Real;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
TIPO_ACCESO_INDIRECTO : SInt := 0;
|
||||
TIPO_ACCESO_PLC : SInt := 1;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Funcion para la gestion de dispositivo de tipo Motor con variador de frecuencia.
|
||||
|
||||
En ella se realizan las siguientes acciones:
|
||||
|
||||
- Se gestiona el multiplexado de los dispositivos para su uso en sistemas HMI/SCADA.
|
||||
- Se gestiona el estado del dispositivo
|
||||
- Se gestiona el tiempo en marcha
|
||||
- Se gestiona la orden de escritura
|
||||
- Se gestiona la trazabilidad de las manualizaciones del dispositivo
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC8_ZC_TRAZA_REGISTRO`, `FC15025_ZC_CONTADOR_TIEMPO` |
|
||||
| FB | - |
|
||||
| DB | DB2016_DISP_M_VF |
|
||||
| UDT | ZC_DISP_M_VF, ZC_DISP_MUX_M_VF, `ZC_CONTADOR_TIEMPO` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 15.10.2020 | (ABH) | Primera version. |
|
||||
| 00.00.02 | 28.11.2020 | (ABH) | Añadidas alarmas mantenimiento |
|
||||
| 00.00.03 | 26.10.2021 | (ABH) | Se integra la gestion de directo/inverso |
|
||||
| 00.00.04 | 26.04.2022 | (HCR) | Cambio en la organizacion del UDT. Se organiza en estructuras en base al tipo de funcion que realizan los datos. Se quita el enclavamiento para orden manual. |
|
||||
| 00.00.05 | 27.04.2022 | (ABH) | Se añaden auxiliares de estado anterior del modo manual y automatico para poder registrar las trazas. |
|
||||
| 00.00.06 | 27.04.2022 | (HCR) | Si no esta habilitado se quita orden manual y se quita el estado manual. Se agrega Ack para alarmas de confirmación de marcha. Se mantiene el estado cuando se pasa a manual. Cambio en lógica de errores. Cambio en la escritura de la salida. Cambio en laógica de modos |
|
||||
| 00.00.07 | 08.11.2022 | (ABH) | Se añade trazabilidad manualizaciones |
|
||||
| 00.00.08 | 08.11.2022 | (HCR) | Se añade trazabilidad de activación manual |
|
||||
| 00.00.09 | 08.11.2022 | (HCR) | Cambio lógica enclavamiento |
|
||||
| 00.00.10 | 18.09.2023 | (ABH) | Cambio en tipo de dato de horas de alarma. Se utiliza el tipo de dato ZC_CONTADOR_TIEMPO y el FC15025_ZC_CONTADOR_TIEMPO |
|
||||
| 00.00.11 | 22.02.2024 | (ABH) | Se añade gestion multiplexado para Scada (no indexado) |
|
||||
| 00.00.12 | 08.01.2025 | (ABH) | Se añade entrada de primer arranque del PLC para resetear indices de multiplexado Se añade movimiento de M[0] a multiplexado en caso de que el indice sea 0. |
|
||||
| 00.00.13 | 24.01.2025 | (ABH) | Se modifica la logica del multiplexado, la asignacion de oldindex se cambia de sitio ya que de vez en cuando (dependiendo de cuando el HMI realiza la comunicacion asincrona con el PLC) no detectaba el cambio y se machacaban valores. |
|
||||
| 00.00.14 | 26.03.2025 | (ABH) | Se añade variable grupo de alarma para separar los nuevos avisos por cuadro. |
|
||||
| 00.00.15 | 24.04.2025 | (HCR) | Se añade gestion de idioma |
|
||||
| 00.00.16 | 11.09.2025 | (ABH) | Se eliminan las constantes de idioma dentro del FC. Se utilizan constantes globales para facilitar su traduccion. |
|
||||
| 00.00.17 | 17.12.2025 | (ABH) | Se eliminan los idiomas. Se utiliza codigos para trazabilidad. Se elimina entrada "Idioma". Se elimina nombre de UDT. Se elimina nombre de UDT. Se añade indexHMI para lista de texto en sistemas de supervision. |
|
||||
| 01.00.00 | 18.05.2026 | (ABH) | Se añade variable `Config_TipoAcceso` para uso de direccionamiento indirecto o uso directo en PLC. |
|
||||
| 01.01.00 | 08.07.2026 | (ABH) | Se extrae el multiplexado a FC independiente. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// Resetear todas las alarmas para que se vuelvan a generar
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2016_M_VF".Agrup[#for_i].AlgunaAlarma := FALSE;
|
||||
"DB2016_M_VF".Agrup[#for_i].AlgunaEnManual := FALSE;
|
||||
END_FOR;
|
||||
|
||||
// Numero maximo de dispositivos para limitar en HMI/Scada
|
||||
"DB2016_M_VF".Mux.NumDispositivos := "N_MAX_DISP_M_VF";
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_M_VF" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_M_VF";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO HABILITADO
|
||||
// =============================================================================
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Config_Habilitar THEN
|
||||
|
||||
REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Config_GrupoAlarma < 0 THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Config_GrupoAlarma := 0;
|
||||
END_IF;
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Config_GrupoAlarma > "N_MAX_DISP_AGRUP" THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Config_GrupoAlarma := "N_MAX_DISP_AGRUP";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
// =============================================================================
|
||||
// PUESTA A CERO DE LA SALIDA
|
||||
#t_Activar := FALSE;
|
||||
#t_Frecuencia := 0.0;
|
||||
|
||||
REGION LECTURA_VALORES
|
||||
|
||||
CASE "DB2016_M_VF".M_VF[#for_i].Config_TipoAcceso OF
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO:
|
||||
(* AREA: Pueden seleccionarse las siguientes áreas: 16#81: Input, 16#82: Output, 16#83: Marcas, 16#84: DB, 16#1: Entrada de periferia (solo S7-1500)
|
||||
DBNUMBER: Número del bloque de datos si AREA = DB, de lo contrario "0"
|
||||
BYTEOFFSET: Dirección en la que se lee. Solo se utilizan los 16 bits menos significativos.*)
|
||||
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetTermicoByte >= 0 THEN
|
||||
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_EntradaTermico := PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetTermicoByte,
|
||||
bitOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetTermicoBit);
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Config_HabilitarInvertirTermico THEN
|
||||
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_EntradaTermico := NOT (PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetTermicoByte,
|
||||
bitOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetTermicoBit));
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// RETORNO CONFIRMACION DE MARCHA
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetConfMarchaByte >= 0 THEN
|
||||
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_EntradaConfMarcha := PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetConfMarchaByte,
|
||||
bitOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetConfMarchaBit);
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Config_HabilitarInvertirConfMarcha THEN
|
||||
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_EntradaConfMarcha := NOT (PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetConfMarchaByte,
|
||||
bitOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetConfMarchaBit));
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
|
||||
#TIPO_ACCESO_PLC:
|
||||
;
|
||||
|
||||
END_CASE;
|
||||
|
||||
END_REGION LECTURA_VALORES
|
||||
|
||||
|
||||
REGION MODOS_DE_TRABAJO
|
||||
|
||||
// =============================================================================
|
||||
// MODO MANUAL
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Estado_AutoMan THEN
|
||||
"DB2016_M_VF".Agrup["DB2016_M_VF".M_VF[#for_i].Config_GrupoAlarma].AlgunaEnManual := TRUE;
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Orden_ActivarManual = TRUE AND #SeguridadesOK AND "DB2016_M_VF".M_VF[#for_i].Estado_SeguridadOk AND NOT "DB2016_M_VF".M_VF[#for_i].Alarmas_Termico THEN //En caso de enclavar manual NOT "DB2037_TMF1_DISP_M_VF".M_VF[#i].Estado_Enclavado
|
||||
#t_Activar := TRUE;
|
||||
#t_Frecuencia := "DB2016_M_VF".M_VF[#for_i].Orden_ConsignaManual;
|
||||
ELSE
|
||||
#t_Activar := FALSE;
|
||||
#t_Frecuencia := 0.0;
|
||||
"DB2016_M_VF".M_VF[#for_i].Orden_ActivarManual := FALSE;
|
||||
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2016_M_VF".M_VF[#for_i].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MODO AUTO
|
||||
IF NOT "DB2016_M_VF".M_VF[#for_i].Estado_AutoMan THEN
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Orden_ActivarAuto = TRUE AND NOT "DB2016_M_VF".M_VF[#for_i].Estado_Enclavado AND #SeguridadesOK AND "DB2016_M_VF".M_VF[#for_i].Estado_SeguridadOk AND NOT "DB2016_M_VF".M_VF[#for_i].Alarmas_Termico THEN
|
||||
#t_Activar := TRUE;
|
||||
#t_Frecuencia := "DB2016_M_VF".M_VF[#for_i].Orden_ConsignaAuto;
|
||||
"DB2016_M_VF".M_VF[#for_i].Orden_ConsignaManual := "DB2016_M_VF".M_VF[#for_i].Orden_ConsignaAuto;
|
||||
ELSE
|
||||
#t_Activar := FALSE;
|
||||
#t_Frecuencia := 0.0;
|
||||
END_IF;
|
||||
|
||||
"DB2016_M_VF".M_VF[#for_i].Orden_ActivarManual := "DB2016_M_VF".M_VF[#for_i].Estado_Activado;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION MODOS_DE_TRABAJO
|
||||
|
||||
|
||||
REGION ESTADO_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// MOTOR SIMULADO
|
||||
IF #Simulacion THEN
|
||||
|
||||
IF #t_Activar THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MOTOR RETORNO TERMICO Y CONFIRMACION DE MARCHA
|
||||
IF NOT #Simulacion AND "DB2016_M_VF".M_VF[#for_i].Config_HabilitarRetornoTermico
|
||||
AND "DB2016_M_VF".M_VF[#for_i].Config_HabilitarRetornoConfMarcha
|
||||
THEN
|
||||
|
||||
IF NOT "DB2016_M_VF".M_VF[#for_i].Estado_EntradaTermico AND "DB2016_M_VF".M_VF[#for_i].Estado_EntradaConfMarcha THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MOTOR RETORNO SOLO TERMICO
|
||||
IF NOT #Simulacion AND "DB2016_M_VF".M_VF[#for_i].Config_HabilitarRetornoTermico
|
||||
AND NOT "DB2016_M_VF".M_VF[#for_i].Config_HabilitarRetornoConfMarcha THEN
|
||||
|
||||
IF NOT "DB2016_M_VF".M_VF[#for_i].Estado_EntradaTermico AND #t_Activar THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MOTOR RETORNO SOLO CONFIRMACION DE MARCHA
|
||||
IF NOT #Simulacion AND NOT "DB2016_M_VF".M_VF[#for_i].Config_HabilitarRetornoTermico
|
||||
AND "DB2016_M_VF".M_VF[#for_i].Config_HabilitarRetornoConfMarcha THEN
|
||||
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Estado_EntradaConfMarcha THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MOTOR SIN RETORNOS
|
||||
IF NOT #Simulacion AND NOT "DB2016_M_VF".M_VF[#for_i].Config_HabilitarRetornoTermico
|
||||
AND NOT "DB2016_M_VF".M_VF[#for_i].Config_HabilitarRetornoConfMarcha THEN
|
||||
|
||||
IF #t_Activar THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Activado := TRUE;
|
||||
ELSE
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Activado := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION ESTADO_DEL_DISPOSITIVO
|
||||
|
||||
|
||||
REGION ERRORES
|
||||
|
||||
// =============================================================================
|
||||
// CHEQUEO RETORNO TERMICO
|
||||
IF NOT #Simulacion AND "DB2016_M_VF".M_VF[#for_i].Config_HabilitarRetornoTermico
|
||||
AND "DB2016_M_VF".M_VF[#for_i].Estado_EntradaTermico THEN
|
||||
#t_ErrorTermico := TRUE;
|
||||
ELSE
|
||||
#t_ErrorTermico := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// CHEQUEO RETORNO CONFIRMACION DE MARCHA
|
||||
IF NOT #Simulacion AND "DB2016_M_VF".M_VF[#for_i].Config_HabilitarRetornoConfMarcha AND
|
||||
(
|
||||
(#t_Activar AND NOT "DB2016_M_VF".M_VF[#for_i].Estado_EntradaConfMarcha)
|
||||
OR
|
||||
(NOT #t_Activar AND "DB2016_M_VF".M_VF[#for_i].Estado_EntradaConfMarcha)
|
||||
) THEN
|
||||
#t_ErrorConfirmacionMarcha := TRUE;
|
||||
ELSE
|
||||
#t_ErrorConfirmacionMarcha := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// TEMPORIZADO DE ERRORES
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Config_HabilitarRetornoConfMarcha
|
||||
AND #t_ErrorConfirmacionMarcha
|
||||
AND NOT "DB2016_M_VF".M_VF[#for_i].Alarmas_ConfirmacionMarcha
|
||||
AND NOT "DB2016_M_VF".M_VF[#for_i].Alarmas_Termico
|
||||
THEN
|
||||
IF NOT #Simulacion AND #Pulso1seg THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Tiempos_Alarma += 1;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2016_M_VF".M_VF[#for_i].Tiempos_Alarma := 0;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ERROR TERMICO
|
||||
IF #t_ErrorTermico THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_Termico := TRUE;
|
||||
END_IF;
|
||||
IF NOT #t_ErrorTermico THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_Termico := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ERROR CONFIRMACION DE MARCHA
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Tiempos_Alarma >= "DB2016_M_VF".M_VF[#for_i].Tiempos_SetPointAlarma AND #t_ErrorConfirmacionMarcha THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_ConfirmacionMarcha := TRUE;
|
||||
END_IF;
|
||||
IF NOT #t_ErrorConfirmacionMarcha THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_ConfirmacionMarcha := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ERROR GLOBAL
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Alarmas_Termico OR
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_ConfirmacionMarcha
|
||||
THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_General := TRUE;
|
||||
END_IF;
|
||||
IF #Ack AND
|
||||
NOT "DB2016_M_VF".M_VF[#for_i].Alarmas_Termico AND
|
||||
NOT "DB2016_M_VF".M_VF[#for_i].Alarmas_ConfirmacionMarcha
|
||||
THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_General := FALSE;
|
||||
END_IF;
|
||||
//"DB2016_M_VF".M_VF[#for_i].Alarmas_General := "DB2016_M_VF".M_VF[#for_i].Alarmas_Termico OR "DB2016_M_VF".M_VF[#for_i].Alarmas_ConfirmacionMarcha OR "DB2016_M_VF".M_VF[#for_i].Alarmas_Escritura;
|
||||
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Alarmas_General THEN
|
||||
"DB2016_M_VF".Agrup["DB2016_M_VF".M_VF[#for_i].Config_GrupoAlarma].AlgunaAlarma := TRUE;
|
||||
// =============================================================================
|
||||
// SI TENEMOS UN ERROR DESACTIVAMOS LA SALIDA
|
||||
#t_Frecuencia := 0.0;
|
||||
END_IF;
|
||||
|
||||
END_REGION ERRORES
|
||||
|
||||
|
||||
REGION DIAGNOSIS
|
||||
|
||||
// =============================================================================
|
||||
// CONTADOR DE HORAS DE FUNCIONAMIENTO
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Orden_ResetHoras THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Orden_ResetHoras := FALSE;
|
||||
END_IF;
|
||||
IF NOT #Simulacion AND #Pulso1seg AND "DB2016_M_VF".M_VF[#for_i].Estado_Activado THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Tiempos_Mantenimiento += 0.00027778;
|
||||
END_IF;
|
||||
// =============================================================================
|
||||
// ALARMA HORAS PARA MANTENIMIENTO ALCANZADOS
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_Mantenimiento := FALSE;
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Config_HabilitarMantenimiento
|
||||
AND
|
||||
"DB2016_M_VF".M_VF[#for_i].Tiempos_Mantenimiento > "DB2016_M_VF".M_VF[#for_i].Tiempos_SetPointMantenimiento
|
||||
THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_Mantenimiento := TRUE;
|
||||
END_IF;
|
||||
|
||||
|
||||
END_REGION DIAGNOSIS
|
||||
|
||||
|
||||
REGION ESCRITURA_SALIDA
|
||||
|
||||
CASE "DB2016_M_VF".M_VF[#for_i].Config_TipoAcceso OF
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO:
|
||||
// =============================================================================
|
||||
// ESCRITURA SALIDA
|
||||
(* AREA: Pueden seleccionarse las siguientes áreas:16#81: Input, 16#82: Output, 16#83: Marcas, 16#84: DB, 16#2: Salida de periferia (solo S7-1500)
|
||||
DBNUMBER: Número del bloque de datos si AREA = DB, de lo contrario "0"
|
||||
BYTEOFFSET: Dirección que se escribe, Solo se utilizan los 16 bits menos significativos.
|
||||
BITOFFSET: Bit que se escribe,
|
||||
VALUE: Valor que se escribe *)
|
||||
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Config_DireccionSalidaByte >= 0 THEN
|
||||
|
||||
IF #t_Activar AND NOT "DB2016_M_VF".M_VF[#for_i].Alarmas_General THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Salida := TRUE;
|
||||
POKE_BOOL(area := 16#82,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionSalidaByte,
|
||||
bitOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionSalidaBit,
|
||||
value := TRUE);
|
||||
ELSE
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Salida := FALSE;
|
||||
POKE_BOOL(area := 16#82,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionSalidaByte,
|
||||
bitOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionSalidaBit,
|
||||
value := FALSE);
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
#TIPO_ACCESO_PLC:
|
||||
IF #t_Activar AND NOT "DB2016_M_VF".M_VF[#for_i].Alarmas_General THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Salida := TRUE;
|
||||
ELSE
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Salida := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_CASE;
|
||||
|
||||
END_REGION ESCRITURA_SALIDA
|
||||
|
||||
|
||||
REGION SALIDA
|
||||
|
||||
// =============================================================================
|
||||
// TRASPASO DE PARAMETROS
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_ValorActual := #t_Frecuencia;
|
||||
|
||||
// =============================================================================
|
||||
// CONVERSIÓN DE VALORES
|
||||
#t_y0 := INT_TO_REAL(0);
|
||||
#t_y1 := INT_TO_REAL(27648);
|
||||
#t_x := "DB2016_M_VF".M_VF[#for_i].Estado_ValorActual;
|
||||
#t_x0 := "DB2016_M_VF".M_VF[#for_i].Config_EscaladoMinIngenieria;
|
||||
#t_x1 := "DB2016_M_VF".M_VF[#for_i].Config_EscaladoMaxIngenieria;
|
||||
|
||||
// SI TENEMOS ORDEN DE ACTIVAR
|
||||
IF #t_Activar THEN
|
||||
|
||||
// =============================================================================
|
||||
// ESCALADO Y = (X-x0)*((y1-y0)/(x1-x0)) + y0
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Config_EscaladoMaxIngenieria > "DB2016_M_VF".M_VF[#for_i].Config_EscaladoMinIngenieria THEN
|
||||
#t_ValorSalida := ((#t_x - #t_x0) * ((#t_y1 - #t_y0) / (#t_x1 - #t_x0))) + #t_y0;
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_Parametros := FALSE;
|
||||
ELSE
|
||||
#t_ValorSalida := 0.0;
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_Parametros := TRUE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
#t_ValorSalida := 0.0;
|
||||
END_IF;
|
||||
|
||||
|
||||
REGION ESCRITURA_SALIDA
|
||||
|
||||
CASE "DB2016_M_VF".M_VF[#for_i].Config_TipoAcceso OF
|
||||
|
||||
#TIPO_ACCESO_INDIRECTO:
|
||||
// =============================================================================
|
||||
// ESCRITURA DEL CANAL - POKE (area) 16#2 para CPU 1500 ; 16#82 para CPU 1200
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Config_DireccionSalidaAnalogicaByte > 0 THEN
|
||||
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_ValorTarjeta := REAL_TO_INT(#t_ValorSalida);
|
||||
|
||||
POKE(area := 16#82,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2016_M_VF".M_VF[#for_i].Config_DireccionSalidaByte,
|
||||
value := INT_TO_WORD("DB2016_M_VF".M_VF[#for_i].Estado_ValorTarjeta));
|
||||
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Escritura := GET_ERR_ID();
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Estado_Escritura <> 0 THEN
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_Escritura := TRUE;
|
||||
ELSE
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_Escritura := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_ValorTarjeta := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
#TIPO_ACCESO_PLC:
|
||||
// =============================================================================
|
||||
// ESCRITURA VALORES DE LA TARJETA
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_ValorTarjeta := REAL_TO_INT(#t_ValorSalida);
|
||||
|
||||
END_CASE;
|
||||
|
||||
END_REGION ESCRITURA_SALIDA
|
||||
|
||||
|
||||
END_REGION SALIDA
|
||||
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// RESET ORDEN ACTIVAR EN AUTO
|
||||
"DB2016_M_VF".M_VF[#for_i].Orden_ActivarAuto := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Enclavado := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Orden_ConsignaAuto := 0.0;
|
||||
|
||||
|
||||
REGION TRAZABILIDAD_MANUALIZACION
|
||||
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Estado_AutoMan AND NOT "DB2016_M_VF".M_VF[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_16_DISP_M_VF",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_M_VF",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF NOT "DB2016_M_VF".M_VF[#for_i].Estado_AutoMan AND "DB2016_M_VF".M_VF[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_16_DISP_M_VF",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_M_VF",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_AUTO",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Estado_AutoMan AND "DB2016_M_VF".M_VF[#for_i].Estado_Activado AND NOT "DB2016_M_VF".M_VF[#for_i].Aux_oldActivado THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_16_DISP_M_VF",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_M_VF",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_ON",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Estado_AutoMan AND NOT "DB2016_M_VF".M_VF[#for_i].Estado_Activado AND "DB2016_M_VF".M_VF[#for_i].Aux_oldActivado THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_16_DISP_M_VF",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_M_VF",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_OFF",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
|
||||
END_REGION TRAZABILIDAD_MANUALIZACION
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Estado anterior manual/automatico
|
||||
"DB2016_M_VF".M_VF[#for_i].Aux_oldAutoMan := "DB2016_M_VF".M_VF[#for_i].Estado_AutoMan;
|
||||
"DB2016_M_VF".M_VF[#for_i].Aux_oldActivado := "DB2016_M_VF".M_VF[#for_i].Estado_Activado;
|
||||
ELSE
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO NO HABILITADO
|
||||
// =============================================================================
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_General := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_Termico := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_ConfirmacionMarcha := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_Mantenimiento := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Alarmas_Escritura := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_EntradaTermico := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_EntradaConfMarcha := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Enclavado := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_ValorTarjeta := 0;
|
||||
"DB2016_M_VF".M_VF[#for_i].Orden_ActivarAuto := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_Activado := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Tiempos_Alarma := 0;
|
||||
"DB2016_M_VF".M_VF[#for_i].Orden_ConsignaAuto := 0.0;
|
||||
"DB2016_M_VF".M_VF[#for_i].Orden_ConsignaManual := 0.0;
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_ValorActual := 0.0;
|
||||
"DB2016_M_VF".M_VF[#for_i].Estado_AutoMan := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Orden_ActivarManual := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
REGION GESTION_HMI
|
||||
|
||||
// =============================================================================
|
||||
// GESTION BITS PARA VISUALIZACION
|
||||
// Bit 0 Habilitacion
|
||||
// Bit 1 ManualAutomatico
|
||||
// Bit 2 Enclavado
|
||||
// Bit 3 Activado 1
|
||||
// Bit 4 Activado 2
|
||||
// Bit 5 Reserva
|
||||
// Bit 6 Reserva
|
||||
// Bit 7 Reserva
|
||||
// Bit 8 Alarma General
|
||||
// Bit 9 Alarma 1
|
||||
// Bit 10 Alarma 2
|
||||
// Bit 11 Alarma 3
|
||||
// Bit 12 Alarma 4
|
||||
// Bit 13 Alarma Mantenimiento
|
||||
// Bit 14 Reserva
|
||||
// Bit 15 Reserva
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X0 := "DB2016_M_VF".M_VF[#for_i].Config_Habilitar;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X1 := "DB2016_M_VF".M_VF[#for_i].Estado_AutoMan;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X2 := "DB2016_M_VF".M_VF[#for_i].Estado_Enclavado;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X3 := "DB2016_M_VF".M_VF[#for_i].Estado_Activado;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X4 := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X5 := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X6 := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X7 := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X8 := "DB2016_M_VF".M_VF[#for_i].Alarmas_General;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X9 := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X10 := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X11 := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X12 := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X13 := "DB2016_M_VF".M_VF[#for_i].Alarmas_Mantenimiento;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X14 := FALSE;
|
||||
"DB2016_M_VF".M_VF[#for_i].Hmi_Estado.%X15 := FALSE;
|
||||
|
||||
END_REGION GESTION_HMI
|
||||
|
||||
REGION GESTION_NUEVA_ALARMA
|
||||
|
||||
// =============================================================================
|
||||
// DETECCION DE NUEVA ALARMA
|
||||
IF "DB2016_M_VF".M_VF[#for_i].Alarmas_General AND NOT "DB2016_M_VF".M_VF[#for_i].Aux_oldAlarma THEN
|
||||
"DB2016_M_VF".Agrup["DB2016_M_VF".M_VF[#for_i].Config_GrupoAlarma].NuevaAlarma := TRUE;
|
||||
END_IF;
|
||||
|
||||
// Estado anterior de las alarmas
|
||||
"DB2016_M_VF".M_VF[#for_i].Aux_oldAlarma := "DB2016_M_VF".M_VF[#for_i].Alarmas_General;
|
||||
|
||||
END_REGION GESTION_NUEVA_ALARMA
|
||||
|
||||
|
||||
END_FOR;
|
||||
|
||||
// =============================================================================
|
||||
// ACUSE DE NUEVAS ALARMAS
|
||||
IF #Ack THEN
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2016_M_VF".Agrup[#for_i].NuevaAlarma := FALSE;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
END_REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
FUNCTION "FC2025_ZC_TOT" : Void
|
||||
TITLE = FC2025_TOT
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Bloque de funcion para gestion de totalizadores.
|
||||
VAR_INPUT
|
||||
Pulso100ms : Bool; // Pulso de 100 milisegundos
|
||||
Simulacion : Bool; // Simulacion
|
||||
Arranque : Bool; // Primer arranque
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CaudalSegundos : LReal;
|
||||
t_LReal : LReal;
|
||||
t_RT_Dummy : LReal;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
VALOR_MAXIMO_CONTADORES : Real := 1000000.0; // VALOR MÁXIMO DE ACUMULADOR
|
||||
NUMERO_MAXIMO_DESBORDE : Int := 32000; // VALOR MÁXIMO NUMERO DE DESBORDE
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Funcion para la gestion de dispositivo de tipo Totalizador.
|
||||
|
||||
En ella se realizan las siguientes acciones:
|
||||
|
||||
- Se gestiona el multiplexado de los dispositivos para su uso en sistemas HMI/SCADA.
|
||||
- Se gestiona el estado del dispositivo
|
||||
- Se gestiona el contaje del totalizador por entrada digital o por entrada analogica
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 15.10.2020 | (ABH) | Primera version. |
|
||||
| 00.00.02 | 28.01.2022 | (HCR) | Se añade corrección. |
|
||||
| 00.00.03 | 05.09.2023 | (HCR) | Se añade contador por desborde |
|
||||
| 00.00.04 | 18.09.2023 | (ABH) | Se estandariza nombre variables para gestion de tiempo de ciclo para integracion de EA. |
|
||||
| 00.00.05 | 28.02.2024 | (ABH) | Se añade gestion multiplexado para Scada (no indexado) |
|
||||
| 00.00.06 | 08.01.2025 | (ABH) | Se añade entrada de primer arranque del PLC para resetear indices de multiplexado. Se añade movimiento de TOT[0] a multiplexado en caso de que el indice sea 0. |
|
||||
| 00.00.07 | 24.01.2025 | (ABH) | Se modifica la logica del multiplexado, la asignacion de oldindex se cambia de sitio ya que de vez en cuando (dependiendo de cuando el HMI realiza la comunicacion asincrona con el PLC) no detectaba el cambio y se machacaban valores. |
|
||||
| 01.00.00 | 28.07.2025 | (ABH) | Se extrae el multiplexado a FC independiente. Se corrige reset de ordenes reset totalizadores en multiplexado. Se añade totalizador usuario. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION TIEMPO_CICLO_INTEGRACION
|
||||
|
||||
// Tiempo ciclo para integración EA
|
||||
"DB2025_TOT".TiempoCiclo.Actual := LREAL_TO_REAL(RUNTIME("DB2025_TOT".TiempoCiclo.auxMem));
|
||||
"DB2025_TOT".TiempoCiclo.Actual := ("DB2025_TOT".TiempoCiclo.Actual * 1000.0);
|
||||
|
||||
END_REGION TIEMPO_CICLO_INTEGRACION
|
||||
|
||||
|
||||
REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
// Numero maximo de dispositivos para limitar en HMI/Scada
|
||||
"DB2025_TOT".Mux.NumDispositivos := "N_MAX_DISP_TOT";
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_TOT" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_TOT";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
// Dispositivo habilitado
|
||||
IF "DB2025_TOT".TOT[#for_i].Config_Habilitar THEN
|
||||
|
||||
REGION LECTURA_VALORES
|
||||
|
||||
REGION ENTRADA_PULSOS
|
||||
|
||||
IF NOT #Simulacion THEN
|
||||
|
||||
IF "DB2025_TOT".TOT[#for_i].Config_DireccionEntradaByte > 0 THEN
|
||||
|
||||
// Lectura de la entrada digital
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Pulso := PEEK_BOOL(area := 16#81,
|
||||
dbNumber := 0,
|
||||
byteOffset := "DB2025_TOT".TOT[#for_i].Config_DireccionEntradaByte,
|
||||
bitOffset := "DB2025_TOT".TOT[#for_i].Config_DireccionEntradaBit);
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Pulso := #Pulso100ms;
|
||||
END_IF;
|
||||
|
||||
END_REGION ENTRADA_PULSOS
|
||||
|
||||
|
||||
REGION CAUDAL
|
||||
|
||||
IF "DB2025_TOT".TOT[#for_i].Estado_Valor > 0.0 THEN
|
||||
#t_CaudalSegundos := (("DB2025_TOT".TOT[#for_i].Estado_Valor / 3600000.0 * "DB2025_TOT".TiempoCiclo.Actual));
|
||||
ELSE
|
||||
#t_CaudalSegundos := 0.0;
|
||||
END_IF;
|
||||
|
||||
END_REGION CAUDAL
|
||||
|
||||
|
||||
|
||||
END_REGION LECTURA_VALORES
|
||||
|
||||
|
||||
REGION MODO_TRABAJO
|
||||
|
||||
REGION TOTALIZADORES
|
||||
|
||||
// Orden activacion totalizadores
|
||||
IF "DB2025_TOT".TOT[#for_i].Orden_Activar THEN
|
||||
|
||||
// 0 = TOTALIZADOR POR PULSOS
|
||||
// 1 = TOTALIZADOR POR EA
|
||||
IF NOT "DB2025_TOT".TOT[#for_i].Config_Tipo THEN // Caudalímetro por Pulso
|
||||
|
||||
IF "DB2025_TOT".TOT[#for_i].Estado_Pulso AND NOT "DB2025_TOT".TOT[#for_i].Aux_oldActivado THEN
|
||||
|
||||
IF NOT "DB2025_TOT".TOT[#for_i].Config_IncrDecr THEN
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Parcial += "DB2025_TOT".TOT[#for_i].Config_LitroXPulso;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Total += "DB2025_TOT".TOT[#for_i].Config_LitroXPulso;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Proceso += "DB2025_TOT".TOT[#for_i].Config_LitroXPulso;
|
||||
ELSE
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Parcial -= "DB2025_TOT".TOT[#for_i].Config_LitroXPulso;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Total -= "DB2025_TOT".TOT[#for_i].Config_LitroXPulso;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Proceso -= "DB2025_TOT".TOT[#for_i].Config_LitroXPulso;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
|
||||
ELSE
|
||||
|
||||
// Totalizador por EA
|
||||
IF NOT "DB2025_TOT".TOT[#for_i].Config_IncrDecr THEN
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Parcial += #t_CaudalSegundos;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Total += #t_CaudalSegundos;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Proceso += #t_CaudalSegundos;
|
||||
ELSE
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Parcial -= #t_CaudalSegundos;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Total -= #t_CaudalSegundos;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Proceso -= #t_CaudalSegundos;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TOTALIZADORES
|
||||
|
||||
|
||||
REGION TOTALIZADOR_USUARIO
|
||||
|
||||
IF "DB2025_TOT".TOT[#for_i].Orden_Usuario THEN
|
||||
|
||||
// 0 = TOTALIZADOR POR PULSOS
|
||||
// 1 = TOTALIZADOR POR EA
|
||||
IF NOT "DB2025_TOT".TOT[#for_i].Config_Tipo THEN // Caudalímetro por Pulso
|
||||
|
||||
IF "DB2025_TOT".TOT[#for_i].Estado_Pulso AND NOT "DB2025_TOT".TOT[#for_i].Aux_oldActivado THEN
|
||||
|
||||
IF NOT "DB2025_TOT".TOT[#for_i].Config_IncrDecr THEN
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Usuario += "DB2025_TOT".TOT[#for_i].Config_LitroXPulso;
|
||||
ELSE
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Usuario -= "DB2025_TOT".TOT[#for_i].Config_LitroXPulso;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// Totalizador por EA
|
||||
IF NOT "DB2025_TOT".TOT[#for_i].Config_IncrDecr THEN
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Usuario += #t_CaudalSegundos;
|
||||
ELSE
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Usuario -= #t_CaudalSegundos;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TOTALIZADOR_USUARIO
|
||||
|
||||
|
||||
REGION CALCULO_CAUDAL_TEORICO
|
||||
|
||||
IF NOT "DB2025_TOT".TOT[#for_i].Config_Tipo AND "DB2025_TOT".TOT[#for_i].Orden_Activar THEN
|
||||
|
||||
// Calculo teorico L/H
|
||||
IF #Pulso100ms THEN
|
||||
"DB2025_TOT".TOT[#for_i].Aux_AcuTiempo += 1;
|
||||
|
||||
IF "DB2025_TOT".TOT[#for_i].Aux_AcuTiempo > 10 THEN
|
||||
#t_LReal := "DB2025_TOT".TOT[#for_i].Estado_Total - "DB2025_TOT".TOT[#for_i].Aux_TotalizadorMem;
|
||||
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Valor := LREAL_TO_REAL(#t_LReal) * 36000.0 / "DB2025_TOT".TOT[#for_i].Aux_AcuTiempo;
|
||||
|
||||
"DB2025_TOT".TOT[#for_i].Aux_AcuTiempo := 0;
|
||||
"DB2025_TOT".TOT[#for_i].Aux_TotalizadorMem := "DB2025_TOT".TOT[#for_i].Estado_Total;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
ELSIF NOT "DB2025_TOT".TOT[#for_i].Config_Tipo AND "DB2025_TOT".TOT[#for_i].Orden_Usuario THEN
|
||||
|
||||
// Calculo teorico L/H
|
||||
IF #Pulso100ms THEN
|
||||
"DB2025_TOT".TOT[#for_i].Aux_AcuTiempo += 1;
|
||||
|
||||
IF "DB2025_TOT".TOT[#for_i].Aux_AcuTiempo > 10 THEN
|
||||
#t_LReal := "DB2025_TOT".TOT[#for_i].Estado_Usuario - "DB2025_TOT".TOT[#for_i].Aux_TotalizadorMem;
|
||||
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Valor := LREAL_TO_REAL(#t_LReal) * 36000.0 / "DB2025_TOT".TOT[#for_i].Aux_AcuTiempo;
|
||||
|
||||
"DB2025_TOT".TOT[#for_i].Aux_AcuTiempo := 0;
|
||||
"DB2025_TOT".TOT[#for_i].Aux_TotalizadorMem := "DB2025_TOT".TOT[#for_i].Estado_Usuario;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
"DB2025_TOT".TOT[#for_i].Aux_TotalizadorMem := 0.0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
// Estado anterior del pulso
|
||||
"DB2025_TOT".TOT[#for_i].Aux_oldActivado := "DB2025_TOT".TOT[#for_i].Estado_Pulso;
|
||||
|
||||
END_REGION MODO_TRABAJO
|
||||
|
||||
|
||||
REGION DIAGNOSIS
|
||||
|
||||
// Reset totalizador total por desbordamiento
|
||||
IF "DB2025_TOT".TOT[#for_i].Estado_Total >= #VALOR_MAXIMO_CONTADORES THEN
|
||||
"DB2025_TOT".TOT[#for_i].Estado_DesbordeTotal += 1;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Total := 0.0;
|
||||
END_IF;
|
||||
|
||||
// Reset totalizador parcial por desbordamiento
|
||||
IF "DB2025_TOT".TOT[#for_i].Estado_Parcial >= #VALOR_MAXIMO_CONTADORES THEN
|
||||
"DB2025_TOT".TOT[#for_i].Estado_DesbordeParcial += 1;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Parcial := 0.0;
|
||||
END_IF;
|
||||
|
||||
// Reset totalizador usuario por desbordamiento
|
||||
IF "DB2025_TOT".TOT[#for_i].Estado_Usuario >= #VALOR_MAXIMO_CONTADORES THEN
|
||||
"DB2025_TOT".TOT[#for_i].Estado_DesbordeUsuario += 1;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Usuario := 0.0;
|
||||
END_IF;
|
||||
|
||||
// Reset totalizador parcial
|
||||
IF "DB2025_TOT".TOT[#for_i].Orden_ResetParcial OR "DB2025_TOT".TOT[#for_i].Estado_DesbordeParcial > #NUMERO_MAXIMO_DESBORDE THEN
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Parcial := 0.0;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_DesbordeParcial := 0;
|
||||
"DB2025_TOT".TOT[#for_i].Orden_ResetParcial := FALSE;
|
||||
END_IF;
|
||||
|
||||
// Reset totalizador total
|
||||
IF "DB2025_TOT".TOT[#for_i].Orden_ResetTotal OR "DB2025_TOT".TOT[#for_i].Estado_DesbordeTotal > #NUMERO_MAXIMO_DESBORDE THEN
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Total := 0.0;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_DesbordeTotal := 0;
|
||||
"DB2025_TOT".TOT[#for_i].Orden_ResetTotal := FALSE;
|
||||
END_IF;
|
||||
|
||||
// Reset totalizador proceso
|
||||
IF "DB2025_TOT".TOT[#for_i].Orden_ResetProceso THEN
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Proceso := 0.0;
|
||||
"DB2025_TOT".TOT[#for_i].Orden_ResetProceso := FALSE;
|
||||
END_IF;
|
||||
|
||||
// Reset totalizador usuario
|
||||
IF "DB2025_TOT".TOT[#for_i].Orden_ResetUsuario THEN
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Usuario := 0.0;
|
||||
"DB2025_TOT".TOT[#for_i].Orden_ResetUsuario := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
ELSE
|
||||
|
||||
// Dispositivo no habilitado
|
||||
"DB2025_TOT".TOT[#for_i].Orden_Activar := FALSE;
|
||||
"DB2025_TOT".TOT[#for_i].Orden_ResetParcial := FALSE;
|
||||
"DB2025_TOT".TOT[#for_i].Orden_ResetProceso := FALSE;
|
||||
"DB2025_TOT".TOT[#for_i].Orden_ResetTotal := FALSE;
|
||||
"DB2025_TOT".TOT[#for_i].Orden_ResetUsuario := FALSE;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Valor := 0.0;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Parcial := 0.0;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Total := 0.0;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Proceso := 0.0;
|
||||
"DB2025_TOT".TOT[#for_i].Estado_Usuario := 0.0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
FUNCTION "FC2026_ZC_FF" : Void
|
||||
TITLE = FC2026_ZC_FF
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion de flip flop
|
||||
VAR_INPUT
|
||||
Pulso1Seg : Bool; // Pulso de 1 segundo
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
REPOSO : SInt := 0;
|
||||
FLOP : SInt := 10;
|
||||
PARO1 : SInt := 20;
|
||||
FLIP : SInt := 30;
|
||||
PARO2 : SInt := 40;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo flip flop con funcion de paro entre cambios.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y calculos de tiempo de cambio entre ordenes Flip, Flop y paro.
|
||||
- Adicionalmente, se gestiona tambien la posibilidad de pausar el contaje del tiempo, para evitar su reinicializacion en caso de pausa.
|
||||
- En los cambios entre ´flip´ <--> ´flop´, se activa tambien la marca ´paro´ para poder gestionar los cambios y evitar golpes de ariete.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2026_FF` |
|
||||
| UDT | `UDT_ZC_DISP_FF_PARO` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 10.08.2020 | (ABH) | Primera version. |
|
||||
| 00.00.02 | 02.10.2020 | (ABH) | Cambio en la logica del dispositivo, ya que al cambio de flip a flop, se perdia un segundo del contaje de tienmpo. |
|
||||
| 00.00.03 | 28.11.2023 | (ABH) | Se añade condicion de activacion del Flip Flop a que algun SP sea mayor que 0.. |
|
||||
| 00.00.04 | 15.10.2025 | (ABH) | Se añade orden pausa para dejar de contar. |
|
||||
| 01.00.00 | 06.07.2026 | (ABH) | Refactorizacion de logica para optimizacion. Se añade ordenes de paro (opcionales) para su uso para evitar golpes de ariete. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_FF" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_FF";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION COMPROBACIONES_INICIALES
|
||||
|
||||
// Si no hay orden o faltan tiempos, reseteamos valores y salimos de la funcion
|
||||
IF NOT "DB2026_FF".FF[#for_i].Orden_Activar OR ("DB2026_FF".FF[#for_i].Config_SetPointTiempoFlip <= 0 AND "DB2026_FF".FF[#for_i].Config_SetPointTiempoFlop <= 0) THEN
|
||||
"DB2026_FF".FF[#for_i].Estado_Flip := FALSE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Flop := FALSE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Paro1 := FALSE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Paro2 := FALSE;
|
||||
|
||||
"DB2026_FF".FF[#for_i].Aux_Tiempo := 0;
|
||||
"DB2026_FF".FF[#for_i].Estado_Etapa := #REPOSO;
|
||||
|
||||
"DB2026_FF".FF[#for_i].Aux_Inicializado := FALSE;
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
END_REGION COMPROBACIONES_INICIALES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION INICIALIZACION
|
||||
|
||||
// Arranque inicial forzado a Flop si no hay estado activo
|
||||
IF NOT "DB2026_FF".FF[#for_i].Aux_Inicializado THEN
|
||||
"DB2026_FF".FF[#for_i].Estado_Etapa := #FLOP;
|
||||
"DB2026_FF".FF[#for_i].Aux_Inicializado := TRUE;
|
||||
END_IF;
|
||||
|
||||
END_REGION INICIALIZACION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION LOGICA_DE_ESTADOS
|
||||
|
||||
CASE "DB2026_FF".FF[#for_i].Estado_Etapa OF
|
||||
|
||||
#FLOP:
|
||||
// Salidas
|
||||
"DB2026_FF".FF[#for_i].Estado_Flip := FALSE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Flop := TRUE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Paro1 := FALSE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Paro2 := FALSE;
|
||||
|
||||
// Conteo de tiempo
|
||||
IF #Pulso1Seg AND NOT "DB2026_FF".FF[#for_i].Orden_Pausa THEN
|
||||
"DB2026_FF".FF[#for_i].Aux_Tiempo += 1;
|
||||
END_IF;
|
||||
|
||||
// Transición
|
||||
IF "DB2026_FF".FF[#for_i].Aux_Tiempo >= "DB2026_FF".FF[#for_i].Config_SetPointTiempoFlop THEN
|
||||
"DB2026_FF".FF[#for_i].Aux_Tiempo := 0;
|
||||
// Si no tenemos tiempo de paro configurado, saltamos a FLIP
|
||||
IF "DB2026_FF".FF[#for_i].Config_SetPointTiempoParo <= 0 THEN
|
||||
"DB2026_FF".FF[#for_i].Estado_Etapa := #FLIP;
|
||||
ELSE
|
||||
"DB2026_FF".FF[#for_i].Estado_Etapa := #PARO1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
#PARO1:
|
||||
// Salidas
|
||||
"DB2026_FF".FF[#for_i].Estado_Flip := FALSE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Flop := FALSE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Paro1 := TRUE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Paro2 := FALSE;
|
||||
|
||||
// Conteo de tiempo
|
||||
IF #Pulso1Seg AND NOT "DB2026_FF".FF[#for_i].Orden_Pausa THEN
|
||||
"DB2026_FF".FF[#for_i].Aux_Tiempo += 1;
|
||||
END_IF;
|
||||
|
||||
// Transición
|
||||
IF "DB2026_FF".FF[#for_i].Aux_Tiempo >= "DB2026_FF".FF[#for_i].Config_SetPointTiempoParo THEN
|
||||
"DB2026_FF".FF[#for_i].Aux_Tiempo := 0;
|
||||
"DB2026_FF".FF[#for_i].Estado_Etapa := #FLIP;
|
||||
END_IF;
|
||||
|
||||
|
||||
#FLIP:
|
||||
// Salidas
|
||||
"DB2026_FF".FF[#for_i].Estado_Flip := TRUE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Flop := FALSE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Paro1 := FALSE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Paro2 := FALSE;
|
||||
|
||||
// Conteo de tiempo
|
||||
IF #Pulso1Seg AND NOT "DB2026_FF".FF[#for_i].Orden_Pausa THEN
|
||||
"DB2026_FF".FF[#for_i].Aux_Tiempo += 1;
|
||||
END_IF;
|
||||
|
||||
// Transición
|
||||
IF "DB2026_FF".FF[#for_i].Aux_Tiempo >= "DB2026_FF".FF[#for_i].Config_SetPointTiempoFlip THEN
|
||||
"DB2026_FF".FF[#for_i].Aux_Tiempo := 0;
|
||||
// Si no tenemos tiempo de paro configurado, saltamos a FLOP
|
||||
IF "DB2026_FF".FF[#for_i].Config_SetPointTiempoParo <= 0 THEN
|
||||
"DB2026_FF".FF[#for_i].Estado_Etapa := #FLOP;
|
||||
ELSE
|
||||
"DB2026_FF".FF[#for_i].Estado_Etapa := #PARO2;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
|
||||
#PARO2:
|
||||
// Salidas
|
||||
"DB2026_FF".FF[#for_i].Estado_Flip := FALSE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Flop := FALSE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Paro1 := FALSE;
|
||||
"DB2026_FF".FF[#for_i].Estado_Paro2 := TRUE;
|
||||
|
||||
// Conteo de tiempo
|
||||
IF #Pulso1Seg AND NOT "DB2026_FF".FF[#for_i].Orden_Pausa THEN
|
||||
"DB2026_FF".FF[#for_i].Aux_Tiempo += 1;
|
||||
END_IF;
|
||||
|
||||
// Transición
|
||||
IF "DB2026_FF".FF[#for_i].Aux_Tiempo >= "DB2026_FF".FF[#for_i].Config_SetPointTiempoParo THEN
|
||||
"DB2026_FF".FF[#for_i].Aux_Tiempo := 0;
|
||||
"DB2026_FF".FF[#for_i].Estado_Etapa := #FLOP;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
"DB2026_FF".FF[#for_i].Estado_Etapa := #REPOSO;
|
||||
END_CASE;
|
||||
|
||||
END_REGION LOGICA_DE_ESTADOS
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
FUNCTION "FC2027_ZC_FF_SEC" : Void
|
||||
TITLE = FC2027_ZC_FF_SEC
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion de Flip Flop secuencial
|
||||
VAR_INPUT
|
||||
Pulso1Seg : Bool; // Pulso 1 segundo
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
for_j : Int;
|
||||
t_SumaFlip : Int;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
REPOSO : SInt := 0;
|
||||
FLOP : SInt := 10;
|
||||
FLIP : SInt := 20;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2023 - 2025
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo flip flop secuencial.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y calculos de tiempo de cambio entre ordenes Flip y Flop.
|
||||
- Adicionalmente, se gestiona tambien la posibilidad de pausar el contaje del tiempo, para evitar su reinicializacion en caso de pausa.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2027_FF_SEC` |
|
||||
| UDT | `UDT_ZC_DISP_FF_SEC` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 02.10.2023 | (ABH) | Primera version. |
|
||||
| 00.00.02 | 28.11.2023 | (ABH) | Se añade condicion de activacion del Flip Flop a que algun SP sea mayor que 0. |
|
||||
| 01.00.00 | 15.10.2025 | (ABH) | Se añade orden pausa para dejar de contar. Refactorizacion de logica de gestion de flips. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_FF_SEC" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_FF_SEC";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION COMPROBACIONES_INICIALES
|
||||
|
||||
// Suma de seguridad por FOR (Determinista)
|
||||
#t_SumaFlip := 0;
|
||||
FOR #for_j := 1 TO 10 DO
|
||||
#t_SumaFlip += "DB2027_FF_SEC".FF_SEC[#for_i].Config_SetPointTiempoFlip[#for_j];
|
||||
END_FOR;
|
||||
|
||||
// Si no hay orden o los tiempos globales son 0, reseteamos valores y salimos de la funcion
|
||||
IF NOT "DB2027_FF_SEC".FF_SEC[#for_i].Orden_Activar OR (#t_SumaFlip <= 0 AND "DB2027_FF_SEC".FF_SEC[#for_i].Config_SetPointTiempoFlop <= 0) THEN
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Estado_SalidaFlop := FALSE;
|
||||
FOR #for_j := 1 TO 10 DO
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Estado_SalidaFlip[#for_j] := FALSE;
|
||||
END_FOR;
|
||||
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_Tiempo := 0;
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Estado_Etapa := #REPOSO;
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_FlipActual := 0;
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_Inicializacion := FALSE;
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
END_REGION COMPROBACIONES_INICIALES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION INICIALIZACION
|
||||
|
||||
// Arranque inicial forzado a Flop si no hay estado activo
|
||||
IF NOT "DB2027_FF_SEC".FF_SEC[#for_i].Aux_Inicializacion THEN
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Estado_Etapa := #FLOP;
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_FlipActual := 0;
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_Inicializacion := TRUE;
|
||||
END_IF;
|
||||
|
||||
END_REGION INICIALIZACION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION LOGICA_DE_ESTADOS
|
||||
|
||||
CASE "DB2027_FF_SEC".FF_SEC[#for_i].Estado_Etapa OF
|
||||
|
||||
#FLOP:
|
||||
// Salidas
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Estado_SalidaFlop := TRUE;
|
||||
FOR #for_j := 1 TO 10 DO
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Estado_SalidaFlip[#for_j] := FALSE;
|
||||
END_FOR;
|
||||
|
||||
// Conteo de tiempo
|
||||
IF #Pulso1Seg AND NOT "DB2027_FF_SEC".FF_SEC[#for_i].Orden_Pausa THEN
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_Tiempo += 1;
|
||||
END_IF;
|
||||
|
||||
// Transición
|
||||
IF "DB2027_FF_SEC".FF_SEC[#for_i].Aux_Tiempo >= "DB2027_FF_SEC".FF_SEC[#for_i].Config_SetPointTiempoFlop THEN
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_Tiempo := 0;
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_FlipActual := 11; // Fallback por defecto
|
||||
|
||||
// Buscar primer Flip válido
|
||||
FOR #for_j := 1 TO 10 DO
|
||||
IF "DB2027_FF_SEC".FF_SEC[#for_i].Config_SetPointTiempoFlip[#for_j] > 0 THEN
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_FlipActual := #for_j;
|
||||
EXIT; // Corta el FOR en el primer acierto
|
||||
END_IF;
|
||||
END_FOR;
|
||||
|
||||
// Transición si encontró algo válido
|
||||
IF "DB2027_FF_SEC".FF_SEC[#for_i].Aux_FlipActual <= 10 THEN
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Estado_Etapa := #FLIP;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
#FLIP:
|
||||
// Salidas
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Estado_SalidaFlop := FALSE;
|
||||
FOR #for_j := 1 TO 10 DO
|
||||
IF #for_j = "DB2027_FF_SEC".FF_SEC[#for_i].Aux_FlipActual THEN
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Estado_SalidaFlip[#for_j] := TRUE;
|
||||
ELSE
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Estado_SalidaFlip[#for_j] := FALSE;
|
||||
END_IF;
|
||||
END_FOR;
|
||||
|
||||
// Conteo de tiempo
|
||||
IF #Pulso1Seg AND NOT "DB2027_FF_SEC".FF_SEC[#for_i].Orden_Pausa THEN
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_Tiempo += 1;
|
||||
END_IF;
|
||||
|
||||
/// Transición
|
||||
IF "DB2027_FF_SEC".FF_SEC[#for_i].Aux_Tiempo >= "DB2027_FF_SEC".FF_SEC[#for_i].Config_SetPointTiempoFlip["DB2027_FF_SEC".FF_SEC[#for_i].Aux_FlipActual] THEN
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_Tiempo := 0;
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_FlipActual += 1; // Apunta al siguiente
|
||||
|
||||
// Búsqueda del siguiente Flip válido
|
||||
FOR #for_j := "DB2027_FF_SEC".FF_SEC[#for_i].Aux_FlipActual TO 10 DO
|
||||
IF "DB2027_FF_SEC".FF_SEC[#for_i].Config_SetPointTiempoFlip[#for_j] > 0 THEN
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_FlipActual := #for_j;
|
||||
EXIT;
|
||||
END_IF;
|
||||
// Si llega al final sin encontrar nada
|
||||
IF #for_j = 10 THEN
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Aux_FlipActual := 11;
|
||||
END_IF;
|
||||
END_FOR;
|
||||
|
||||
// Si rebasó el límite, vuelve al Flop
|
||||
IF "DB2027_FF_SEC".FF_SEC[#for_i].Aux_FlipActual > 10 THEN
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Estado_Etapa := #FLOP;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
"DB2027_FF_SEC".FF_SEC[#for_i].Estado_Etapa := #REPOSO;
|
||||
END_CASE;
|
||||
|
||||
END_REGION LOGICA_DE_ESTADOS
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
FUNCTION "FC2028_ZC_TEMP" : Void
|
||||
TITLE = FC2028_ZC_TEMP
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion de temporizadorres TON, TOF, TONR y TP (Base 1 seg)
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2022 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo TON.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y temporizacion de la activacion del temporizador.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2028_TEMP` |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 02.10.2022 | (ABH) | Primera version. |
|
||||
| 00.00.02 | 03.05.2022 | (ABH) | TONR. Se añade tiempo Restante. |
|
||||
| 00.00.03 | 13.09.2023 | (ABH) | TP. Se elimina la marca "Flanco" ya que no es necesaria. Se utiliza solamente la marca "oldIN" para la deteccion de flancos. |
|
||||
| 00.00.04 | 13.08.2025 | (ABH) | TONR. Se modifica activacion de salida Q sin dependencia de entrada IN. |
|
||||
| 01.00.00 | 06.07.2026 | (ABH) | Se unifican los temporizadores en un solo DB y en un solo FC |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO_TON
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_TON";
|
||||
|
||||
IF #t_N_MAX >= 1 THEN
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
IF "DB2028_TEMP".TON[#for_i].IN THEN
|
||||
IF "DB2028_TEMP".TON[#for_i].ET >= "DB2028_TEMP".TON[#for_i].SP THEN
|
||||
"DB2028_TEMP".TON[#for_i].Q := TRUE;
|
||||
ELSE
|
||||
IF #Pulso1seg THEN
|
||||
"DB2028_TEMP".TON[#for_i].ET += 1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2028_TEMP".TON[#for_i].ET := 0;
|
||||
"DB2028_TEMP".TON[#for_i].Q := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO_TON
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO_TOF
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_TOF";
|
||||
|
||||
IF #t_N_MAX >= 1 THEN
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
IF "DB2028_TEMP".TOF[#for_i].IN THEN
|
||||
"DB2028_TEMP".TOF[#for_i].OldActivar := TRUE;
|
||||
"DB2028_TEMP".TOF[#for_i].Q := TRUE;
|
||||
END_IF;
|
||||
IF "DB2028_TEMP".TOF[#for_i].OldActivar AND NOT "DB2028_TEMP".TOF[#for_i].IN THEN
|
||||
|
||||
IF "DB2028_TEMP".TOF[#for_i].ET <= 0 THEN
|
||||
"DB2028_TEMP".TOF[#for_i].Q := FALSE;
|
||||
"DB2028_TEMP".TOF[#for_i].OldActivar := FALSE;
|
||||
ELSE
|
||||
IF #Pulso1seg THEN
|
||||
"DB2028_TEMP".TOF[#for_i].ET -= 1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2028_TEMP".TOF[#for_i].ET := "DB2028_TEMP".TOF[#for_i].SP;
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO_TOF
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO_TONR
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_TONR";
|
||||
|
||||
IF #t_N_MAX >= 1 THEN
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
IF "DB2028_TEMP".TONR[#for_i].RESET THEN
|
||||
"DB2028_TEMP".TONR[#for_i].ET := 0;
|
||||
"DB2028_TEMP".TONR[#for_i].Q := FALSE;
|
||||
"DB2028_TEMP".TONR[#for_i].RESET := FALSE;
|
||||
END_IF;
|
||||
|
||||
IF "DB2028_TEMP".TONR[#for_i].IN AND
|
||||
"DB2028_TEMP".TONR[#for_i].ET < "DB2028_TEMP".TONR[#for_i].SP AND
|
||||
#Pulso1seg
|
||||
THEN
|
||||
"DB2028_TEMP".TONR[#for_i].ET += 1;
|
||||
"DB2028_TEMP".TONR[#for_i].Q := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
IF "DB2028_TEMP".TONR[#for_i].ET >= "DB2028_TEMP".TONR[#for_i].SP THEN
|
||||
"DB2028_TEMP".TONR[#for_i].Q := TRUE;
|
||||
END_IF;
|
||||
|
||||
"DB2028_TEMP".TONR[#for_i].RT := "DB2028_TEMP".TONR[#for_i].SP - "DB2028_TEMP".TONR[#for_i].ET;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO_TONR
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO_TP
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_TP";
|
||||
|
||||
IF #t_N_MAX >= 1 THEN
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
// =============================================================================
|
||||
// Detección de flanco
|
||||
IF "DB2028_TEMP".TP[#for_i].IN AND NOT "DB2028_TEMP".TP[#for_i].oldIN THEN
|
||||
"DB2028_TEMP".TP[#for_i].Q := TRUE;
|
||||
END_IF;
|
||||
|
||||
// Actualizo valor de memoria
|
||||
"DB2028_TEMP".TP[#for_i].oldIN := "DB2028_TEMP".TP[#for_i].IN;
|
||||
|
||||
// =============================================================================
|
||||
// Reinicio memoria de activación cuando piedo salida y cuento tiempo
|
||||
IF NOT "DB2028_TEMP".TP[#for_i].IN THEN
|
||||
"DB2028_TEMP".TP[#for_i].oldIN := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// Incremento de tiempo
|
||||
IF "DB2028_TEMP".TP[#for_i].Q
|
||||
AND
|
||||
"DB2028_TEMP".TP[#for_i].ET < "DB2028_TEMP".TP[#for_i].PT
|
||||
AND
|
||||
#Pulso1seg
|
||||
THEN
|
||||
"DB2028_TEMP".TP[#for_i].ET += 1;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// Desactivo salida cuando cumplo tiempo de retardo de salida
|
||||
IF "DB2028_TEMP".TP[#for_i].ET >= "DB2028_TEMP".TP[#for_i].PT THEN
|
||||
"DB2028_TEMP".TP[#for_i].Q := FALSE;
|
||||
"DB2028_TEMP".TP[#for_i].ET := 0;
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO_TP
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
FUNCTION "FC2037_ZC_MEDIA" : Void
|
||||
TITLE = FC2037_ZC_MEDIA
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion medias
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool; // Pulso de 1 segundo
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
t_NumeroDatos : LReal;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2022 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo Media.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y calculo de la media.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2037_MEDIA` |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 01.02.2022 | (ABH) | Primera version. |
|
||||
| 00.00.02 | 18.09.2023 | (ABH) | Se añade valor maximo y valor minimo del valor instanteneo de la media cuando esta iniciada la media. |
|
||||
| 01.00.00 | 06.07.2026 | (ABH) | Cambio a SCL. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_MEDIA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_MEDIA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION REINICIALIZACION_DE_DATOS
|
||||
|
||||
// Reset temporizador interno si no esta habilitada la media
|
||||
IF NOT "DB2037_MEDIA".MEDIA[#for_i].IniciarMedia THEN
|
||||
"DB2037_MEDIA".MEDIA[#for_i].auxTiempo := 0;
|
||||
END_IF;
|
||||
|
||||
// Reinicializacion de datos al inicializar
|
||||
IF "DB2037_MEDIA".MEDIA[#for_i].Inicializar AND NOT "DB2037_MEDIA".MEDIA[#for_i].auxInicializar THEN
|
||||
"DB2037_MEDIA".MEDIA[#for_i].auxAcumulado := 0.0;
|
||||
"DB2037_MEDIA".MEDIA[#for_i].auxIndice := 0;
|
||||
"DB2037_MEDIA".MEDIA[#for_i].auxTiempo := 0;
|
||||
"DB2037_MEDIA".MEDIA[#for_i].ValorMinimo := 9999999.0;
|
||||
"DB2037_MEDIA".MEDIA[#for_i].ValorMaximo := -9999999.0;
|
||||
END_IF;
|
||||
|
||||
// Estado anterior
|
||||
"DB2037_MEDIA".MEDIA[#for_i].auxInicializar := "DB2037_MEDIA".MEDIA[#for_i].Inicializar;
|
||||
|
||||
END_REGION REINICIALIZACION_DE_DATOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION TOMA_DE_VALORES
|
||||
|
||||
IF "DB2037_MEDIA".MEDIA[#for_i].IniciarMedia AND #Pulso1seg THEN
|
||||
|
||||
// Incrementamos el indice de tiempo
|
||||
"DB2037_MEDIA".MEDIA[#for_i].auxTiempo += 1;
|
||||
|
||||
// En caso de superar el tiempo de muestreo, incrementamos el acumulado, reseteamos el tiempo y aumentamos el indice
|
||||
IF "DB2037_MEDIA".MEDIA[#for_i].auxTiempo >= "DB2037_MEDIA".MEDIA[#for_i].TiempoMuestreo THEN
|
||||
|
||||
"DB2037_MEDIA".MEDIA[#for_i].auxAcumulado := "DB2037_MEDIA".MEDIA[#for_i].ValorActual + "DB2037_MEDIA".MEDIA[#for_i].auxAcumulado;
|
||||
"DB2037_MEDIA".MEDIA[#for_i].auxIndice += 1;
|
||||
"DB2037_MEDIA".MEDIA[#for_i].auxTiempo := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
// Guardamos el valor minimo alcanzado
|
||||
IF "DB2037_MEDIA".MEDIA[#for_i].ValorActual < "DB2037_MEDIA".MEDIA[#for_i].ValorMinimo THEN
|
||||
"DB2037_MEDIA".MEDIA[#for_i].ValorMinimo := "DB2037_MEDIA".MEDIA[#for_i].ValorActual;
|
||||
END_IF;
|
||||
|
||||
// Guardamos el valor maximo alcanzado
|
||||
IF "DB2037_MEDIA".MEDIA[#for_i].ValorActual > "DB2037_MEDIA".MEDIA[#for_i].ValorMaximo THEN
|
||||
"DB2037_MEDIA".MEDIA[#for_i].ValorMaximo := "DB2037_MEDIA".MEDIA[#for_i].ValorActual;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// Conversion de indice a REAL para calculos
|
||||
#t_NumeroDatos := DINT_TO_LREAL("DB2037_MEDIA".MEDIA[#for_i].auxIndice);
|
||||
|
||||
END_REGION TOMA_DE_VALORES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION CALCULO_MEDIA
|
||||
|
||||
IF "DB2037_MEDIA".MEDIA[#for_i].auxIndice > 0 THEN
|
||||
"DB2037_MEDIA".MEDIA[#for_i].Media := "DB2037_MEDIA".MEDIA[#for_i].auxAcumulado / #t_NumeroDatos;
|
||||
ELSE
|
||||
"DB2037_MEDIA".MEDIA[#for_i].Media := 0.0;
|
||||
END_IF;
|
||||
|
||||
END_REGION CALCULO_MEDIA
|
||||
|
||||
END_FOR;
|
||||
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
FUNCTION "FC2038_ZC_MEDIA_VOL" : Void
|
||||
TITLE = FC2038_ZC_MEDIA_VOL
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion de media teniendo en cuenta el volumen/caudal.
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool; // Pulso de 1 segundo
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
t_NumeroDatos : LReal;
|
||||
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 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo Media volumen.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y calculo de la media teniendo en cuenta el volumen/caudal.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_DISP_MEDIA_VOLUMEN` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 01.02.2024 | (ABH) | Primera version. |
|
||||
| 00.00.02 | 16.02.2024 | (ABH) | Cambio de tipo de dato auxVolumen de REAL a LREAL. |
|
||||
| 01.00.00 | 06.07.2026 | (ABH) | Cambio a SCL. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivo declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_MEDIA_VOLUMEN" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_MEDIA_VOLUMEN";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION REINICIALIZACION_DE_DATOS
|
||||
|
||||
// Reset temporizador interno si no esta habilitada la media
|
||||
IF NOT "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].IniciarMedia THEN
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxTiempo := 0;
|
||||
END_IF;
|
||||
|
||||
// Reinicializacion de datos al inicializar
|
||||
IF "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].Inicializar AND NOT "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxInicializar THEN
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxAcumulado :=
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxVolumen :=
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxValorMedia :=
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].Media := 0.0;
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxTiempo := 0;
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].ValorMinimo := 9999999.0;
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].ValorMaximo := -9999999.0;
|
||||
END_IF;
|
||||
|
||||
// Estado anterior
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxInicializar := "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].Inicializar;
|
||||
|
||||
END_REGION REINICIALIZACION_DE_DATOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION TOMA_DE_VALORES
|
||||
|
||||
IF "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].IniciarMedia AND #Pulso1seg THEN
|
||||
|
||||
// Incrementamos el indice de tiempo
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxTiempo += 1;
|
||||
|
||||
// En caso de superar el tiempo de muestreo, incrementamos el acumulado, reseteamos el tiempo y aumentamos el indice
|
||||
IF "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxTiempo >= "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].TiempoMuestreo THEN
|
||||
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxValorMedia := ("DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].Volumen - "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxVolumen) * "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].ValorActual;
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxVolumen := "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].Volumen;
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxAcumulado := "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxValorMedia + "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxAcumulado;
|
||||
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].Media := "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxAcumulado / "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].Volumen;
|
||||
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].auxTiempo := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
// Guardamos el valor minimo alcanzado
|
||||
IF "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].ValorActual < "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].ValorMinimo THEN
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].ValorMinimo := "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].ValorActual;
|
||||
END_IF;
|
||||
|
||||
// Guardamos el valor maximo alcanzado
|
||||
IF "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].ValorActual > "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].ValorMaximo THEN
|
||||
"DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].ValorMaximo := "DB2038_MEDIA_VOL".MEDIA_VOL[#for_i].ValorActual;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TOMA_DE_VALORES
|
||||
|
||||
END_FOR;
|
||||
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
FUNCTION "FC2041_ZC_TQ_AE" : Void
|
||||
TITLE = FC2041_ZC_TQ_AE
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : HCR
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool;
|
||||
Arranque : Bool;
|
||||
Ack : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_N_MAX : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : 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
|
||||
Bloque de gestión de dispositivos `TQ Aire Estéril`. Realiza la lógica de control, supervisión, alarmas y trazabilidad de los tanques de aire estéril de la planta, así como el multiplexado de los dispositivos hacia los distintos clientes HMI/SCADA.
|
||||
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
Acciones detalladas:
|
||||
- Inicializa los índices de multiplexado a `0` en el arranque del PLC.
|
||||
- Gestiona los límites del índice (`Index`) y el flag `MaxVisible` para cada cliente HMI/SCADA.
|
||||
- Realiza la carga inicial del dispositivo seleccionado al detectar un cambio de índice.
|
||||
- Sincroniza los datos de lectura del dispositivo hacia la estructura del multiplexado (`Mux[...]`).
|
||||
- Sincroniza los datos de escritura desde el multiplexado hacia el dispositivo, marcando `ExisteCambio` cuando se modifica algún valor.
|
||||
- Propaga los cambios realizados desde SCADA al resto de multiplexados que tengan seleccionado el mismo dispositivo.
|
||||
- Resetea los flags `AlgunaAlarma` y `AlgunaEnManual` de las agrupaciones de alarma en cada ciclo.
|
||||
- Gestiona los modos de trabajo `AutoMan` y la orden `Orden_Manual`.
|
||||
- Gestiona las alarmas de configuración, presión baja y presión alta, con temporización de confirmación mediante `Pulso1seg`.
|
||||
- Controla la válvula de ducha durante el ciclo CIP mediante lógica flip-flop temporizada.
|
||||
- Controla la válvula de venteo, inhibida por las alarmas de presión.
|
||||
- Controla la válvula de estéril de forma modulante en función de la presión de trabajo.
|
||||
- Registra la trazabilidad de los cambios de modo Auto/Manual y de la activación/desactivación de la orden manual mediante `FC8_ZC_TRAZA_REGISTRO`.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC8_ZC_TRAZA_REGISTRO` |
|
||||
| FB | - |
|
||||
| DB | `DB2041_ZC_TQ_AE` |
|
||||
| UDT | `ZC_DISP_TQ_AE` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 15.10.2024 | (HCR) | Primera versión. |
|
||||
| 00.00.02 | 28.01.2025 | (ABH) | Se añade estado AutoMan y orden manual. Se añade trazabilidad. Se añade multiplexado. |
|
||||
| 00.00.03 | 26.03.2025 | (ABH) | Se añade variable grupo de alarma para separar los nuevos avisos por cuadro. |
|
||||
| 00.00.04 | 24.04.2025 | (HCR) | Se añade gestión de idioma. |
|
||||
| 00.00.05 | 11.09.2025 | (ABH) | Se eliminan las constantes de idioma dentro del FC. Se utilizan constantes globales para facilitar su traducción. |
|
||||
| 00.00.06 | 17.12.2025 | (ABH) | Se eliminan los idiomas. Se utiliza códigos para trazabilidad. Se elimina entrada "Idioma". Se elimina nombre de UDT. |
|
||||
| 01.00.00 | 08.07.2026 | (ABH) | Se extrae el multiplexado a FC independiente. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// Resetear todas las alarmas para que se vuelvan a generar
|
||||
FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
|
||||
"DB2041_TQ_AE".Agrup[#for_i].AlgunaAlarma := FALSE;
|
||||
"DB2041_TQ_AE".Agrup[#for_i].AlgunaEnManual := FALSE;
|
||||
END_FOR;
|
||||
|
||||
// Numero maximo de dispositivos para limitar en HMI/Scada
|
||||
"DB2041_TQ_AE".Mux.NumDispositivos := "N_MAX_DISP_TQ_AE";
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay dispositivos declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_DISP_TQ_AE" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_DISP_TQ_AE";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
FOR #for_i := 1 TO #t_N_MAX DO
|
||||
|
||||
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Config_Habilitar THEN
|
||||
|
||||
REGION MODOS_DE_TRABAJO
|
||||
|
||||
// =============================================================================
|
||||
// MODO MANUAL
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan THEN
|
||||
"DB2041_TQ_AE".Agrup["DB2041_TQ_AE".TQ_AE[#for_i].Config_GrupoAlarma].AlgunaEnManual := TRUE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// MODO AUTO
|
||||
IF NOT "DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Orden_Manual := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION ALARMAS
|
||||
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Config_HabilitarAlarmas THEN
|
||||
|
||||
// =============================================================================
|
||||
// ALARMA DE CONFIGURACION
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Alarma_Configuracion := TRUE;
|
||||
IF ("DB2041_TQ_AE".TQ_AE[#for_i].Config_PresionMinAlarma < "DB2041_TQ_AE".TQ_AE[#for_i].Config_PresionMinTrabajo) AND
|
||||
("DB2041_TQ_AE".TQ_AE[#for_i].Config_PresionMinTrabajo < "DB2041_TQ_AE".TQ_AE[#for_i].Config_PresionMaxTrabajo) AND
|
||||
("DB2041_TQ_AE".TQ_AE[#for_i].Config_PresionMaxTrabajo < "DB2041_TQ_AE".TQ_AE[#for_i].Config_PresionMaxAlarma) THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Alarma_Configuracion := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ALARMA MINIMA PRESION
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Alarma_PresionBaja := FALSE;
|
||||
IF ("DB2041_TQ_AE".TQ_AE[#for_i].Estado_ValorPresion < "DB2041_TQ_AE".TQ_AE[#for_i].Config_PresionMinAlarma)
|
||||
AND
|
||||
NOT #Ack
|
||||
THEN
|
||||
IF ("DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_AlarmaMinPresion >= "DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_SetPointAlarmaMinPresion) AND "DB2041_TQ_AE".TQ_AE[#for_i].Orden_Vaciado THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Alarma_PresionBaja := TRUE;
|
||||
ELSE
|
||||
IF #Pulso1seg THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_AlarmaMinPresion += 1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_AlarmaMinPresion := 0;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ALARMA MAXIMA PRESION
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Alarma_PresionAlta := FALSE;
|
||||
IF ("DB2041_TQ_AE".TQ_AE[#for_i].Estado_ValorPresion > "DB2041_TQ_AE".TQ_AE[#for_i].Config_PresionMaxAlarma)
|
||||
|
||||
THEN
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_AlarmaMaxPresion >= "DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_SetPointAlarmaMaxPresion THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Alarma_PresionAlta := TRUE;
|
||||
ELSE
|
||||
IF #Pulso1seg THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_AlarmaMaxPresion += 1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_AlarmaMaxPresion := 0;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Alarma_Configuracion :=
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Alarma_PresionAlta :=
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Alarma_PresionBaja := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION VALVULA_DUCHA
|
||||
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Orden_CIP AND
|
||||
("DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_SetPointFlipDucha > 0
|
||||
OR
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_SetPointFlopDucha > 0)
|
||||
THEN
|
||||
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaFlanco = FALSE THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaSalidaFlop := TRUE;
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaFlanco := TRUE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// GESTION TIEMPO FLIP FLOP
|
||||
IF #Pulso1seg THEN
|
||||
|
||||
// =============================================================================
|
||||
// CUENTA FLIP
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaFlipActivo = TRUE THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_DuchaTiempoFlip += 1;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// CUENTA FLOP
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaFlopActivo = TRUE THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_DuchaTiempoFlop += 1;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// GESTION LOGICA Y SALIDAS FLIP
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_DuchaTiempoFlip >= "DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_SetPointFlipDucha THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaSalidaFlip := FALSE;
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaSalidaFlop := TRUE;
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_DuchaTiempoFlip := 0;
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaFlipActivo := false;
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaFlopActivo := true;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// GESTION LOGICA Y SALIDAS FLOP
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_DuchaTiempoFlop >= "DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_SetPointFlopDucha THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaSalidaFlip := TRUE;
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaSalidaFlop := FALSE;
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Tiempos_DuchaTiempoFlop := 0;
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaFlipActivo := true;
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaFlopActivo := false;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// GESTION LOGICA SALIDA DUCHA
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Salida_ValvulaDucha :=
|
||||
|
||||
(
|
||||
NOT "DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan
|
||||
AND
|
||||
(
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Orden_Produccion
|
||||
OR
|
||||
("DB2041_TQ_AE".TQ_AE[#for_i].Orden_CIP AND "DB2041_TQ_AE".TQ_AE[#for_i].Aux_DuchaSalidaFlip)
|
||||
)
|
||||
)
|
||||
OR
|
||||
("DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan AND "DB2041_TQ_AE".TQ_AE[#for_i].Orden_Manual);
|
||||
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION VALVULA_VENTEO
|
||||
|
||||
// =============================================================================
|
||||
// GESTION LOGICA SALIDA VENTEO
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Salida_ValvulaVenteo :=
|
||||
(
|
||||
(NOT "DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan AND "DB2041_TQ_AE".TQ_AE[#for_i].Orden_Produccion)
|
||||
OR
|
||||
("DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan AND "DB2041_TQ_AE".TQ_AE[#for_i].Orden_Manual)
|
||||
)
|
||||
AND
|
||||
NOT "DB2041_TQ_AE".TQ_AE[#for_i].Alarma_PresionAlta AND NOT "DB2041_TQ_AE".TQ_AE[#for_i].Alarma_PresionBaja;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION VALVULA_ESTERIL
|
||||
|
||||
// =============================================================================
|
||||
// GESTION LOGICA SALIDA ESTERIL
|
||||
IF (NOT "DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan AND "DB2041_TQ_AE".TQ_AE[#for_i].Orden_Produccion)
|
||||
OR
|
||||
("DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan AND "DB2041_TQ_AE".TQ_AE[#for_i].Orden_Manual)
|
||||
THEN
|
||||
IF NOT "DB2041_TQ_AE".TQ_AE[#for_i].Alarma_Configuracion AND NOT "DB2041_TQ_AE".TQ_AE[#for_i].Alarma_PresionBaja THEN
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Estado_ValorPresion <= "DB2041_TQ_AE".TQ_AE[#for_i].Config_PresionMinTrabajo THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Salida_ValvulaEsteril := TRUE;
|
||||
END_IF;
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Estado_ValorPresion >= "DB2041_TQ_AE".TQ_AE[#for_i].Config_PresionMaxTrabajo THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Salida_ValvulaEsteril := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Salida_ValvulaEsteril := FALSE;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Salida_ValvulaEsteril := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION TRAZABILIDAD_MANUALIZACION
|
||||
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan AND NOT "DB2041_TQ_AE".TQ_AE[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := "DB1_SYS".FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_20_DISP_TQ_AE",
|
||||
User := "DB1_SYS".Usuario.Actual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_TQ_AE",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF NOT "DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan AND "DB2041_TQ_AE".TQ_AE[#for_i].Aux_oldAutoMan THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := "DB1_SYS".FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_20_DISP_TQ_AE",
|
||||
User := "DB1_SYS".Usuario.Actual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_TQ_AE",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_AUTO",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan AND "DB2041_TQ_AE".TQ_AE[#for_i].Orden_Manual AND NOT "DB2041_TQ_AE".TQ_AE[#for_i].Aux_oldOrdenManual THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := "DB1_SYS".FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_20_DISP_TQ_AE",
|
||||
User := "DB1_SYS".Usuario.Actual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_TQ_AE",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_ON",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
IF "DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan AND NOT "DB2041_TQ_AE".TQ_AE[#for_i].Orden_Manual AND "DB2041_TQ_AE".TQ_AE[#for_i].Aux_oldOrdenManual THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := "DB1_SYS".FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_20_DISP_TQ_AE",
|
||||
User := "DB1_SYS".Usuario.Actual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_TQ_AE",
|
||||
CodInt_2 := #for_i,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_OFF",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Estado anterior manual/automatico
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Aux_oldOrdenManual := "DB2041_TQ_AE".TQ_AE[#for_i].Orden_Manual;
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Aux_oldAutoMan := "DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan;
|
||||
|
||||
ELSE
|
||||
|
||||
// =============================================================================
|
||||
// INICIALIZACIÓN DE SALIDAS
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Estado_AutoMan :=
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Orden_Manual :=
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Orden_Produccion :=
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Orden_CIP :=
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Orden_Vaciado :=
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Alarma_Configuracion :=
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Alarma_PresionAlta :=
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Alarma_PresionBaja :=
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Salida_ValvulaDucha :=
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Salida_ValvulaEsteril :=
|
||||
"DB2041_TQ_AE".TQ_AE[#for_i].Salida_ValvulaVenteo := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
FUNCTION "FC2926_ZC_FF_INDV" : Void
|
||||
TITLE = FC2926_ZC_FF
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion de flip flop
|
||||
VAR_INPUT
|
||||
Pulso1Seg : Bool; // Pulso de 1 segundo
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
FF : "UDT_ZC_DISP_FF";
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
REPOSO : SInt := 0;
|
||||
FLOP : SInt := 10;
|
||||
PARO1 : SInt := 20;
|
||||
FLIP : SInt := 30;
|
||||
PARO2 : SInt := 40;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2026 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo flip flop con funcion de paro entre cambios.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y calculos de tiempo de cambio entre ordenes Flip, Flop y paro.
|
||||
- Adicionalmente, se gestiona tambien la posibilidad de pausar el contaje del tiempo, para evitar su reinicializacion en caso de pausa.
|
||||
- En los cambios entre ´flip´ <--> ´flop´, se activa tambien la marca ´paro´ para poder gestionar los cambios y evitar golpes de ariete.
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_DISP_FF_PARO` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 02.06.2026 | (ABH) | Primera version. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION COMPROBACIONES_INICIALES
|
||||
|
||||
// Si no hay orden o faltan tiempos, reseteamos valores y salimos de la funcion
|
||||
IF NOT #FF.Orden_Activar OR (#FF.Config_SetPointTiempoFlip <= 0 AND #FF.Config_SetPointTiempoFlop <= 0) THEN
|
||||
#FF.Estado_Flip := FALSE;
|
||||
#FF.Estado_Flop := FALSE;
|
||||
#FF.Estado_Paro1 := FALSE;
|
||||
#FF.Estado_Paro2 := FALSE;
|
||||
|
||||
#FF.Aux_Tiempo := 0;
|
||||
#FF.Estado_Etapa := #REPOSO;
|
||||
|
||||
#FF.Aux_Inicializado := FALSE;
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
END_REGION COMPROBACIONES_INICIALES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION INICIALIZACION
|
||||
|
||||
// Arranque inicial forzado a Flop si no hay estado activo
|
||||
IF NOT #FF.Aux_Inicializado THEN
|
||||
#FF.Estado_Etapa := #FLOP;
|
||||
#FF.Aux_Inicializado := TRUE;
|
||||
END_IF;
|
||||
|
||||
END_REGION INICIALIZACION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION LOGICA_DE_ESTADOS
|
||||
|
||||
CASE #FF.Estado_Etapa OF
|
||||
|
||||
#FLOP:
|
||||
// Salidas
|
||||
#FF.Estado_Flip := FALSE;
|
||||
#FF.Estado_Flop := TRUE;
|
||||
#FF.Estado_Paro1 := FALSE;
|
||||
#FF.Estado_Paro2 := FALSE;
|
||||
|
||||
// Conteo de tiempo
|
||||
IF #Pulso1Seg AND NOT #FF.Orden_Pausa THEN
|
||||
#FF.Aux_Tiempo += 1;
|
||||
END_IF;
|
||||
|
||||
// Transición
|
||||
IF #FF.Aux_Tiempo >= #FF.Config_SetPointTiempoFlop THEN
|
||||
#FF.Aux_Tiempo := 0;
|
||||
// Si no tenemos tiempo de paro configurado, saltamos a FLIP
|
||||
IF #FF.Config_SetPointTiempoParo <= 0 THEN
|
||||
#FF.Estado_Etapa := #FLIP;
|
||||
ELSE
|
||||
#FF.Estado_Etapa := #PARO1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
#PARO1:
|
||||
// Salidas
|
||||
#FF.Estado_Flip := FALSE;
|
||||
#FF.Estado_Flop := FALSE;
|
||||
#FF.Estado_Paro1 := TRUE;
|
||||
#FF.Estado_Paro2 := FALSE;
|
||||
|
||||
// Conteo de tiempo
|
||||
IF #Pulso1Seg AND NOT #FF.Orden_Pausa THEN
|
||||
#FF.Aux_Tiempo += 1;
|
||||
END_IF;
|
||||
|
||||
// Transición
|
||||
IF #FF.Aux_Tiempo >= #FF.Config_SetPointTiempoParo THEN
|
||||
#FF.Aux_Tiempo := 0;
|
||||
#FF.Estado_Etapa := #FLIP;
|
||||
END_IF;
|
||||
|
||||
|
||||
#FLIP:
|
||||
// Salidas
|
||||
#FF.Estado_Flip := TRUE;
|
||||
#FF.Estado_Flop := FALSE;
|
||||
#FF.Estado_Paro1 := FALSE;
|
||||
#FF.Estado_Paro2 := FALSE;
|
||||
|
||||
// Conteo de tiempo
|
||||
IF #Pulso1Seg AND NOT #FF.Orden_Pausa THEN
|
||||
#FF.Aux_Tiempo += 1;
|
||||
END_IF;
|
||||
|
||||
// Transición
|
||||
IF #FF.Aux_Tiempo >= #FF.Config_SetPointTiempoFlip THEN
|
||||
#FF.Aux_Tiempo := 0;
|
||||
// Si no tenemos tiempo de paro configurado, saltamos a FLOP
|
||||
IF #FF.Config_SetPointTiempoParo <= 0 THEN
|
||||
#FF.Estado_Etapa := #FLOP;
|
||||
ELSE
|
||||
#FF.Estado_Etapa := #PARO2;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
|
||||
#PARO2:
|
||||
// Salidas
|
||||
#FF.Estado_Flip := FALSE;
|
||||
#FF.Estado_Flop := FALSE;
|
||||
#FF.Estado_Paro1 := FALSE;
|
||||
#FF.Estado_Paro2 := TRUE;
|
||||
|
||||
// Conteo de tiempo
|
||||
IF #Pulso1Seg AND NOT #FF.Orden_Pausa THEN
|
||||
#FF.Aux_Tiempo += 1;
|
||||
END_IF;
|
||||
|
||||
// Transición
|
||||
IF #FF.Aux_Tiempo >= #FF.Config_SetPointTiempoParo THEN
|
||||
#FF.Aux_Tiempo := 0;
|
||||
#FF.Estado_Etapa := #FLOP;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
#FF.Estado_Etapa := #REPOSO;
|
||||
END_CASE;
|
||||
|
||||
END_REGION LOGICA_DE_ESTADOS
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
FUNCTION "FC2927_ZC_FF_SEC_INDV" : Void
|
||||
TITLE = FC2927_FF_SEC
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion de Flip Flop secuencial
|
||||
VAR_INPUT
|
||||
Pulso1Seg : Bool; // Pulso 1 segundo
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
FF_SEC : "UDT_ZC_DISP_FF_SEC";
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_SumaFlip : Int;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
REPOSO : SInt := 0;
|
||||
FLOP : SInt := 10;
|
||||
FLIP : SInt := 20;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2023 - 2025
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo flip flop secuencial.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y calculos de tiempo de cambio entre ordenes Flip y Flop.
|
||||
- Adicionalmente, se gestiona tambien la posibilidad de pausar el contaje del tiempo, para evitar su reinicializacion en caso de pausa.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_DISP_FF_SEC` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 02.10.2023 | (ABH) | Primera version. |
|
||||
| 00.00.02 | 28.11.2023 | (ABH) | Se añade condicion de activacion del Flip Flop a que algun SP sea mayor que 0. |
|
||||
| 01.00.00 | 15.10.2025 | (ABH) | Se añade orden pausa para dejar de contar. Refactorizacion de logica de gestion de flips. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION COMPROBACIONES_INICIALES
|
||||
|
||||
// Suma de seguridad por FOR (Determinista)
|
||||
#t_SumaFlip := 0;
|
||||
FOR #for_i := 1 TO 10 DO
|
||||
#t_SumaFlip += #FF_SEC.Config_SetPointTiempoFlip[#for_i];
|
||||
END_FOR;
|
||||
|
||||
// Si no hay orden o los tiempos globales son 0, reseteamos valores y salimos de la funcion
|
||||
IF NOT #FF_SEC.Orden_Activar OR (#t_SumaFlip <= 0 AND #FF_SEC.Config_SetPointTiempoFlop <= 0) THEN
|
||||
#FF_SEC.Estado_SalidaFlop := FALSE;
|
||||
FOR #for_i := 1 TO 10 DO
|
||||
#FF_SEC.Estado_SalidaFlip[#for_i] := FALSE;
|
||||
END_FOR;
|
||||
|
||||
#FF_SEC.Aux_Tiempo := 0;
|
||||
#FF_SEC.Estado_Etapa := #REPOSO;
|
||||
#FF_SEC.Aux_FlipActual := 0;
|
||||
#FF_SEC.Aux_Inicializacion := FALSE;
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
END_REGION COMPROBACIONES_INICIALES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION INICIALIZACION
|
||||
|
||||
// Arranque inicial forzado a Flop si no hay estado activo
|
||||
IF NOT #FF_SEC.Aux_Inicializacion THEN
|
||||
#FF_SEC.Estado_Etapa := #FLOP;
|
||||
#FF_SEC.Aux_FlipActual := 0;
|
||||
#FF_SEC.Aux_Inicializacion := TRUE;
|
||||
END_IF;
|
||||
|
||||
END_REGION INICIALIZACION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION LOGICA_DE_ESTADOS
|
||||
|
||||
CASE #FF_SEC.Estado_Etapa OF
|
||||
|
||||
#FLOP:
|
||||
// Salidas
|
||||
#FF_SEC.Estado_SalidaFlop := TRUE;
|
||||
FOR #for_i := 1 TO 10 DO
|
||||
#FF_SEC.Estado_SalidaFlip[#for_i] := FALSE;
|
||||
END_FOR;
|
||||
|
||||
// Conteo de tiempo
|
||||
IF #Pulso1Seg AND NOT #FF_SEC.Orden_Pausa THEN
|
||||
#FF_SEC.Aux_Tiempo += 1;
|
||||
END_IF;
|
||||
|
||||
// Transición
|
||||
IF #FF_SEC.Aux_Tiempo >= #FF_SEC.Config_SetPointTiempoFlop THEN
|
||||
#FF_SEC.Aux_Tiempo := 0;
|
||||
#FF_SEC.Aux_FlipActual := 11; // Fallback por defecto
|
||||
|
||||
// Buscar primer Flip válido
|
||||
FOR #for_i := 1 TO 10 DO
|
||||
IF #FF_SEC.Config_SetPointTiempoFlip[#for_i] > 0 THEN
|
||||
#FF_SEC.Aux_FlipActual := #for_i;
|
||||
EXIT; // Corta el FOR en el primer acierto
|
||||
END_IF;
|
||||
END_FOR;
|
||||
|
||||
// Transición si encontró algo válido
|
||||
IF #FF_SEC.Aux_FlipActual <= 10 THEN
|
||||
#FF_SEC.Estado_Etapa := #FLIP;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
#FLIP:
|
||||
// Salidas
|
||||
#FF_SEC.Estado_SalidaFlop := FALSE;
|
||||
FOR #for_i := 1 TO 10 DO
|
||||
IF #for_i = #FF_SEC.Aux_FlipActual THEN
|
||||
#FF_SEC.Estado_SalidaFlip[#for_i] := TRUE;
|
||||
ELSE
|
||||
#FF_SEC.Estado_SalidaFlip[#for_i] := FALSE;
|
||||
END_IF;
|
||||
END_FOR;
|
||||
|
||||
// Conteo de tiempo
|
||||
IF #Pulso1Seg AND NOT #FF_SEC.Orden_Pausa THEN
|
||||
#FF_SEC.Aux_Tiempo += 1;
|
||||
END_IF;
|
||||
|
||||
/// Transición
|
||||
IF #FF_SEC.Aux_Tiempo >= #FF_SEC.Config_SetPointTiempoFlip[#FF_SEC.Aux_FlipActual] THEN
|
||||
#FF_SEC.Aux_Tiempo := 0;
|
||||
#FF_SEC.Aux_FlipActual += 1; // Apunta al siguiente
|
||||
|
||||
// Búsqueda del siguiente Flip válido
|
||||
FOR #for_i := #FF_SEC.Aux_FlipActual TO 10 DO
|
||||
IF #FF_SEC.Config_SetPointTiempoFlip[#for_i] > 0 THEN
|
||||
#FF_SEC.Aux_FlipActual := #for_i;
|
||||
EXIT;
|
||||
END_IF;
|
||||
// Si llega al final sin encontrar nada
|
||||
IF #for_i = 10 THEN
|
||||
#FF_SEC.Aux_FlipActual := 11;
|
||||
END_IF;
|
||||
END_FOR;
|
||||
|
||||
// Si rebasó el límite, vuelve al Flop
|
||||
IF #FF_SEC.Aux_FlipActual > 10 THEN
|
||||
#FF_SEC.Estado_Etapa := #FLOP;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
#FF_SEC.Estado_Etapa := #REPOSO;
|
||||
END_CASE;
|
||||
|
||||
END_REGION LOGICA_DE_ESTADOS
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
FUNCTION "FC2928_ZC_TON_INDV" : Void
|
||||
TITLE = FC2928_TON
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion temporizador TON (Base 1 seg)
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
TON : "UDT_ZC_DISP_TON";
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2022 - 2022
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo TON.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y temporizacion de la activacion del temporizador.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_DISP_TON` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 02.10.2022 | (ABH) | Primera version. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO
|
||||
|
||||
IF #TON.IN THEN
|
||||
IF #TON.ET >= #TON.SP THEN
|
||||
#TON.Q := TRUE;
|
||||
ELSE
|
||||
IF #Pulso1seg THEN
|
||||
#TON.ET += 1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
ELSE
|
||||
#TON.ET := 0;
|
||||
#TON.Q := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
FUNCTION "FC2929_ZC_TOF_INDV" : Void
|
||||
TITLE = FC2929_TOF
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion temporizador TOF (Base 1 seg)
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
TOF : "UDT_ZC_DISP_TOF";
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2023 - 2025
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo TOF.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y temporizacion de la activacion del temporizador.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_DISP_TOF` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 02.10.2022 | (ABH) | Primera version. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO
|
||||
|
||||
IF #TOF.IN THEN
|
||||
#TOF.OldActivar := TRUE;
|
||||
#TOF.Q := TRUE;
|
||||
END_IF;
|
||||
IF #TOF.OldActivar AND NOT #TOF.IN THEN
|
||||
|
||||
IF #TOF.ET <= 0 THEN
|
||||
#TOF.Q := FALSE;
|
||||
#TOF.OldActivar := FALSE;
|
||||
ELSE
|
||||
IF #Pulso1seg THEN
|
||||
#TOF.ET -= 1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
ELSE
|
||||
#TOF.ET := #TOF.SP;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
FUNCTION "FC2930_ZC_TONR_INDV" : Void
|
||||
TITLE = FC2930_TONR
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion temporizador TONR (Base 1 seg)
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
TONR : "UDT_ZC_DISP_TONR";
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2022 - 2025
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo TONR.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y temporizacion de la activacion del temporizador.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_DISP_TONR` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 02.10.2022 | (ABH) | Primera version. |
|
||||
| 01.00.01 | 13.08.2025 | (ABH) | Se modifica activacion de salida Q sin dependencia de entrada IN. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO
|
||||
|
||||
IF #TONR.RESET THEN
|
||||
#TONR.ET := 0;
|
||||
#TONR.Q := FALSE;
|
||||
#TONR.RESET := FALSE;
|
||||
END_IF;
|
||||
|
||||
IF #TONR.IN AND
|
||||
#TONR.ET < #TONR.SP AND
|
||||
#Pulso1seg
|
||||
THEN
|
||||
#TONR.ET += 1;
|
||||
#TONR.Q := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
IF #TONR.ET >= #TONR.SP THEN
|
||||
#TONR.Q := TRUE;
|
||||
END_IF;
|
||||
|
||||
#TONR.RT := #TONR.SP - #TONR.ET;
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
FUNCTION "FC2931_ZC_TP_INDV" : Void
|
||||
TITLE = FC2931_TP
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion temporizador TP (Base 1 seg)
|
||||
VAR_INPUT
|
||||
Pulso1Seg : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
TP : "UDT_ZC_DISP_TP";
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2022 - 2022
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo TP.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y temporizacion de la activacion del temporizador.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_DISP_TP` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 02.10.2022 | (ABH) | Primera version. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO
|
||||
|
||||
// =============================================================================
|
||||
// Detección de flanco
|
||||
IF #TP.IN AND NOT #TP.oldIN THEN
|
||||
#TP.Q := TRUE;
|
||||
END_IF;
|
||||
|
||||
// Actualizo valor de memoria
|
||||
#TP.oldIN := #TP.IN;
|
||||
|
||||
// =============================================================================
|
||||
// Reinicio memoria de activación cuando piedo salida y cuento tiempo
|
||||
IF NOT #TP.IN THEN
|
||||
#TP.oldIN := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// Incremento de tiempo
|
||||
IF #TP.Q
|
||||
AND
|
||||
#TP.ET < #TP.PT
|
||||
AND
|
||||
#Pulso1Seg
|
||||
THEN
|
||||
#TP.ET += 1;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// Desactivo salida cuando cumplo tiempo de retardo de salida
|
||||
IF #TP.ET >= #TP.PT THEN
|
||||
#TP.Q := FALSE;
|
||||
#TP.ET := 0;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
FUNCTION "FC2935_ZC_PID_INDV" : Void
|
||||
TITLE = FC2935_ZC_PID_INDV
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion dispositivo PID
|
||||
VAR_INPUT
|
||||
PV : Real; // Valor de proceso
|
||||
DispManAuto : Bool; // Dispositivo Manual - Auto
|
||||
DispValorActual : Real; // Dispositivo valor actual
|
||||
Ack : Bool; // Acuse general
|
||||
Fecha {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
Usuario : String; // Usuario actual
|
||||
NumeroPID : Int; // Numero de PID
|
||||
RangoSuperiorEscalado : Real; // Rango superior de valor de proceso para escalado 0-100%
|
||||
RangoInferiorEscalado : Real; // Rango inferior de valor de proceso para escalado 0-100%
|
||||
UsuarioActual : String; // Usuario actual
|
||||
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
PID_CompactConfig {InstructionName := 'PID_CompactConfig'; LibVersion := '1.2'} : PID_CompactConfig;
|
||||
PID_CompactControlParams {InstructionName := 'PID_CompactControlParams'; LibVersion := '1.2'} : PID_CompactControlParams;
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
t_Norm_X : LReal;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Funcion para la gestion de dispositivo de tipo PID.
|
||||
|
||||
En ella se realizan las siguientes acciones:
|
||||
|
||||
- Se gestiona el estado del dispositivo
|
||||
- Se gestiona la orden de activacion y activacion retardada
|
||||
- Se gestiona la trazabilidad de las manualizaciones del dispositivo
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 12.05.2023 | (ABH) | Primera version |
|
||||
| 01.00.01 | 18.07.2023 | (ABH) | Cambio en interfaz bloque. Se pasa IN/OUT solo el PID_COMPACT. Se añade a UDT el nombre del PID. Se añade como Input el numero de PID en el array de dispositivo PID. |
|
||||
| 01.00.02 | 05.09.2023 | (ABH) | Cambio en UDT PID para añadir rampa para gestion de Set Point. Se añade gestion de rampa SP PID. |
|
||||
| 01.00.03 | 18.09.2023 | (ABH) | Reset de consigna auto al final de la gestion del dispositivo. Se añade trazabilidad de forzado. |
|
||||
| 01.00.04 | 16.02.2024 | (ABH) | Se elimina el PID compact y la gestion de la rampa en este FC. Se separa en FC2036_PID_COMPACT para ser llamado en OB de interrupcion. |
|
||||
| 01.00.05 | 13.06.2024 | (ABH) | Se añade gestion multiplexado para Scada (no indexado) |
|
||||
| 01.00.06 | 08.01.2025 | (ABH) | Se elimina multiplexado PID. Se realiza en FC aparte. |
|
||||
| 01.00.07 | 24.04.2025 | (HCR) | Se añade gestion de idioma |
|
||||
| 01.00.08 | 11.09.2025 | (ABH) | Se eliminan las constantes de idioma dentro del FC. Se utilizan constantes globales para facilitar su traduccion. Se añade indexHMI para lista de texto en sistemas de supervision. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION TRASPASO_DE_PARAMETROS
|
||||
|
||||
// Numero maximo de dispositivos para limitar en HMI/Scada
|
||||
"DB2035_PID".Mux.NumDispositivos := "N_MAX_DISP_PID";
|
||||
|
||||
// ===============================================================================================================
|
||||
// TRASPASO DE PARAMETROS A PID COMPACT
|
||||
// Valores regulacion
|
||||
#PID_CompactControlParams.Gain := "DB2035_PID".PID[#NumeroPID].Config_Gain;
|
||||
#PID_CompactControlParams.Ti := "DB2035_PID".PID[#NumeroPID].Config_Ti;
|
||||
#PID_CompactControlParams.Td := "DB2035_PID".PID[#NumeroPID].Config_Td;
|
||||
// Tipo Entrada
|
||||
#PID_CompactConfig.InputPerOn := "DB2035_PID".PID[#NumeroPID].Config_TipoEntrada;
|
||||
// Tipo de control (Directo/Inverso)
|
||||
#PID_CompactConfig.InvertControl := "DB2035_PID".PID[#NumeroPID].Config_InvertirControl;
|
||||
// Limites y avisos
|
||||
#PID_CompactConfig.InputUpperLimit := 99999.0;
|
||||
#PID_CompactConfig.InputLowerLimit := -99999.0;
|
||||
#PID_CompactConfig.InputUpperWarning := 99999.0;
|
||||
#PID_CompactConfig.InputLowerWarning := -99999.0;
|
||||
// Valor proceso
|
||||
"DB2035_PID".PID[#NumeroPID].Estado_PV := #PV;
|
||||
|
||||
"DB2035_PID".PID[#NumeroPID].Config_LimiteSuperiorEntrada := #RangoSuperiorEscalado;
|
||||
"DB2035_PID".PID[#NumeroPID].Config_LimiteInferiorEntrada := #RangoInferiorEscalado;
|
||||
|
||||
"DB2035_PID".PID[#NumeroPID].Orden_Ack := #Ack;
|
||||
|
||||
END_REGION TRASPASO_DE_PARAMETROS
|
||||
|
||||
|
||||
REGION MODOS_DE_TRABAJO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Selector: (0) Automatico / (1) Manual
|
||||
"DB2035_PID".PID[#NumeroPID].Estado_AutoMan :=
|
||||
(#DispManAuto) OR
|
||||
("DB2035_PID".PID[#NumeroPID].Orden_ActivarAuto AND "DB2035_PID".PID[#NumeroPID].Orden_Forzar) OR
|
||||
(NOT "DB2035_PID".PID[#NumeroPID].Orden_ActivarAuto);
|
||||
|
||||
// Reset señal forzado
|
||||
IF NOT "DB2035_PID".PID[#NumeroPID].Orden_ActivarAuto THEN
|
||||
"DB2035_PID".PID[#NumeroPID].Orden_Forzar := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION MODOS_DE_TRABAJO
|
||||
|
||||
|
||||
REGION LIMITES_SALIDA
|
||||
|
||||
// ===============================================================================================================
|
||||
// Configuracion del limite de la salida del PID en funcion del estado Manual/Automatico
|
||||
IF "DB2035_PID".PID[#NumeroPID].Estado_AutoMan THEN
|
||||
// En modo manual, configuramos el limite de la salida de 0-100%, para que al manualizar el PID se pueda poner el valor que se quiera
|
||||
#PID_CompactConfig.OutputUpperLimit := 100.0;
|
||||
#PID_CompactConfig.OutputLowerLimit := 0.0;
|
||||
ELSE
|
||||
#PID_CompactConfig.OutputUpperLimit := "DB2035_PID".PID[#NumeroPID].Config_LimiteSuperiorSalida;
|
||||
#PID_CompactConfig.OutputLowerLimit := "DB2035_PID".PID[#NumeroPID].Config_LimiteInferiorSalida;
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES_SALIDA
|
||||
|
||||
|
||||
REGION ESTADOS
|
||||
|
||||
// ===============================================================================================================
|
||||
// REALIMENTACION DE LAS ENTRADAS/SALIDAS DEL PID
|
||||
// Estado automatico
|
||||
IF NOT "DB2035_PID".PID[#NumeroPID].Estado_AutoMan THEN
|
||||
"DB2035_PID".PID[#NumeroPID].Aux_SP_Manual := "DB2035_PID".PID[#NumeroPID].Estado_ValorSalida;
|
||||
"DB2035_PID".PID[#NumeroPID].Orden_ConsignaForzado := "DB2035_PID".PID[#NumeroPID].Estado_ValorSalida;
|
||||
ELSE
|
||||
|
||||
// Estado manual - Consigna forzar PID
|
||||
IF NOT #DispManAuto AND "DB2035_PID".PID[#NumeroPID].Orden_Forzar THEN
|
||||
"DB2035_PID".PID[#NumeroPID].Aux_SP_Manual := "DB2035_PID".PID[#NumeroPID].Orden_ConsignaForzado;
|
||||
// Estado manual - Dispositivo forzado
|
||||
ELSIF #DispManAuto AND NOT "DB2035_PID".PID[#NumeroPID].Orden_Forzar THEN
|
||||
"DB2035_PID".PID[#NumeroPID].Aux_SP_Manual := "DB2035_PID".PID[#NumeroPID].Orden_ConsignaForzado := #DispValorActual;
|
||||
ELSIF #DispManAuto AND "DB2035_PID".PID[#NumeroPID].Orden_Forzar THEN
|
||||
"DB2035_PID".PID[#NumeroPID].Aux_SP_Manual := "DB2035_PID".PID[#NumeroPID].Orden_ConsignaForzado := #DispValorActual;
|
||||
ELSE
|
||||
"DB2035_PID".PID[#NumeroPID].Aux_SP_Manual := "DB2035_PID".PID[#NumeroPID].Orden_ConsignaForzado := #DispValorActual;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
|
||||
// ===============================================================================================================
|
||||
// CALCULO DE VALORES EN 0-100%
|
||||
// SP
|
||||
#t_Norm_X := NORM_X(MIN := #RangoInferiorEscalado, VALUE := "DB2035_PID".PID[#NumeroPID].Orden_ConsignaAuto, MAX := #RangoSuperiorEscalado);
|
||||
"DB2035_PID".PID[#NumeroPID].Estado_SP_0_100 := LREAL_TO_REAL(SCALE_X(MIN := 0.0, VALUE := #t_Norm_X, MAX := 100.0));
|
||||
|
||||
// PV
|
||||
#t_Norm_X := NORM_X(MIN := #RangoInferiorEscalado, VALUE := "DB2035_PID".PID[#NumeroPID].Estado_PV, MAX := #RangoSuperiorEscalado);
|
||||
"DB2035_PID".PID[#NumeroPID].Estado_PV_0_100 := LREAL_TO_REAL(SCALE_X(MIN := 0.0, VALUE := #t_Norm_X, MAX := 100.0));
|
||||
|
||||
// Error SP - PV
|
||||
"DB2035_PID".PID[#NumeroPID].Estado_Error_SP_PV_0_100 := ABS("DB2035_PID".PID[#NumeroPID].Estado_SP_0_100 - "DB2035_PID".PID[#NumeroPID].Estado_PV_0_100);
|
||||
|
||||
END_REGION ESTADOS
|
||||
|
||||
|
||||
REGION CAMBIO_MODO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Gestion modo de trabajo del PID (Manual/Automatico)
|
||||
IF "DB2035_PID".PID[#NumeroPID].Estado_AutoMan THEN
|
||||
"DB2035_PID".PID[#NumeroPID].Estado_Mode := 4;
|
||||
ELSE
|
||||
"DB2035_PID".PID[#NumeroPID].Estado_Mode := 3;
|
||||
END_IF;
|
||||
|
||||
// Flanco para cambio de modo
|
||||
"DB2035_PID".PID[#NumeroPID].Estado_ModeActivate := "DB2035_PID".PID[#NumeroPID].Estado_Mode <> "DB2035_PID".PID[#NumeroPID].Aux_oldMode;
|
||||
// Valor anterior de modo para flancos
|
||||
"DB2035_PID".PID[#NumeroPID].Aux_oldMode := "DB2035_PID".PID[#NumeroPID].Estado_Mode;
|
||||
|
||||
END_REGION CAMBIO_MODO
|
||||
|
||||
|
||||
REGION TRAZABILIDAD
|
||||
|
||||
// =============================================================================================
|
||||
// TRAZA CAMBIOS EN VALOR P
|
||||
IF "DB2035_PID".PID[#NumeroPID].Aux_oldGain <> "DB2035_PID".PID[#NumeroPID].Config_Gain THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_18_DISP_PID_VAL",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_PID",
|
||||
CodInt_2 := #NumeroPID,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_CAM_P",
|
||||
CodInt_4 := "TRZ_SYS_COM_FLECHA",
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := "DB2035_PID".PID[#NumeroPID].Aux_oldGain,
|
||||
CodReal_2 := "DB2035_PID".PID[#NumeroPID].Config_Gain);
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================================
|
||||
// TRAZA CAMBIOS EN VALOR P
|
||||
IF "DB2035_PID".PID[#NumeroPID].Aux_oldTi <> "DB2035_PID".PID[#NumeroPID].Config_Ti THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_18_DISP_PID_VAL",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_PID",
|
||||
CodInt_2 := #NumeroPID,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_CAM_I",
|
||||
CodInt_4 := "TRZ_SYS_COM_FLECHA",
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := "DB2035_PID".PID[#NumeroPID].Aux_oldTi,
|
||||
CodReal_2 := "DB2035_PID".PID[#NumeroPID].Config_Ti);
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================================
|
||||
// TRAZA CAMBIOS EN VALOR P
|
||||
IF "DB2035_PID".PID[#NumeroPID].Aux_oldTd <> "DB2035_PID".PID[#NumeroPID].Config_Td THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_18_DISP_PID_VAL",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_PID",
|
||||
CodInt_2 := #NumeroPID,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_CAM_D",
|
||||
CodInt_4 := "TRZ_SYS_COM_FLECHA",
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := "DB2035_PID".PID[#NumeroPID].Aux_oldTd,
|
||||
CodReal_2 := "DB2035_PID".PID[#NumeroPID].Config_Td);
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================================
|
||||
// TRAZA FORZADO PID
|
||||
IF "DB2035_PID".PID[#NumeroPID].Orden_Forzar AND NOT "DB2035_PID".PID[#NumeroPID].Aux_oldForzar THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_19_DISP_PID_ORD",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_PID",
|
||||
CodInt_2 := #NumeroPID,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_MAN",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
IF NOT "DB2035_PID".PID[#NumeroPID].Orden_Forzar AND "DB2035_PID".PID[#NumeroPID].Aux_oldForzar THEN
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_19_DISP_PID_ORD",
|
||||
User := #UsuarioActual,
|
||||
CodInt_1 := "TRZ_SYS_DISP_TIPO_PID",
|
||||
CodInt_2 := #NumeroPID,
|
||||
CodInt_3 := "TRZ_SYS_DISP_ACC_AUTO",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := 0.0,
|
||||
CodReal_2 := 0.0);
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================================
|
||||
// Guardamos valores anteriores
|
||||
"DB2035_PID".PID[#NumeroPID].Aux_oldGain := "DB2035_PID".PID[#NumeroPID].Config_Gain;
|
||||
"DB2035_PID".PID[#NumeroPID].Aux_oldTi := "DB2035_PID".PID[#NumeroPID].Config_Ti;
|
||||
"DB2035_PID".PID[#NumeroPID].Aux_oldTd := "DB2035_PID".PID[#NumeroPID].Config_Td;
|
||||
"DB2035_PID".PID[#NumeroPID].Aux_oldForzar := "DB2035_PID".PID[#NumeroPID].Orden_Forzar;
|
||||
|
||||
END_REGION TRAZABILIDAD
|
||||
|
||||
|
||||
"DB2035_PID".PID[#NumeroPID].Aux_SP_Auto := "DB2035_PID".PID[#NumeroPID].Orden_ConsignaAuto;
|
||||
|
||||
// =============================================================================
|
||||
// Reset de orden automatica
|
||||
"DB2035_PID".PID[#NumeroPID].Orden_ActivarAuto := FALSE;
|
||||
"DB2035_PID".PID[#NumeroPID].Orden_ConsignaAuto := 0.0;
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
FUNCTION "FC2937_ZC_MEDIA_INDV" : Void
|
||||
TITLE = FC2937_ZC_MEDIA
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion medias
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool; // Pulso de 1 segundo
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
Media : "UDT_ZC_DISP_MEDIA"; // Media
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
t_NumeroDatos : LReal;
|
||||
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:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo Media.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y calculo de la media.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_DISP_MEDIA` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 20.03.2025 | (ABH) | Primera version. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION REINICIALIZACION_DE_DATOS
|
||||
|
||||
// Reset temporizador interno si no esta habilitada la media
|
||||
IF NOT #Media.IniciarMedia THEN
|
||||
#Media.auxTiempo := 0;
|
||||
END_IF;
|
||||
|
||||
// Reinicializacion de datos al inicializar
|
||||
IF #Media.Inicializar AND NOT #Media.auxInicializar THEN
|
||||
#Media.auxAcumulado := 0.0;
|
||||
#Media.auxIndice := 0;
|
||||
#Media.auxTiempo := 0;
|
||||
#Media.ValorMinimo := 9999999.0;
|
||||
#Media.ValorMaximo := -9999999.0;
|
||||
END_IF;
|
||||
|
||||
// Estado anterior
|
||||
#Media.auxInicializar := #Media.Inicializar;
|
||||
|
||||
END_REGION REINICIALIZACION_DE_DATOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION TOMA_DE_VALORES
|
||||
|
||||
IF #Media.IniciarMedia AND #Pulso1seg THEN
|
||||
|
||||
// Incrementamos el indice de tiempo
|
||||
#Media.auxTiempo += 1;
|
||||
|
||||
// En caso de superar el tiempo de muestreo, incrementamos el acumulado, reseteamos el tiempo y aumentamos el indice
|
||||
IF #Media.auxTiempo >= #Media.TiempoMuestreo THEN
|
||||
|
||||
#Media.auxAcumulado := #Media.ValorActual + #Media.auxAcumulado;
|
||||
#Media.auxIndice += 1;
|
||||
#Media.auxTiempo := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
// Guardamos el valor minimo alcanzado
|
||||
IF #Media.ValorActual < #Media.ValorMinimo THEN
|
||||
#Media.ValorMinimo := #Media.ValorActual;
|
||||
END_IF;
|
||||
|
||||
// Guardamos el valor maximo alcanzado
|
||||
IF #Media.ValorActual > #Media.ValorMaximo THEN
|
||||
#Media.ValorMaximo := #Media.ValorActual;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// Conversion de indice a REAL para calculos
|
||||
#t_NumeroDatos := DINT_TO_LREAL(#Media.auxIndice);
|
||||
|
||||
END_REGION TOMA_DE_VALORES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION CALCULO_MEDIA
|
||||
|
||||
IF #Media.auxIndice > 0 THEN
|
||||
#Media.Media := #Media.auxAcumulado / #t_NumeroDatos;
|
||||
ELSE
|
||||
#Media.Media := 0.0;
|
||||
END_IF;
|
||||
|
||||
END_REGION CALCULO_MEDIA
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
FUNCTION "FC2938_ZC_MEDIA_VOL_INDV" : Void
|
||||
TITLE = FC2938_ZC_MEDIA_VOL
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion de media teniendo en cuenta el volumen/caudal.
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool; // Pulso de 1 segundo
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
Media : "UDT_ZC_DISP_MEDIA_VOLUMEN"; // Media
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
t_NumeroDatos : LReal;
|
||||
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:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de gestionar un dispositivo Media volumen.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Gestionar la activacion y calculo de la media teniendo en cuenta el volumen/caudal.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_DISP_MEDIA_VOLUMEN` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 14.10.2025 | (ABH) | Primera version. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPOSITIVO
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION REINICIALIZACION_DE_DATOS
|
||||
|
||||
// Reset temporizador interno si no esta habilitada la media
|
||||
IF NOT #Media.IniciarMedia THEN
|
||||
#Media.auxTiempo := 0;
|
||||
END_IF;
|
||||
|
||||
// Reinicializacion de datos al inicializar
|
||||
IF #Media.Inicializar AND NOT #Media.auxInicializar THEN
|
||||
#Media.auxAcumulado :=
|
||||
#Media.auxVolumen :=
|
||||
#Media.auxValorMedia :=
|
||||
#Media.Media := 0.0;
|
||||
#Media.auxTiempo := 0;
|
||||
#Media.ValorMinimo := 9999999.0;
|
||||
#Media.ValorMaximo := -9999999.0;
|
||||
END_IF;
|
||||
|
||||
// Estado anterior
|
||||
#Media.auxInicializar := #Media.Inicializar;
|
||||
|
||||
END_REGION REINICIALIZACION_DE_DATOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION TOMA_DE_VALORES
|
||||
|
||||
IF #Media.IniciarMedia AND #Pulso1seg THEN
|
||||
|
||||
// Incrementamos el indice de tiempo
|
||||
#Media.auxTiempo += 1;
|
||||
|
||||
// En caso de superar el tiempo de muestreo, incrementamos el acumulado, reseteamos el tiempo y aumentamos el indice
|
||||
IF #Media.auxTiempo >= #Media.TiempoMuestreo THEN
|
||||
|
||||
#Media.auxValorMedia := (#Media.Volumen - #Media.auxVolumen) * #Media.ValorActual;
|
||||
#Media.auxVolumen := #Media.Volumen;
|
||||
#Media.auxAcumulado := #Media.auxValorMedia + #Media.auxAcumulado;
|
||||
|
||||
#Media.Media := #Media.auxAcumulado / #Media.Volumen;
|
||||
|
||||
#Media.auxTiempo := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
// Guardamos el valor minimo alcanzado
|
||||
IF #Media.ValorActual < #Media.ValorMinimo THEN
|
||||
#Media.ValorMinimo := #Media.ValorActual;
|
||||
END_IF;
|
||||
|
||||
// Guardamos el valor maximo alcanzado
|
||||
IF #Media.ValorActual > #Media.ValorMaximo THEN
|
||||
#Media.ValorMaximo := #Media.ValorActual;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TOMA_DE_VALORES
|
||||
|
||||
END_REGION GESTION_DISPOSITIVO
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,608 @@
|
||||
FUNCTION "FC2940_ZC_TQ_INDV" : Void
|
||||
TITLE = FC2940_ZC_TQ_INDV
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : HCR
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion dispositivo tanque.
|
||||
VAR_INPUT
|
||||
Pulso1seg : Bool; // Pulso de 1 segundo
|
||||
Arranque : Bool; // Arranque
|
||||
EstadoBocaHombre : Bool; // Estado boca de hombre
|
||||
EstadoNivelBajo : Bool; // Estado nivel bajo
|
||||
EstadoNivelAlto : Bool; // Estado nivel alto
|
||||
EstadoComOK : Bool; // Estado comunicaciones Ok
|
||||
ValorNivelPresion : Real; // Valor de nivel / presion
|
||||
ValorTemperatura : Real; // Valor temperatura
|
||||
HisteresisAltoNivelAgitacion : Real; // Histeresis superior nivel agitacion
|
||||
HisteresisBajoNivelAgitacion : Real; // Histeresis inferior nivel agitacion
|
||||
HisteresisAltoNivelTemp : Real; // Histeresis superior nivel temperatura
|
||||
HisteresisBajoNivelTemp : Real; // Histeresis inferior nivel temperatura
|
||||
TiempoTanqueVacio : Int; // Tiempo retardo tanque vacio
|
||||
TiempoTanqueLLeno : Int; // Tiempo retardo tanque lleno
|
||||
HabilitarFrecAgitacion : Bool; // Habilitar Frecuencia en Agitacion
|
||||
NumeroTanque : Int; // Numero de tanque
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
t_RadioCilindro : Real;
|
||||
t_RadioConoInf : Real;
|
||||
t_RadioActual : Real;
|
||||
t_Vol1 : Real;
|
||||
t_Vol2 : Real;
|
||||
t_Vol3 : Real;
|
||||
t_ConsignaAgitador : Real;
|
||||
t_VacioLL : Bool;
|
||||
t_VacioEA : Bool;
|
||||
t_HistPositiva : Real;
|
||||
t_HistNegativa : Real;
|
||||
t_LLenoHL : Bool;
|
||||
t_LlenoEA : Bool;
|
||||
t_x0 : Real;
|
||||
t_x1 : Real;
|
||||
t_x : Real;
|
||||
t_y0 : Real;
|
||||
t_y1 : Real;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
CONSTANTE_EMPIRICA : Real := 10.1;
|
||||
CONSTANTE_PI : Real := 3.141593;
|
||||
ESTADO_DESHABILITADO : Int := 0;
|
||||
ESTADO_SUCIO : Int := 1;
|
||||
ESTADO_LIMPIO : Int := 2;
|
||||
ESTADO_PRODUCTO : Int := 3;
|
||||
ESTADO_CIP : Int := 4;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
//=======================================================================
|
||||
// (C)Copyright ZeusControl 2022 - 2026
|
||||
//=======================================================================
|
||||
(*
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
El bloque implementa el modelo de dispositivo "Tanque" (`TQ`) para el control integral de depósitos en procesos industriales. Centraliza la adquisición de señales de campo, la gestión de estados del tanque, el cálculo de volumen por geometría cónica-cilíndrica, el control del agitador, el control de temperatura y la supervisión de alarmas, exponiendo toda la información al sistema SCADA mediante direccionamiento multiplexado.
|
||||
|
||||
Funcionalidades principales:
|
||||
- Gestión del estado global del tanque: deshabilitado, sucio, CIP (limpieza in-situ), limpio y con producto.
|
||||
- Lectura y validación de señales digitales y analógicas: detectores de nivel bajo (`LL`), nivel alto (`HL`), boca de hombre, valor de presión y valor de temperatura.
|
||||
- Cálculo de la altura de columna de líquido a partir de la presión medida mediante una constante empírica configurable.
|
||||
- Cálculo del volumen diferenciando dos tramos geométricos: zona cónica inferior (con radio variable en función del ángulo del cono y radio del cilindro) y zona cilíndrica superior.
|
||||
- Detección robusta de tanque vacío y tanque lleno combinando las señales de los detectores con temporizadores (`FC2928_ZC_TON_INDV`) que filtran el volumen por consignas configurables.
|
||||
- Gestión de alarmas: nivel bajo, nivel alto, boca de hombre y sobrecapacidad, con agrupación configurable por cuadro para integración en SCADA.
|
||||
- Control del agitador con dos modos de operación: fijo (marcha continua) o alternado por tiempos ON/OFF (`FC2926_ZC_FF_INDV`), con consigna de velocidad fija o proporcional al volumen.
|
||||
- Control de temperatura en modo calefacción o refrigeración con histéresis configurable y desactivación por nivel mínimo.
|
||||
- Seguimiento del producto: registro del producto activo, transición automática entre `Producto1` y `Producto2`, detección de mezcla y borrado al salir del estado PRODUCTO.
|
||||
- Soporte de cambio de estado y cambio de producto desde HMI/SCADA mediante flags de orden.
|
||||
- Direccionamiento multiplexado para SCADA (no indexado), con reset de índices en el primer arranque del PLC y reubicación del tanque `TQ[0]` cuando el índice vale 0.
|
||||
- Contadores de tiempo en estados LIMPIO y PRODUCTO (`FC15025_ZC_CONTADOR_TIEMPO`) para trazabilidad de proceso.
|
||||
|
||||
> **Restricciones:** PLC serie 1200/1500.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC15025_ZC_CONTADOR_TIEMPO`, `FC2928_ZC_TON_INDV`, `FC2926_ZC_FF_INDV` |
|
||||
| FB | - |
|
||||
| DB | `DB2040_TQ`, `DB1_SYS` |
|
||||
| UDT | `ZC_DISP_TQ`, `ZC_MUX`, `ZC_TON`, `ZC_CONTADOR_TIEMPO` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.01 | 26.04.2022 | (HCR) | Primera versión. |
|
||||
| 01.00.02 | 09.10.2023 | (HCR) | Cambio en activación dispositivos para que actúe solamente cuando tenga producto. |
|
||||
| 01.00.03 | 15.04.2024 | (ABH) | Se añade gestión multiplexado para Scada (no indexado). |
|
||||
| 01.00.04 | 08.01.2025 | (ABH) | Se añade entrada de primer arranque del PLC para resetear índices de multiplexado. Se añade movimiento de `TQ[0]` a multiplexado en caso de que el índice sea 0. |
|
||||
| 01.00.05 | 24.01.2025 | (ABH) | Se modifica la lógica del multiplexado, la asignación de `oldindex` se cambia de sitio ya que de vez en cuando (dependiendo de cuándo el HMI realiza la comunicación asíncrona con el PLC) no detectaba el cambio y se machacaban valores. |
|
||||
| 01.00.16 | 26.03.2025 | (ABH) | Se añade variable grupo de alarma para separar los nuevos avisos por cuadro. |
|
||||
| 02.00.00 | 17.12.2025 | (ABH) | Se eliminan los idiomas. Se utiliza códigos para trazabilidad. Se elimina entrada "Idioma". Se elimina nombre de UDT. Se añade `indexHMI` para lista de texto en sistemas de supervisión. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
// Numero maximo de dispositivos para limitar en HMI/Scada
|
||||
"DB2040_TQ".Mux.NumDispositivos := "N_MAX_DISP_TQ";
|
||||
|
||||
// Cambio de estado desde HMI/SCADA
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Orden_CambioEstado THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque := "DB2040_TQ".TQ[#NumeroTanque].Estado_TanqueNuevo;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_CambioEstado := FALSE;
|
||||
END_IF;
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Config_Habilitar := ("DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque <> #ESTADO_DESHABILITADO);
|
||||
|
||||
// =============================================================================
|
||||
// DISPOSITIVO HABILITADO
|
||||
// =============================================================================
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Config_Habilitar THEN
|
||||
|
||||
REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Config_GrupoAlarma < 0 THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Config_GrupoAlarma := 0;
|
||||
END_IF;
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Config_GrupoAlarma > "N_MAX_DISP_AGRUP" THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Config_GrupoAlarma := "N_MAX_DISP_AGRUP";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITE_GRUPO_ALARMA
|
||||
|
||||
|
||||
REGION ASIGNAR_ESTADOS
|
||||
|
||||
// =============================================================================
|
||||
// DETECTOR BOCA DE HOMBRE
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_BocaHombre := #EstadoBocaHombre;
|
||||
// =============================================================================
|
||||
// DETECTOR LL
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_NivelBajo := #EstadoNivelBajo;
|
||||
// =============================================================================
|
||||
// DETECTOR HL
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_NivelAlto := #EstadoNivelAlto;
|
||||
// =============================================================================
|
||||
// LECTURA VALOR NIVEL
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_ValorNivelPresion := #ValorNivelPresion;
|
||||
// =============================================================================
|
||||
// LECTURA VALOR INGENERIA TEMPERATURA
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_ValorTemperatura := #ValorTemperatura;
|
||||
|
||||
END_REGION ASIGNAR_ESTADOS
|
||||
|
||||
|
||||
REGION ALARMAS
|
||||
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Config_HabilitarAlarmas THEN
|
||||
// =============================================================================
|
||||
// ALARMA DETECTOR NIVEL MÍNIMO
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_NivelBajo := NOT "DB2040_TQ".TQ[#NumeroTanque].Estado_NivelBajo;
|
||||
// =============================================================================
|
||||
// ALARMA DETECTOR NIVEL MÁXIMO
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_NivelAlto := "DB2040_TQ".TQ[#NumeroTanque].Estado_NivelAlto;
|
||||
// =============================================================================
|
||||
// ALARMA DETECTOR BOCA HOMBRE
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_BocaHombre := NOT "DB2040_TQ".TQ[#NumeroTanque].Estado_BocaHombre;
|
||||
// =============================================================================
|
||||
// ALARMA POR CAPACIDAD
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_Capacidad := "DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen > "DB2040_TQ".TQ[#NumeroTanque].Config_CapacidadTanque;
|
||||
// =============================================================================
|
||||
// ALARMA GENERAL
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_General := "DB2040_TQ".TQ[#NumeroTanque].Alarmas_NivelBajo OR
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_NivelAlto OR
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_BocaHombre OR
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_Capacidad;
|
||||
ELSE
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_General := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_NivelBajo := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_NivelAlto := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_BocaHombre := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_Capacidad := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION ALARMAS
|
||||
|
||||
|
||||
REGION VOLUMEN
|
||||
|
||||
REGION ESTADO_VOLUMEN
|
||||
|
||||
// =============================================================================
|
||||
// POSICIÓN DE ALTURA
|
||||
// 0 - Altura en cono, 1 - Altura por encima del cono
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_PocisionAltura := ("DB2040_TQ".TQ[#NumeroTanque].Estado_Altura > "DB2040_TQ".TQ[#NumeroTanque].Config_AlturaCono);
|
||||
|
||||
// =============================================================================
|
||||
// TANQUE VACÍO DETECTOR
|
||||
#t_VacioLL := "DB2040_TQ".TQ[#NumeroTanque].Alarmas_NivelBajo;
|
||||
// =============================================================================
|
||||
// TANQUE VACÍO GESTION TON PARA EA < VOLUMEN TANQUE VACIO
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_RetTanqueVacio.SP := #TiempoTanqueVacio;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_RetTanqueVacio.IN := ("DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen < "DB2040_TQ".TQ[#NumeroTanque].Config_VolumenTanqueVacio);
|
||||
"FC2928_ZC_TON_INDV"(Pulso1seg := #Pulso1seg,
|
||||
TON := "DB2040_TQ".TQ[#NumeroTanque].Tiempo_RetTanqueVacio);
|
||||
#t_VacioEA := "DB2040_TQ".TQ[#NumeroTanque].Tiempo_RetTanqueVacio.Q;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_TanqueVacio := #t_VacioLL OR #t_VacioEA;
|
||||
|
||||
// =============================================================================
|
||||
// TANQUE LLENO DETECTOR
|
||||
#t_LLenoHL := "DB2040_TQ".TQ[#NumeroTanque].Alarmas_NivelAlto;
|
||||
// =============================================================================
|
||||
// TANQUE LLENO GESTION TON PARA EA > VOLUMEN TANQUE LLENO O CAPACIDAD
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_RetTanqueLleno.SP := #TiempoTanqueLLeno;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_RetTanqueLleno.IN := (("DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen > "DB2040_TQ".TQ[#NumeroTanque].Config_VolumenTanqueLleno) OR ("DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen > "DB2040_TQ".TQ[#NumeroTanque].Config_CapacidadTanque));
|
||||
"FC2928_ZC_TON_INDV"(Pulso1seg := #Pulso1seg,
|
||||
TON := "DB2040_TQ".TQ[#NumeroTanque].Tiempo_RetTanqueLleno);
|
||||
#t_LlenoEA := "DB2040_TQ".TQ[#NumeroTanque].Tiempo_RetTanqueLleno.Q;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_TanqueLleno := #t_LLenoHL OR #t_LlenoEA;
|
||||
|
||||
END_REGION ESTADO_VOLUMEN
|
||||
|
||||
|
||||
REGION CALCULO_VOLUMEN_TANQUE
|
||||
|
||||
// =============================================================================
|
||||
// SEÑAL EN AUTOMATICO
|
||||
IF NOT "DB2040_TQ".TQ[#NumeroTanque].Estado_AutoMan THEN
|
||||
|
||||
// =============================================================================
|
||||
// HABILITADO CALCULO DE VOLUMEN
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Config_HabilitarCalculoVol THEN
|
||||
// =============================================================================
|
||||
// VALOR PRESION
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Presion := "DB2040_TQ".TQ[#NumeroTanque].Estado_ValorNivelPresion;
|
||||
|
||||
// =============================================================================
|
||||
// CÁLCULO DE COLUMNA DE LÍQUIDO
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Altura := "DB2040_TQ".TQ[#NumeroTanque].Estado_Presion * #CONSTANTE_EMPIRICA;
|
||||
|
||||
// =============================================================================
|
||||
// CÁLCULO DE DIMENSIONES
|
||||
#t_RadioCilindro := "DB2040_TQ".TQ[#NumeroTanque].Config_DiametroCilindro / 2.0;
|
||||
#t_RadioConoInf := "DB2040_TQ".TQ[#NumeroTanque].Config_DiametroConoInferior / 2.0;
|
||||
#t_RadioActual := #t_RadioCilindro;
|
||||
|
||||
// =============================================================================
|
||||
// ALTURA INFERIOR AL CONO
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_Altura < "DB2040_TQ".TQ[#NumeroTanque].Config_AlturaCono THEN
|
||||
#t_RadioActual := ("DB2040_TQ".TQ[#NumeroTanque].Estado_Altura / TAN("DB2040_TQ".TQ[#NumeroTanque].Config_AnguloCono)); //+0.13
|
||||
// =============================================================================
|
||||
// LÍMITE RADIO
|
||||
IF #t_RadioActual > #t_RadioCilindro THEN
|
||||
#t_RadioActual := #t_RadioCilindro;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// CÁLCULO DE VOLUMEN INFERIOR AL CONO
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_Altura > 0 THEN
|
||||
#t_Vol1 := (#t_RadioConoInf * #t_RadioConoInf) + (#t_RadioActual * #t_RadioActual) + (#t_RadioConoInf * #t_RadioActual);
|
||||
#t_Vol2 := (#CONSTANTE_PI * "DB2040_TQ".TQ[#NumeroTanque].Estado_Altura) / 3.0;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen := #t_Vol1 * #t_Vol2 * 1000.0;
|
||||
ELSE
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen := 0.0;
|
||||
END_IF;
|
||||
// =============================================================================
|
||||
// ALTURA SUPERIOR AL CONO
|
||||
ELSE
|
||||
#t_Vol1 := (#t_RadioConoInf * #t_RadioConoInf) + (#t_RadioActual * #t_RadioActual) + (#t_RadioConoInf * #t_RadioActual);
|
||||
#t_Vol2 := (#CONSTANTE_PI * "DB2040_TQ".TQ[#NumeroTanque].Estado_Altura) / 3.0;
|
||||
#t_Vol3 := #CONSTANTE_PI * #t_RadioCilindro * #t_RadioCilindro * ("DB2040_TQ".TQ[#NumeroTanque].Estado_Altura - "DB2040_TQ".TQ[#NumeroTanque].Config_AlturaCono);
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen := ((#t_Vol1 * #t_Vol2) + #t_Vol3) * 1000.0;
|
||||
END_IF;
|
||||
ELSE
|
||||
// =============================================================================
|
||||
// VALOR PRESION
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen := "DB2040_TQ".TQ[#NumeroTanque].Estado_ValorNivelPresion;
|
||||
END_IF;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_ConsignaManualVolumen := "DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen;
|
||||
ELSE
|
||||
// =============================================================================
|
||||
// ESTADO MANUAL DE EA DE NIVEL
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen := "DB2040_TQ".TQ[#NumeroTanque].Orden_ConsignaManualVolumen;
|
||||
END_IF;
|
||||
|
||||
|
||||
END_REGION CALCULO_VOLUMEN_TANQUE
|
||||
|
||||
END_REGION VOLUMEN
|
||||
|
||||
|
||||
REGION ESTADO
|
||||
|
||||
// =============================================================================
|
||||
// ESTADO SUCIO
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque = #ESTADO_PRODUCTO AND "DB2040_TQ".TQ[#NumeroTanque].Estado_TanqueVacio AND #EstadoComOK THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque := #ESTADO_SUCIO;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ESTADO CIP
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Orden_CIP AND NOT "DB2040_TQ".TQ[#NumeroTanque].Aux_MemEstadoCIP THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque := #ESTADO_CIP;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemEstadoCIP := "DB2040_TQ".TQ[#NumeroTanque].Orden_CIP;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// ESTADO LIMPIO
|
||||
IF NOT "DB2040_TQ".TQ[#NumeroTanque].Orden_CIP AND "DB2040_TQ".TQ[#NumeroTanque].Aux_MemEstadoCIP THEN
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Aux_CipOK THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque := #ESTADO_LIMPIO;
|
||||
END_IF;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemEstadoCIP := "DB2040_TQ".TQ[#NumeroTanque].Orden_CIP;
|
||||
END_IF;
|
||||
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque = #ESTADO_CIP AND NOT "DB2040_TQ".TQ[#NumeroTanque].Orden_CIP AND NOT "DB2040_TQ".TQ[#NumeroTanque].Aux_CipOK THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque := #ESTADO_SUCIO;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemEstadoCIP := "DB2040_TQ".TQ[#NumeroTanque].Orden_CIP;
|
||||
END_IF;
|
||||
|
||||
// CONTADOR TIEMPO LIMPIO
|
||||
"FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg := #Pulso1seg,
|
||||
Iniciar := "DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque = #ESTADO_LIMPIO,
|
||||
Reset := "DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque <> #ESTADO_LIMPIO,
|
||||
Contador := "DB2040_TQ".TQ[#NumeroTanque].Tiempo_TiempoLimpio);
|
||||
|
||||
// =============================================================================
|
||||
// ESTADO PRODUCTO
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Orden_Producto AND NOT "DB2040_TQ".TQ[#NumeroTanque].Estado_TanqueVacio THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque := #ESTADO_PRODUCTO;
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// CAMBIO DE ESTADO DESDE HMI/SCADA
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Orden_CambioProd1 THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Producto1 := "DB2040_TQ".TQ[#NumeroTanque].Estado_ProductoNuevo;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_CambioProd1 := FALSE;
|
||||
END_IF;
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Orden_CambioProd2 THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Producto2 := "DB2040_TQ".TQ[#NumeroTanque].Estado_ProductoNuevo;
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_CambioProd2 := FALSE;
|
||||
END_IF;
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// PRODUCTOS
|
||||
IF ("DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque = #ESTADO_PRODUCTO) THEN
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Orden_Producto AND NOT "DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenProducto THEN
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_Producto2 = 0 AND "DB2040_TQ".TQ[#NumeroTanque].Estado_Producto1 <> 0 THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Producto2 := "DB2040_TQ".TQ[#NumeroTanque].Orden_TipoProducto;
|
||||
END_IF;
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_Producto1 = 0 THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Producto1 := "DB2040_TQ".TQ[#NumeroTanque].Orden_TipoProducto;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_IF;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenProducto := "DB2040_TQ".TQ[#NumeroTanque].Orden_Producto;
|
||||
|
||||
IF NOT "DB2040_TQ".TQ[#NumeroTanque].Orden_Producto OR NOT ("DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque = #ESTADO_PRODUCTO) THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenProducto := FALSE;
|
||||
END_IF;
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_Producto := FALSE;
|
||||
|
||||
// CONTADOR TIEMPO PRODUCTO
|
||||
"FC15025_ZC_CONTADOR_TIEMPO"(Pulso1seg := #Pulso1seg,
|
||||
Iniciar := "DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque = #ESTADO_PRODUCTO,
|
||||
Reset := "DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque <> #ESTADO_PRODUCTO,
|
||||
Contador := "DB2040_TQ".TQ[#NumeroTanque].Tiempo_TiempoProducto);
|
||||
|
||||
// =============================================================================
|
||||
// TANQUE MEZCLA
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Mezcla := "DB2040_TQ".TQ[#NumeroTanque].Estado_Producto1 <> 0 AND "DB2040_TQ".TQ[#NumeroTanque].Estado_Producto2 <> 0 AND "DB2040_TQ".TQ[#NumeroTanque].Estado_Producto1 <> "DB2040_TQ".TQ[#NumeroTanque].Estado_Producto2;
|
||||
|
||||
// =============================================================================
|
||||
// BORRADO DE PRODUCTOS
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque <> #ESTADO_PRODUCTO THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Producto1 := 0;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Producto2 := 0;
|
||||
END_IF;
|
||||
|
||||
END_REGION ESTADO
|
||||
|
||||
|
||||
REGION AGITADOR
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].FlipAgitador.Orden_Activar := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Config_HabilitarFrecuenciaAgitacion := #HabilitarFrecAgitacion;
|
||||
|
||||
// =============================================================================
|
||||
// TANQUE CON AGITADOR
|
||||
// IF "DB2039_TQ".TQ[N_Tanque].Config_HabilitarAgitador AND NOT "DB2039_TQ".TQ[N_Tanque].Orden_ParoControlAgitador THEN
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Config_HabilitarAgitador THEN
|
||||
|
||||
// =============================================================================
|
||||
// SE AÑADE 50 LITROS POR ENCIMA PARA EMPEZAR A AGITAR
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen > "DB2040_TQ".TQ[#NumeroTanque].Config_VolumenMinControlAgitador + #HisteresisAltoNivelAgitacion THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenAgitador := TRUE;
|
||||
END_IF;
|
||||
// =============================================================================
|
||||
//PARO AGITACIÓN POR NIVEL
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenAgitador AND "DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen < "DB2040_TQ".TQ[#NumeroTanque].Config_VolumenMinControlAgitador - #HisteresisBajoNivelAgitacion THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenAgitador := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
//TIPO DE AGITACIÓN POR TIEMPO
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Config_TipoAgitacionTiempo = 1 THEN
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].FlipAgitador.Config_SetPointTiempoFlip := "DB2040_TQ".TQ[#NumeroTanque].Tiempo_AgitadorONConsigna;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].FlipAgitador.Config_SetPointTiempoFlop := "DB2040_TQ".TQ[#NumeroTanque].Tiempo_AgitadorOFFConsigna;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].FlipAgitador.Orden_Pausa := "DB2040_TQ".TQ[#NumeroTanque].Orden_ParoControlAgitador;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].FlipAgitador.Orden_Activar := "DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenAgitador;
|
||||
|
||||
"FC2926_ZC_FF_INDV"(Pulso1Seg := #Pulso1seg,
|
||||
FF := "DB2040_TQ".TQ[#NumeroTanque].FlipAgitador);
|
||||
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].FlipAgitador.Estado_Flip THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_AgitadorONActual := "DB2040_TQ".TQ[#NumeroTanque].FlipAgitador.Aux_Tiempo;
|
||||
ELSE
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_AgitadorONActual := 0;
|
||||
END_IF;
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].FlipAgitador.Estado_Flop THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_AgitadorOFFActual := "DB2040_TQ".TQ[#NumeroTanque].FlipAgitador.Aux_Tiempo;
|
||||
ELSE
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_AgitadorOFFActual := 0;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
// =============================================================================
|
||||
// TIPO DE AGITACIÓN FIJO
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_AgitadorOFFActual := 0;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_AgitadorONActual := 0;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
//ORDEN ACTIVAR AGITADOR
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_Agitacion :=
|
||||
"DB2040_TQ".TQ[#NumeroTanque].FlipAgitador.Estado_Flip AND
|
||||
NOT "DB2040_TQ".TQ[#NumeroTanque].Orden_ParoControlAgitador AND
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_BocaHombre AND
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque = #ESTADO_PRODUCTO;
|
||||
|
||||
// =============================================================================
|
||||
//FRECUENCIA DE AGITADOR
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Orden_Agitacion AND "DB2040_TQ".TQ[#NumeroTanque].Config_HabilitarFrecuenciaAgitacion THEN
|
||||
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Config_TipoAgitacionVelocidad = 0 THEN
|
||||
// =============================================================================
|
||||
//VELOCIDAD FIJA
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_ConsignaAgitador := "DB2040_TQ".TQ[#NumeroTanque].Config_VelocidadFijaAgitador;
|
||||
|
||||
ELSE
|
||||
// =============================================================================
|
||||
//VELOCIDAD POR NIVEL
|
||||
#t_x0 := "DB2040_TQ".TQ[#NumeroTanque].Config_VolumenMinControlAgitador;
|
||||
#t_x1 := "DB2040_TQ".TQ[#NumeroTanque].Config_VolumenMaxControlAgitador;
|
||||
#t_x := "DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen;
|
||||
#t_y0 := "DB2040_TQ".TQ[#NumeroTanque].Config_VelocidadMinAgitador;
|
||||
#t_y1 := "DB2040_TQ".TQ[#NumeroTanque].Config_VelocidadMaxAgitador;
|
||||
#t_ConsignaAgitador := #t_y0 + (#t_y1 - #t_y0) * ((#t_x - #t_x0) / (#t_x1 - #t_x0));
|
||||
IF #t_ConsignaAgitador > #t_y1 THEN
|
||||
#t_ConsignaAgitador := #t_y1;
|
||||
END_IF;
|
||||
IF #t_ConsignaAgitador < #t_y0 THEN
|
||||
#t_ConsignaAgitador := #t_y0;
|
||||
END_IF;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_ConsignaAgitador := #t_ConsignaAgitador;
|
||||
END_IF;
|
||||
ELSE
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_ConsignaAgitador := 0.0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_Agitacion := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenAgitador := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_AgitadorOFFActual := 0;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_AgitadorONActual := 0;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_ConsignaAgitador := 0.0;
|
||||
END_IF;
|
||||
|
||||
END_REGION AGITADOR
|
||||
|
||||
|
||||
REGION VALVULA
|
||||
|
||||
// =============================================================================
|
||||
// HABILITAR CONTROL DE TEMPERATURA
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Config_HabilitarControlTemp AND NOT "DB2040_TQ".TQ[#NumeroTanque].Orden_ParoControlTemp AND "DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque = #ESTADO_PRODUCTO THEN
|
||||
|
||||
#t_HistPositiva := "DB2040_TQ".TQ[#NumeroTanque].Config_ConsignaTemperatura + "DB2040_TQ".TQ[#NumeroTanque].Config_HisteresisTemperatura;
|
||||
#t_HistNegativa := "DB2040_TQ".TQ[#NumeroTanque].Config_ConsignaTemperatura - "DB2040_TQ".TQ[#NumeroTanque].Config_HisteresisTemperatura;
|
||||
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen > "DB2040_TQ".TQ[#NumeroTanque].Config_VolumenMinControlTemp + #HisteresisAltoNivelTemp THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenTemperatura := TRUE;
|
||||
// =============================================================================
|
||||
// CONTROL DE TEMPERATURA ENFRIAR
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Config_TipoControlTemperatura THEN
|
||||
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_ValorTemperatura > "DB2040_TQ".TQ[#NumeroTanque].Config_ConsignaTemperatura THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_Temperatura := TRUE;
|
||||
END_IF;
|
||||
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_ValorTemperatura < #t_HistNegativa THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_Temperatura := FALSE;
|
||||
END_IF;
|
||||
// =============================================================================
|
||||
// CONTROL DE TEMPERATURA CALENTAR
|
||||
ELSE
|
||||
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_ValorTemperatura < "DB2040_TQ".TQ[#NumeroTanque].Config_ConsignaTemperatura THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_Temperatura := TRUE;
|
||||
END_IF;
|
||||
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Estado_ValorTemperatura > #t_HistPositiva THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_Temperatura := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
END_IF;
|
||||
// =============================================================================
|
||||
//PARAO CONTROL DE TEMPERATURA POR NIVEL
|
||||
IF "DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenTemperatura AND "DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen < "DB2040_TQ".TQ[#NumeroTanque].Config_VolumenMinControlTemp - #HisteresisBajoNivelTemp THEN
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_Temperatura := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenTemperatura := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_Temperatura := FALSE;
|
||||
END_IF;
|
||||
|
||||
// =============================================================================
|
||||
// VISIBILIDAD CONSIGNA DE TEMPERATURA
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Vis_ConsignaTemperatura :=
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Config_HabilitarControlTemp AND
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenTemperatura AND
|
||||
NOT "DB2040_TQ".TQ[#NumeroTanque].Orden_CIP AND ("DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque = #ESTADO_PRODUCTO) AND
|
||||
NOT "DB2040_TQ".TQ[#NumeroTanque].Orden_ParoControlTemp;
|
||||
|
||||
END_REGION VALVULA
|
||||
|
||||
ELSE
|
||||
// =============================================================================
|
||||
// DISPOSITIVO DESHABILITADO
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_Temperatura := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_Agitacion := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_ConsignaAgitador := 0.0;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_CIP := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_Producto := FALSE;
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_CambioEstado := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_CambioProd1 := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_CambioProd2 := FALSE;
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemEstadoCIP := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenProducto := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenTemperatura := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Aux_MemOrdenAgitador := FALSE;
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_TanqueVacio := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_PocisionAltura := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_NivelBajo := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_NivelAlto := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_BocaHombre := FALSE;
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Tanque := 0; // Deshabilitado
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Producto1 := 0;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Producto2 := 0;
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_NivelBajo := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_NivelAlto := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_BocaHombre := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_Capacidad := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Alarmas_General := FALSE;
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Volumen := 0.0;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Presion := 0.0;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Estado_Altura := 0.0;
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Config_HabilitarControlTemp := FALSE;
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_AgitadorONActual := 0;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_AgitadorOFFActual := 0;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_RetTanqueVacio.ET := 0;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Tiempo_RetTanqueVacio.Q := FALSE;
|
||||
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_ParoControlAgitador := FALSE;
|
||||
"DB2040_TQ".TQ[#NumeroTanque].Orden_ParoControlTemp := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION LOGICA_DEL_DISPOSITIVO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
FUNCTION "FC2800_ZC_ED_MUX" : Void
|
||||
TITLE = FC2800_ZC_ED_MUX
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion multiplexado dispositivo Entrada digital
|
||||
VAR_INPUT
|
||||
Arranque : Bool; // Primer arranque
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_mux : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2026 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- - -
|
||||
### Descripción Funcional
|
||||
El bloque implementa la gestión de multiplexado estático para el dispositivo entrada digital, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
|
||||
|
||||
Funcionalidades principales de la arquitectura:
|
||||
- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
|
||||
- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_ED`.
|
||||
- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2000_ED.ED[X]`) en la interfaz del multiplexor.
|
||||
- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
|
||||
- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
|
||||
- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
|
||||
- Caso especial de índice `0`: carga la estructura `ED[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
|
||||
|
||||
> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
|
||||
|
||||
- - -
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2000_ED` |
|
||||
| UDT | `ZC_DISP_ED`, `ZC_DISP_MUX_ED` |
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 10.07.2026 | (ABH) | Primera versión extraído a FC independiente. Refactorizacion de multiplexado para su uso solo en WinCC Professional.|
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay Scada declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_SCADA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_SCADA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
REGION MULTIPLEXADO
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
|
||||
IF #Arranque THEN
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
"DB2000_ED".Mux.Scada[#for_mux].Index :=
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestion de multiplexado
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Antes de iniciar la logica del multiplexado, revisamos los limites
|
||||
REGION LIMITES
|
||||
|
||||
// ===========================================================================================================
|
||||
// Limites
|
||||
IF "DB2000_ED".Mux.Scada[#for_mux].Index < 0 THEN
|
||||
"DB2000_ED".Mux.Scada[#for_mux].Index := 0;
|
||||
END_IF;
|
||||
IF "DB2000_ED".Mux.Scada[#for_mux].Index > "N_MAX_DISP_ED" THEN
|
||||
"DB2000_ED".Mux.Scada[#for_mux].Index := "N_MAX_DISP_ED";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
// Traspaso de limites a variable temporal para evitar cambios no deseados
|
||||
REGION INDICES
|
||||
|
||||
#t_Index := "DB2000_ED".Mux.Scada[#for_mux].Index;
|
||||
#t_oldIndex := "DB2000_ED".Mux.Scada[#for_mux].oldIndex;
|
||||
|
||||
END_REGION INDICES
|
||||
|
||||
|
||||
IF "DB2000_ED".Mux.Scada[#for_mux].Habilitar THEN
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestionamos solo los tipos
|
||||
IF #t_Index > 0 THEN
|
||||
|
||||
REGION CARGA_INICIAL
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice y almacenamos el estado original
|
||||
IF #t_Index <> #t_oldIndex THEN
|
||||
|
||||
// Traspaso de dispositivos al multiplexado
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED := "DB2000_ED".ED[#t_Index];
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED := "DB2000_ED".ED[#t_Index];
|
||||
|
||||
// ===========================================================================================================
|
||||
// Valor anterior del indice
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldIndex := #t_Index;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION CARGA_INICIAL
|
||||
|
||||
|
||||
REGION DATOS_LECTURA
|
||||
|
||||
// ===========================================================================================================
|
||||
// Movimiento de datos gestionados en FC
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Hmi_Estado := "DB2000_ED".ED[#t_Index].Hmi_Estado;
|
||||
IF NOT "DB2000_ED".ED[#t_Index].Estado_AutoMan THEN
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Orden_ActivarManual := "DB2000_ED".ED[#t_Index].Orden_ActivarManual;
|
||||
END_IF;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Estado_Activado := "DB2000_ED".ED[#t_Index].Estado_Activado;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Estado_EntradaCanal := "DB2000_ED".ED[#t_Index].Estado_EntradaCanal;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Aux_oldActivado := "DB2000_ED".ED[#t_Index].Aux_oldActivado;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Aux_oldAutoMan := "DB2000_ED".ED[#t_Index].Aux_oldAutoMan;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Tiempos_TiempoAct := "DB2000_ED".ED[#t_Index].Tiempos_TiempoAct;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Tiempos_TiempoDes := "DB2000_ED".ED[#t_Index].Tiempos_TiempoDes;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Config_GrupoAlarma := "DB2000_ED".ED[#t_Index].Config_GrupoAlarma;
|
||||
|
||||
END_REGION DATOS_LECTURA
|
||||
|
||||
|
||||
REGION DATOS_ESCRITURA
|
||||
|
||||
REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
// ===========================================================================================================
|
||||
// Estado Auto/Manual
|
||||
IF "DB2000_ED".ED[#t_Index].Estado_AutoMan <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Estado_AutoMan THEN
|
||||
// Cambio desde HMI
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Estado_AutoMan := "DB2000_ED".ED[#t_Index].Estado_AutoMan;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Estado_AutoMan := "DB2000_ED".ED[#t_Index].Estado_AutoMan;
|
||||
ELSIF "DB2000_ED".Mux.Scada[#for_mux].ED.Estado_AutoMan <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Estado_AutoMan THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2000_ED".ED[#t_Index].Estado_AutoMan := "DB2000_ED".Mux.Scada[#for_mux].ED.Estado_AutoMan;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Estado_AutoMan := "DB2000_ED".Mux.Scada[#for_mux].ED.Estado_AutoMan;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Activar Manual
|
||||
IF "DB2000_ED".ED[#t_Index].Orden_ActivarManual <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Orden_ActivarManual THEN
|
||||
// Cambio desde HMI
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Orden_ActivarManual := "DB2000_ED".ED[#t_Index].Orden_ActivarManual;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Orden_ActivarManual := "DB2000_ED".ED[#t_Index].Orden_ActivarManual;
|
||||
ELSIF "DB2000_ED".Mux.Scada[#for_mux].ED.Orden_ActivarManual <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Orden_ActivarManual THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2000_ED".ED[#t_Index].Orden_ActivarManual := "DB2000_ED".Mux.Scada[#for_mux].ED.Orden_ActivarManual;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Orden_ActivarManual := "DB2000_ED".Mux.Scada[#for_mux].ED.Orden_ActivarManual;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
|
||||
REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde HMI
|
||||
// Comparamos el dispositivo original con el dispositivo real, para detectar cambios desde PLC o desde HMI
|
||||
#t_CambioDesdeHMI :=
|
||||
("DB2000_ED".Mux.Scada[#for_mux].oldED.Config_DirEntradaBit <> "DB2000_ED".ED[#t_Index].Config_DirEntradaBit)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].oldED.Config_DirEntradaByte <> "DB2000_ED".ED[#t_Index].Config_DirEntradaByte)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].oldED.Config_Habilitar <> "DB2000_ED".ED[#t_Index].Config_Habilitar)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].oldED.Config_HabilitarInvertir <> "DB2000_ED".ED[#t_Index].Config_HabilitarInvertir)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoAct <> "DB2000_ED".ED[#t_Index].Config_HabilitarRetardoAct)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoDes <> "DB2000_ED".ED[#t_Index].Config_HabilitarRetardoDes)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].oldED.Config_TipoAcceso <> "DB2000_ED".ED[#t_Index].Config_TipoAcceso)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoAct <> "DB2000_ED".ED[#t_Index].Tiempos_SPTiempoAct)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoDes <> "DB2000_ED".ED[#t_Index].Tiempos_SPTiempoDes);
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde MUX SCADA
|
||||
// Comparamos el dispositivo original con el multiplexado, para detectar cambios desde multiplexado
|
||||
#t_CambioDesdeMux :=
|
||||
("DB2000_ED".Mux.Scada[#for_mux].ED.Config_DirEntradaBit <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Config_DirEntradaBit)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].ED.Config_DirEntradaByte <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Config_DirEntradaByte)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].ED.Config_Habilitar <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Config_Habilitar)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].ED.Config_HabilitarInvertir <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Config_HabilitarInvertir)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoAct <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoAct)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoDes <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoDes)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].ED.Config_TipoAcceso <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Config_TipoAcceso)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoAct <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoAct)
|
||||
OR ("DB2000_ED".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoDes <> "DB2000_ED".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoDes);
|
||||
|
||||
END_REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
|
||||
REGION TRASPASO_DATOS
|
||||
|
||||
IF #t_CambioDesdeHMI THEN
|
||||
|
||||
// Al detectar un cambio desde el HMI, cargamos sus valores de nuevo al multiplexado
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Estado_AutoMan := "DB2000_ED".ED[#t_Index].Estado_AutoMan;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Orden_ActivarManual := "DB2000_ED".ED[#t_Index].Orden_ActivarManual;
|
||||
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Config_DirEntradaBit := "DB2000_ED".ED[#t_Index].Config_DirEntradaBit;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Config_DirEntradaByte := "DB2000_ED".ED[#t_Index].Config_DirEntradaByte;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Config_Habilitar := "DB2000_ED".ED[#t_Index].Config_Habilitar;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Config_HabilitarInvertir := "DB2000_ED".ED[#t_Index].Config_HabilitarInvertir;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoAct := "DB2000_ED".ED[#t_Index].Config_HabilitarRetardoAct;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoDes := "DB2000_ED".ED[#t_Index].Config_HabilitarRetardoDes;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Config_TipoAcceso := "DB2000_ED".ED[#t_Index].Config_TipoAcceso;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoAct := "DB2000_ED".ED[#t_Index].Tiempos_SPTiempoAct;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoDes := "DB2000_ED".ED[#t_Index].Tiempos_SPTiempoDes;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Estado_AutoMan := "DB2000_ED".ED[#t_Index].Estado_AutoMan;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Orden_ActivarManual := "DB2000_ED".ED[#t_Index].Orden_ActivarManual;
|
||||
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_DirEntradaBit := "DB2000_ED".ED[#t_Index].Config_DirEntradaBit;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_DirEntradaByte := "DB2000_ED".ED[#t_Index].Config_DirEntradaByte;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_Habilitar := "DB2000_ED".ED[#t_Index].Config_Habilitar;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_HabilitarInvertir := "DB2000_ED".ED[#t_Index].Config_HabilitarInvertir;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoAct := "DB2000_ED".ED[#t_Index].Config_HabilitarRetardoAct;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoDes := "DB2000_ED".ED[#t_Index].Config_HabilitarRetardoDes;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_TipoAcceso := "DB2000_ED".ED[#t_Index].Config_TipoAcceso;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoAct := "DB2000_ED".ED[#t_Index].Tiempos_SPTiempoAct;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoDes := "DB2000_ED".ED[#t_Index].Tiempos_SPTiempoDes;
|
||||
|
||||
ELSIF #t_CambioDesdeMux THEN
|
||||
|
||||
// Al detectar un cambio desde el MUX, cargamos sus valores al dispositivo
|
||||
"DB2000_ED".ED[#t_Index].Estado_AutoMan := "DB2000_ED".Mux.Scada[#for_mux].ED.Estado_AutoMan;
|
||||
"DB2000_ED".ED[#t_Index].Orden_ActivarManual := "DB2000_ED".Mux.Scada[#for_mux].ED.Orden_ActivarManual;
|
||||
|
||||
"DB2000_ED".ED[#t_Index].Config_DirEntradaBit := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_DirEntradaBit;
|
||||
"DB2000_ED".ED[#t_Index].Config_DirEntradaByte := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_DirEntradaByte;
|
||||
"DB2000_ED".ED[#t_Index].Config_Habilitar := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_Habilitar;
|
||||
"DB2000_ED".ED[#t_Index].Config_HabilitarInvertir := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_HabilitarInvertir;
|
||||
"DB2000_ED".ED[#t_Index].Config_HabilitarRetardoAct := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoAct;
|
||||
"DB2000_ED".ED[#t_Index].Config_HabilitarRetardoDes := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoDes;
|
||||
"DB2000_ED".ED[#t_Index].Config_TipoAcceso := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_TipoAcceso;
|
||||
"DB2000_ED".ED[#t_Index].Tiempos_SPTiempoAct := "DB2000_ED".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoAct;
|
||||
"DB2000_ED".ED[#t_Index].Tiempos_SPTiempoDes := "DB2000_ED".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoDes;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Estado_AutoMan := "DB2000_ED".Mux.Scada[#for_mux].ED.Estado_AutoMan;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Orden_ActivarManual := "DB2000_ED".Mux.Scada[#for_mux].ED.Orden_ActivarManual;
|
||||
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_DirEntradaBit := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_DirEntradaBit;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_DirEntradaByte := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_DirEntradaByte;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_Habilitar := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_Habilitar;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_HabilitarInvertir := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_HabilitarInvertir;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoAct := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoAct;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoDes := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoDes;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Config_TipoAcceso := "DB2000_ED".Mux.Scada[#for_mux].ED.Config_TipoAcceso;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoAct := "DB2000_ED".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoAct;
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoDes := "DB2000_ED".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoDes;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_DATOS
|
||||
|
||||
END_REGION DATOS_ESCRITURA
|
||||
|
||||
ELSE
|
||||
|
||||
// ===========================================================================================================
|
||||
// En caso de que el indice sea 0, movemos el valor de la ED[0] que no se usa para escribir el index.
|
||||
"DB2000_ED".Mux.Scada[#for_mux].ED := "DB2000_ED".ED[0];
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldED := "DB2000_ED".ED[0];
|
||||
|
||||
// Actualizacion de estado anterior
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// Multiplexado no habilitado
|
||||
"DB2000_ED".Mux.Scada[#for_mux].Index :=
|
||||
"DB2000_ED".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION MULTIPLEXADO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
FUNCTION "FC2801_ZC_EA_MUX" : Void
|
||||
TITLE = FC2801_ZC_EA_MUX
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion multiplexado dispositivo Entrada analogica
|
||||
VAR_INPUT
|
||||
Arranque : Bool; // Primer arranque
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_mux : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2026 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- - -
|
||||
### Descripción Funcional
|
||||
El bloque implementa la gestión de multiplexado estático para el dispositivo entrada analogica, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
|
||||
|
||||
Funcionalidades principales de la arquitectura:
|
||||
- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
|
||||
- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_EA`.
|
||||
- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2001_EA.EA[X]`) en la interfaz del multiplexor.
|
||||
- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
|
||||
- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
|
||||
- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
|
||||
- Caso especial de índice `0`: carga la estructura `EA[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
|
||||
|
||||
> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
|
||||
|
||||
- - -
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2001_EA` |
|
||||
| UDT | `ZC_DISP_EA`, `ZC_DISP_MUX_EA` |
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 10.07.2026 | (ABH) | Primera versión extraído a FC independiente. Refactorizacion de multiplexado para su uso solo en WinCC Professional.|
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay Scada declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_SCADA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_SCADA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
REGION MULTIPLEXADO
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
|
||||
IF #Arranque THEN
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
"DB2001_EA".Mux.Scada[#for_mux].Index :=
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestion de multiplexado
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Antes de iniciar la logica del multiplexado, revisamos los limites
|
||||
REGION LIMITES
|
||||
|
||||
// ===========================================================================================================
|
||||
// Limites
|
||||
IF "DB2001_EA".Mux.Scada[#for_mux].Index < 0 THEN
|
||||
"DB2001_EA".Mux.Scada[#for_mux].Index := 0;
|
||||
END_IF;
|
||||
IF "DB2001_EA".Mux.Scada[#for_mux].Index > "N_MAX_DISP_EA" THEN
|
||||
"DB2001_EA".Mux.Scada[#for_mux].Index := "N_MAX_DISP_EA";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
// Traspaso de limites a variable temporal para evitar cambios no deseados
|
||||
REGION INDICES
|
||||
|
||||
#t_Index := "DB2001_EA".Mux.Scada[#for_mux].Index;
|
||||
#t_oldIndex := "DB2001_EA".Mux.Scada[#for_mux].oldIndex;
|
||||
|
||||
END_REGION INDICES
|
||||
|
||||
|
||||
IF "DB2001_EA".Mux.Scada[#for_mux].Habilitar THEN
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestionamos solo los tipos
|
||||
IF #t_Index > 0 THEN
|
||||
|
||||
REGION CARGA_INICIAL
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice.
|
||||
IF #t_Index <> #t_oldIndex THEN
|
||||
|
||||
// Traspaso de dispositivos al multiplexado
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA := "DB2001_EA".EA[#t_Index];
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA := "DB2001_EA".EA[#t_Index];
|
||||
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Valor anterior del indice
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldIndex := #t_Index;
|
||||
|
||||
END_REGION CARGA_INICIAL
|
||||
|
||||
|
||||
REGION DATOS_LECTURA
|
||||
|
||||
// ===========================================================================================================
|
||||
// Movimiento de datos gestionados en FC
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Hmi_Estado := "DB2001_EA".EA[#t_Index].Hmi_Estado;
|
||||
IF NOT "DB2001_EA".EA[#t_Index].Estado_AutoMan THEN
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Orden_ConsignaManual := "DB2001_EA".EA[#t_Index].Orden_ConsignaManual;
|
||||
END_IF;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Estado_ValorIngenieria := "DB2001_EA".EA[#t_Index].Estado_ValorIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Estado_ValorTarjeta := "DB2001_EA".EA[#t_Index].Estado_ValorTarjeta;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Alarmas_General := "DB2001_EA".EA[#t_Index].Alarmas_General;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Alarmas_HiloRoto := "DB2001_EA".EA[#t_Index].Alarmas_HiloRoto;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Alarmas_Lectura := "DB2001_EA".EA[#t_Index].Alarmas_Lectura;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Alarmas_Max := "DB2001_EA".EA[#t_Index].Alarmas_Max;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Alarmas_Min := "DB2001_EA".EA[#t_Index].Alarmas_Min;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Alarmas_Parametros := "DB2001_EA".EA[#t_Index].Alarmas_Parametros;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Aux_Estado := "DB2001_EA".EA[#t_Index].Aux_Estado;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Aux_oldAlarma := "DB2001_EA".EA[#t_Index].Aux_oldAlarma;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Aux_oldAutoMan := "DB2001_EA".EA[#t_Index].Aux_oldAutoMan;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_GrupoAlarma := "DB2001_EA".EA[#t_Index].Config_GrupoAlarma;
|
||||
|
||||
END_REGION DATOS_LECTURA
|
||||
|
||||
|
||||
REGION DATOS_ESCRITURA
|
||||
|
||||
REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
// ===========================================================================================================
|
||||
// Estado Auto/Manual
|
||||
IF "DB2001_EA".EA[#t_Index].Estado_AutoMan <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Estado_AutoMan THEN
|
||||
// Cambio desde HMI
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Estado_AutoMan := "DB2001_EA".EA[#t_Index].Estado_AutoMan;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Estado_AutoMan := "DB2001_EA".EA[#t_Index].Estado_AutoMan;
|
||||
ELSIF "DB2001_EA".Mux.Scada[#for_mux].EA.Estado_AutoMan <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Estado_AutoMan THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2001_EA".EA[#t_Index].Estado_AutoMan := "DB2001_EA".Mux.Scada[#for_mux].EA.Estado_AutoMan;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Estado_AutoMan := "DB2001_EA".Mux.Scada[#for_mux].EA.Estado_AutoMan;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Activar Manual
|
||||
IF "DB2001_EA".EA[#t_Index].Orden_ConsignaManual <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Orden_ConsignaManual THEN
|
||||
// Cambio desde HMI
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Orden_ConsignaManual := "DB2001_EA".EA[#t_Index].Orden_ConsignaManual;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Orden_ConsignaManual := "DB2001_EA".EA[#t_Index].Orden_ConsignaManual;
|
||||
ELSIF "DB2001_EA".Mux.Scada[#for_mux].EA.Orden_ConsignaManual <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Orden_ConsignaManual THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2001_EA".EA[#t_Index].Orden_ConsignaManual := "DB2001_EA".Mux.Scada[#for_mux].EA.Orden_ConsignaManual;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Orden_ConsignaManual := "DB2001_EA".Mux.Scada[#for_mux].EA.Orden_ConsignaManual;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
|
||||
REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde HMI
|
||||
// Comparamos el dispositivo original con el dispositivo real, para detectar cambios desde PLC o desde HMI
|
||||
#t_CambioDesdeHMI :=
|
||||
("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_DireccionEntradaByte <> "DB2001_EA".EA[#t_Index].Config_DireccionEntradaByte)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxHisteresis <> "DB2001_EA".EA[#t_Index].Config_ErrorMaxHisteresis)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxIngenieria <> "DB2001_EA".EA[#t_Index].Config_ErrorMaxIngenieria)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMinHisteresis <> "DB2001_EA".EA[#t_Index].Config_ErrorMinHisteresis)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMinIngenieria <> "DB2001_EA".EA[#t_Index].Config_ErrorMinIngenieria)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxIngenieria <> "DB2001_EA".EA[#t_Index].Config_EscaladoMaxIngenieria)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxTarjeta <> "DB2001_EA".EA[#t_Index].Config_EscaladoMaxTarjeta)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinIngenieria <> "DB2001_EA".EA[#t_Index].Config_EscaladoMinIngenieria)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinTarjeta <> "DB2001_EA".EA[#t_Index].Config_EscaladoMinTarjeta)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoOffset <> "DB2001_EA".EA[#t_Index].Config_EscaladoOffset)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_Habilitar <> "DB2001_EA".EA[#t_Index].Config_Habilitar)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMax <> "DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMax)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMin <> "DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMin)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_TipoAcceso <> "DB2001_EA".EA[#t_Index].Config_TipoAcceso)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_HisteresisTipo <> "DB2001_EA".EA[#t_Index].Config_HisteresisTipo);
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde MUX SCADA
|
||||
// Comparamos el dispositivo original con el multiplexado, para detectar cambios desde multiplexado
|
||||
#t_CambioDesdeMux :=
|
||||
("DB2001_EA".Mux.Scada[#for_mux].EA.Config_DireccionEntradaByte <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_DireccionEntradaByte)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMaxHisteresis <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxHisteresis)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMaxIngenieria <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxIngenieria)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMinHisteresis <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMinHisteresis)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMinIngenieria <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMinIngenieria)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMaxIngenieria <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxIngenieria)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMaxTarjeta <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxTarjeta)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMinIngenieria <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinIngenieria)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMinTarjeta <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinTarjeta)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoOffset <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoOffset)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_Habilitar <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_Habilitar)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMax <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMax)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMin <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMin)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_TipoAcceso <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_TipoAcceso)
|
||||
OR ("DB2001_EA".Mux.Scada[#for_mux].EA.Config_HisteresisTipo <> "DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_HisteresisTipo);
|
||||
|
||||
END_REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
|
||||
REGION TRASPASO_DATOS
|
||||
|
||||
IF #t_CambioDesdeHMI THEN
|
||||
|
||||
// Al detectar un cambio desde el HMI, cargamos sus valores de nuevo al multiplexado
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Estado_AutoMan := "DB2001_EA".EA[#t_Index].Estado_AutoMan;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Orden_ConsignaManual := "DB2001_EA".EA[#t_Index].Orden_ConsignaManual;
|
||||
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_DireccionEntradaByte := "DB2001_EA".EA[#t_Index].Config_DireccionEntradaByte;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMaxHisteresis := "DB2001_EA".EA[#t_Index].Config_ErrorMaxHisteresis;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMaxIngenieria := "DB2001_EA".EA[#t_Index].Config_ErrorMaxIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMinHisteresis := "DB2001_EA".EA[#t_Index].Config_ErrorMinHisteresis;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMinIngenieria := "DB2001_EA".EA[#t_Index].Config_ErrorMinIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMaxIngenieria := "DB2001_EA".EA[#t_Index].Config_EscaladoMaxIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMaxTarjeta := "DB2001_EA".EA[#t_Index].Config_EscaladoMaxTarjeta;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMinIngenieria := "DB2001_EA".EA[#t_Index].Config_EscaladoMinIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMinTarjeta := "DB2001_EA".EA[#t_Index].Config_EscaladoMinTarjeta;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoOffset := "DB2001_EA".EA[#t_Index].Config_EscaladoOffset;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_Habilitar := "DB2001_EA".EA[#t_Index].Config_Habilitar;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMax := "DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMax;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMin := "DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMin;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_TipoAcceso := "DB2001_EA".EA[#t_Index].Config_TipoAcceso;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA.Config_HisteresisTipo := "DB2001_EA".EA[#t_Index].Config_HisteresisTipo;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_DireccionEntradaByte := "DB2001_EA".EA[#t_Index].Config_DireccionEntradaByte;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxHisteresis := "DB2001_EA".EA[#t_Index].Config_ErrorMaxHisteresis;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxIngenieria := "DB2001_EA".EA[#t_Index].Config_ErrorMaxIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMinHisteresis := "DB2001_EA".EA[#t_Index].Config_ErrorMinHisteresis;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMinIngenieria := "DB2001_EA".EA[#t_Index].Config_ErrorMinIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxIngenieria := "DB2001_EA".EA[#t_Index].Config_EscaladoMaxIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxTarjeta := "DB2001_EA".EA[#t_Index].Config_EscaladoMaxTarjeta;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinIngenieria := "DB2001_EA".EA[#t_Index].Config_EscaladoMinIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinTarjeta := "DB2001_EA".EA[#t_Index].Config_EscaladoMinTarjeta;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoOffset := "DB2001_EA".EA[#t_Index].Config_EscaladoOffset;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_Habilitar := "DB2001_EA".EA[#t_Index].Config_Habilitar;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMax := "DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMax;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMin := "DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMin;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_TipoAcceso := "DB2001_EA".EA[#t_Index].Config_TipoAcceso;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_HisteresisTipo := "DB2001_EA".EA[#t_Index].Config_HisteresisTipo;
|
||||
|
||||
ELSIF #t_CambioDesdeMux THEN
|
||||
|
||||
// Al detectar un cambio desde el MUX, cargamos sus valores al dispositivo
|
||||
"DB2001_EA".EA[#t_Index].Estado_AutoMan := "DB2001_EA".Mux.Scada[#for_mux].EA.Estado_AutoMan;
|
||||
"DB2001_EA".EA[#t_Index].Orden_ConsignaManual := "DB2001_EA".Mux.Scada[#for_mux].EA.Orden_ConsignaManual;
|
||||
|
||||
"DB2001_EA".EA[#t_Index].Config_DireccionEntradaByte := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_DireccionEntradaByte;
|
||||
"DB2001_EA".EA[#t_Index].Config_ErrorMaxHisteresis := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMaxHisteresis;
|
||||
"DB2001_EA".EA[#t_Index].Config_ErrorMaxIngenieria := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMaxIngenieria;
|
||||
"DB2001_EA".EA[#t_Index].Config_ErrorMinHisteresis := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMinHisteresis;
|
||||
"DB2001_EA".EA[#t_Index].Config_ErrorMinIngenieria := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMinIngenieria;
|
||||
"DB2001_EA".EA[#t_Index].Config_EscaladoMaxIngenieria := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMaxIngenieria;
|
||||
"DB2001_EA".EA[#t_Index].Config_EscaladoMaxTarjeta := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMaxTarjeta;
|
||||
"DB2001_EA".EA[#t_Index].Config_EscaladoMinIngenieria := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMinIngenieria;
|
||||
"DB2001_EA".EA[#t_Index].Config_EscaladoMinTarjeta := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMinTarjeta;
|
||||
"DB2001_EA".EA[#t_Index].Config_EscaladoOffset := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoOffset;
|
||||
"DB2001_EA".EA[#t_Index].Config_Habilitar := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_Habilitar;
|
||||
"DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMax := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMax;
|
||||
"DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMin := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMin;
|
||||
"DB2001_EA".EA[#t_Index].Config_TipoAcceso := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_TipoAcceso;
|
||||
"DB2001_EA".EA[#t_Index].Config_HisteresisTipo := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_HisteresisTipo;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_DireccionEntradaByte := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_DireccionEntradaByte;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxHisteresis := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMaxHisteresis;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxIngenieria := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMaxIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMinHisteresis := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMinHisteresis;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_ErrorMinIngenieria := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_ErrorMinIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxIngenieria := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMaxIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxTarjeta := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMaxTarjeta;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinIngenieria := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMinIngenieria;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinTarjeta := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoMinTarjeta;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_EscaladoOffset := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_EscaladoOffset;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_Habilitar := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_Habilitar;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMax := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMax;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMin := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMin;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_TipoAcceso := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_TipoAcceso;
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA.Config_HisteresisTipo := "DB2001_EA".Mux.Scada[#for_mux].EA.Config_HisteresisTipo;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_DATOS
|
||||
|
||||
END_REGION DATOS_ESCRITURA
|
||||
|
||||
ELSE
|
||||
|
||||
// ===========================================================================================================
|
||||
// En caso de que el indice sea 0, movemos el valor de la EA[0] que no se usa para escribir el index.
|
||||
"DB2001_EA".Mux.Scada[#for_mux].EA := "DB2001_EA".EA[0];
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldEA := "DB2001_EA".EA[0];
|
||||
|
||||
// Actualizacion de estado anterior
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// Multiplexado no habilitado
|
||||
"DB2001_EA".Mux.Scada[#for_mux].Index :=
|
||||
"DB2001_EA".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION MULTIPLEXADO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
FUNCTION "FC2805_ZC_SD_MUX" : Void
|
||||
TITLE = FC2805_ZC_SD_MUX
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion multiplexado dispositivo Salida digital
|
||||
VAR_INPUT
|
||||
Arranque : Bool; // Primer arranque
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_mux : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2026 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- - -
|
||||
### Descripción Funcional
|
||||
El bloque implementa la gestión de multiplexado estático para el dispositivo salida digital, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
|
||||
|
||||
Funcionalidades principales de la arquitectura:
|
||||
- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
|
||||
- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_SD`.
|
||||
- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2005_SD.SD[X]`) en la interfaz del multiplexor.
|
||||
- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
|
||||
- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
|
||||
- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
|
||||
- Caso especial de índice `0`: carga la estructura `SD[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
|
||||
|
||||
> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
|
||||
|
||||
- - -
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2005_SD` |
|
||||
| UDT | `ZC_DISP_SD`, `ZC_DISP_MUX_SD` |
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 10.07.2026 | (ABH) | Primera versión extraído a FC independiente. Refactorizacion de multiplexado para su uso solo en WinCC Professional.|
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay Scada declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_SCADA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_SCADA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
REGION MULTIPLEXADO
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
|
||||
IF #Arranque THEN
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
"DB2005_SD".Mux.Scada[#for_mux].Index :=
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestion de multiplexado
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Antes de iniciar la logica del multiplexado, revisamos los limites
|
||||
REGION LIMITES
|
||||
|
||||
// ===========================================================================================================
|
||||
// Limites
|
||||
IF "DB2005_SD".Mux.Scada[#for_mux].Index < 0 THEN
|
||||
"DB2005_SD".Mux.Scada[#for_mux].Index := 0;
|
||||
END_IF;
|
||||
IF "DB2005_SD".Mux.Scada[#for_mux].Index > "N_MAX_DISP_SD" THEN
|
||||
"DB2005_SD".Mux.Scada[#for_mux].Index := "N_MAX_DISP_SD";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
// Traspaso de limites a variable temporal para evitar cambios no deseados
|
||||
REGION INDICES
|
||||
|
||||
#t_Index := "DB2005_SD".Mux.Scada[#for_mux].Index;
|
||||
#t_oldIndex := "DB2005_SD".Mux.Scada[#for_mux].oldIndex;
|
||||
|
||||
END_REGION INDICES
|
||||
|
||||
|
||||
IF "DB2005_SD".Mux.Scada[#for_mux].Habilitar THEN
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestionamos solo los tipos
|
||||
IF #t_Index > 0 THEN
|
||||
|
||||
REGION CARGA_INICIAL
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice.
|
||||
IF #t_Index <> #t_oldIndex THEN
|
||||
|
||||
// Traspaso de dispositivos al multiplexado
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD := "DB2005_SD".SD[#t_Index];
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD := "DB2005_SD".SD[#t_Index];
|
||||
|
||||
// ===========================================================================================================
|
||||
// Valor anterior del indice
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldIndex := #t_Index;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION CARGA_INICIAL
|
||||
|
||||
|
||||
REGION DATOS_LECTURA
|
||||
|
||||
// ===========================================================================================================
|
||||
// Movimiento de datos gestionados en FC
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Hmi_Estado := "DB2005_SD".SD[#t_Index].Hmi_Estado;
|
||||
IF NOT "DB2005_SD".SD[#t_Index].Estado_AutoMan THEN
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Orden_ActivarManual := "DB2005_SD".SD["DB2005_SD".Mux.Scada[#for_mux].Index].Orden_ActivarManual;
|
||||
END_IF;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Estado_Activado := "DB2005_SD".SD[#t_Index].Estado_Activado;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Estado_Enclavado := "DB2005_SD".SD[#t_Index].Estado_Enclavado;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Estado_Salida := "DB2005_SD".SD[#t_Index].Estado_Salida;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Estado_SeguridadOk := "DB2005_SD".SD[#t_Index].Estado_SeguridadOk;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Orden_ActivarAuto := "DB2005_SD".SD[#t_Index].Orden_ActivarAuto;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Tiempos_TiempoAct := "DB2005_SD".SD[#t_Index].Tiempos_TiempoAct;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Tiempos_TiempoDes := "DB2005_SD".SD[#t_Index].Tiempos_TiempoDes;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Aux_oldActivado := "DB2005_SD".SD[#t_Index].Aux_oldActivado;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Aux_oldAutoMan := "DB2005_SD".SD[#t_Index].Aux_oldAutoMan;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Config_GrupoAlarma := "DB2005_SD".SD[#t_Index].Config_GrupoAlarma;
|
||||
|
||||
END_REGION DATOS_LECTURA
|
||||
|
||||
|
||||
REGION DATOS_ESCRITURA
|
||||
|
||||
REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
// ===========================================================================================================
|
||||
// Estado Auto/Manual
|
||||
IF "DB2005_SD".SD[#t_Index].Estado_AutoMan <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Estado_AutoMan THEN
|
||||
// Cambio desde HMI
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Estado_AutoMan := "DB2005_SD".SD[#t_Index].Estado_AutoMan;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Estado_AutoMan := "DB2005_SD".SD[#t_Index].Estado_AutoMan;
|
||||
ELSIF "DB2005_SD".Mux.Scada[#for_mux].SD.Estado_AutoMan <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Estado_AutoMan THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2005_SD".SD[#t_Index].Estado_AutoMan := "DB2005_SD".Mux.Scada[#for_mux].SD.Estado_AutoMan;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Estado_AutoMan := "DB2005_SD".Mux.Scada[#for_mux].SD.Estado_AutoMan;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Activar Manual
|
||||
IF "DB2005_SD".SD[#t_Index].Orden_ActivarManual <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Orden_ActivarManual THEN
|
||||
// Cambio desde HMI
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Orden_ActivarManual := "DB2005_SD".SD[#t_Index].Orden_ActivarManual;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Orden_ActivarManual := "DB2005_SD".SD[#t_Index].Orden_ActivarManual;
|
||||
ELSIF "DB2005_SD".Mux.Scada[#for_mux].SD.Orden_ActivarManual <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Orden_ActivarManual THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2005_SD".SD[#t_Index].Orden_ActivarManual := "DB2005_SD".Mux.Scada[#for_mux].SD.Orden_ActivarManual;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Orden_ActivarManual := "DB2005_SD".Mux.Scada[#for_mux].SD.Orden_ActivarManual;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
|
||||
REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde HMI
|
||||
// Comparamos el dispositivo original con el dispositivo real, para detectar cambios desde PLC o desde HMI
|
||||
#t_CambioDesdeHMI :=
|
||||
("DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaBit <> "DB2005_SD".SD[#t_Index].Config_DireccionSalidaBit)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaByte <> "DB2005_SD".SD[#t_Index].Config_DireccionSalidaByte)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_Habilitar <> "DB2005_SD".SD[#t_Index].Config_Habilitar)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_HabilitarInvertir <> "DB2005_SD".SD[#t_Index].Config_HabilitarInvertir)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoAct <> "DB2005_SD".SD[#t_Index].Config_HabilitarRetardoAct)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoDes <> "DB2005_SD".SD[#t_Index].Config_HabilitarRetardoDes)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_TipoAcceso <> "DB2005_SD".SD[#t_Index].Config_TipoAcceso)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoAct <> "DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoAct)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoDes <> "DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoDes);
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde MUX SCADA
|
||||
// Comparamos el dispositivo original con el multiplexado, para detectar cambios desde multiplexado
|
||||
#t_CambioDesdeMux :=
|
||||
("DB2005_SD".Mux.Scada[#for_mux].SD.Config_DireccionSalidaBit <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaBit)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].SD.Config_DireccionSalidaByte <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaByte)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].SD.Config_Habilitar <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_Habilitar)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].SD.Config_HabilitarInvertir <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_HabilitarInvertir)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoAct <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoAct)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoDes <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoDes)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].SD.Config_TipoAcceso <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_TipoAcceso)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoAct <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoAct)
|
||||
OR ("DB2005_SD".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoDes <> "DB2005_SD".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoDes);
|
||||
|
||||
END_REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
|
||||
REGION TRASPASO_DATOS
|
||||
|
||||
IF #t_CambioDesdeHMI THEN
|
||||
|
||||
// Al detectar un cambio desde el HMI, cargamos sus valores de nuevo al multiplexado
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Estado_AutoMan := "DB2005_SD".SD[#t_Index].Estado_AutoMan;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Orden_ActivarManual := "DB2005_SD".SD[#t_Index].Orden_ActivarManual;
|
||||
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Config_DireccionSalidaBit := "DB2005_SD".SD[#t_Index].Config_DireccionSalidaBit;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Config_DireccionSalidaByte := "DB2005_SD".SD[#t_Index].Config_DireccionSalidaByte;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Config_Habilitar := "DB2005_SD".SD[#t_Index].Config_Habilitar;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Config_HabilitarInvertir := "DB2005_SD".SD[#t_Index].Config_HabilitarInvertir;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoAct := "DB2005_SD".SD[#t_Index].Config_HabilitarRetardoAct;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoDes := "DB2005_SD".SD[#t_Index].Config_HabilitarRetardoDes;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Config_TipoAcceso := "DB2005_SD".SD[#t_Index].Config_TipoAcceso;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoAct := "DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoAct;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoDes := "DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoDes;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaBit := "DB2005_SD".SD[#t_Index].Config_DireccionSalidaBit;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaByte := "DB2005_SD".SD[#t_Index].Config_DireccionSalidaByte;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_Habilitar := "DB2005_SD".SD[#t_Index].Config_Habilitar;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_HabilitarInvertir := "DB2005_SD".SD[#t_Index].Config_HabilitarInvertir;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoAct := "DB2005_SD".SD[#t_Index].Config_HabilitarRetardoAct;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoDes := "DB2005_SD".SD[#t_Index].Config_HabilitarRetardoDes;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_TipoAcceso := "DB2005_SD".SD[#t_Index].Config_TipoAcceso;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoAct := "DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoAct;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoDes := "DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoDes;
|
||||
|
||||
ELSIF #t_CambioDesdeMux THEN
|
||||
|
||||
// Al detectar un cambio desde el MUX, cargamos sus valores al dispositivo
|
||||
"DB2005_SD".SD[#t_Index].Estado_AutoMan := "DB2005_SD".Mux.Scada[#for_mux].SD.Estado_AutoMan;
|
||||
"DB2005_SD".SD[#t_Index].Orden_ActivarManual := "DB2005_SD".Mux.Scada[#for_mux].SD.Orden_ActivarManual;
|
||||
|
||||
"DB2005_SD".SD[#t_Index].Config_DireccionSalidaBit := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_DireccionSalidaBit;
|
||||
"DB2005_SD".SD[#t_Index].Config_DireccionSalidaByte := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_DireccionSalidaByte;
|
||||
"DB2005_SD".SD[#t_Index].Config_Habilitar := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_Habilitar;
|
||||
"DB2005_SD".SD[#t_Index].Config_HabilitarInvertir := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_HabilitarInvertir;
|
||||
"DB2005_SD".SD[#t_Index].Config_HabilitarRetardoAct := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoAct;
|
||||
"DB2005_SD".SD[#t_Index].Config_HabilitarRetardoDes := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoDes;
|
||||
"DB2005_SD".SD[#t_Index].Config_TipoAcceso := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_TipoAcceso;
|
||||
"DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoAct := "DB2005_SD".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoAct;
|
||||
"DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoDes := "DB2005_SD".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoDes;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaBit := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_DireccionSalidaBit;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaByte := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_DireccionSalidaByte;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_Habilitar := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_Habilitar;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_HabilitarInvertir := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_HabilitarInvertir;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoAct := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoAct;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoDes := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoDes;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Config_TipoAcceso := "DB2005_SD".Mux.Scada[#for_mux].SD.Config_TipoAcceso;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoAct := "DB2005_SD".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoAct;
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoDes := "DB2005_SD".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoDes;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_DATOS
|
||||
|
||||
|
||||
END_REGION DATOS_ESCRITURA
|
||||
|
||||
ELSE
|
||||
|
||||
// ===========================================================================================================
|
||||
// En caso de que el indice sea 0, movemos el valor de la SD[0] que no se usa para escribir el index.
|
||||
"DB2005_SD".Mux.Scada[#for_mux].SD := "DB2005_SD".SD[0];
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldSD := "DB2005_SD".SD[0];
|
||||
|
||||
// Actualizacion de estado anterior
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
"DB2005_SD".Mux.Scada[#for_mux].Index :=
|
||||
"DB2005_SD".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION MULTIPLEXADO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
FUNCTION "FC2806_ZC_SA_MUX" : Void
|
||||
TITLE = FC2806_ZC_SA_MUX
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion multiplexado dispositivo Salida analogica
|
||||
VAR_INPUT
|
||||
Arranque : Bool; // Primer arranque
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_mux : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2026 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- - -
|
||||
### Descripción Funcional
|
||||
El bloque implementa la gestión de multiplexado estático para el dispositivo salida analogica, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
|
||||
|
||||
Funcionalidades principales de la arquitectura:
|
||||
- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
|
||||
- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_SA`.
|
||||
- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2006_SA.SA[X]`) en la interfaz del multiplexor.
|
||||
- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
|
||||
- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
|
||||
- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
|
||||
- Caso especial de índice `0`: carga la estructura `SA[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
|
||||
|
||||
> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
|
||||
|
||||
- - -
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2006_SA` |
|
||||
| UDT | `ZC_DISP_SA`, `ZC_DISP_MUX_SA` |
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 10.07.2026 | (ABH) | Primera versión extraído a FC independiente. Refactorizacion de multiplexado para su uso solo en WinCC Professional.|
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay Scada declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_SCADA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_SCADA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
REGION MULTIPLEXADO
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
|
||||
IF #Arranque THEN
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
"DB2006_SA".Mux.Scada[#for_mux].Index :=
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestion de multiplexado
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Antes de iniciar la logica del multiplexado, revisamos los limites
|
||||
REGION LIMITES
|
||||
|
||||
// ===========================================================================================================
|
||||
// Limites
|
||||
IF "DB2006_SA".Mux.Scada[#for_mux].Index < 0 THEN
|
||||
"DB2006_SA".Mux.Scada[#for_mux].Index := 0;
|
||||
END_IF;
|
||||
IF "DB2006_SA".Mux.Scada[#for_mux].Index > "N_MAX_DISP_SA" THEN
|
||||
"DB2006_SA".Mux.Scada[#for_mux].Index := "N_MAX_DISP_SA";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
REGION INDICES
|
||||
|
||||
// Pasamos el indice a variable temporal para evisar cambios no deseados
|
||||
#t_Index := "DB2006_SA".Mux.Scada[#for_mux].Index;
|
||||
#t_oldIndex := "DB2006_SA".Mux.Scada[#for_mux].oldIndex;
|
||||
|
||||
END_REGION INDICES
|
||||
|
||||
|
||||
IF "DB2006_SA".Mux.Scada[#for_mux].Habilitar THEN
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestionamos solo los tipos
|
||||
IF #t_Index > 0 THEN
|
||||
|
||||
REGION CARGA_INICIAL
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice.
|
||||
IF #t_Index <> #t_oldIndex THEN
|
||||
|
||||
// Traspaso de dispositivos al multiplexado
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA := "DB2006_SA".SA[#t_Index];
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA := "DB2006_SA".SA[#t_Index];
|
||||
|
||||
// ===========================================================================================================
|
||||
// Valor anterior del indice
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldIndex := #t_Index;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION CARGA_INICIAL
|
||||
|
||||
|
||||
REGION DATOS_LECTURA
|
||||
|
||||
// ===========================================================================================================
|
||||
// Movimiento de datos gestionados en FC
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Hmi_Estado := "DB2006_SA".SA[#t_Index].Hmi_Estado;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Estado_SeguridadOk := "DB2006_SA".SA[#t_Index].Estado_SeguridadOk;
|
||||
IF NOT "DB2006_SA".SA[#t_Index].Estado_AutoMan THEN
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaManual := "DB2006_SA".SA[#t_Index].Orden_ConsignaManual;
|
||||
END_IF;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Estado_ValorActual := "DB2006_SA".SA[#t_Index].Estado_ValorActual;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Estado_ValorTarjeta := "DB2006_SA".SA[#t_Index].Estado_ValorTarjeta;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Estado_Enclavado := "DB2006_SA".SA[#t_Index].Estado_Enclavado;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Alarmas_Escritura := "DB2006_SA".SA[#t_Index].Alarmas_Escritura;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Alarmas_General := "DB2006_SA".SA[#t_Index].Alarmas_General;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Alarmas_Max := "DB2006_SA".SA[#t_Index].Alarmas_Max;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Alarmas_Min := "DB2006_SA".SA[#t_Index].Alarmas_Min;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Alarmas_Parametros := "DB2006_SA".SA[#t_Index].Alarmas_Parametros;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaAuto := "DB2006_SA".SA[#t_Index].Orden_ConsignaAuto;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Aux_Estado := "DB2006_SA".SA[#t_Index].Aux_Estado;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Aux_oldAlarma := "DB2006_SA".SA[#t_Index].Aux_oldAlarma;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Aux_oldAutoMan := "DB2006_SA".SA[#t_Index].Aux_oldAutoMan;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_GrupoAlarma := "DB2006_SA".SA[#t_Index].Config_GrupoAlarma;
|
||||
|
||||
END_REGION DATOS_LECTURA
|
||||
|
||||
|
||||
REGION DATOS_ESCRITURA
|
||||
|
||||
REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
// ===========================================================================================================
|
||||
// Estado Auto/Manual
|
||||
IF "DB2006_SA".SA[#t_Index].Estado_AutoMan <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Estado_AutoMan THEN
|
||||
// Cambio desde HMI
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Estado_AutoMan := "DB2006_SA".SA[#t_Index].Estado_AutoMan;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Estado_AutoMan := "DB2006_SA".SA[#t_Index].Estado_AutoMan;
|
||||
ELSIF "DB2006_SA".Mux.Scada[#for_mux].SA.Estado_AutoMan <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Estado_AutoMan THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2006_SA".SA[#t_Index].Estado_AutoMan := "DB2006_SA".Mux.Scada[#for_mux].SA.Estado_AutoMan;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Estado_AutoMan := "DB2006_SA".Mux.Scada[#for_mux].SA.Estado_AutoMan;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Consigna Manual
|
||||
IF "DB2006_SA".SA[#t_Index].Orden_ConsignaManual <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Orden_ConsignaManual THEN
|
||||
// Cambio desde HMI
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaManual := "DB2006_SA".SA[#t_Index].Orden_ConsignaManual;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Orden_ConsignaManual := "DB2006_SA".SA[#t_Index].Orden_ConsignaManual;
|
||||
ELSIF "DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaManual <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Orden_ConsignaManual THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2006_SA".SA[#t_Index].Orden_ConsignaManual := "DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaManual;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Orden_ConsignaManual := "DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaManual;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Consigna enclavado
|
||||
IF "DB2006_SA".SA[#t_Index].Orden_ConsignaEnclavado <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Orden_ConsignaEnclavado THEN
|
||||
// Cambio desde HMI
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaEnclavado := "DB2006_SA".SA[#t_Index].Orden_ConsignaEnclavado;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Orden_ConsignaEnclavado := "DB2006_SA".SA[#t_Index].Orden_ConsignaEnclavado;
|
||||
ELSIF "DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaEnclavado <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Orden_ConsignaEnclavado THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2006_SA".SA[#t_Index].Orden_ConsignaEnclavado := "DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaEnclavado;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Orden_ConsignaEnclavado := "DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaEnclavado;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
|
||||
REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde HMI
|
||||
// Comparamos el dispositivo original con el dispositivo real, para detectar cambios desde PLC o desde HMI
|
||||
#t_CambioDesdeHMI :=
|
||||
("DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_DireccionSalidaByte <> "DB2006_SA".SA[#t_Index].Config_DireccionSalidaByte)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_ErrorMaxIngenieria <> "DB2006_SA".SA[#t_Index].Config_ErrorMaxIngenieria)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_ErrorMinIngenieria <> "DB2006_SA".SA[#t_Index].Config_ErrorMinIngenieria)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxIngenieria <> "DB2006_SA".SA[#t_Index].Config_EscaladoMaxIngenieria)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxTarjeta <> "DB2006_SA".SA[#t_Index].Config_EscaladoMaxTarjeta)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinIngenieria <> "DB2006_SA".SA[#t_Index].Config_EscaladoMinIngenieria)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinTarjeta <> "DB2006_SA".SA[#t_Index].Config_EscaladoMinTarjeta)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoOffset <> "DB2006_SA".SA[#t_Index].Config_EscaladoOffset)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_Habilitar <> "DB2006_SA".SA[#t_Index].Config_Habilitar)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMax <> "DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMax)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMin <> "DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMin)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_TipoAcceso <> "DB2006_SA".SA[#t_Index].Config_TipoAcceso);
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde MUX SCADA
|
||||
// Comparamos el dispositivo original con el multiplexado, para detectar cambios desde multiplexado
|
||||
#t_CambioDesdeMux :=
|
||||
("DB2006_SA".Mux.Scada[#for_mux].SA.Config_DireccionSalidaByte <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_DireccionSalidaByte)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].SA.Config_ErrorMaxIngenieria <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_ErrorMaxIngenieria)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].SA.Config_ErrorMinIngenieria <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_ErrorMinIngenieria)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMaxIngenieria <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxIngenieria)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMaxTarjeta <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxTarjeta)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMinIngenieria <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinIngenieria)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMinTarjeta <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinTarjeta)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoOffset <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoOffset)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].SA.Config_Habilitar <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_Habilitar)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMax <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMax)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMin <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMin)
|
||||
OR ("DB2006_SA".Mux.Scada[#for_mux].SA.Config_TipoAcceso <> "DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_TipoAcceso);
|
||||
|
||||
END_REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
|
||||
REGION TRASPASO_DATOS
|
||||
|
||||
IF #t_CambioDesdeHMI THEN
|
||||
|
||||
// Al detectar un cambio desde el HMI, cargamos sus valores de nuevo al multiplexado
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Estado_AutoMan := "DB2006_SA".SA[#t_Index].Estado_AutoMan;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaManual := "DB2006_SA".SA[#t_Index].Orden_ConsignaManual;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaEnclavado := "DB2006_SA".SA[#t_Index].Orden_ConsignaEnclavado;
|
||||
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_DireccionSalidaByte := "DB2006_SA".SA[#t_Index].Config_DireccionSalidaByte;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_ErrorMaxIngenieria := "DB2006_SA".SA[#t_Index].Config_ErrorMaxIngenieria;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_ErrorMinIngenieria := "DB2006_SA".SA[#t_Index].Config_ErrorMinIngenieria;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMaxIngenieria := "DB2006_SA".SA[#t_Index].Config_EscaladoMaxIngenieria;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMaxTarjeta := "DB2006_SA".SA[#t_Index].Config_EscaladoMaxTarjeta;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMinIngenieria := "DB2006_SA".SA[#t_Index].Config_EscaladoMinIngenieria;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMinTarjeta := "DB2006_SA".SA[#t_Index].Config_EscaladoMinTarjeta;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoOffset := "DB2006_SA".SA[#t_Index].Config_EscaladoOffset;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_Habilitar := "DB2006_SA".SA[#t_Index].Config_Habilitar;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMax := "DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMax;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMin := "DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMin;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA.Config_TipoAcceso := "DB2006_SA".SA[#t_Index].Config_TipoAcceso;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_DireccionSalidaByte := "DB2006_SA".SA[#t_Index].Config_DireccionSalidaByte;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_ErrorMaxIngenieria := "DB2006_SA".SA[#t_Index].Config_ErrorMaxIngenieria;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_ErrorMinIngenieria := "DB2006_SA".SA[#t_Index].Config_ErrorMinIngenieria;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxIngenieria := "DB2006_SA".SA[#t_Index].Config_EscaladoMaxIngenieria;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxTarjeta := "DB2006_SA".SA[#t_Index].Config_EscaladoMaxTarjeta;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinIngenieria := "DB2006_SA".SA[#t_Index].Config_EscaladoMinIngenieria;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinTarjeta := "DB2006_SA".SA[#t_Index].Config_EscaladoMinTarjeta;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoOffset := "DB2006_SA".SA[#t_Index].Config_EscaladoOffset;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_Habilitar := "DB2006_SA".SA[#t_Index].Config_Habilitar;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMax := "DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMax;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMin := "DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMin;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_TipoAcceso := "DB2006_SA".SA[#t_Index].Config_TipoAcceso;
|
||||
|
||||
|
||||
ELSIF #t_CambioDesdeMux THEN
|
||||
|
||||
// Al detectar un cambio desde el MUX, cargamos sus valores al dispositivo
|
||||
"DB2006_SA".SA[#t_Index].Estado_AutoMan := "DB2006_SA".Mux.Scada[#for_mux].SA.Estado_AutoMan;
|
||||
"DB2006_SA".SA[#t_Index].Orden_ConsignaManual := "DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaManual;
|
||||
"DB2006_SA".SA[#t_Index].Orden_ConsignaEnclavado := "DB2006_SA".Mux.Scada[#for_mux].SA.Orden_ConsignaEnclavado;
|
||||
|
||||
"DB2006_SA".SA[#t_Index].Config_DireccionSalidaByte := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_DireccionSalidaByte;
|
||||
"DB2006_SA".SA[#t_Index].Config_ErrorMaxIngenieria := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_ErrorMaxIngenieria;
|
||||
"DB2006_SA".SA[#t_Index].Config_ErrorMinIngenieria := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_ErrorMinIngenieria;
|
||||
"DB2006_SA".SA[#t_Index].Config_EscaladoMaxIngenieria := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMaxIngenieria;
|
||||
"DB2006_SA".SA[#t_Index].Config_EscaladoMaxTarjeta := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMaxTarjeta;
|
||||
"DB2006_SA".SA[#t_Index].Config_EscaladoMinIngenieria := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMinIngenieria;
|
||||
"DB2006_SA".SA[#t_Index].Config_EscaladoMinTarjeta := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMinTarjeta;
|
||||
"DB2006_SA".SA[#t_Index].Config_EscaladoOffset := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoOffset;
|
||||
"DB2006_SA".SA[#t_Index].Config_Habilitar := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_Habilitar;
|
||||
"DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMax := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMax;
|
||||
"DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMin := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMin;
|
||||
"DB2006_SA".SA[#t_Index].Config_TipoAcceso := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_TipoAcceso;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_DireccionSalidaByte := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_DireccionSalidaByte;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_ErrorMaxIngenieria := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_ErrorMaxIngenieria;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_ErrorMinIngenieria := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_ErrorMinIngenieria;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxIngenieria := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMaxIngenieria;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxTarjeta := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMaxTarjeta;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinIngenieria := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMinIngenieria;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinTarjeta := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoMinTarjeta;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_EscaladoOffset := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_EscaladoOffset;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_Habilitar := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_Habilitar;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMax := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMax;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMin := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMin;
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA.Config_TipoAcceso := "DB2006_SA".Mux.Scada[#for_mux].SA.Config_TipoAcceso;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_DATOS
|
||||
|
||||
END_REGION DATOS_ESCRITURA
|
||||
|
||||
ELSE
|
||||
|
||||
// ===========================================================================================================
|
||||
// En caso de que el indice sea 0, movemos el valor de la SA[0] que no se usa para escribir el index.
|
||||
"DB2006_SA".Mux.Scada[#for_mux].SA := "DB2006_SA".SA[0];
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldSA := "DB2006_SA".SA[0];
|
||||
|
||||
// Actualizacion de estado anterior
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// Multiplexado no habilitado
|
||||
"DB2006_SA".Mux.Scada[#for_mux].Index :=
|
||||
"DB2006_SA".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION MULTIPLEXADO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,391 @@
|
||||
FUNCTION "FC2810_ZC_V_MUX" : Void
|
||||
TITLE = FC2810_ZC_V_MUX
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion multiplexado dispositivo valvula
|
||||
VAR_INPUT
|
||||
Arranque : Bool; // Primer arranque
|
||||
SeguridadesOK : Bool; // Seguridades OK
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_mux : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2026 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- - -
|
||||
### Descripción Funcional
|
||||
El bloque implementa la gestión de multiplexado estático para el dispositivo valvula, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
|
||||
|
||||
Funcionalidades principales de la arquitectura:
|
||||
- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
|
||||
- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_V`.
|
||||
- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2010_V.V[X]`) en la interfaz del multiplexor.
|
||||
- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
|
||||
- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
|
||||
- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
|
||||
- Caso especial de índice `0`: carga la estructura `V[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
|
||||
|
||||
> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
|
||||
|
||||
- - -
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2010_V` |
|
||||
| UDT | `ZC_DISP_V`, `ZC_DISP_MUX_V` |
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 10.07.2026 | (ABH) | Primera versión extraído a FC independiente. Refactorizacion de multiplexado para su uso solo en WinCC Professional.|
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay Scada declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_SCADA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_SCADA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
REGION MULTIPLEXADO
|
||||
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
|
||||
IF #Arranque THEN
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
"DB2010_V".Mux.Scada[#for_mux].Index :=
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestion de multiplexado
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Antes de iniciar la logica del multiplexado, revisamos los limites
|
||||
REGION LIMITES
|
||||
|
||||
// ===========================================================================================================
|
||||
// Limites
|
||||
IF "DB2010_V".Mux.Scada[#for_mux].Index < 0 THEN
|
||||
"DB2010_V".Mux.Scada[#for_mux].Index := 0;
|
||||
END_IF;
|
||||
IF "DB2010_V".Mux.Scada[#for_mux].Index > "N_MAX_DISP_V" THEN
|
||||
"DB2010_V".Mux.Scada[#for_mux].Index := "N_MAX_DISP_V";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
REGION INDICES
|
||||
|
||||
// Pasamos el indice a variable temporal para evisar cambios no deseados
|
||||
#t_Index := "DB2010_V".Mux.Scada[#for_mux].Index;
|
||||
#t_oldIndex := "DB2010_V".Mux.Scada[#for_mux].oldIndex;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
IF "DB2010_V".Mux.Scada[#for_mux].Habilitar THEN
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestionamos solo los tipos
|
||||
IF #t_Index > 0 THEN
|
||||
|
||||
REGION CARGA_INICIAL
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice.
|
||||
IF #t_Index <> #t_oldIndex THEN
|
||||
|
||||
// Traspaso de dispositivos al multiplexado
|
||||
"DB2010_V".Mux.Scada[#for_mux].V := "DB2010_V".V[#t_Index];
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV := "DB2010_V".V[#t_Index];
|
||||
|
||||
// ===========================================================================================================
|
||||
// Valor anterior del indice
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldIndex := #t_Index;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION CARGA_INICIAL
|
||||
|
||||
|
||||
REGION DATOS_LECTURA
|
||||
|
||||
// ===========================================================================================================
|
||||
// Movimiento de datos gestionados en FC
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Hmi_Estado := "DB2010_V".V[#t_Index].Hmi_Estado;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Estado_SeguridadOk := "DB2010_V".V[#t_Index].Estado_SeguridadOk;
|
||||
IF NOT "DB2010_V".V[#t_Index].Estado_AutoMan THEN
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Orden_ActivarManual := "DB2010_V".V[#t_Index].Orden_ActivarManual;
|
||||
ELSE
|
||||
IF NOT #SeguridadesOK OR NOT "DB2010_V".Mux.Scada[#for_mux].V.Estado_SeguridadOk THEN
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Orden_ActivarManual :=
|
||||
"DB2010_V".V[#t_Index].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
END_IF;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Estado_Activado := "DB2010_V".V[#t_Index].Estado_Activado;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Estado_Enclavado := "DB2010_V".V[#t_Index].Estado_Enclavado;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Estado_Salida := "DB2010_V".V[#t_Index].Estado_Salida;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Estado_EntradaRetornoReposo := "DB2010_V".V[#t_Index].Estado_EntradaRetornoReposo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Estado_EntradaRetornoTrabajo := "DB2010_V".V[#t_Index].Estado_EntradaRetornoTrabajo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Alarmas_Doble := "DB2010_V".V[#t_Index].Alarmas_Doble;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Alarmas_General := "DB2010_V".V[#t_Index].Alarmas_General;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Alarmas_Mantenimiento := "DB2010_V".V[#t_Index].Alarmas_Mantenimiento;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Alarmas_Reposo := "DB2010_V".V[#t_Index].Alarmas_Reposo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Alarmas_Trabajo := "DB2010_V".V[#t_Index].Alarmas_Trabajo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Orden_ActivarAuto := "DB2010_V".V[#t_Index].Orden_ActivarAuto;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Tiempos_Alarma := "DB2010_V".V[#t_Index].Tiempos_Alarma;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Tiempos_Ciclos := "DB2010_V".V[#t_Index].Tiempos_Ciclos;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Aux_oldActivado := "DB2010_V".V[#t_Index].Aux_oldActivado;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Aux_oldAlarma := "DB2010_V".V[#t_Index].Aux_oldAlarma;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Aux_oldAutoMan := "DB2010_V".V[#t_Index].Aux_oldAutoMan;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_GrupoAlarma := "DB2010_V".V[#t_Index].Config_GrupoAlarma;
|
||||
|
||||
END_REGION DATOS_LECTURA
|
||||
|
||||
|
||||
REGION DATOS_ESCRITURA
|
||||
|
||||
REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
// ===========================================================================================================
|
||||
// Estado Auto/Manual
|
||||
IF "DB2010_V".V[#t_Index].Estado_AutoMan <> "DB2010_V".Mux.Scada[#for_mux].oldV.Estado_AutoMan THEN
|
||||
// Cambio desde HMI
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Estado_AutoMan := "DB2010_V".V[#t_Index].Estado_AutoMan;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Estado_AutoMan := "DB2010_V".V[#t_Index].Estado_AutoMan;
|
||||
ELSIF "DB2010_V".Mux.Scada[#for_mux].V.Estado_AutoMan <> "DB2010_V".Mux.Scada[#for_mux].oldV.Estado_AutoMan THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2010_V".V[#t_Index].Estado_AutoMan := "DB2010_V".Mux.Scada[#for_mux].V.Estado_AutoMan;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Estado_AutoMan := "DB2010_V".Mux.Scada[#for_mux].V.Estado_AutoMan;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Activar Manual
|
||||
IF "DB2010_V".V[#t_Index].Orden_ActivarManual <> "DB2010_V".Mux.Scada[#for_mux].oldV.Orden_ActivarManual THEN
|
||||
// Cambio desde HMI
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Orden_ActivarManual := "DB2010_V".V[#t_Index].Orden_ActivarManual;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Orden_ActivarManual := "DB2010_V".V[#t_Index].Orden_ActivarManual;
|
||||
ELSIF "DB2010_V".Mux.Scada[#for_mux].V.Orden_ActivarManual <> "DB2010_V".Mux.Scada[#for_mux].oldV.Orden_ActivarManual THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2010_V".V[#t_Index].Orden_ActivarManual := "DB2010_V".Mux.Scada[#for_mux].V.Orden_ActivarManual;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Orden_ActivarManual := "DB2010_V".Mux.Scada[#for_mux].V.Orden_ActivarManual;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Reset ciclos
|
||||
IF "DB2010_V".V[#t_Index].Orden_ResetCiclos <> "DB2010_V".Mux.Scada[#for_mux].oldV.Orden_ResetCiclos THEN
|
||||
// Cambio desde HMI
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Orden_ResetCiclos := "DB2010_V".V[#t_Index].Orden_ResetCiclos;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Orden_ResetCiclos := "DB2010_V".V[#t_Index].Orden_ResetCiclos;
|
||||
ELSIF "DB2010_V".Mux.Scada[#for_mux].V.Orden_ResetCiclos <> "DB2010_V".Mux.Scada[#for_mux].oldV.Orden_ResetCiclos THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2010_V".V[#t_Index].Orden_ResetCiclos := "DB2010_V".Mux.Scada[#for_mux].V.Orden_ResetCiclos;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Orden_ResetCiclos := "DB2010_V".Mux.Scada[#for_mux].V.Orden_ResetCiclos;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Orden_ResetCiclos := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
|
||||
REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde HMI
|
||||
// Comparamos el dispositivo original con el dispositivo real, para detectar cambios desde PLC o desde HMI
|
||||
#t_CambioDesdeHMI :=
|
||||
("DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetReposoBit <> "DB2010_V".V[#t_Index].Config_DireccionRetReposoBit)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetReposoByte <> "DB2010_V".V[#t_Index].Config_DireccionRetReposoByte)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetTrabajoBit <> "DB2010_V".V[#t_Index].Config_DireccionRetTrabajoBit)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetTrabajoByte <> "DB2010_V".V[#t_Index].Config_DireccionRetTrabajoByte)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionSalidaBit <> "DB2010_V".V[#t_Index].Config_DireccionSalidaBit)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionSalidaByte <> "DB2010_V".V[#t_Index].Config_DireccionSalidaByte)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Config_Habilitar <> "DB2010_V".V[#t_Index].Config_Habilitar)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarInvertirReposo <> "DB2010_V".V[#t_Index].Config_HabilitarInvertirReposo)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarInvertirTrabajo <> "DB2010_V".V[#t_Index].Config_HabilitarInvertirTrabajo)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarMantenimiento <> "DB2010_V".V[#t_Index].Config_HabilitarMantenimiento)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarRetornoReposo <> "DB2010_V".V[#t_Index].Config_HabilitarRetornoReposo)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarRetornoTrabajo <> "DB2010_V".V[#t_Index].Config_HabilitarRetornoTrabajo)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Config_TipoAcceso <> "DB2010_V".V[#t_Index].Config_TipoAcceso)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Tiempos_SetPointTiempoAlarma <> "DB2010_V".V[#t_Index].Tiempos_SetPointTiempoAlarma)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].oldV.Tiempos_SetPointCiclos <> "DB2010_V".V[#t_Index].Tiempos_SetPointCiclos);
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde MUX SCADA
|
||||
// Comparamos el dispositivo original con el multiplexado, para detectar cambios desde multiplexado
|
||||
#t_CambioDesdeMux :=
|
||||
("DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetReposoBit <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetReposoBit)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetReposoByte <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetReposoByte)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetTrabajoBit <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetTrabajoBit)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetTrabajoByte <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetTrabajoByte)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionSalidaBit <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionSalidaBit)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionSalidaByte <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionSalidaByte)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Config_Habilitar <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_Habilitar)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarInvertirReposo <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarInvertirReposo)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarInvertirTrabajo <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarInvertirTrabajo)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarMantenimiento <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarMantenimiento)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarRetornoReposo <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarRetornoReposo)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarRetornoTrabajo <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarRetornoTrabajo)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Config_TipoAcceso <> "DB2010_V".Mux.Scada[#for_mux].oldV.Config_TipoAcceso)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Tiempos_SetPointTiempoAlarma <> "DB2010_V".Mux.Scada[#for_mux].oldV.Tiempos_SetPointTiempoAlarma)
|
||||
OR ("DB2010_V".Mux.Scada[#for_mux].V.Tiempos_SetPointCiclos <> "DB2010_V".Mux.Scada[#for_mux].oldV.Tiempos_SetPointCiclos);
|
||||
|
||||
END_REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
|
||||
REGION TRASPASO_DATOS
|
||||
|
||||
IF #t_CambioDesdeHMI THEN
|
||||
|
||||
// Al detectar un cambio desde el HMI, cargamos sus valores de nuevo al multiplexado
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Estado_AutoMan := "DB2010_V".V[#t_Index].Estado_AutoMan;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Orden_ActivarManual := "DB2010_V".V[#t_Index].Orden_ActivarManual;
|
||||
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetReposoBit := "DB2010_V".V[#t_Index].Config_DireccionRetReposoBit;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetReposoByte := "DB2010_V".V[#t_Index].Config_DireccionRetReposoByte;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetTrabajoBit := "DB2010_V".V[#t_Index].Config_DireccionRetTrabajoBit;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetTrabajoByte := "DB2010_V".V[#t_Index].Config_DireccionRetTrabajoByte;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionSalidaBit := "DB2010_V".V[#t_Index].Config_DireccionSalidaBit;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionSalidaByte := "DB2010_V".V[#t_Index].Config_DireccionSalidaByte;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_Habilitar := "DB2010_V".V[#t_Index].Config_Habilitar;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarInvertirReposo := "DB2010_V".V[#t_Index].Config_HabilitarInvertirReposo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarInvertirTrabajo := "DB2010_V".V[#t_Index].Config_HabilitarInvertirTrabajo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarMantenimiento := "DB2010_V".V[#t_Index].Config_HabilitarMantenimiento;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarRetornoReposo := "DB2010_V".V[#t_Index].Config_HabilitarRetornoReposo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarRetornoTrabajo := "DB2010_V".V[#t_Index].Config_HabilitarRetornoTrabajo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Config_TipoAcceso := "DB2010_V".V[#t_Index].Config_TipoAcceso;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Tiempos_SetPointTiempoAlarma := "DB2010_V".V[#t_Index].Tiempos_SetPointTiempoAlarma;
|
||||
"DB2010_V".Mux.Scada[#for_mux].V.Tiempos_SetPointCiclos := "DB2010_V".V[#t_Index].Tiempos_SetPointCiclos;
|
||||
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Estado_AutoMan := "DB2010_V".V[#t_Index].Estado_AutoMan;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Orden_ActivarManual := "DB2010_V".V[#t_Index].Orden_ActivarManual;
|
||||
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetReposoBit := "DB2010_V".V[#t_Index].Config_DireccionRetReposoBit;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetReposoByte := "DB2010_V".V[#t_Index].Config_DireccionRetReposoByte;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetTrabajoBit := "DB2010_V".V[#t_Index].Config_DireccionRetTrabajoBit;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetTrabajoByte := "DB2010_V".V[#t_Index].Config_DireccionRetTrabajoByte;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionSalidaBit := "DB2010_V".V[#t_Index].Config_DireccionSalidaBit;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionSalidaByte := "DB2010_V".V[#t_Index].Config_DireccionSalidaByte;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_Habilitar := "DB2010_V".V[#t_Index].Config_Habilitar;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarInvertirReposo := "DB2010_V".V[#t_Index].Config_HabilitarInvertirReposo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarInvertirTrabajo := "DB2010_V".V[#t_Index].Config_HabilitarInvertirTrabajo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarMantenimiento := "DB2010_V".V[#t_Index].Config_HabilitarMantenimiento;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarRetornoReposo := "DB2010_V".V[#t_Index].Config_HabilitarRetornoReposo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarRetornoTrabajo := "DB2010_V".V[#t_Index].Config_HabilitarRetornoTrabajo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_TipoAcceso := "DB2010_V".V[#t_Index].Config_TipoAcceso;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Tiempos_SetPointTiempoAlarma := "DB2010_V".V[#t_Index].Tiempos_SetPointTiempoAlarma;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Tiempos_SetPointCiclos := "DB2010_V".V[#t_Index].Tiempos_SetPointCiclos;
|
||||
|
||||
ELSIF #t_CambioDesdeMux THEN
|
||||
|
||||
// Al detectar un cambio desde el MUX, cargamos sus valores al dispositivo
|
||||
"DB2010_V".V[#t_Index].Estado_AutoMan := "DB2010_V".Mux.Scada[#for_mux].V.Estado_AutoMan;
|
||||
"DB2010_V".V[#t_Index].Orden_ActivarManual := "DB2010_V".Mux.Scada[#for_mux].V.Orden_ActivarManual;
|
||||
|
||||
"DB2010_V".V[#t_Index].Config_DireccionRetReposoBit := "DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetReposoBit;
|
||||
"DB2010_V".V[#t_Index].Config_DireccionRetReposoByte := "DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetReposoByte;
|
||||
"DB2010_V".V[#t_Index].Config_DireccionRetTrabajoBit := "DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetTrabajoBit;
|
||||
"DB2010_V".V[#t_Index].Config_DireccionRetTrabajoByte := "DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetTrabajoByte;
|
||||
"DB2010_V".V[#t_Index].Config_DireccionSalidaBit := "DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionSalidaBit;
|
||||
"DB2010_V".V[#t_Index].Config_DireccionSalidaByte := "DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionSalidaByte;
|
||||
"DB2010_V".V[#t_Index].Config_Habilitar := "DB2010_V".Mux.Scada[#for_mux].V.Config_Habilitar;
|
||||
"DB2010_V".V[#t_Index].Config_HabilitarInvertirReposo := "DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarInvertirReposo;
|
||||
"DB2010_V".V[#t_Index].Config_HabilitarInvertirTrabajo := "DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarInvertirTrabajo;
|
||||
"DB2010_V".V[#t_Index].Config_HabilitarMantenimiento := "DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarMantenimiento;
|
||||
"DB2010_V".V[#t_Index].Config_HabilitarRetornoReposo := "DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarRetornoReposo;
|
||||
"DB2010_V".V[#t_Index].Config_HabilitarRetornoTrabajo := "DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarRetornoTrabajo;
|
||||
"DB2010_V".V[#t_Index].Config_TipoAcceso := "DB2010_V".Mux.Scada[#for_mux].V.Config_TipoAcceso;
|
||||
"DB2010_V".V[#t_Index].Tiempos_SetPointTiempoAlarma := "DB2010_V".Mux.Scada[#for_mux].V.Tiempos_SetPointTiempoAlarma;
|
||||
"DB2010_V".V[#t_Index].Tiempos_SetPointCiclos := "DB2010_V".Mux.Scada[#for_mux].V.Tiempos_SetPointCiclos;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Estado_AutoMan := "DB2010_V".Mux.Scada[#for_mux].V.Estado_AutoMan;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Orden_ActivarManual := "DB2010_V".Mux.Scada[#for_mux].V.Orden_ActivarManual;
|
||||
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetReposoBit := "DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetReposoBit;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetReposoByte := "DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetReposoByte;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetTrabajoBit := "DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetTrabajoBit;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionRetTrabajoByte := "DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionRetTrabajoByte;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionSalidaBit := "DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionSalidaBit;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_DireccionSalidaByte := "DB2010_V".Mux.Scada[#for_mux].V.Config_DireccionSalidaByte;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_Habilitar := "DB2010_V".Mux.Scada[#for_mux].V.Config_Habilitar;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarInvertirReposo := "DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarInvertirReposo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarInvertirTrabajo := "DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarInvertirTrabajo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarMantenimiento := "DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarMantenimiento;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarRetornoReposo := "DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarRetornoReposo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_HabilitarRetornoTrabajo := "DB2010_V".Mux.Scada[#for_mux].V.Config_HabilitarRetornoTrabajo;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Config_TipoAcceso := "DB2010_V".Mux.Scada[#for_mux].V.Config_TipoAcceso;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Tiempos_SetPointTiempoAlarma := "DB2010_V".Mux.Scada[#for_mux].V.Tiempos_SetPointTiempoAlarma;
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV.Tiempos_SetPointCiclos := "DB2010_V".Mux.Scada[#for_mux].V.Tiempos_SetPointCiclos;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_DATOS
|
||||
|
||||
END_REGION DATOS_ESCRITURA
|
||||
|
||||
|
||||
ELSE
|
||||
|
||||
// ===========================================================================================================
|
||||
// En caso de que el indice sea 0, movemos el valor de la V[0] que no se usa para escribir el index.
|
||||
"DB2010_V".Mux.Scada[#for_mux].V := "DB2010_V".V[0];
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldV := "DB2010_V".V[0];
|
||||
|
||||
// Actualizacion de estado anterior
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// Multiplexado no habilitado
|
||||
"DB2010_V".Mux.Scada[#for_mux].Index :=
|
||||
"DB2010_V".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
|
||||
END_REGION MULTIPLEXADO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,385 @@
|
||||
FUNCTION "FC2815_ZC_M_MUX" : Void
|
||||
TITLE = FC2815_ZC_M_MUX
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion multiplexado dispositivo Motor
|
||||
VAR_INPUT
|
||||
Arranque : Bool; // Primer arranque
|
||||
SeguridadesOk : Bool; // Seguridades OK
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_mux : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2026 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- - -
|
||||
### Descripción Funcional
|
||||
El bloque implementa la gestión de multiplexado estático para el dispositivo motor, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
|
||||
|
||||
Funcionalidades principales de la arquitectura:
|
||||
- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
|
||||
- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_M`.
|
||||
- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2015_M.M[X]`) en la interfaz del multiplexor.
|
||||
- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
|
||||
- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
|
||||
- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
|
||||
- Caso especial de índice `0`: carga la estructura `M[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
|
||||
|
||||
> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
|
||||
|
||||
- - -
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2015_M` |
|
||||
| UDT | `ZC_DISP_M`, `ZC_DISP_MUX_M` |
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 10.07.2026 | (ABH) | Primera versión extraído a FC independiente. Refactorizacion de multiplexado para su uso solo en WinCC Professional.|
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay Scada declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_SCADA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_SCADA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
REGION MULTIPLEXADO
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
|
||||
IF #Arranque THEN
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
"DB2015_M".Mux.Scada[#for_mux].Index :=
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestion de multiplexado
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Antes de iniciar la logica del multiplexado, revisamos los limites
|
||||
REGION LIMITES
|
||||
|
||||
// ===========================================================================================================
|
||||
// Limites
|
||||
IF "DB2015_M".Mux.Scada[#for_mux].Index < 0 THEN
|
||||
"DB2015_M".Mux.Scada[#for_mux].Index := 0;
|
||||
END_IF;
|
||||
IF "DB2015_M".Mux.Scada[#for_mux].Index > "N_MAX_DISP_M" THEN
|
||||
"DB2015_M".Mux.Scada[#for_mux].Index := "N_MAX_DISP_M";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
REGION INDICES
|
||||
|
||||
// Pasamos el indice a variable temporal para evisar cambios no deseados
|
||||
#t_Index := "DB2015_M".Mux.Scada[#for_mux].Index;
|
||||
#t_oldIndex := "DB2015_M".Mux.Scada[#for_mux].oldIndex;
|
||||
|
||||
END_REGION INDICES
|
||||
|
||||
|
||||
IF "DB2015_M".Mux.Scada[#for_mux].Habilitar THEN
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestionamos solo los tipos
|
||||
IF #t_Index > 0 THEN
|
||||
|
||||
REGION CARGA_INICIAL
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice.
|
||||
IF #t_Index <> #t_oldIndex THEN
|
||||
|
||||
// Traspaso de dispositivos al multiplexado
|
||||
"DB2015_M".Mux.Scada[#for_mux].M := "DB2015_M".M[#t_Index];
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM := "DB2015_M".M[#t_Index];
|
||||
|
||||
// ===========================================================================================================
|
||||
// Valor anterior del indice
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldIndex := #t_Index;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION CARGA_INICIAL
|
||||
|
||||
|
||||
REGION DATOS_LECTURA
|
||||
|
||||
// ===========================================================================================================
|
||||
// Movimiento de datos gestionados en FC
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Hmi_Estado := "DB2015_M".M[#t_Index].Hmi_Estado;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Estado_SeguridadOk := "DB2015_M".M[#t_Index].Estado_SeguridadOk;
|
||||
IF NOT "DB2015_M".M[#t_Index].Estado_AutoMan THEN
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual := "DB2015_M".M[#t_Index].Orden_ActivarManual;
|
||||
ELSE
|
||||
IF NOT #SeguridadesOk OR NOT "DB2015_M".Mux.Scada[#for_mux].M.Estado_SeguridadOk OR "DB2015_M".M[#t_Index].Alarmas_Termico THEN
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual :=
|
||||
"DB2015_M".M[#t_Index].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
END_IF;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Estado_Activado := "DB2015_M".M[#t_Index].Estado_Activado;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Estado_Enclavado := "DB2015_M".M[#t_Index].Estado_Enclavado;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Estado_Salida := "DB2015_M".M[#t_Index].Estado_Salida;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Estado_EntradaTermico := "DB2015_M".M[#t_Index].Estado_EntradaTermico;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Estado_EntradaConfMarcha := "DB2015_M".M[#t_Index].Estado_EntradaConfMarcha;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Alarmas_ConfirmacionMarcha := "DB2015_M".M[#t_Index].Alarmas_ConfirmacionMarcha;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Alarmas_General := "DB2015_M".M[#t_Index].Alarmas_General;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Alarmas_Mantenimiento := "DB2015_M".M[#t_Index].Alarmas_Mantenimiento;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Alarmas_Termico := "DB2015_M".M[#t_Index].Alarmas_Termico;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarAuto := "DB2015_M".M[#t_Index].Orden_ActivarAuto;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Tiempos_Alarma := "DB2015_M".M[#t_Index].Tiempos_Alarma;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Tiempos_Mantenimiento := "DB2015_M".M[#t_Index].Tiempos_Mantenimiento;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Aux_oldActivado := "DB2015_M".M[#t_Index].Aux_oldActivado;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Aux_oldAlarma := "DB2015_M".M[#t_Index].Aux_oldAlarma;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Aux_oldAutoMan := "DB2015_M".M[#t_Index].Aux_oldAutoMan;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_GrupoAlarma := "DB2015_M".M[#t_Index].Config_GrupoAlarma;
|
||||
|
||||
END_REGION DATOS_LECTURA
|
||||
|
||||
|
||||
REGION DATOS_ESCRITURA
|
||||
|
||||
REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
// ===========================================================================================================
|
||||
// Estado Auto/Manual
|
||||
IF "DB2015_M".M[#t_Index].Estado_AutoMan <> "DB2015_M".Mux.Scada[#for_mux].oldM.Estado_AutoMan THEN
|
||||
// Cambio desde HMI
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan := "DB2015_M".M[#t_Index].Estado_AutoMan;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Estado_AutoMan := "DB2015_M".M[#t_Index].Estado_AutoMan;
|
||||
ELSIF "DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan <> "DB2015_M".Mux.Scada[#for_mux].oldM.Estado_AutoMan THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2015_M".M[#t_Index].Estado_AutoMan := "DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Estado_AutoMan := "DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Activar Manual
|
||||
IF "DB2015_M".M[#t_Index].Orden_ActivarManual <> "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ActivarManual THEN
|
||||
// Cambio desde HMI
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual := "DB2015_M".M[#t_Index].Orden_ActivarManual;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ActivarManual := "DB2015_M".M[#t_Index].Orden_ActivarManual;
|
||||
ELSIF "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual <> "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ActivarManual THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2015_M".M[#t_Index].Orden_ActivarManual := "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ActivarManual := "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Reset horas
|
||||
IF "DB2015_M".M[#t_Index].Orden_ResetHoras <> "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ResetHoras THEN
|
||||
// Cambio desde HMI
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Orden_ResetHoras := "DB2015_M".M[#t_Index].Orden_ResetHoras;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ResetHoras := "DB2015_M".M[#t_Index].Orden_ResetHoras;
|
||||
ELSIF "DB2015_M".Mux.Scada[#for_mux].M.Orden_ResetHoras <> "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ResetHoras THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2015_M".M[#t_Index].Orden_ResetHoras := "DB2015_M".Mux.Scada[#for_mux].M.Orden_ResetHoras;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ResetHoras := "DB2015_M".Mux.Scada[#for_mux].M.Orden_ResetHoras;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Orden_ResetHoras := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
|
||||
REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde HMI
|
||||
// Comparamos el dispositivo original con el dispositivo real, para detectar cambios desde PLC o desde HMI
|
||||
#t_CambioDesdeHMI :=
|
||||
("DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaBit <> "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaBit)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaByte <> "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaByte)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoBit <> "DB2015_M".M[#t_Index].Config_DireccionRetTermicoBit)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoByte <> "DB2015_M".M[#t_Index].Config_DireccionRetTermicoByte)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaBit <> "DB2015_M".M[#t_Index].Config_DireccionSalidaBit)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaByte <> "DB2015_M".M[#t_Index].Config_DireccionSalidaByte)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_Habilitar <> "DB2015_M".M[#t_Index].Config_Habilitar)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirConfMarcha <> "DB2015_M".M[#t_Index].Config_HabilitarInvertirConfMarcha)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirTermico <> "DB2015_M".M[#t_Index].Config_HabilitarInvertirTermico)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarMantenimiento <> "DB2015_M".M[#t_Index].Config_HabilitarMantenimiento)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoConfMarcha <> "DB2015_M".M[#t_Index].Config_HabilitarRetornoConfMarcha)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoTermico <> "DB2015_M".M[#t_Index].Config_HabilitarRetornoTermico)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_TipoAcceso <> "DB2015_M".M[#t_Index].Config_TipoAcceso)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointTiempoAlarma <> "DB2015_M".M[#t_Index].Tiempos_SetPointTiempoAlarma)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointMantenimiento <> "DB2015_M".M[#t_Index].Tiempos_SetPointMantenimiento);
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde MUX SCADA
|
||||
// Comparamos el dispositivo original con el multiplexado, para detectar cambios desde multiplexado
|
||||
#t_CambioDesdeMux :=
|
||||
("DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaBit <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaBit)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaByte <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaByte)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoBit <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoBit)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoByte <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoByte)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaBit <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaBit)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaByte <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaByte)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_Habilitar <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_Habilitar)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirConfMarcha <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirConfMarcha)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirTermico <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirTermico)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarMantenimiento <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarMantenimiento)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoConfMarcha <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoConfMarcha)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoTermico <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoTermico)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_TipoAcceso <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_TipoAcceso)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointTiempoAlarma <> "DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointTiempoAlarma)
|
||||
OR ("DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointMantenimiento <> "DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointMantenimiento);
|
||||
|
||||
END_REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
|
||||
REGION TRASPASO_DATOS
|
||||
|
||||
IF #t_CambioDesdeHMI THEN
|
||||
|
||||
// Al detectar un cambio desde el HMI, cargamos sus valores de nuevo al multiplexado
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan := "DB2015_M".M[#t_Index].Estado_AutoMan;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual := "DB2015_M".M[#t_Index].Orden_ActivarManual;
|
||||
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaBit := "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaBit;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaByte := "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaByte;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoBit := "DB2015_M".M[#t_Index].Config_DireccionRetTermicoBit;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoByte := "DB2015_M".M[#t_Index].Config_DireccionRetTermicoByte;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaBit := "DB2015_M".M[#t_Index].Config_DireccionSalidaBit;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaByte := "DB2015_M".M[#t_Index].Config_DireccionSalidaByte;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_Habilitar := "DB2015_M".M[#t_Index].Config_Habilitar;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirConfMarcha := "DB2015_M".M[#t_Index].Config_HabilitarInvertirConfMarcha;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirTermico := "DB2015_M".M[#t_Index].Config_HabilitarInvertirTermico;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarMantenimiento := "DB2015_M".M[#t_Index].Config_HabilitarMantenimiento;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoConfMarcha := "DB2015_M".M[#t_Index].Config_HabilitarRetornoConfMarcha;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoTermico := "DB2015_M".M[#t_Index].Config_HabilitarRetornoTermico;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Config_TipoAcceso := "DB2015_M".M[#t_Index].Config_TipoAcceso;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointTiempoAlarma := "DB2015_M".M[#t_Index].Tiempos_SetPointTiempoAlarma;
|
||||
"DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointMantenimiento := "DB2015_M".M[#t_Index].Tiempos_SetPointMantenimiento;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Estado_AutoMan := "DB2015_M".M[#t_Index].Estado_AutoMan;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ActivarManual := "DB2015_M".M[#t_Index].Orden_ActivarManual;
|
||||
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaBit := "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaBit;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaByte := "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaByte;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoBit := "DB2015_M".M[#t_Index].Config_DireccionRetTermicoBit;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoByte := "DB2015_M".M[#t_Index].Config_DireccionRetTermicoByte;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaBit := "DB2015_M".M[#t_Index].Config_DireccionSalidaBit;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaByte := "DB2015_M".M[#t_Index].Config_DireccionSalidaByte;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_Habilitar := "DB2015_M".M[#t_Index].Config_Habilitar;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirConfMarcha := "DB2015_M".M[#t_Index].Config_HabilitarInvertirConfMarcha;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirTermico := "DB2015_M".M[#t_Index].Config_HabilitarInvertirTermico;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarMantenimiento := "DB2015_M".M[#t_Index].Config_HabilitarMantenimiento;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoConfMarcha := "DB2015_M".M[#t_Index].Config_HabilitarRetornoConfMarcha;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoTermico := "DB2015_M".M[#t_Index].Config_HabilitarRetornoTermico;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_TipoAcceso := "DB2015_M".M[#t_Index].Config_TipoAcceso;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointTiempoAlarma := "DB2015_M".M[#t_Index].Tiempos_SetPointTiempoAlarma;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointMantenimiento := "DB2015_M".M[#t_Index].Tiempos_SetPointMantenimiento;
|
||||
|
||||
ELSIF #t_CambioDesdeMux THEN
|
||||
|
||||
// Al detectar un cambio desde el MUX, cargamos sus valores al dispositivo
|
||||
"DB2015_M".M[#t_Index].Estado_AutoMan := "DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan;
|
||||
"DB2015_M".M[#t_Index].Orden_ActivarManual := "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual;
|
||||
|
||||
"DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaBit := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaBit;
|
||||
"DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaByte := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaByte;
|
||||
"DB2015_M".M[#t_Index].Config_DireccionRetTermicoBit := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoBit;
|
||||
"DB2015_M".M[#t_Index].Config_DireccionRetTermicoByte := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoByte;
|
||||
"DB2015_M".M[#t_Index].Config_DireccionSalidaBit := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaBit;
|
||||
"DB2015_M".M[#t_Index].Config_DireccionSalidaByte := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaByte;
|
||||
"DB2015_M".M[#t_Index].Config_Habilitar := "DB2015_M".Mux.Scada[#for_mux].M.Config_Habilitar;
|
||||
"DB2015_M".M[#t_Index].Config_HabilitarInvertirConfMarcha := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirConfMarcha;
|
||||
"DB2015_M".M[#t_Index].Config_HabilitarInvertirTermico := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirTermico;
|
||||
"DB2015_M".M[#t_Index].Config_HabilitarMantenimiento := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarMantenimiento;
|
||||
"DB2015_M".M[#t_Index].Config_HabilitarRetornoConfMarcha := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoConfMarcha;
|
||||
"DB2015_M".M[#t_Index].Config_HabilitarRetornoTermico := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoTermico;
|
||||
"DB2015_M".M[#t_Index].Config_TipoAcceso := "DB2015_M".Mux.Scada[#for_mux].M.Config_TipoAcceso;
|
||||
"DB2015_M".M[#t_Index].Tiempos_SetPointTiempoAlarma := "DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointTiempoAlarma;
|
||||
"DB2015_M".M[#t_Index].Tiempos_SetPointMantenimiento := "DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointMantenimiento;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Estado_AutoMan := "DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ActivarManual := "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual;
|
||||
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaBit := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaBit;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaByte := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaByte;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoBit := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoBit;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoByte := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoByte;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaBit := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaBit;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaByte := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaByte;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_Habilitar := "DB2015_M".Mux.Scada[#for_mux].M.Config_Habilitar;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirConfMarcha := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirConfMarcha;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirTermico := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirTermico;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarMantenimiento := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarMantenimiento;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoConfMarcha := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoConfMarcha;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoTermico := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoTermico;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Config_TipoAcceso := "DB2015_M".Mux.Scada[#for_mux].M.Config_TipoAcceso;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointTiempoAlarma := "DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointTiempoAlarma;
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointMantenimiento := "DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointMantenimiento;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_DATOS
|
||||
|
||||
END_REGION DATOS_ESCRITURA
|
||||
|
||||
ELSE
|
||||
|
||||
// ===========================================================================================================
|
||||
// En caso de que el indice sea 0, movemos el valor de la M[0] que no se usa para escribir el index.
|
||||
"DB2015_M".Mux.Scada[#for_mux].M := "DB2015_M".M[0];
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldM := "DB2015_M".M[0];
|
||||
|
||||
// Actualizacion de estado anterior
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// Multiplexado no habilitado
|
||||
"DB2015_M".Mux.Scada[#for_mux].Index :=
|
||||
"DB2015_M".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION MULTIPLEXADO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,432 @@
|
||||
FUNCTION "FC2816_ZC_M_VF_MUX" : Void
|
||||
TITLE = FC2816_ZC_M_VF_MUX
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion multiplexado dispositivo Motor variador
|
||||
VAR_INPUT
|
||||
Arranque : Bool; // Primer arranque
|
||||
SeguridadesOK : Bool; // Seguridades OK
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_mux : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2026 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- - -
|
||||
### Descripción Funcional
|
||||
El bloque implementa la gestión de multiplexado estático para el dispositivo motor variador, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
|
||||
|
||||
Funcionalidades principales de la arquitectura:
|
||||
- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
|
||||
- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_M_VF`.
|
||||
- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2016_M_VF.M_VF[X]`) en la interfaz del multiplexor.
|
||||
- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
|
||||
- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
|
||||
- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
|
||||
- Caso especial de índice `0`: carga la estructura `M_VF[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
|
||||
|
||||
> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
|
||||
|
||||
- - -
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2016_M_VF` |
|
||||
| UDT | `ZC_DISP_M_VF`, `ZC_DISP_MUX_M_VF` |
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 10.07.2026 | (ABH) | Primera versión extraído a FC independiente. Refactorizacion de multiplexado para su uso solo en WinCC Professional.|
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay Scada declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_SCADA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_SCADA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
REGION MULTIPLEXADO
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
|
||||
IF #Arranque THEN
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].Index :=
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestion de multiplexado
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Antes de iniciar la logica del multiplexado, revisamos los limites
|
||||
REGION LIMITES
|
||||
|
||||
// ===========================================================================================================
|
||||
// Limites
|
||||
IF "DB2016_M_VF".Mux.Scada[#for_mux].Index < 0 THEN
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].Index := 0;
|
||||
END_IF;
|
||||
IF "DB2016_M_VF".Mux.Scada[#for_mux].Index > "N_MAX_DISP_M_VF" THEN
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].Index := "N_MAX_DISP_M_VF";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
REGION INDICES
|
||||
|
||||
// Pasamos el indice a variable temporal para evisar cambios no deseados
|
||||
#t_Index := "DB2016_M_VF".Mux.Scada[#for_mux].Index;
|
||||
#t_oldIndex := "DB2016_M_VF".Mux.Scada[#for_mux].oldIndex;
|
||||
|
||||
END_REGION INDICES
|
||||
|
||||
|
||||
IF "DB2016_M_VF".Mux.Scada[#for_mux].Habilitar THEN
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestionamos solo los tipos
|
||||
IF #t_Index > 0 THEN
|
||||
|
||||
REGION CARGA_INICIAL
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice.
|
||||
IF #t_Index <> #t_oldIndex THEN
|
||||
|
||||
// Traspaso de dispositivos al multiplexado
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF := "DB2016_M_VF".M_VF[#t_Index];
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF := "DB2016_M_VF".M_VF[#t_Index];
|
||||
|
||||
// ===========================================================================================================
|
||||
// Valor anterior del indice
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldIndex := #t_Index;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION CARGA_INICIAL
|
||||
|
||||
|
||||
REGION DATOS_LECTURA
|
||||
|
||||
// ===========================================================================================================
|
||||
// Movimiento de datos gestionados en FC
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Hmi_Estado := "DB2016_M_VF".M_VF[#t_Index].Hmi_Estado;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_SeguridadOk := "DB2016_M_VF".M_VF[#t_Index].Estado_SeguridadOk;
|
||||
IF NOT "DB2016_M_VF".M_VF[#t_Index].Estado_AutoMan AND #SeguridadesOK AND "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_SeguridadOk AND NOT "DB2016_M_VF".M_VF[#t_Index].Alarmas_Termico THEN
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ActivarManual := "DB2016_M_VF".M_VF[#t_Index].Orden_ActivarManual;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ConsignaManual := "DB2016_M_VF".M_VF[#t_Index].Orden_ConsignaManual;
|
||||
ELSE
|
||||
IF NOT #SeguridadesOK OR NOT "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_SeguridadOk OR "DB2016_M_VF".M_VF[#t_Index].Alarmas_Termico THEN
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ActivarManual :=
|
||||
"DB2016_M_VF".M_VF[#t_Index].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
END_IF;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_Activado := "DB2016_M_VF".M_VF[#t_Index].Estado_Activado;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_Enclavado := "DB2016_M_VF".M_VF[#t_Index].Estado_Enclavado;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_Salida := "DB2016_M_VF".M_VF[#t_Index].Estado_Salida;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_EntradaTermico := "DB2016_M_VF".M_VF[#t_Index].Estado_EntradaTermico;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_EntradaConfMarcha := "DB2016_M_VF".M_VF[#t_Index].Estado_EntradaConfMarcha;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_ValorActual := "DB2016_M_VF".M_VF[#t_Index].Estado_ValorActual;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_ValorTarjeta := "DB2016_M_VF".M_VF[#t_Index].Estado_ValorTarjeta;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_Escritura := "DB2016_M_VF".M_VF[#t_Index].Estado_Escritura;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Alarmas_ConfirmacionMarcha := "DB2016_M_VF".M_VF[#t_Index].Alarmas_ConfirmacionMarcha;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Alarmas_Escritura := "DB2016_M_VF".M_VF[#t_Index].Alarmas_Escritura;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Alarmas_General := "DB2016_M_VF".M_VF[#t_Index].Alarmas_General;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Alarmas_Mantenimiento := "DB2016_M_VF".M_VF[#t_Index].Alarmas_Mantenimiento;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Alarmas_Parametros := "DB2016_M_VF".M_VF[#t_Index].Alarmas_Parametros;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Alarmas_Termico := "DB2016_M_VF".M_VF[#t_Index].Alarmas_Termico;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ActivarAuto := "DB2016_M_VF".M_VF[#t_Index].Orden_ActivarAuto;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ConsignaAuto := "DB2016_M_VF".M_VF[#t_Index].Orden_ConsignaAuto;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Tiempos_Alarma := "DB2016_M_VF".M_VF[#t_Index].Tiempos_Alarma;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Tiempos_Mantenimiento := "DB2016_M_VF".M_VF[#t_Index].Tiempos_Mantenimiento;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Aux_oldActivado := "DB2016_M_VF".M_VF[#t_Index].Aux_oldActivado;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Aux_oldAlarma := "DB2016_M_VF".M_VF[#t_Index].Aux_oldAlarma;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Aux_oldAutoMan := "DB2016_M_VF".M_VF[#t_Index].Aux_oldAutoMan;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_GrupoAlarma := "DB2016_M_VF".M_VF[#t_Index].Config_GrupoAlarma;
|
||||
|
||||
END_REGION DATOS_LECTURA
|
||||
|
||||
|
||||
REGION DATOS_ESCRITURA
|
||||
|
||||
REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
// ===========================================================================================================
|
||||
// Estado Auto/Manual
|
||||
IF "DB2016_M_VF".M_VF[#t_Index].Estado_AutoMan <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Estado_AutoMan THEN
|
||||
// Cambio desde HMI
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_AutoMan := "DB2016_M_VF".M_VF[#t_Index].Estado_AutoMan;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Estado_AutoMan := "DB2016_M_VF".M_VF[#t_Index].Estado_AutoMan;
|
||||
ELSIF "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_AutoMan <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Estado_AutoMan THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2016_M_VF".M_VF[#t_Index].Estado_AutoMan := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_AutoMan;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Estado_AutoMan := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_AutoMan;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Activar Manual
|
||||
IF "DB2016_M_VF".M_VF[#t_Index].Orden_ActivarManual <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ActivarManual THEN
|
||||
// Cambio desde HMI
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ActivarManual := "DB2016_M_VF".M_VF[#t_Index].Orden_ActivarManual;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ActivarManual := "DB2016_M_VF".M_VF[#t_Index].Orden_ActivarManual;
|
||||
ELSIF "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ActivarManual <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ActivarManual THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2016_M_VF".M_VF[#t_Index].Orden_ActivarManual := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ActivarManual;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ActivarManual := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ActivarManual;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Consigna Manual
|
||||
IF "DB2016_M_VF".M_VF[#t_Index].Orden_ConsignaManual <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ConsignaManual THEN
|
||||
// Cambio desde HMI
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ConsignaManual := "DB2016_M_VF".M_VF[#t_Index].Orden_ConsignaManual;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ConsignaManual := "DB2016_M_VF".M_VF[#t_Index].Orden_ConsignaManual;
|
||||
ELSIF "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ConsignaManual <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ConsignaManual THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2016_M_VF".M_VF[#t_Index].Orden_ConsignaManual := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ConsignaManual;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ConsignaManual := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ConsignaManual;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Reset horas
|
||||
IF "DB2016_M_VF".M_VF[#t_Index].Orden_ResetHoras <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ResetHoras THEN
|
||||
// Cambio desde HMI
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ResetHoras := "DB2016_M_VF".M_VF[#t_Index].Orden_ResetHoras;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ResetHoras := "DB2016_M_VF".M_VF[#t_Index].Orden_ResetHoras;
|
||||
ELSIF "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ResetHoras <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ResetHoras THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2016_M_VF".M_VF[#t_Index].Orden_ResetHoras := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ResetHoras;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ResetHoras := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ResetHoras;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ResetHoras := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
|
||||
REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde HMI
|
||||
// Comparamos el dispositivo original con el dispositivo real, para detectar cambios desde PLC o desde HMI
|
||||
#t_CambioDesdeHMI :=
|
||||
("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetConfMarchaBit <> "DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetConfMarchaBit)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetConfMarchaByte <> "DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetConfMarchaByte)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetTermicoBit <> "DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetTermicoBit)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetTermicoByte <> "DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetTermicoByte)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionSalidaAnalogicaByte <> "DB2016_M_VF".M_VF[#t_Index].Config_DireccionSalidaAnalogicaByte)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionSalidaBit <> "DB2016_M_VF".M_VF[#t_Index].Config_DireccionSalidaBit)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionSalidaByte <> "DB2016_M_VF".M_VF[#t_Index].Config_DireccionSalidaByte)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_EscaladoMaxIngenieria <> "DB2016_M_VF".M_VF[#t_Index].Config_EscaladoMaxIngenieria)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_EscaladoMinIngenieria <> "DB2016_M_VF".M_VF[#t_Index].Config_EscaladoMinIngenieria)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_Habilitar <> "DB2016_M_VF".M_VF[#t_Index].Config_Habilitar)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarAlarmaEscrituraSalida <> "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarAlarmaEscrituraSalida)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarInvertirConfMarcha <> "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarInvertirConfMarcha)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarInvertirTermico <> "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarInvertirTermico)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarMantenimiento <> "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarMantenimiento)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarRetornoConfMarcha <> "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarRetornoConfMarcha)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarRetornoTermico <> "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarRetornoTermico)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_TipoAcceso <> "DB2016_M_VF".M_VF[#t_Index].Config_TipoAcceso)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Tiempos_SetPointAlarma <> "DB2016_M_VF".M_VF[#t_Index].Tiempos_SetPointAlarma)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Tiempos_SetPointMantenimiento <> "DB2016_M_VF".M_VF[#t_Index].Tiempos_SetPointMantenimiento);
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde MUX SCADA
|
||||
// Comparamos el dispositivo original con el multiplexado, para detectar cambios desde multiplexado
|
||||
#t_CambioDesdeMux :=
|
||||
("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetConfMarchaBit <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetConfMarchaBit)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetConfMarchaByte <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetConfMarchaByte)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetTermicoBit <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetTermicoBit)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetTermicoByte <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetTermicoByte)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionSalidaAnalogicaByte <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionSalidaAnalogicaByte)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionSalidaBit <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionSalidaBit)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionSalidaByte <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionSalidaByte)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_EscaladoMaxIngenieria <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_EscaladoMaxIngenieria)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_EscaladoMinIngenieria <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_EscaladoMinIngenieria)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_Habilitar <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_Habilitar)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarAlarmaEscrituraSalida <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarAlarmaEscrituraSalida)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarInvertirConfMarcha <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarInvertirConfMarcha)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarInvertirTermico <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarInvertirTermico)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarMantenimiento <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarMantenimiento)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarRetornoConfMarcha <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarRetornoConfMarcha)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarRetornoTermico <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarRetornoTermico)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_TipoAcceso <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_TipoAcceso)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Tiempos_SetPointAlarma <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Tiempos_SetPointAlarma)
|
||||
OR ("DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Tiempos_SetPointMantenimiento <> "DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Tiempos_SetPointMantenimiento);
|
||||
|
||||
END_REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
|
||||
REGION TRASPASO_DATOS
|
||||
|
||||
IF #t_CambioDesdeHMI THEN
|
||||
|
||||
// Al detectar un cambio desde el HMI, cargamos sus valores de nuevo al multiplexado
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_AutoMan := "DB2016_M_VF".M_VF[#t_Index].Estado_AutoMan;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ActivarManual := "DB2016_M_VF".M_VF[#t_Index].Orden_ActivarManual;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ConsignaManual := "DB2016_M_VF".M_VF[#t_Index].Orden_ConsignaManual;
|
||||
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetConfMarchaBit := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetConfMarchaBit;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetConfMarchaByte := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetConfMarchaByte;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetTermicoBit := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetTermicoBit;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetTermicoByte := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetTermicoByte;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionSalidaAnalogicaByte := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionSalidaAnalogicaByte;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionSalidaBit := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionSalidaBit;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionSalidaByte := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionSalidaByte;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_EscaladoMaxIngenieria := "DB2016_M_VF".M_VF[#t_Index].Config_EscaladoMaxIngenieria;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_EscaladoMinIngenieria := "DB2016_M_VF".M_VF[#t_Index].Config_EscaladoMinIngenieria;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_Habilitar := "DB2016_M_VF".M_VF[#t_Index].Config_Habilitar;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarAlarmaEscrituraSalida := "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarAlarmaEscrituraSalida;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarInvertirConfMarcha := "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarInvertirConfMarcha;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarInvertirTermico := "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarInvertirTermico;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarMantenimiento := "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarMantenimiento;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarRetornoConfMarcha := "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarRetornoConfMarcha;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarRetornoTermico := "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarRetornoTermico;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_TipoAcceso := "DB2016_M_VF".M_VF[#t_Index].Config_TipoAcceso;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Tiempos_SetPointAlarma := "DB2016_M_VF".M_VF[#t_Index].Tiempos_SetPointAlarma;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Tiempos_SetPointMantenimiento := "DB2016_M_VF".M_VF[#t_Index].Tiempos_SetPointMantenimiento;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Estado_AutoMan := "DB2016_M_VF".M_VF[#t_Index].Estado_AutoMan;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ActivarManual := "DB2016_M_VF".M_VF[#t_Index].Orden_ActivarManual;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ConsignaManual := "DB2016_M_VF".M_VF[#t_Index].Orden_ConsignaManual;
|
||||
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetConfMarchaBit := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetConfMarchaBit;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetConfMarchaByte := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetConfMarchaByte;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetTermicoBit := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetTermicoBit;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetTermicoByte := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetTermicoByte;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionSalidaAnalogicaByte := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionSalidaAnalogicaByte;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionSalidaBit := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionSalidaBit;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionSalidaByte := "DB2016_M_VF".M_VF[#t_Index].Config_DireccionSalidaByte;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_EscaladoMaxIngenieria := "DB2016_M_VF".M_VF[#t_Index].Config_EscaladoMaxIngenieria;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_EscaladoMinIngenieria := "DB2016_M_VF".M_VF[#t_Index].Config_EscaladoMinIngenieria;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_Habilitar := "DB2016_M_VF".M_VF[#t_Index].Config_Habilitar;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarAlarmaEscrituraSalida := "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarAlarmaEscrituraSalida;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarInvertirConfMarcha := "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarInvertirConfMarcha;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarInvertirTermico := "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarInvertirTermico;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarMantenimiento := "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarMantenimiento;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarRetornoConfMarcha := "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarRetornoConfMarcha;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarRetornoTermico := "DB2016_M_VF".M_VF[#t_Index].Config_HabilitarRetornoTermico;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_TipoAcceso := "DB2016_M_VF".M_VF[#t_Index].Config_TipoAcceso;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Tiempos_SetPointAlarma := "DB2016_M_VF".M_VF[#t_Index].Tiempos_SetPointAlarma;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Tiempos_SetPointMantenimiento := "DB2016_M_VF".M_VF[#t_Index].Tiempos_SetPointMantenimiento;
|
||||
|
||||
ELSIF #t_CambioDesdeMux THEN
|
||||
|
||||
// Al detectar un cambio desde el MUX, cargamos sus valores al dispositivo
|
||||
"DB2016_M_VF".M_VF[#t_Index].Estado_AutoMan := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_AutoMan;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Orden_ActivarManual := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ActivarManual;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Orden_ConsignaManual := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ConsignaManual;
|
||||
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetConfMarchaBit := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetConfMarchaBit;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetConfMarchaByte := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetConfMarchaByte;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetTermicoBit := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetTermicoBit;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_DireccionRetTermicoByte := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetTermicoByte;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_DireccionSalidaAnalogicaByte := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionSalidaAnalogicaByte;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_DireccionSalidaBit := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionSalidaBit;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_DireccionSalidaByte := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionSalidaByte;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_EscaladoMaxIngenieria := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_EscaladoMaxIngenieria;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_EscaladoMinIngenieria := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_EscaladoMinIngenieria;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_Habilitar := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_Habilitar;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_HabilitarAlarmaEscrituraSalida := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarAlarmaEscrituraSalida;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_HabilitarInvertirConfMarcha := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarInvertirConfMarcha;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_HabilitarInvertirTermico := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarInvertirTermico;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_HabilitarMantenimiento := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarMantenimiento;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_HabilitarRetornoConfMarcha := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarRetornoConfMarcha;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_HabilitarRetornoTermico := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarRetornoTermico;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Config_TipoAcceso := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_TipoAcceso;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Tiempos_SetPointAlarma := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Tiempos_SetPointAlarma;
|
||||
"DB2016_M_VF".M_VF[#t_Index].Tiempos_SetPointMantenimiento := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Tiempos_SetPointMantenimiento;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Estado_AutoMan := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Estado_AutoMan;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ActivarManual := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ActivarManual;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Orden_ConsignaManual := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Orden_ConsignaManual;
|
||||
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetConfMarchaBit := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetConfMarchaBit;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetConfMarchaByte := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetConfMarchaByte;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetTermicoBit := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetTermicoBit;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionRetTermicoByte := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionRetTermicoByte;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionSalidaAnalogicaByte := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionSalidaAnalogicaByte;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionSalidaBit := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionSalidaBit;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_DireccionSalidaByte := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_DireccionSalidaByte;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_EscaladoMaxIngenieria := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_EscaladoMaxIngenieria;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_EscaladoMinIngenieria := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_EscaladoMinIngenieria;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_Habilitar := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_Habilitar;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarAlarmaEscrituraSalida := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarAlarmaEscrituraSalida;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarInvertirConfMarcha := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarInvertirConfMarcha;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarInvertirTermico := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarInvertirTermico;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarMantenimiento := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarMantenimiento;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarRetornoConfMarcha := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarRetornoConfMarcha;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_HabilitarRetornoTermico := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_HabilitarRetornoTermico;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Config_TipoAcceso := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Config_TipoAcceso;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Tiempos_SetPointAlarma := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Tiempos_SetPointAlarma;
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF.Tiempos_SetPointMantenimiento := "DB2016_M_VF".Mux.Scada[#for_mux].M_VF.Tiempos_SetPointMantenimiento;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_DATOS
|
||||
|
||||
END_REGION DATOS_ESCRITURA
|
||||
|
||||
ELSE
|
||||
|
||||
// ===========================================================================================================
|
||||
// En caso de que el indice sea 0, movemos el valor de la M_VF[0] que no se usa para escribir el index.
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].M_VF := "DB2016_M_VF".M_VF[0];
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldM_VF := "DB2016_M_VF".M_VF[0];
|
||||
|
||||
// Actualizacion de estado anterior
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// Multiplexado no habilitado
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].Index :=
|
||||
"DB2016_M_VF".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION MULTIPLEXADO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,412 @@
|
||||
FUNCTION "FC2817_ZC_M_SINA_MUX" : Void
|
||||
TITLE = FC2817_ZC_M_SINA_MUX
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion multiplexado dispositivo Motor Sinamics
|
||||
VAR_INPUT
|
||||
Arranque : Bool; // Primer arranque
|
||||
SeguridadesOk : Bool; // Seguridades OK
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_mux : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2026 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- - -
|
||||
### Descripción Funcional
|
||||
El bloque implementa la gestión de multiplexado estático para el dispositivo motor sinamics, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
|
||||
|
||||
Funcionalidades principales de la arquitectura:
|
||||
- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
|
||||
- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_M_SINA`.
|
||||
- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2017_M_SINA.M_SINA[X]`) en la interfaz del multiplexor.
|
||||
- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
|
||||
- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
|
||||
- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
|
||||
- Caso especial de índice `0`: carga la estructura `M_SINA[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
|
||||
|
||||
> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
|
||||
|
||||
- - -
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2017_M_SINA` |
|
||||
| UDT | `ZC_DISP_M_SINA`, `ZC_DISP_MUX_M_SINA` |
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 10.07.2026 | (ABH) | Primera versión extraído a FC independiente. Refactorizacion de multiplexado para su uso solo en WinCC Professional.|
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay Scada declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_SCADA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_SCADA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
REGION MULTIPLEXADO
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
|
||||
IF #Arranque THEN
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].Index :=
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestion de multiplexado
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Antes de iniciar la logica del multiplexado, revisamos los limites
|
||||
REGION LIMITES
|
||||
|
||||
// ===========================================================================================================
|
||||
// Limites
|
||||
IF "DB2017_M_SINA".Mux.Scada[#for_mux].Index < 0 THEN
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].Index := 0;
|
||||
END_IF;
|
||||
IF "DB2017_M_SINA".Mux.Scada[#for_mux].Index > "N_MAX_DISP_M_SINA" THEN
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].Index := "N_MAX_DISP_M_SINA";
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION INDICES
|
||||
|
||||
// Pasamos el indice a variable temporal para evisar cambios no deseados
|
||||
#t_Index := "DB2017_M_SINA".Mux.Scada[#for_mux].Index;
|
||||
#t_oldIndex := "DB2017_M_SINA".Mux.Scada[#for_mux].oldIndex;
|
||||
|
||||
END_REGION INDICES
|
||||
|
||||
|
||||
IF "DB2017_M_SINA".Mux.Scada[#for_mux].Habilitar THEN
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestionamos solo los tipos
|
||||
IF #t_Index > 0 THEN
|
||||
|
||||
REGION CARGA_INICIAL
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice.
|
||||
IF #t_oldIndex <> #t_Index THEN
|
||||
|
||||
// Traspaso de dispositivos al multiplexado
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA := "DB2017_M_SINA".M_SINA[#t_Index];
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA := "DB2017_M_SINA".M_SINA[#t_Index];
|
||||
|
||||
// ===========================================================================================================
|
||||
// Valor anterior del indice
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldIndex := #t_Index;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION DATOS_LECTURA
|
||||
|
||||
// ===========================================================================================================
|
||||
// Movimiento de datos gestionados en FC
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Hmi_Estado := "DB2017_M_SINA".M_SINA[#t_Index].Hmi_Estado;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_SeguridadOk := "DB2017_M_SINA".M_SINA[#t_Index].Estado_SeguridadOk;
|
||||
IF NOT "DB2017_M_SINA".M_SINA[#t_Index].Estado_AutoMan AND #SeguridadesOk AND "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_SeguridadOk AND NOT "DB2017_M_SINA".M_SINA[#t_Index].Alarmas_Termico THEN
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ActivarManual := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ActivarManual;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ConsignaManual := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ConsignaManual;
|
||||
ELSE
|
||||
IF NOT #SeguridadesOk OR NOT "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_SeguridadOk OR "DB2017_M_SINA".M_SINA[#t_Index].Alarmas_Termico THEN
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ActivarManual :=
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Orden_ActivarManual := FALSE;
|
||||
END_IF;
|
||||
END_IF;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_Activado := "DB2017_M_SINA".M_SINA[#t_Index].Estado_Activado;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_Enclavado := "DB2017_M_SINA".M_SINA[#t_Index].Estado_Enclavado;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_PermisoInvertirSentido := "DB2017_M_SINA".M_SINA[#t_Index].Estado_PermisoInvertirSentido;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_RetornoTermico := "DB2017_M_SINA".M_SINA[#t_Index].Estado_RetornoTermico;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_EjeBloqueado := "DB2017_M_SINA".M_SINA[#t_Index].Estado_EjeBloqueado;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_EjeHabilitado := "DB2017_M_SINA".M_SINA[#t_Index].Estado_EjeHabilitado;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_ValorActual := "DB2017_M_SINA".M_SINA[#t_Index].Estado_ValorActual;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_VelocidadSalida := "DB2017_M_SINA".M_SINA[#t_Index].Estado_VelocidadSalida;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_Estado := "DB2017_M_SINA".M_SINA[#t_Index].Estado_Estado;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_CodigoFallo := "DB2017_M_SINA".M_SINA[#t_Index].Estado_CodigoFallo;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Alarmas_General := "DB2017_M_SINA".M_SINA[#t_Index].Alarmas_General;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Alarmas_Mantenimiento := "DB2017_M_SINA".M_SINA[#t_Index].Alarmas_Mantenimiento;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Alarmas_SinaSpeed := "DB2017_M_SINA".M_SINA[#t_Index].Alarmas_SinaSpeed;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Alarmas_Termico := "DB2017_M_SINA".M_SINA[#t_Index].Alarmas_Termico;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ActivarAuto := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ActivarAuto;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ConsignaAuto := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ConsignaAuto;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Tiempos_Alarma := "DB2017_M_SINA".M_SINA[#t_Index].Tiempos_Alarma;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Tiempos_Mantenimiento := "DB2017_M_SINA".M_SINA[#t_Index].Tiempos_Mantenimiento;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Aux_oldActivado := "DB2017_M_SINA".M_SINA[#t_Index].Aux_oldActivado;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Aux_oldAlarma := "DB2017_M_SINA".M_SINA[#t_Index].Aux_oldAlarma;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Aux_oldAutoMan := "DB2017_M_SINA".M_SINA[#t_Index].Aux_oldAutoMan;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_GrupoAlarma := "DB2017_M_SINA".M_SINA[#t_Index].Config_GrupoAlarma;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
REGION DATOS_ESCRITURA
|
||||
|
||||
REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
// ===========================================================================================================
|
||||
// Estado Auto/Manual
|
||||
IF "DB2017_M_SINA".M_SINA[#t_Index].Estado_AutoMan <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Estado_AutoMan THEN
|
||||
// Cambio desde HMI
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_AutoMan := "DB2017_M_SINA".M_SINA[#t_Index].Estado_AutoMan;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Estado_AutoMan := "DB2017_M_SINA".M_SINA[#t_Index].Estado_AutoMan;
|
||||
ELSIF "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_AutoMan <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Estado_AutoMan THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Estado_AutoMan := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_AutoMan;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Estado_AutoMan := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_AutoMan;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Activar Manual
|
||||
IF "DB2017_M_SINA".M_SINA[#t_Index].Orden_ActivarManual <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ActivarManual THEN
|
||||
// Cambio desde HMI
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ActivarManual := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ActivarManual;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ActivarManual := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ActivarManual;
|
||||
ELSIF "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ActivarManual <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ActivarManual THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Orden_ActivarManual := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ActivarManual;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ActivarManual := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ActivarManual;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Consigna Manual
|
||||
IF "DB2017_M_SINA".M_SINA[#t_Index].Orden_ConsignaManual <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ConsignaManual THEN
|
||||
// Cambio desde HMI
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ConsignaManual := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ConsignaManual;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ConsignaManual := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ConsignaManual;
|
||||
ELSIF "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ConsignaManual <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ConsignaManual THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Orden_ConsignaManual := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ConsignaManual;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ConsignaManual := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ConsignaManual;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Reset horas
|
||||
IF "DB2017_M_SINA".M_SINA[#t_Index].Orden_ResetHoras <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ResetHoras THEN
|
||||
// Cambio desde HMI
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ResetHoras := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ResetHoras;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ResetHoras := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ResetHoras;
|
||||
ELSIF "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ResetHoras <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ResetHoras THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Orden_ResetHoras := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ResetHoras;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ResetHoras := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ResetHoras;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ResetHoras := FALSE;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Reset fallos
|
||||
IF "DB2017_M_SINA".M_SINA[#t_Index].Orden_ResetFallos <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ResetFallos THEN
|
||||
// Cambio desde HMI
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ResetFallos := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ResetFallos;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ResetFallos := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ResetFallos;
|
||||
ELSIF "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ResetFallos <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ResetFallos THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Orden_ResetFallos := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ResetFallos;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ResetFallos := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ResetFallos;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Invertir
|
||||
IF "DB2017_M_SINA".M_SINA[#t_Index].Orden_SeleccionInverso <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_SeleccionInverso THEN
|
||||
// Cambio desde HMI
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_SeleccionInverso := "DB2017_M_SINA".M_SINA[#t_Index].Orden_SeleccionInverso;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_SeleccionInverso := "DB2017_M_SINA".M_SINA[#t_Index].Orden_SeleccionInverso;
|
||||
ELSIF "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_SeleccionInverso <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_SeleccionInverso THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Orden_SeleccionInverso := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_SeleccionInverso;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_SeleccionInverso := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_SeleccionInverso;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
|
||||
REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde HMI
|
||||
// Comparamos el dispositivo original con el dispositivo real, para detectar cambios desde PLC o desde HMI
|
||||
#t_CambioDesdeHMI :=
|
||||
("DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_DireccionRetTermicoBit <> "DB2017_M_SINA".M_SINA[#t_Index].Config_DireccionRetTermicoBit)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_DireccionRetTermicoByte <> "DB2017_M_SINA".M_SINA[#t_Index].Config_DireccionRetTermicoByte)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_Habilitar <> "DB2017_M_SINA".M_SINA[#t_Index].Config_Habilitar)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_HabilitarInvertirTermico <> "DB2017_M_SINA".M_SINA[#t_Index].Config_HabilitarInvertirTermico)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_HabilitarMantenimiento <> "DB2017_M_SINA".M_SINA[#t_Index].Config_HabilitarMantenimiento)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_HabilitarRetornoTermico <> "DB2017_M_SINA".M_SINA[#t_Index].Config_HabilitarRetornoTermico)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_K_Velocidad <> "DB2017_M_SINA".M_SINA[#t_Index].Config_K_Velocidad)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_VelocidadMax <> "DB2017_M_SINA".M_SINA[#t_Index].Config_VelocidadMax)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_VelocidadMin <> "DB2017_M_SINA".M_SINA[#t_Index].Config_VelocidadMin)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Tiempos_SetPointTiempoAlarma <> "DB2017_M_SINA".M_SINA[#t_Index].Tiempos_SetPointTiempoAlarma)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Tiempos_SetPointMantenimiento <> "DB2017_M_SINA".M_SINA[#t_Index].Tiempos_SetPointMantenimiento);
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde MUX SCADA
|
||||
// Comparamos el dispositivo original con el multiplexado, para detectar cambios desde multiplexado
|
||||
#t_CambioDesdeMux :=
|
||||
("DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_DireccionRetTermicoBit <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_DireccionRetTermicoBit)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_DireccionRetTermicoByte <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_DireccionRetTermicoByte)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_Habilitar <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_Habilitar)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_HabilitarInvertirTermico <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_HabilitarInvertirTermico)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_HabilitarMantenimiento <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_HabilitarMantenimiento)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_HabilitarRetornoTermico <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_HabilitarRetornoTermico)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_K_Velocidad <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_K_Velocidad)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_VelocidadMax <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_VelocidadMax)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_VelocidadMin <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_VelocidadMin)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Tiempos_SetPointTiempoAlarma <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Tiempos_SetPointTiempoAlarma)
|
||||
OR ("DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Tiempos_SetPointMantenimiento <> "DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Tiempos_SetPointMantenimiento);
|
||||
|
||||
END_REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
|
||||
REGION TRASPASO_DATOS
|
||||
|
||||
IF #t_CambioDesdeHMI THEN
|
||||
|
||||
// Al detectar un cambio desde el HMI, cargamos sus valores de nuevo al multiplexado
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_AutoMan := "DB2017_M_SINA".M_SINA[#t_Index].Estado_AutoMan;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ActivarManual := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ActivarManual;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ConsignaManual := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ConsignaManual;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_SeleccionInverso := "DB2017_M_SINA".M_SINA[#t_Index].Orden_SeleccionInverso;
|
||||
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_DireccionRetTermicoBit := "DB2017_M_SINA".M_SINA[#t_Index].Config_DireccionRetTermicoBit;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_DireccionRetTermicoByte := "DB2017_M_SINA".M_SINA[#t_Index].Config_DireccionRetTermicoByte;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_Habilitar := "DB2017_M_SINA".M_SINA[#t_Index].Config_Habilitar;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_HabilitarInvertirTermico := "DB2017_M_SINA".M_SINA[#t_Index].Config_HabilitarInvertirTermico;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_HabilitarMantenimiento := "DB2017_M_SINA".M_SINA[#t_Index].Config_HabilitarMantenimiento;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_HabilitarRetornoTermico := "DB2017_M_SINA".M_SINA[#t_Index].Config_HabilitarRetornoTermico;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_K_Velocidad := "DB2017_M_SINA".M_SINA[#t_Index].Config_K_Velocidad;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_VelocidadMax := "DB2017_M_SINA".M_SINA[#t_Index].Config_VelocidadMax;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_VelocidadMin := "DB2017_M_SINA".M_SINA[#t_Index].Config_VelocidadMin;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Tiempos_SetPointTiempoAlarma := "DB2017_M_SINA".M_SINA[#t_Index].Tiempos_SetPointTiempoAlarma;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Tiempos_SetPointMantenimiento := "DB2017_M_SINA".M_SINA[#t_Index].Tiempos_SetPointMantenimiento;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Estado_AutoMan := "DB2017_M_SINA".M_SINA[#t_Index].Estado_AutoMan;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ActivarManual := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ActivarManual;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ConsignaManual := "DB2017_M_SINA".M_SINA[#t_Index].Orden_ConsignaManual;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_SeleccionInverso := "DB2017_M_SINA".M_SINA[#t_Index].Orden_SeleccionInverso;
|
||||
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_DireccionRetTermicoBit := "DB2017_M_SINA".M_SINA[#t_Index].Config_DireccionRetTermicoBit;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_DireccionRetTermicoByte := "DB2017_M_SINA".M_SINA[#t_Index].Config_DireccionRetTermicoByte;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_Habilitar := "DB2017_M_SINA".M_SINA[#t_Index].Config_Habilitar;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_HabilitarInvertirTermico := "DB2017_M_SINA".M_SINA[#t_Index].Config_HabilitarInvertirTermico;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_HabilitarMantenimiento := "DB2017_M_SINA".M_SINA[#t_Index].Config_HabilitarMantenimiento;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_HabilitarRetornoTermico := "DB2017_M_SINA".M_SINA[#t_Index].Config_HabilitarRetornoTermico;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_K_Velocidad := "DB2017_M_SINA".M_SINA[#t_Index].Config_K_Velocidad;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_VelocidadMax := "DB2017_M_SINA".M_SINA[#t_Index].Config_VelocidadMax;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_VelocidadMin := "DB2017_M_SINA".M_SINA[#t_Index].Config_VelocidadMin;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Tiempos_SetPointTiempoAlarma := "DB2017_M_SINA".M_SINA[#t_Index].Tiempos_SetPointTiempoAlarma;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Tiempos_SetPointMantenimiento := "DB2017_M_SINA".M_SINA[#t_Index].Tiempos_SetPointMantenimiento;
|
||||
|
||||
ELSIF #t_CambioDesdeMux THEN
|
||||
|
||||
// Al detectar un cambio desde el MUX, cargamos sus valores al dispositivo
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Estado_AutoMan := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_AutoMan;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Orden_ActivarManual := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ActivarManual;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Orden_ConsignaManual := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ConsignaManual;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Orden_SeleccionInverso := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_SeleccionInverso;
|
||||
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Config_DireccionRetTermicoBit := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_DireccionRetTermicoBit;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Config_DireccionRetTermicoByte := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_DireccionRetTermicoByte;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Config_Habilitar := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_Habilitar;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Config_HabilitarInvertirTermico := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_HabilitarInvertirTermico;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Config_HabilitarMantenimiento := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_HabilitarMantenimiento;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Config_HabilitarRetornoTermico := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_HabilitarRetornoTermico;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Config_K_Velocidad := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_K_Velocidad;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Config_VelocidadMax := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_VelocidadMax;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Config_VelocidadMin := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_VelocidadMin;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Tiempos_SetPointTiempoAlarma := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Tiempos_SetPointTiempoAlarma;
|
||||
"DB2017_M_SINA".M_SINA[#t_Index].Tiempos_SetPointMantenimiento := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Tiempos_SetPointMantenimiento;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Estado_AutoMan := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Estado_AutoMan;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ActivarManual := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ActivarManual;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_ConsignaManual := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_ConsignaManual;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Orden_SeleccionInverso := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Orden_SeleccionInverso;
|
||||
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_DireccionRetTermicoBit := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_DireccionRetTermicoBit;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_DireccionRetTermicoByte := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_DireccionRetTermicoByte;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_Habilitar := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_Habilitar;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_HabilitarInvertirTermico := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_HabilitarInvertirTermico;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_HabilitarMantenimiento := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_HabilitarMantenimiento;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_HabilitarRetornoTermico := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_HabilitarRetornoTermico;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_K_Velocidad := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_K_Velocidad;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_VelocidadMax := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_VelocidadMax;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Config_VelocidadMin := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Config_VelocidadMin;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Tiempos_SetPointTiempoAlarma := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Tiempos_SetPointTiempoAlarma;
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA.Tiempos_SetPointMantenimiento := "DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA.Tiempos_SetPointMantenimiento;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_DATOS
|
||||
|
||||
END_REGION DATOS_ESCRITURA
|
||||
|
||||
ELSE
|
||||
|
||||
// ===========================================================================================================
|
||||
// En caso de que el indice sea 0, movemos el valor de la M_SINA[0] que no se usa para escribir el index.
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].M_SINA := "DB2017_M_SINA".M_SINA[0];
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldM_SINA := "DB2017_M_SINA".M_SINA[0];
|
||||
|
||||
// Actualizacion de estado anterior
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// Multiplexado no habilitado
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].Index :=
|
||||
"DB2017_M_SINA".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
FUNCTION "FC2825_ZC_TOT_MUX" : Void
|
||||
TITLE = FC2825_ZC_TOT_MUX
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion multiplexado dispositivo Totalizador
|
||||
VAR_INPUT
|
||||
Arranque : Bool; // Primer arranque
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_mux : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2026 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- - -
|
||||
### Descripción Funcional
|
||||
El bloque implementa la gestión de multiplexado estático para el dispositivo totalizador, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
|
||||
|
||||
Funcionalidades principales de la arquitectura:
|
||||
- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
|
||||
- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_TOT`.
|
||||
- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2025_TOT.TOT[X]`) en la interfaz del multiplexor.
|
||||
- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
|
||||
- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
|
||||
- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
|
||||
- Caso especial de índice `0`: carga la estructura `TOT[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
|
||||
|
||||
> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
|
||||
|
||||
- - -
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2025_TOT` |
|
||||
| UDT | `ZC_DISP_TOT`, `ZC_DISP_MUX_TOT` |
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 10.07.2026 | (ABH) | Primera versión extraído a FC independiente. Refactorizacion de multiplexado para su uso solo en WinCC Professional.|
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay Scada declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_SCADA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_SCADA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
REGION MULTIPLEXADO
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
|
||||
IF #Arranque THEN
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].Index :=
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
// Gestion de multiplexado
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
|
||||
// Antes de iniciar la logica del multiplexado, revisamos los limites
|
||||
REGION LIMITES
|
||||
|
||||
// Limites
|
||||
IF "DB2025_TOT".Mux.Scada[#for_mux].Index < 0 THEN
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].Index := 0;
|
||||
END_IF;
|
||||
IF "DB2025_TOT".Mux.Scada[#for_mux].Index > "N_MAX_DISP_TOT" THEN
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].Index := "N_MAX_DISP_TOT";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
REGION INDICES
|
||||
|
||||
// Pasamos el indice a variable temporal para evisar cambios no deseados
|
||||
#t_Index := "DB2025_TOT".Mux.Scada[#for_mux].Index;
|
||||
#t_oldIndex := "DB2025_TOT".Mux.Scada[#for_mux].oldIndex;
|
||||
|
||||
END_REGION INDICES
|
||||
|
||||
|
||||
IF "DB2025_TOT".Mux.Scada[#for_mux].Habilitar THEN
|
||||
|
||||
// Gestionamos solo los tipos
|
||||
IF #t_Index > 0 THEN
|
||||
|
||||
REGION CARGA_INICIAL
|
||||
|
||||
// Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice.
|
||||
IF #t_Index <> #t_oldIndex THEN
|
||||
|
||||
// Traspaso de dispositivos al multiplexado
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT := "DB2025_TOT".TOT[#t_Index];
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT := "DB2025_TOT".TOT[#t_Index];
|
||||
|
||||
// ===========================================================================================================
|
||||
// Valor anterior del indice
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldIndex := #t_Index;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION CARGA_INICIAL
|
||||
|
||||
|
||||
REGION DATOS_LECTURA
|
||||
|
||||
// ===========================================================================================================
|
||||
// Movimiento de datos gestionados en FC
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Hmi_Estado := "DB2025_TOT".TOT[#t_Index].Hmi_Estado;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Estado_Pulso := "DB2025_TOT".TOT[#t_Index].Estado_Pulso;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Estado_Valor := "DB2025_TOT".TOT[#t_Index].Estado_Valor;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Estado_Total := "DB2025_TOT".TOT[#t_Index].Estado_Total;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Estado_Parcial := "DB2025_TOT".TOT[#t_Index].Estado_Parcial;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Estado_Proceso := "DB2025_TOT".TOT[#t_Index].Estado_Proceso;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Estado_Usuario := "DB2025_TOT".TOT[#t_Index].Estado_Proceso;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Estado_DesbordeTotal := "DB2025_TOT".TOT[#t_Index].Estado_DesbordeTotal;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Estado_DesbordeParcial := "DB2025_TOT".TOT[#t_Index].Estado_DesbordeParcial;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Estado_DesbordeUsuario := "DB2025_TOT".TOT[#t_Index].Estado_DesbordeUsuario;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_Activar := "DB2025_TOT".TOT[#t_Index].Orden_Activar;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetProceso := "DB2025_TOT".TOT[#t_Index].Orden_ResetProceso;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Aux_oldActivado := "DB2025_TOT".TOT[#t_Index].Aux_oldActivado;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Aux_oldAlarma := "DB2025_TOT".TOT[#t_Index].Aux_oldAlarma;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Aux_AcuTiempo := "DB2025_TOT".TOT[#t_Index].Aux_AcuTiempo;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Aux_TotalizadorMem := "DB2025_TOT".TOT[#t_Index].Aux_TotalizadorMem;
|
||||
|
||||
|
||||
END_REGION DATOS_LECTURA
|
||||
|
||||
|
||||
REGION DATOS_ESCRITURA
|
||||
|
||||
REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden activar usuario
|
||||
IF "DB2025_TOT".TOT[#t_Index].Orden_Usuario <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_Usuario THEN
|
||||
// Cambio desde HMI
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_Usuario := "DB2025_TOT".TOT[#t_Index].Orden_Usuario;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_Usuario := "DB2025_TOT".TOT[#t_Index].Orden_Usuario;
|
||||
ELSIF "DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_Usuario <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_Usuario THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2025_TOT".TOT[#t_Index].Orden_Usuario := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_Usuario;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_Usuario := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_Usuario;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Reset parcial
|
||||
IF "DB2025_TOT".TOT[#t_Index].Orden_ResetParcial <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_ResetParcial THEN
|
||||
// Cambio desde HMI
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetParcial := "DB2025_TOT".TOT[#t_Index].Orden_ResetParcial;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_ResetParcial := "DB2025_TOT".TOT[#t_Index].Orden_ResetParcial;
|
||||
ELSIF "DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetParcial <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_ResetParcial THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2025_TOT".TOT[#t_Index].Orden_ResetParcial := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetParcial;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_ResetParcial := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetParcial;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetParcial := FALSE;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Reset total
|
||||
IF "DB2025_TOT".TOT[#t_Index].Orden_ResetTotal <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_ResetTotal THEN
|
||||
// Cambio desde HMI
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetTotal := "DB2025_TOT".TOT[#t_Index].Orden_ResetTotal;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_ResetTotal := "DB2025_TOT".TOT[#t_Index].Orden_ResetTotal;
|
||||
ELSIF "DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetTotal <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_ResetTotal THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2025_TOT".TOT[#t_Index].Orden_ResetTotal := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetTotal;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_ResetTotal := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetTotal;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetTotal := FALSE;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Reset usuario
|
||||
IF "DB2025_TOT".TOT[#t_Index].Orden_ResetUsuario <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_ResetUsuario THEN
|
||||
// Cambio desde HMI
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetUsuario := "DB2025_TOT".TOT[#t_Index].Orden_ResetUsuario;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_ResetUsuario := "DB2025_TOT".TOT[#t_Index].Orden_ResetUsuario;
|
||||
ELSIF "DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetUsuario <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_ResetUsuario THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2025_TOT".TOT[#t_Index].Orden_ResetUsuario := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetUsuario;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Orden_ResetUsuario := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetUsuario;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Orden_ResetUsuario := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
|
||||
REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde HMI
|
||||
// Comparamos el dispositivo original con el dispositivo real, para detectar cambios desde PLC o desde HMI
|
||||
#t_CambioDesdeHMI :=
|
||||
("DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_Habilitar <> "DB2025_TOT".TOT[#t_Index].Config_Habilitar)
|
||||
OR ("DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_Tipo <> "DB2025_TOT".TOT[#t_Index].Config_Tipo)
|
||||
OR ("DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_IncrDecr <> "DB2025_TOT".TOT[#t_Index].Config_IncrDecr)
|
||||
OR ("DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_DireccionEntradaByte <> "DB2025_TOT".TOT[#t_Index].Config_DireccionEntradaByte)
|
||||
OR ("DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_DireccionEntradaBit <> "DB2025_TOT".TOT[#t_Index].Config_DireccionEntradaBit)
|
||||
OR ("DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_LitroXPulso <> "DB2025_TOT".TOT[#t_Index].Config_LitroXPulso);
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde MUX SCADA
|
||||
// Comparamos el dispositivo original con el multiplexado, para detectar cambios desde multiplexado
|
||||
#t_CambioDesdeMux :=
|
||||
("DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_Habilitar <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_Habilitar)
|
||||
OR ("DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_Tipo <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_Tipo)
|
||||
OR ("DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_IncrDecr <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_IncrDecr)
|
||||
OR ("DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_DireccionEntradaByte <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_DireccionEntradaByte)
|
||||
OR ("DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_DireccionEntradaBit <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_DireccionEntradaBit)
|
||||
OR ("DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_LitroXPulso <> "DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_LitroXPulso);
|
||||
|
||||
END_REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
|
||||
REGION TRASPASO_DATOS
|
||||
|
||||
IF #t_CambioDesdeHMI THEN
|
||||
|
||||
// Al detectar un cambio desde el HMI, cargamos sus valores de nuevo al multiplexado
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_Habilitar := "DB2025_TOT".TOT[#t_Index].Config_Habilitar;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_Tipo := "DB2025_TOT".TOT[#t_Index].Config_Tipo;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_IncrDecr := "DB2025_TOT".TOT[#t_Index].Config_IncrDecr;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_DireccionEntradaByte := "DB2025_TOT".TOT[#t_Index].Config_DireccionEntradaByte;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_DireccionEntradaBit := "DB2025_TOT".TOT[#t_Index].Config_DireccionEntradaBit;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_LitroXPulso := "DB2025_TOT".TOT[#t_Index].Config_LitroXPulso;
|
||||
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_Habilitar := "DB2025_TOT".TOT[#t_Index].Config_Habilitar;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_Tipo := "DB2025_TOT".TOT[#t_Index].Config_Tipo;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_IncrDecr := "DB2025_TOT".TOT[#t_Index].Config_IncrDecr;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_DireccionEntradaByte := "DB2025_TOT".TOT[#t_Index].Config_DireccionEntradaByte;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_DireccionEntradaBit := "DB2025_TOT".TOT[#t_Index].Config_DireccionEntradaBit;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_LitroXPulso := "DB2025_TOT".TOT[#t_Index].Config_LitroXPulso;
|
||||
|
||||
ELSIF #t_CambioDesdeMux THEN
|
||||
|
||||
// Al detectar un cambio desde el MUX, cargamos sus valores al dispositivo
|
||||
"DB2025_TOT".TOT[#t_Index].Config_Habilitar := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_Habilitar;
|
||||
"DB2025_TOT".TOT[#t_Index].Config_Tipo := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_Tipo;
|
||||
"DB2025_TOT".TOT[#t_Index].Config_IncrDecr := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_IncrDecr;
|
||||
"DB2025_TOT".TOT[#t_Index].Config_DireccionEntradaByte := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_DireccionEntradaByte;
|
||||
"DB2025_TOT".TOT[#t_Index].Config_DireccionEntradaBit := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_DireccionEntradaBit;
|
||||
"DB2025_TOT".TOT[#t_Index].Config_LitroXPulso := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_LitroXPulso;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_Habilitar := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_Habilitar;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_Tipo := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_Tipo;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_IncrDecr := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_IncrDecr;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_DireccionEntradaByte := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_DireccionEntradaByte;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_DireccionEntradaBit := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_DireccionEntradaBit;
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT.Config_LitroXPulso := "DB2025_TOT".Mux.Scada[#for_mux].TOT.Config_LitroXPulso;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_DATOS
|
||||
|
||||
END_REGION DATOS_ESCRITURA
|
||||
|
||||
ELSE
|
||||
|
||||
// En caso de que el indice sea 0, movemos el valor de la TOT[0] que no se usa para escribir el index.
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].TOT := "DB2025_TOT".TOT[0];
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldTOT := "DB2025_TOT".TOT[0];
|
||||
|
||||
// Actualizacion de estado anterior
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// Multiplexado no habilitado
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].Index :=
|
||||
"DB2025_TOT".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION MULTIPLEXADO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
FUNCTION "FC2835_ZC_PID_MUX" : Void
|
||||
TITLE = FC2036_ZC_PID_MUX
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion multiplexado dispositivo PID
|
||||
VAR_INPUT
|
||||
Arranque : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_mux : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- - -
|
||||
### Descripción Funcional
|
||||
El bloque implementa la gestión de multiplexado estático para el dispositivo PID, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
|
||||
|
||||
Funcionalidades principales de la arquitectura:
|
||||
- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
|
||||
- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_PID`.
|
||||
- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2035_PID.PID[X]`) en la interfaz del multiplexor.
|
||||
- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
|
||||
- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
|
||||
- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
|
||||
- Caso especial de índice `0`: carga la estructura `PID[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
|
||||
|
||||
> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
|
||||
|
||||
- - -
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2035_PID` |
|
||||
| UDT | `ZC_DISP_PID`, `ZC_DISP_MUX_PID` |
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 10.07.2026 | (ABH) | Primera versión extraído a FC independiente. Refactorizacion de multiplexado para su uso solo en WinCC Professional.|
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay Scada declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_SCADA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_SCADA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
REGION MULTIPLEXADO
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
|
||||
IF #Arranque THEN
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
"DB2035_PID".Mux.Scada[#for_mux].Index :=
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestion de multiplexado
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Antes de iniciar la logica del multiplexado, revisamos los limites
|
||||
REGION LIMITES
|
||||
|
||||
// ===========================================================================================================
|
||||
// Limites
|
||||
IF "DB2035_PID".Mux.Scada[#for_mux].Index < 0 THEN
|
||||
"DB2035_PID".Mux.Scada[#for_mux].Index := 0;
|
||||
END_IF;
|
||||
IF "DB2035_PID".Mux.Scada[#for_mux].Index > "N_MAX_DISP_PID" THEN
|
||||
"DB2035_PID".Mux.Scada[#for_mux].Index := "N_MAX_DISP_PID";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
REGION INDICES
|
||||
|
||||
// Pasamos el indice a variable temporal para evisar cambios no deseados
|
||||
#t_Index := "DB2035_PID".Mux.Scada[#for_mux].Index;
|
||||
#t_oldIndex := "DB2035_PID".Mux.Scada[#for_mux].oldIndex;
|
||||
|
||||
END_REGION INDICES
|
||||
|
||||
|
||||
|
||||
|
||||
IF "DB2035_PID".Mux.Scada[#for_mux].Habilitar THEN
|
||||
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestionamos solo los tipos
|
||||
IF #t_Index > 0 THEN
|
||||
|
||||
REGION CARGA_INICIAL
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice.
|
||||
IF #t_Index <> #t_oldIndex THEN
|
||||
|
||||
// Traspaso de dispositivos al multiplexado
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID := "DB2035_PID".PID[#t_Index];
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID := "DB2035_PID".PID[#t_Index];
|
||||
|
||||
// ===========================================================================================================
|
||||
// Valor anterior del indice
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldIndex := #t_Index;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION CARGA_INICIAL
|
||||
|
||||
|
||||
REGION DATOS_LECTURA
|
||||
|
||||
// ===========================================================================================================
|
||||
// Movimiento de datos gestionados en FC
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Estado_AutoMan := "DB2035_PID".PID[#t_Index].Estado_AutoMan;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Estado_ModeActivate := "DB2035_PID".PID[#t_Index].Estado_ModeActivate;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Estado_PV := "DB2035_PID".PID[#t_Index].Estado_PV;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Estado_ValorSalida := "DB2035_PID".PID[#t_Index].Estado_ValorSalida;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Estado_PV_0_100 := "DB2035_PID".PID[#t_Index].Estado_PV_0_100;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Estado_SP_0_100 := "DB2035_PID".PID[#t_Index].Estado_SP_0_100;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Estado_Error_SP_PV_0_100 := "DB2035_PID".PID[#t_Index].Estado_Error_SP_PV_0_100;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Estado_Mode := "DB2035_PID".PID[#t_Index].Estado_Mode;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Estado_EstadoPID := "DB2035_PID".PID[#t_Index].Estado_EstadoPID;
|
||||
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_ActivarAuto := "DB2035_PID".PID[#t_Index].Orden_ActivarAuto;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_ConsignaAuto := "DB2035_PID".PID[#t_Index].Orden_ConsignaAuto;
|
||||
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Alarmas_Error := "DB2035_PID".PID[#t_Index].Alarmas_Error;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Alarmas_ErrorBits := "DB2035_PID".PID[#t_Index].Alarmas_ErrorBits;
|
||||
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Aux_oldForzar := "DB2035_PID".PID[#t_Index].Aux_oldForzar;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Aux_oldMode := "DB2035_PID".PID[#t_Index].Aux_oldMode;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Aux_SP_Manual := "DB2035_PID".PID[#t_Index].Aux_SP_Manual;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Aux_SP_Auto := "DB2035_PID".PID[#t_Index].Aux_SP_Auto;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Aux_oldGain := "DB2035_PID".PID[#t_Index].Aux_oldGain;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Aux_oldTi := "DB2035_PID".PID[#t_Index].Aux_oldTi;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Aux_oldTd := "DB2035_PID".PID[#t_Index].Aux_oldTd;
|
||||
|
||||
|
||||
IF NOT "DB2035_PID".Mux.Scada[#for_mux].PID.Estado_AutoMan THEN
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_ConsignaForzado := "DB2035_PID".PID[#t_Index].Orden_ConsignaForzado;
|
||||
END_IF;
|
||||
|
||||
IF NOT "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_ActivarAuto THEN
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Forzar := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION DATOS_LECTURA
|
||||
|
||||
|
||||
REGION DATOS_ESCRITURA
|
||||
|
||||
REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
// Estado Auto/Manual
|
||||
IF "DB2035_PID".PID[#t_Index].Estado_AutoMan <> "DB2035_PID".Mux.Scada[#for_mux].oldPID.Estado_AutoMan THEN
|
||||
|
||||
// Cambio desde HMI
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Estado_AutoMan := "DB2035_PID".PID[#t_Index].Estado_AutoMan;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Estado_AutoMan := "DB2035_PID".PID[#t_Index].Estado_AutoMan;
|
||||
|
||||
ELSIF "DB2035_PID".Mux.Scada[#for_mux].PID.Estado_AutoMan <> "DB2035_PID".Mux.Scada[#for_mux].oldPID.Estado_AutoMan THEN
|
||||
|
||||
// Cambio desde Multiplexado
|
||||
"DB2035_PID".PID[#t_Index].Estado_AutoMan := "DB2035_PID".Mux.Scada[#for_mux].PID.Estado_AutoMan;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Estado_AutoMan := "DB2035_PID".Mux.Scada[#for_mux].PID.Estado_AutoMan;
|
||||
|
||||
END_IF;
|
||||
|
||||
// Orden Activar Manual
|
||||
IF "DB2035_PID".PID[#t_Index].Orden_Forzar <> "DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Forzar THEN
|
||||
|
||||
// Cambio desde HMI
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Forzar := "DB2035_PID".PID[#t_Index].Orden_Forzar;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Forzar := "DB2035_PID".PID[#t_Index].Orden_Forzar;
|
||||
|
||||
ELSIF "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Forzar <> "DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Forzar THEN
|
||||
|
||||
// Cambio desde Multiplexado
|
||||
"DB2035_PID".PID[#t_Index].Orden_Forzar := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Forzar;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Forzar := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Forzar;
|
||||
|
||||
END_IF;
|
||||
|
||||
// Orden Consigna Manual
|
||||
IF "DB2035_PID".PID[#t_Index].Orden_ConsignaForzado <> "DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_ConsignaForzado THEN
|
||||
|
||||
// Cambio desde HMI
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_ConsignaForzado := "DB2035_PID".PID[#t_Index].Orden_ConsignaForzado;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_ConsignaForzado := "DB2035_PID".PID[#t_Index].Orden_ConsignaForzado;
|
||||
|
||||
ELSIF "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_ConsignaForzado <> "DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_ConsignaForzado THEN
|
||||
|
||||
// Cambio desde Multiplexado
|
||||
"DB2035_PID".PID[#t_Index].Orden_ConsignaForzado := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_ConsignaForzado;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_ConsignaForzado := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_ConsignaForzado;
|
||||
|
||||
END_IF;
|
||||
|
||||
// Orden Ack
|
||||
IF "DB2035_PID".PID[#t_Index].Orden_Ack <> "DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Ack THEN
|
||||
|
||||
// Cambio desde HMI
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Ack := "DB2035_PID".PID[#t_Index].Orden_Ack;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Ack := "DB2035_PID".PID[#t_Index].Orden_Ack;
|
||||
|
||||
ELSIF "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Ack <> "DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Ack THEN
|
||||
|
||||
// Cambio desde Multiplexado
|
||||
"DB2035_PID".PID[#t_Index].Orden_Ack := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Ack;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Ack := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Ack;
|
||||
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Ack := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
// Orden Reset
|
||||
IF "DB2035_PID".PID[#t_Index].Orden_Reset <> "DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Reset THEN
|
||||
|
||||
// Cambio desde HMI
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Reset := "DB2035_PID".PID[#t_Index].Orden_Reset;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Reset := "DB2035_PID".PID[#t_Index].Orden_Reset;
|
||||
|
||||
ELSIF "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Reset <> "DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Reset THEN
|
||||
|
||||
// Cambio desde Multiplexado
|
||||
"DB2035_PID".PID[#t_Index].Orden_Reset := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Reset;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Reset := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Reset;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Reset := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
|
||||
REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde HMI
|
||||
// Comparamos el dispositivo original con el dispositivo real, para detectar cambios desde PLC o desde HMI
|
||||
#t_CambioDesdeHMI :=
|
||||
("DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_Gain<>"DB2035_PID".PID[#t_Index].Config_Gain)
|
||||
OR ("DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_Ti<>"DB2035_PID".PID[#t_Index].Config_Ti)
|
||||
OR ("DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_Td<>"DB2035_PID".PID[#t_Index].Config_Td)
|
||||
OR ("DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_LimiteSuperiorSalida<>"DB2035_PID".PID[#t_Index].Config_LimiteSuperiorSalida)
|
||||
OR ("DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_LimiteInferiorSalida<>"DB2035_PID".PID[#t_Index].Config_LimiteInferiorSalida);
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde MUX SCADA
|
||||
// Comparamos el dispositivo original con el multiplexado, para detectar cambios desde multiplexado
|
||||
#t_CambioDesdeMux :=
|
||||
("DB2035_PID".Mux.Scada[#for_mux].PID.Config_Gain<>"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_Gain)
|
||||
OR ("DB2035_PID".Mux.Scada[#for_mux].PID.Config_Ti<>"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_Ti)
|
||||
OR ("DB2035_PID".Mux.Scada[#for_mux].PID.Config_Td<>"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_Td)
|
||||
OR ("DB2035_PID".Mux.Scada[#for_mux].PID.Config_LimiteSuperiorSalida<>"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_LimiteSuperiorSalida)
|
||||
OR ("DB2035_PID".Mux.Scada[#for_mux].PID.Config_LimiteInferiorSalida<>"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_LimiteInferiorSalida);
|
||||
|
||||
END_REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
|
||||
REGION TRASPASO_DATOS
|
||||
|
||||
IF #t_CambioDesdeHMI THEN
|
||||
|
||||
// Al detectar un cambio desde el HMI, cargamos sus valores de nuevo al multiplexado
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Estado_AutoMan := "DB2035_PID".PID[#t_Index].Estado_AutoMan;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Forzar := "DB2035_PID".PID[#t_Index].Orden_Forzar;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_ConsignaForzado := "DB2035_PID".PID[#t_Index].Orden_ConsignaForzado;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Ack := "DB2035_PID".PID[#t_Index].Orden_Ack;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Reset := "DB2035_PID".PID[#t_Index].Orden_Reset;
|
||||
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Config_Gain := "DB2035_PID".PID[#t_Index].Config_Gain;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Config_Ti := "DB2035_PID".PID[#t_Index].Config_Ti;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Config_Td := "DB2035_PID".PID[#t_Index].Config_Td;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Config_LimiteSuperiorSalida := "DB2035_PID".PID[#t_Index].Config_LimiteSuperiorSalida;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID.Config_LimiteInferiorSalida := "DB2035_PID".PID[#t_Index].Config_LimiteInferiorSalida;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Estado_AutoMan := "DB2035_PID".PID[#t_Index].Estado_AutoMan;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Forzar := "DB2035_PID".PID[#t_Index].Orden_Forzar;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_ConsignaForzado := "DB2035_PID".PID[#t_Index].Orden_ConsignaForzado;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Ack := "DB2035_PID".PID[#t_Index].Orden_Ack;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Reset := "DB2035_PID".PID[#t_Index].Orden_Reset;
|
||||
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_Gain := "DB2035_PID".PID[#t_Index].Config_Gain;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_Ti := "DB2035_PID".PID[#t_Index].Config_Ti;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_Td := "DB2035_PID".PID[#t_Index].Config_Td;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_LimiteSuperiorSalida := "DB2035_PID".PID[#t_Index].Config_LimiteSuperiorSalida;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_LimiteInferiorSalida := "DB2035_PID".PID[#t_Index].Config_LimiteInferiorSalida;
|
||||
|
||||
ELSIF #t_CambioDesdeMux THEN
|
||||
|
||||
// Al detectar un cambio desde el MUX, cargamos sus valores al dispositivo
|
||||
"DB2035_PID".PID[#t_Index].Estado_AutoMan := "DB2035_PID".Mux.Scada[#for_mux].PID.Estado_AutoMan;
|
||||
"DB2035_PID".PID[#t_Index].Orden_Forzar := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Forzar;
|
||||
"DB2035_PID".PID[#t_Index].Orden_ConsignaForzado := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_ConsignaForzado;
|
||||
"DB2035_PID".PID[#t_Index].Orden_Ack := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Ack;
|
||||
"DB2035_PID".PID[#t_Index].Orden_Reset := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Reset;
|
||||
|
||||
"DB2035_PID".PID[#t_Index].Config_Gain := "DB2035_PID".Mux.Scada[#for_mux].PID.Config_Gain;
|
||||
"DB2035_PID".PID[#t_Index].Config_Ti := "DB2035_PID".Mux.Scada[#for_mux].PID.Config_Ti;
|
||||
"DB2035_PID".PID[#t_Index].Config_Td := "DB2035_PID".Mux.Scada[#for_mux].PID.Config_Td;
|
||||
"DB2035_PID".PID[#t_Index].Config_LimiteSuperiorSalida := "DB2035_PID".Mux.Scada[#for_mux].PID.Config_LimiteSuperiorSalida;
|
||||
"DB2035_PID".PID[#t_Index].Config_LimiteInferiorSalida := "DB2035_PID".Mux.Scada[#for_mux].PID.Config_LimiteInferiorSalida;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Estado_AutoMan := "DB2035_PID".Mux.Scada[#for_mux].PID.Estado_AutoMan;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Forzar := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Forzar;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_ConsignaForzado := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_ConsignaForzado;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Ack := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Ack;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Orden_Reset := "DB2035_PID".Mux.Scada[#for_mux].PID.Orden_Reset;;
|
||||
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_Gain := "DB2035_PID".Mux.Scada[#for_mux].PID.Config_Gain;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_Ti := "DB2035_PID".Mux.Scada[#for_mux].PID.Config_Ti;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_Td := "DB2035_PID".Mux.Scada[#for_mux].PID.Config_Td;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_LimiteSuperiorSalida := "DB2035_PID".Mux.Scada[#for_mux].PID.Config_LimiteSuperiorSalida;
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID.Config_LimiteInferiorSalida := "DB2035_PID".Mux.Scada[#for_mux].PID.Config_LimiteInferiorSalida;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_DATOS
|
||||
|
||||
END_REGION DATOS_ESCRITURA
|
||||
|
||||
ELSE
|
||||
|
||||
// ===========================================================================================================
|
||||
// En caso de que el indice sea 0, movemos el valor de la PID[0] que no se usa para escribir el index.
|
||||
"DB2035_PID".Mux.Scada[#for_mux].PID := "DB2035_PID".PID[0];
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldPID := "DB2035_PID".PID[0];
|
||||
|
||||
// Actualizacion de estado anterior
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// Multiplexado no habilitado
|
||||
"DB2035_PID".Mux.Scada[#for_mux].Index :=
|
||||
"DB2035_PID".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION MULTIPLEXADO
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,539 @@
|
||||
FUNCTION "FC2840_ZC_TQ_MUX" : Void
|
||||
TITLE = FC2840_ZC_TQ_MUX
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : HCR
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion multiplexado dispositivo tanque.
|
||||
VAR_INPUT
|
||||
Arranque : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_mux : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- - -
|
||||
### Descripción Funcional
|
||||
El bloque implementa la gestión de multiplexado estático para el dispositivo tanque, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
|
||||
|
||||
Funcionalidades principales de la arquitectura:
|
||||
- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
|
||||
- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_TQ`.
|
||||
- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2040_TQ.TQ[X]`) en la interfaz del multiplexor.
|
||||
- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
|
||||
- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
|
||||
- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
|
||||
- Caso especial de índice `0`: carga la estructura `TQ[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
|
||||
|
||||
> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
|
||||
|
||||
- - -
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2040_TQ` |
|
||||
| UDT | `ZC_DISP_TQ`, `ZC_DISP_MUX_TQ` |
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 02.07.2026 | (HCR) | Primera versión.|
|
||||
| 01.01.00 | 08.07.2026 | (ABH) | Refactorizacion de multiplexado para su uso solo en WinCC Professional. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay Scada declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_SCADA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_SCADA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
REGION MULTIPLEXADO
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
|
||||
IF #Arranque THEN
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].Index :=
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestion de multiplexado
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Antes de iniciar la logica del multiplexado, revisamos los limites
|
||||
REGION LIMITES
|
||||
|
||||
// ===========================================================================================================
|
||||
// Limites
|
||||
IF "DB2040_TQ".Mux.Scada[#for_mux].Index < 0 THEN
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].Index := 0;
|
||||
END_IF;
|
||||
IF "DB2040_TQ".Mux.Scada[#for_mux].Index > "N_MAX_DISP_TQ" THEN
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].Index := "N_MAX_DISP_TQ";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
// Traspaso de limites a variable temporal para evitar cambios no deseados
|
||||
REGION INDICES
|
||||
|
||||
// Pasamos el indice a variable temporal para evisar cambios no deseados
|
||||
#t_Index := "DB2040_TQ".Mux.Scada[#for_mux].Index;
|
||||
#t_oldIndex := "DB2040_TQ".Mux.Scada[#for_mux].oldIndex;
|
||||
|
||||
END_REGION INDICES
|
||||
|
||||
|
||||
IF "DB2040_TQ".Mux.Scada[#for_mux].Habilitar THEN
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestionamos solo los tipos
|
||||
IF #t_Index > 0 THEN
|
||||
|
||||
REGION CARGA_INICIAL
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice.
|
||||
IF #t_Index <> #t_oldIndex THEN
|
||||
|
||||
// Traspaso de dispositivos al multiplexado
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ := "DB2040_TQ".TQ[#t_Index];
|
||||
|
||||
// ===========================================================================================================
|
||||
// Valor anterior del indice
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldIndex := #t_Index;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION CARGA_INICIAL
|
||||
|
||||
|
||||
REGION DATOS_LECTURA
|
||||
|
||||
// ===========================================================================================================
|
||||
// Movimiento de datos gestionados en FC
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Hmi_Estado := "DB2040_TQ".TQ[#t_Index].Hmi_Estado;
|
||||
IF NOT "DB2040_TQ".TQ[#t_Index].Estado_AutoMan THEN
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_ConsignaManualVolumen := "DB2040_TQ".TQ[#t_Index].Orden_ConsignaManualVolumen;
|
||||
END_IF;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_TanqueVacio := "DB2040_TQ".TQ[#t_Index].Estado_TanqueVacio;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_TanqueLleno := "DB2040_TQ".TQ[#t_Index].Estado_TanqueLleno;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_PocisionAltura := "DB2040_TQ".TQ[#t_Index].Estado_PocisionAltura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_NivelBajo := "DB2040_TQ".TQ[#t_Index].Estado_NivelBajo;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_NivelAlto := "DB2040_TQ".TQ[#t_Index].Estado_NivelAlto;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_BocaHombre := "DB2040_TQ".TQ[#t_Index].Estado_BocaHombre;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_Mezcla := "DB2040_TQ".TQ[#t_Index].Estado_Mezcla;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Alarmas_NivelBajo := "DB2040_TQ".TQ[#t_Index].Alarmas_NivelBajo;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Alarmas_NivelAlto := "DB2040_TQ".TQ[#t_Index].Alarmas_NivelAlto;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Alarmas_BocaHombre := "DB2040_TQ".TQ[#t_Index].Alarmas_BocaHombre;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Alarmas_General := "DB2040_TQ".TQ[#t_Index].Alarmas_General;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Alarmas_Capacidad := "DB2040_TQ".TQ[#t_Index].Alarmas_Capacidad;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Vis_ConsignaTemperatura := "DB2040_TQ".TQ[#t_Index].Vis_ConsignaTemperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Aux_MemOrdenAgitador := "DB2040_TQ".TQ[#t_Index].Aux_MemOrdenAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Aux_MemOrdenTemperatura := "DB2040_TQ".TQ[#t_Index].Aux_MemOrdenTemperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Aux_MemOrdenProducto := "DB2040_TQ".TQ[#t_Index].Aux_MemOrdenProducto;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Aux_MemEstadoCIP := "DB2040_TQ".TQ[#t_Index].Aux_MemEstadoCIP;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Aux_CipOK := "DB2040_TQ".TQ[#t_Index].Aux_CipOK;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_ParoControlAgitador := "DB2040_TQ".TQ[#t_Index].Orden_ParoControlAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_ParoControlTemp := "DB2040_TQ".TQ[#t_Index].Orden_ParoControlTemp;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_Temperatura := "DB2040_TQ".TQ[#t_Index].Orden_Temperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_Agitacion := "DB2040_TQ".TQ[#t_Index].Orden_Agitacion;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CIP := "DB2040_TQ".TQ[#t_Index].Orden_CIP;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_Producto := "DB2040_TQ".TQ[#t_Index].Orden_Producto;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_TipoProducto := "DB2040_TQ".TQ[#t_Index].Orden_TipoProducto;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_ConsignaAgitador := "DB2040_TQ".TQ[#t_Index].Orden_ConsignaAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_Tanque := "DB2040_TQ".TQ[#t_Index].Estado_Tanque;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_Producto1 := "DB2040_TQ".TQ[#t_Index].Estado_Producto1;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_Producto2 := "DB2040_TQ".TQ[#t_Index].Estado_Producto2;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_Volumen := "DB2040_TQ".TQ[#t_Index].Estado_Volumen;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_Presion := "DB2040_TQ".TQ[#t_Index].Estado_Presion;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_Altura := "DB2040_TQ".TQ[#t_Index].Estado_Altura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_ValorNivelPresion := "DB2040_TQ".TQ[#t_Index].Estado_ValorNivelPresion;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_ValorTemperatura := "DB2040_TQ".TQ[#t_Index].Estado_ValorTemperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_TiempoProducto := "DB2040_TQ".TQ[#t_Index].Tiempo_TiempoProducto;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_TiempoLimpio := "DB2040_TQ".TQ[#t_Index].Tiempo_TiempoLimpio;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_RetTanqueVacio := "DB2040_TQ".TQ[#t_Index].Tiempo_RetTanqueVacio;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_RetTanqueLleno := "DB2040_TQ".TQ[#t_Index].Tiempo_RetTanqueLleno;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_AgitadorONActual := "DB2040_TQ".TQ[#t_Index].Tiempo_AgitadorONActual;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_AgitadorOFFActual := "DB2040_TQ".TQ[#t_Index].Tiempo_AgitadorOFFActual;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarCalculoVol := "DB2040_TQ".TQ[#t_Index].Config_HabilitarCalculoVol;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarAlarmas := "DB2040_TQ".TQ[#t_Index].Config_HabilitarAlarmas;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarAgitador := "DB2040_TQ".TQ[#t_Index].Config_HabilitarAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_GrupoAlarma := "DB2040_TQ".TQ[#t_Index].Config_GrupoAlarma;
|
||||
|
||||
|
||||
|
||||
END_REGION DATOS_LECTURA
|
||||
|
||||
|
||||
REGION DATOS_ESCRITURA
|
||||
|
||||
REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
// ===========================================================================================================
|
||||
// Estado Auto/Manual
|
||||
IF "DB2040_TQ".TQ[#t_Index].Estado_AutoMan <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_AutoMan THEN
|
||||
// Cambio desde HMI
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_AutoMan := "DB2040_TQ".TQ[#t_Index].Estado_AutoMan;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_AutoMan := "DB2040_TQ".TQ[#t_Index].Estado_AutoMan;
|
||||
ELSIF "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_AutoMan <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_AutoMan THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2040_TQ".TQ[#t_Index].Estado_AutoMan := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_AutoMan;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_AutoMan := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_AutoMan;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Volumen Manual
|
||||
IF "DB2040_TQ".TQ[#t_Index].Orden_ConsignaManualVolumen <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_ConsignaManualVolumen THEN
|
||||
// Cambio desde HMI
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_ConsignaManualVolumen := "DB2040_TQ".TQ[#t_Index].Orden_ConsignaManualVolumen;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_ConsignaManualVolumen := "DB2040_TQ".TQ[#t_Index].Orden_ConsignaManualVolumen;
|
||||
ELSIF "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_ConsignaManualVolumen <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_ConsignaManualVolumen THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2040_TQ".TQ[#t_Index].Orden_ConsignaManualVolumen := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_ConsignaManualVolumen;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_ConsignaManualVolumen := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_ConsignaManualVolumen;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Estado Tanque Nuevo
|
||||
IF "DB2040_TQ".TQ[#t_Index].Estado_TanqueNuevo <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_TanqueNuevo THEN
|
||||
// Cambio desde HMI
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_TanqueNuevo := "DB2040_TQ".TQ[#t_Index].Estado_TanqueNuevo;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_TanqueNuevo := "DB2040_TQ".TQ[#t_Index].Estado_TanqueNuevo;
|
||||
ELSIF "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_TanqueNuevo <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_TanqueNuevo THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2040_TQ".TQ[#t_Index].Estado_TanqueNuevo := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_TanqueNuevo;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_TanqueNuevo := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_TanqueNuevo;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Estado Producto Nuevo
|
||||
IF "DB2040_TQ".TQ[#t_Index].Estado_ProductoNuevo <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_ProductoNuevo THEN
|
||||
// Cambio desde HMI
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_ProductoNuevo := "DB2040_TQ".TQ[#t_Index].Estado_ProductoNuevo;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_ProductoNuevo := "DB2040_TQ".TQ[#t_Index].Estado_ProductoNuevo;
|
||||
ELSIF "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_ProductoNuevo <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_ProductoNuevo THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2040_TQ".TQ[#t_Index].Estado_ProductoNuevo := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_ProductoNuevo;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_ProductoNuevo := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_ProductoNuevo;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Cambio Estado
|
||||
IF "DB2040_TQ".TQ[#t_Index].Orden_CambioEstado <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_CambioEstado THEN
|
||||
// Cambio desde HMI
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioEstado := "DB2040_TQ".TQ[#t_Index].Orden_CambioEstado;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_CambioEstado := "DB2040_TQ".TQ[#t_Index].Orden_CambioEstado;
|
||||
ELSIF "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioEstado <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_CambioEstado THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2040_TQ".TQ[#t_Index].Orden_CambioEstado := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioEstado;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_CambioEstado := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioEstado;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioEstado := FALSE;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Cambio Producto 1
|
||||
IF "DB2040_TQ".TQ[#t_Index].Orden_CambioProd1 <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_CambioProd1 THEN
|
||||
// Cambio desde HMI
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioProd1 := "DB2040_TQ".TQ[#t_Index].Orden_CambioProd1;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_CambioProd1 := "DB2040_TQ".TQ[#t_Index].Orden_CambioProd1;
|
||||
ELSIF "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioProd1 <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_CambioProd1 THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2040_TQ".TQ[#t_Index].Orden_CambioProd1 := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioProd1;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_CambioProd1 := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioProd1;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioProd1 := FALSE;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Orden Cambio Producto 2
|
||||
IF "DB2040_TQ".TQ[#t_Index].Orden_CambioProd2 <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_CambioProd2 THEN
|
||||
// Cambio desde HMI
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioProd2 := "DB2040_TQ".TQ[#t_Index].Orden_CambioProd2;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_CambioProd2 := "DB2040_TQ".TQ[#t_Index].Orden_CambioProd2;
|
||||
ELSIF "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioProd2 <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_CambioProd2 THEN
|
||||
// Cambio desde Multiplexado
|
||||
"DB2040_TQ".TQ[#t_Index].Orden_CambioProd2 := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioProd2;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_CambioProd2 := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioProd2;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_CambioProd2 := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
|
||||
REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde HMI
|
||||
// Comparamos el dispositivo original con el dispositivo real, para detectar cambios desde PLC o desde HMI
|
||||
#t_CambioDesdeHMI :=
|
||||
("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarControlTemp <> "DB2040_TQ".TQ[#t_Index].Config_HabilitarControlTemp)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_TipoControlTemperatura <> "DB2040_TQ".TQ[#t_Index].Config_TipoControlTemperatura)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_TipoAgitacionTiempo <> "DB2040_TQ".TQ[#t_Index].Config_TipoAgitacionTiempo)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_TipoAgitacionVelocidad <> "DB2040_TQ".TQ[#t_Index].Config_TipoAgitacionVelocidad)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_ConsignaTemperatura <> "DB2040_TQ".TQ[#t_Index].Config_ConsignaTemperatura)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HisteresisTemperatura <> "DB2040_TQ".TQ[#t_Index].Config_HisteresisTemperatura)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMinControlTemp <> "DB2040_TQ".TQ[#t_Index].Config_VolumenMinControlTemp)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMaxControlTemp <> "DB2040_TQ".TQ[#t_Index].Config_VolumenMaxControlTemp)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMinControlAgitador <> "DB2040_TQ".TQ[#t_Index].Config_VolumenMinControlAgitador)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMaxControlAgitador <> "DB2040_TQ".TQ[#t_Index].Config_VolumenMaxControlAgitador)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenTanqueVacio <> "DB2040_TQ".TQ[#t_Index].Config_VolumenTanqueVacio)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenTanqueLleno <> "DB2040_TQ".TQ[#t_Index].Config_VolumenTanqueLleno)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VelocidadMinAgitador <> "DB2040_TQ".TQ[#t_Index].Config_VelocidadMinAgitador)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VelocidadMaxAgitador <> "DB2040_TQ".TQ[#t_Index].Config_VelocidadMaxAgitador)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VelocidadFijaAgitador <> "DB2040_TQ".TQ[#t_Index].Config_VelocidadFijaAgitador)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_CapacidadTanque <> "DB2040_TQ".TQ[#t_Index].Config_CapacidadTanque)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_DiametroCilindro <> "DB2040_TQ".TQ[#t_Index].Config_DiametroCilindro)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_AlturaCilindro <> "DB2040_TQ".TQ[#t_Index].Config_AlturaCilindro)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_DiametroConoInferior <> "DB2040_TQ".TQ[#t_Index].Config_DiametroConoInferior)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_AnguloCono <> "DB2040_TQ".TQ[#t_Index].Config_AnguloCono)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_AlturaCono <> "DB2040_TQ".TQ[#t_Index].Config_AlturaCono)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarCalculoVol <> "DB2040_TQ".TQ[#t_Index].Config_HabilitarCalculoVol)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarAlarmas <> "DB2040_TQ".TQ[#t_Index].Config_HabilitarAlarmas)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarAgitador <> "DB2040_TQ".TQ[#t_Index].Config_HabilitarAgitador)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_GrupoAlarma <> "DB2040_TQ".TQ[#t_Index].Config_GrupoAlarma)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Tiempo_AgitadorONConsigna <> "DB2040_TQ".TQ[#t_Index].Tiempo_AgitadorONConsigna)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Tiempo_AgitadorOFFConsigna <> "DB2040_TQ".TQ[#t_Index].Tiempo_AgitadorOFFConsigna);
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde MUX SCADA
|
||||
// Comparamos el dispositivo original con el multiplexado, para detectar cambios desde multiplexado
|
||||
#t_CambioDesdeMux :=
|
||||
("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarControlTemp <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarControlTemp)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_TipoControlTemperatura <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_TipoControlTemperatura)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_TipoAgitacionTiempo <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_TipoAgitacionTiempo)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_TipoAgitacionVelocidad <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_TipoAgitacionVelocidad)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_ConsignaTemperatura <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_ConsignaTemperatura)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HisteresisTemperatura <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HisteresisTemperatura)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMinControlTemp <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMinControlTemp)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMaxControlTemp <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMaxControlTemp)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMinControlAgitador <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMinControlAgitador)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMaxControlAgitador <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMaxControlAgitador)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenTanqueVacio <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenTanqueVacio)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenTanqueLleno <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenTanqueLleno)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VelocidadMinAgitador <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VelocidadMinAgitador)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VelocidadMaxAgitador <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VelocidadMaxAgitador)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VelocidadFijaAgitador <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VelocidadFijaAgitador)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_CapacidadTanque <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_CapacidadTanque)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_DiametroCilindro <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_DiametroCilindro)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_AlturaCilindro <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_AlturaCilindro)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_DiametroConoInferior <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_DiametroConoInferior)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_AnguloCono <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_AnguloCono)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_AlturaCono <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_AlturaCono)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarCalculoVol <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarCalculoVol)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarAlarmas <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarAlarmas)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarAgitador <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarAgitador)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_GrupoAlarma <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_GrupoAlarma)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_AgitadorONConsigna <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Tiempo_AgitadorONConsigna)
|
||||
OR ("DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_AgitadorOFFConsigna <> "DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Tiempo_AgitadorOFFConsigna);
|
||||
|
||||
END_REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
|
||||
REGION TRASPASO_DATOS
|
||||
|
||||
IF #t_CambioDesdeHMI THEN
|
||||
|
||||
// Al detectar un cambio desde el HMI, cargamos sus valores de nuevo al multiplexado
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_AutoMan := "DB2040_TQ".TQ[#t_Index].Estado_AutoMan;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_ConsignaManualVolumen := "DB2040_TQ".TQ[#t_Index].Orden_ConsignaManualVolumen;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_TanqueNuevo := "DB2040_TQ".TQ[#t_Index].Estado_TanqueNuevo;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_ProductoNuevo := "DB2040_TQ".TQ[#t_Index].Estado_ProductoNuevo;
|
||||
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarControlTemp := "DB2040_TQ".TQ[#t_Index].Config_HabilitarControlTemp;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_TipoControlTemperatura := "DB2040_TQ".TQ[#t_Index].Config_TipoControlTemperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_TipoAgitacionTiempo := "DB2040_TQ".TQ[#t_Index].Config_TipoAgitacionTiempo;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_TipoAgitacionVelocidad := "DB2040_TQ".TQ[#t_Index].Config_TipoAgitacionVelocidad;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_ConsignaTemperatura := "DB2040_TQ".TQ[#t_Index].Config_ConsignaTemperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HisteresisTemperatura := "DB2040_TQ".TQ[#t_Index].Config_HisteresisTemperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMinControlTemp := "DB2040_TQ".TQ[#t_Index].Config_VolumenMinControlTemp;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMaxControlTemp := "DB2040_TQ".TQ[#t_Index].Config_VolumenMaxControlTemp;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMinControlAgitador := "DB2040_TQ".TQ[#t_Index].Config_VolumenMinControlAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMaxControlAgitador := "DB2040_TQ".TQ[#t_Index].Config_VolumenMaxControlAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenTanqueVacio := "DB2040_TQ".TQ[#t_Index].Config_VolumenTanqueVacio;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenTanqueLleno := "DB2040_TQ".TQ[#t_Index].Config_VolumenTanqueLleno;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VelocidadMinAgitador := "DB2040_TQ".TQ[#t_Index].Config_VelocidadMinAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VelocidadMaxAgitador := "DB2040_TQ".TQ[#t_Index].Config_VelocidadMaxAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VelocidadFijaAgitador := "DB2040_TQ".TQ[#t_Index].Config_VelocidadFijaAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_CapacidadTanque := "DB2040_TQ".TQ[#t_Index].Config_CapacidadTanque;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_DiametroCilindro := "DB2040_TQ".TQ[#t_Index].Config_DiametroCilindro;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_AlturaCilindro := "DB2040_TQ".TQ[#t_Index].Config_AlturaCilindro;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_DiametroConoInferior := "DB2040_TQ".TQ[#t_Index].Config_DiametroConoInferior;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_AnguloCono := "DB2040_TQ".TQ[#t_Index].Config_AnguloCono;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_AlturaCono := "DB2040_TQ".TQ[#t_Index].Config_AlturaCono;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarCalculoVol := "DB2040_TQ".TQ[#t_Index].Config_HabilitarCalculoVol;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarAlarmas := "DB2040_TQ".TQ[#t_Index].Config_HabilitarAlarmas;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarAgitador := "DB2040_TQ".TQ[#t_Index].Config_HabilitarAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_GrupoAlarma := "DB2040_TQ".TQ[#t_Index].Config_GrupoAlarma;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_AgitadorONConsigna := "DB2040_TQ".TQ[#t_Index].Tiempo_AgitadorONConsigna;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_AgitadorOFFConsigna := "DB2040_TQ".TQ[#t_Index].Tiempo_AgitadorOFFConsigna;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_AutoMan := "DB2040_TQ".TQ[#t_Index].Estado_AutoMan;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_ConsignaManualVolumen := "DB2040_TQ".TQ[#t_Index].Orden_ConsignaManualVolumen;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_TanqueNuevo := "DB2040_TQ".TQ[#t_Index].Estado_TanqueNuevo;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_ProductoNuevo := "DB2040_TQ".TQ[#t_Index].Estado_ProductoNuevo;
|
||||
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarControlTemp := "DB2040_TQ".TQ[#t_Index].Config_HabilitarControlTemp;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_TipoControlTemperatura := "DB2040_TQ".TQ[#t_Index].Config_TipoControlTemperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_TipoAgitacionTiempo := "DB2040_TQ".TQ[#t_Index].Config_TipoAgitacionTiempo;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_TipoAgitacionVelocidad := "DB2040_TQ".TQ[#t_Index].Config_TipoAgitacionVelocidad;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_ConsignaTemperatura := "DB2040_TQ".TQ[#t_Index].Config_ConsignaTemperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HisteresisTemperatura := "DB2040_TQ".TQ[#t_Index].Config_HisteresisTemperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMinControlTemp := "DB2040_TQ".TQ[#t_Index].Config_VolumenMinControlTemp;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMaxControlTemp := "DB2040_TQ".TQ[#t_Index].Config_VolumenMaxControlTemp;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMinControlAgitador := "DB2040_TQ".TQ[#t_Index].Config_VolumenMinControlAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMaxControlAgitador := "DB2040_TQ".TQ[#t_Index].Config_VolumenMaxControlAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenTanqueVacio := "DB2040_TQ".TQ[#t_Index].Config_VolumenTanqueVacio;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenTanqueLleno := "DB2040_TQ".TQ[#t_Index].Config_VolumenTanqueLleno;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VelocidadMinAgitador := "DB2040_TQ".TQ[#t_Index].Config_VelocidadMinAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VelocidadMaxAgitador := "DB2040_TQ".TQ[#t_Index].Config_VelocidadMaxAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VelocidadFijaAgitador := "DB2040_TQ".TQ[#t_Index].Config_VelocidadFijaAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_CapacidadTanque := "DB2040_TQ".TQ[#t_Index].Config_CapacidadTanque;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_DiametroCilindro := "DB2040_TQ".TQ[#t_Index].Config_DiametroCilindro;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_AlturaCilindro := "DB2040_TQ".TQ[#t_Index].Config_AlturaCilindro;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_DiametroConoInferior := "DB2040_TQ".TQ[#t_Index].Config_DiametroConoInferior;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_AnguloCono := "DB2040_TQ".TQ[#t_Index].Config_AnguloCono;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_AlturaCono := "DB2040_TQ".TQ[#t_Index].Config_AlturaCono;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarCalculoVol := "DB2040_TQ".TQ[#t_Index].Config_HabilitarCalculoVol;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarAlarmas := "DB2040_TQ".TQ[#t_Index].Config_HabilitarAlarmas;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarAgitador := "DB2040_TQ".TQ[#t_Index].Config_HabilitarAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_GrupoAlarma := "DB2040_TQ".TQ[#t_Index].Config_GrupoAlarma;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Tiempo_AgitadorONConsigna := "DB2040_TQ".TQ[#t_Index].Tiempo_AgitadorONConsigna;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Tiempo_AgitadorOFFConsigna := "DB2040_TQ".TQ[#t_Index].Tiempo_AgitadorOFFConsigna;
|
||||
|
||||
ELSIF #t_CambioDesdeMux THEN
|
||||
|
||||
// Al detectar un cambio desde el MUX, cargamos sus valores al dispositivo
|
||||
"DB2040_TQ".TQ[#t_Index].Estado_AutoMan := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_AutoMan;
|
||||
"DB2040_TQ".TQ[#t_Index].Orden_ConsignaManualVolumen := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_ConsignaManualVolumen;
|
||||
"DB2040_TQ".TQ[#t_Index].Estado_TanqueNuevo := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_TanqueNuevo;
|
||||
"DB2040_TQ".TQ[#t_Index].Estado_ProductoNuevo := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_ProductoNuevo;
|
||||
|
||||
"DB2040_TQ".TQ[#t_Index].Config_HabilitarControlTemp := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarControlTemp;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_TipoControlTemperatura := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_TipoControlTemperatura;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_TipoAgitacionTiempo := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_TipoAgitacionTiempo;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_TipoAgitacionVelocidad := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_TipoAgitacionVelocidad;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_ConsignaTemperatura := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_ConsignaTemperatura;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_HisteresisTemperatura := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HisteresisTemperatura;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_VolumenMinControlTemp := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMinControlTemp;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_VolumenMaxControlTemp := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMaxControlTemp;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_VolumenMinControlAgitador := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMinControlAgitador;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_VolumenMaxControlAgitador := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMaxControlAgitador;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_VolumenTanqueVacio := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenTanqueVacio;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_VolumenTanqueLleno := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenTanqueLleno;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_VelocidadMinAgitador := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VelocidadMinAgitador;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_VelocidadMaxAgitador := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VelocidadMaxAgitador;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_VelocidadFijaAgitador := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VelocidadFijaAgitador;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_CapacidadTanque := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_CapacidadTanque;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_DiametroCilindro := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_DiametroCilindro;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_AlturaCilindro := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_AlturaCilindro;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_DiametroConoInferior := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_DiametroConoInferior;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_AnguloCono := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_AnguloCono;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_AlturaCono := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_AlturaCono;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_HabilitarCalculoVol := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarCalculoVol;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_HabilitarAlarmas := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarAlarmas;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_HabilitarAgitador := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarAgitador;
|
||||
"DB2040_TQ".TQ[#t_Index].Config_GrupoAlarma := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_GrupoAlarma;
|
||||
"DB2040_TQ".TQ[#t_Index].Tiempo_AgitadorONConsigna := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_AgitadorONConsigna;
|
||||
"DB2040_TQ".TQ[#t_Index].Tiempo_AgitadorOFFConsigna := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_AgitadorOFFConsigna;
|
||||
|
||||
// Actualizamos el estado original para configuraciones
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_AutoMan := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_AutoMan;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Orden_ConsignaManualVolumen := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Orden_ConsignaManualVolumen;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_TanqueNuevo := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_TanqueNuevo;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Estado_ProductoNuevo := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Estado_ProductoNuevo;
|
||||
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarControlTemp := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarControlTemp;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_TipoControlTemperatura := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_TipoControlTemperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_TipoAgitacionTiempo := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_TipoAgitacionTiempo;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_TipoAgitacionVelocidad := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_TipoAgitacionVelocidad;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_ConsignaTemperatura := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_ConsignaTemperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HisteresisTemperatura := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HisteresisTemperatura;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMinControlTemp := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMinControlTemp;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMaxControlTemp := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMaxControlTemp;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMinControlAgitador := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMinControlAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenMaxControlAgitador := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenMaxControlAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenTanqueVacio := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenTanqueVacio;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VolumenTanqueLleno := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VolumenTanqueLleno;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VelocidadMinAgitador := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VelocidadMinAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VelocidadMaxAgitador := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VelocidadMaxAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_VelocidadFijaAgitador := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_VelocidadFijaAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_CapacidadTanque := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_CapacidadTanque;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_DiametroCilindro := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_DiametroCilindro;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_AlturaCilindro := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_AlturaCilindro;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_DiametroConoInferior := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_DiametroConoInferior;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_AnguloCono := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_AnguloCono;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_AlturaCono := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_AlturaCono;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarCalculoVol := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarCalculoVol;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarAlarmas := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarAlarmas;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_HabilitarAgitador := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_HabilitarAgitador;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Config_GrupoAlarma := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Config_GrupoAlarma;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Tiempo_AgitadorONConsigna := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_AgitadorONConsigna;
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ.Tiempo_AgitadorOFFConsigna := "DB2040_TQ".Mux.Scada[#for_mux].TQ.Tiempo_AgitadorOFFConsigna;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_DATOS
|
||||
|
||||
END_REGION DATOS_ESCRITURA
|
||||
|
||||
ELSE
|
||||
|
||||
// ===========================================================================================================
|
||||
// En caso de que el indice sea 0, movemos el valor de la EA[0] que no se usa para escribir el index.
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].TQ := "DB2040_TQ".TQ[0];
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldTQ := "DB2040_TQ".TQ[0];
|
||||
|
||||
// Actualizacion de estado anterior
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// Multiplexado no habilitado
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].Index :=
|
||||
"DB2040_TQ".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION MULTIPLEXADO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
FUNCTION "FC2841_ZC_TQ_AE_MUX" : Void
|
||||
TITLE = FC2841_ZC_TQ_AE_MUX
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : HCR
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion de gestion multiplexado dispositivo Tanque aire esteril.
|
||||
VAR_INPUT
|
||||
Arranque : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_mux : Int;
|
||||
t_Index : Int;
|
||||
t_oldIndex : Int;
|
||||
t_N_MAX : Int;
|
||||
t_CambioDesdeHMI : Bool;
|
||||
t_CambioDesdeMux : Bool;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
- - -
|
||||
### Descripción Funcional
|
||||
El bloque implementa la gestión de multiplexado estático para el dispositivo tanque aire esteril, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
|
||||
|
||||
Funcionalidades principales de la arquitectura:
|
||||
- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
|
||||
- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_TQ_AE`.
|
||||
- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2041_TQ_AE.TQ_AE[X]`) en la interfaz del multiplexor.
|
||||
- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
|
||||
- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
|
||||
- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
|
||||
- Caso especial de índice `0`: carga la estructura `TQ_AE[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
|
||||
|
||||
> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
|
||||
|
||||
- - -
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2041_TQ_AE` |
|
||||
| UDT | `ZC_DISP_TQ_AE`, `ZC_DISP_MUX_TQ_AE` |
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 10.07.2026 | (ABH) | Primera versión extraído a FC independiente. Refactorizacion de multiplexado para su uso solo en WinCC Professional.|
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
REGION COMPROBACION_N_MAX
|
||||
|
||||
// Si no hay Scada declarados, salimos del bloque inmediatamente
|
||||
IF "N_MAX_SCADA" <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
|
||||
#t_N_MAX := "N_MAX_SCADA";
|
||||
|
||||
END_REGION COMPROBACION_N_MAX
|
||||
|
||||
|
||||
REGION MULTIPLEXADO
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
|
||||
IF #Arranque THEN
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].Index :=
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
END_FOR;
|
||||
END_IF;
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestion de multiplexado
|
||||
FOR #for_mux := 1 TO #t_N_MAX DO
|
||||
|
||||
// ===============================================================================================================
|
||||
// Antes de iniciar la logica del multiplexado, revisamos los limites
|
||||
REGION LIMITES
|
||||
|
||||
// ===========================================================================================================
|
||||
// Limites
|
||||
IF "DB2041_TQ_AE".Mux.Scada[#for_mux].Index < 0 THEN
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].Index := 0;
|
||||
END_IF;
|
||||
IF "DB2041_TQ_AE".Mux.Scada[#for_mux].Index > "N_MAX_DISP_TQ_AE" THEN
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].Index := "N_MAX_DISP_TQ_AE";
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
REGION INDICES
|
||||
|
||||
// Pasamos el indice a variable temporal para evisar cambios no deseados
|
||||
#t_Index := "DB2041_TQ_AE".Mux.Scada[#for_mux].Index;
|
||||
#t_oldIndex := "DB2041_TQ_AE".Mux.Scada[#for_mux].oldIndex;
|
||||
|
||||
END_REGION INDICES
|
||||
|
||||
|
||||
IF "DB2041_TQ_AE".Mux.Scada[#for_mux].Habilitar THEN
|
||||
|
||||
// ===========================================================================================================
|
||||
// Gestionamos solo los tipos
|
||||
IF #t_Index > 0 THEN
|
||||
|
||||
REGION CARGA_INICIAL
|
||||
|
||||
// ===========================================================================================================
|
||||
// Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice.
|
||||
IF #t_Index <> #t_oldIndex THEN
|
||||
|
||||
// Traspaso de dispositivos al multiplexado
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE := "DB2041_TQ_AE".TQ_AE[#t_Index];
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE := "DB2041_TQ_AE".TQ_AE[#t_Index];
|
||||
|
||||
// ===========================================================================================================
|
||||
// Valor anterior del indice
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldIndex := #t_Index;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION CARGA_INICIAL
|
||||
|
||||
|
||||
REGION DATOS_LECTURA
|
||||
|
||||
// ===========================================================================================================
|
||||
// Movimiento de datos gestionados en FC
|
||||
IF NOT "DB2041_TQ_AE".TQ_AE[#t_Index].Estado_AutoMan THEN
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Orden_Manual := "DB2041_TQ_AE".TQ_AE[#t_Index].Orden_Manual;
|
||||
END_IF;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Hmi_Estado := "DB2041_TQ_AE".TQ_AE[#t_Index].Hmi_Estado;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Orden_Produccion := "DB2041_TQ_AE".TQ_AE[#t_Index].Orden_Produccion;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Orden_CIP := "DB2041_TQ_AE".TQ_AE[#t_Index].Orden_CIP;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Orden_Vaciado := "DB2041_TQ_AE".TQ_AE[#t_Index].Orden_Vaciado;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Alarma_PresionBaja := "DB2041_TQ_AE".TQ_AE[#t_Index].Alarma_PresionBaja;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Alarma_PresionAlta := "DB2041_TQ_AE".TQ_AE[#t_Index].Alarma_PresionAlta;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Alarma_Configuracion := "DB2041_TQ_AE".TQ_AE[#t_Index].Alarma_Configuracion;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Salida_ValvulaVenteo := "DB2041_TQ_AE".TQ_AE[#t_Index].Salida_ValvulaVenteo;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Salida_ValvulaEsteril := "DB2041_TQ_AE".TQ_AE[#t_Index].Salida_ValvulaEsteril;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Salida_ValvulaDucha := "DB2041_TQ_AE".TQ_AE[#t_Index].Salida_ValvulaDucha;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Aux_DuchaFlipActivo := "DB2041_TQ_AE".TQ_AE[#t_Index].Aux_DuchaFlipActivo;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Aux_DuchaFlopActivo := "DB2041_TQ_AE".TQ_AE[#t_Index].Aux_DuchaFlopActivo;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Aux_DuchaFlanco := "DB2041_TQ_AE".TQ_AE[#t_Index].Aux_DuchaFlanco;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Aux_DuchaSalidaFlip := "DB2041_TQ_AE".TQ_AE[#t_Index].Aux_DuchaSalidaFlip;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Aux_DuchaSalidaFlop := "DB2041_TQ_AE".TQ_AE[#t_Index].Aux_DuchaSalidaFlop;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Aux_oldOrdenManual := "DB2041_TQ_AE".TQ_AE[#t_Index].Aux_oldOrdenManual;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Aux_oldAutoMan := "DB2041_TQ_AE".TQ_AE[#t_Index].Aux_oldAutoMan;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Estado_ValorPresion := "DB2041_TQ_AE".TQ_AE[#t_Index].Estado_ValorPresion;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_AlarmaMaxPresion := "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_AlarmaMaxPresion;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_AlarmaMinPresion := "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_AlarmaMinPresion;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_DuchaTiempoFlip := "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_DuchaTiempoFlip;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_DuchaTiempoFlop := "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_DuchaTiempoFlop;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_GrupoAlarma := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_GrupoAlarma;
|
||||
|
||||
END_REGION DATOS_LECTURA
|
||||
|
||||
|
||||
REGION DATOS_ESCRITURA
|
||||
|
||||
REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
// Estado auto/manual
|
||||
IF "DB2041_TQ_AE".TQ_AE[#t_Index].Estado_AutoMan <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Estado_AutoMan THEN
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Estado_AutoMan := "DB2041_TQ_AE".TQ_AE[#t_Index].Estado_AutoMan;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Estado_AutoMan := "DB2041_TQ_AE".TQ_AE[#t_Index].Estado_AutoMan;
|
||||
ELSIF "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Estado_AutoMan <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Estado_AutoMan THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#t_Index].Estado_AutoMan := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Estado_AutoMan;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Estado_AutoMan := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Estado_AutoMan;
|
||||
END_IF;
|
||||
|
||||
// Ordenes (Respetando el diseño original del usuario)
|
||||
IF "DB2041_TQ_AE".TQ_AE[#t_Index].Orden_Manual <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Orden_Manual THEN
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Orden_Manual := "DB2041_TQ_AE".TQ_AE[#t_Index].Orden_Manual;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Orden_Manual := "DB2041_TQ_AE".TQ_AE[#t_Index].Orden_Manual;
|
||||
ELSIF "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Orden_Manual <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Orden_Manual THEN
|
||||
"DB2041_TQ_AE".TQ_AE[#t_Index].Orden_Manual := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Orden_Manual;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Orden_Manual := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Orden_Manual;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_CAMBIOS_DINAMICOS
|
||||
|
||||
|
||||
REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde HMI
|
||||
#t_CambioDesdeHMI :=
|
||||
("DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_Habilitar <> "DB2041_TQ_AE".TQ_AE[#t_Index].Config_Habilitar)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_HabilitarAlarmas <> "DB2041_TQ_AE".TQ_AE[#t_Index].Config_HabilitarAlarmas)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMaxTrabajo <> "DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMaxTrabajo)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMinTrabajo <> "DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMinTrabajo)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMaxAlarma <> "DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMaxAlarma)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMinAlarma <> "DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMinAlarma)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointAlarmaMaxPresion <> "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointAlarmaMaxPresion)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointAlarmaMinPresion <> "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointAlarmaMinPresion)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointFlipDucha <> "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointFlipDucha)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointFlopDucha <> "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointFlopDucha);
|
||||
|
||||
// Marca auxiliar para indicar que el cambio es desde MUX SCADA
|
||||
#t_CambioDesdeMux :=
|
||||
("DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_Habilitar <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_Habilitar)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_HabilitarAlarmas <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_HabilitarAlarmas)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMaxTrabajo <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMaxTrabajo)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMinTrabajo <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMinTrabajo)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMaxAlarma <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMaxAlarma)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMinAlarma <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMinAlarma)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointAlarmaMaxPresion <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointAlarmaMaxPresion)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointAlarmaMinPresion <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointAlarmaMinPresion)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointFlipDucha <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointFlipDucha)
|
||||
OR ("DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointFlopDucha <> "DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointFlopDucha);
|
||||
|
||||
END_REGION GESTION_CAMBIOS_CONFIG
|
||||
|
||||
|
||||
REGION TRASPASO_DATOS
|
||||
|
||||
IF #t_CambioDesdeHMI THEN
|
||||
|
||||
// Carga al Mux
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_Habilitar := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_Habilitar;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_HabilitarAlarmas := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_HabilitarAlarmas;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMaxTrabajo := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMaxTrabajo;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMinTrabajo := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMinTrabajo;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMaxAlarma := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMaxAlarma;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMinAlarma := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMinAlarma;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointAlarmaMaxPresion := "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointAlarmaMaxPresion;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointAlarmaMinPresion := "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointAlarmaMinPresion;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointFlipDucha := "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointFlipDucha;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointFlopDucha := "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointFlopDucha;
|
||||
|
||||
// Carga a Old
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_Habilitar := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_Habilitar;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_HabilitarAlarmas := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_HabilitarAlarmas;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMaxTrabajo := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMaxTrabajo;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMinTrabajo := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMinTrabajo;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMaxAlarma := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMaxAlarma;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMinAlarma := "DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMinAlarma;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointAlarmaMaxPresion := "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointAlarmaMaxPresion;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointAlarmaMinPresion := "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointAlarmaMinPresion;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointFlipDucha := "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointFlipDucha;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointFlopDucha := "DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointFlopDucha;
|
||||
|
||||
ELSIF #t_CambioDesdeMux THEN
|
||||
|
||||
// Carga al PLC
|
||||
"DB2041_TQ_AE".TQ_AE[#t_Index].Config_Habilitar := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_Habilitar;
|
||||
"DB2041_TQ_AE".TQ_AE[#t_Index].Config_HabilitarAlarmas := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_HabilitarAlarmas;
|
||||
"DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMaxTrabajo := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMaxTrabajo;
|
||||
"DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMinTrabajo := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMinTrabajo;
|
||||
"DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMaxAlarma := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMaxAlarma;
|
||||
"DB2041_TQ_AE".TQ_AE[#t_Index].Config_PresionMinAlarma := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMinAlarma;
|
||||
"DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointAlarmaMaxPresion := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointAlarmaMaxPresion;
|
||||
"DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointAlarmaMinPresion := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointAlarmaMinPresion;
|
||||
"DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointFlipDucha := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointFlipDucha;
|
||||
"DB2041_TQ_AE".TQ_AE[#t_Index].Tiempos_SetPointFlopDucha := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointFlopDucha;
|
||||
|
||||
// Carga a Old
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_Habilitar := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_Habilitar;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_HabilitarAlarmas := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_HabilitarAlarmas;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMaxTrabajo := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMaxTrabajo;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMinTrabajo := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMinTrabajo;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMaxAlarma := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMaxAlarma;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Config_PresionMinAlarma := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Config_PresionMinAlarma;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointAlarmaMaxPresion := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointAlarmaMaxPresion;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointAlarmaMinPresion := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointAlarmaMinPresion;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointFlipDucha := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointFlipDucha;
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE.Tiempos_SetPointFlopDucha := "DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE.Tiempos_SetPointFlopDucha;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_DATOS
|
||||
|
||||
END_REGION DATOS_ESCRITURA
|
||||
|
||||
ELSE
|
||||
|
||||
// ===========================================================================================================
|
||||
// En caso de que el indice sea 0, movemos el valor de la AE[0] que no se usa para escribir el index.
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].TQ_AE := "DB2041_TQ_AE".TQ_AE[0];
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldTQ_AE := "DB2041_TQ_AE".TQ_AE[0];
|
||||
|
||||
// Actualizacion de estado anterior
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
|
||||
// Multiplexado no habilitado
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].Index :=
|
||||
"DB2041_TQ_AE".Mux.Scada[#for_mux].oldIndex := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION MULTIPLEXADO
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
FUNCTION_BLOCK "FB15152_ZC_PARO_SEC"
|
||||
TITLE = FB15152_ZC_PARO_SEC
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Bloque de funcion para la gestion de paro secuencial de dispositivos
|
||||
VAR_INPUT
|
||||
Pulso1Seg : Bool; // Pulso de 1 segundo
|
||||
MarchaSecuenciaParo : Bool; // Orden marcha secuencia de paro
|
||||
NumeroDispositivos { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Int := 4; // Numero de dispositivos
|
||||
TiempoEntreEtapas { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Int := 2; // Tiempo entre etapas
|
||||
ConfirmacionDisp { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Array[1..#N_MAX] of Bool; // Confirmacion activado dispositivo
|
||||
END_VAR
|
||||
|
||||
VAR_OUTPUT
|
||||
SecParoFinalizada : Bool; // Secuencia de paro completada
|
||||
SecReposo : Bool; // Secuencia en reposo
|
||||
ParoDispositivo { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Array[1..#N_MAX] of Bool; // Orden paro dispositivo
|
||||
END_VAR
|
||||
|
||||
VAR
|
||||
s_NumeroDispositivos { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Numero de dispositivos
|
||||
END_VAR
|
||||
VAR RETAIN
|
||||
s_EtapaActual { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Etapa actual
|
||||
s_Indice { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Indice dispositivo actual
|
||||
s_TiempoActual { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Tiempo actual
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
N_MAX : Int := 8;
|
||||
REPOSO : Int := 0;
|
||||
PARANDO : Int := 10;
|
||||
REARMANDO : Int := 20;
|
||||
FINALIZADO : Int := 30;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
//=======================================================================
|
||||
// (C)Copyright ZeusControl 2023 - 2026
|
||||
//=======================================================================
|
||||
(*
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
El bloque `FB15051_PARO_SECUENCIAL` implementa un secuenciador bidireccional para el paro ordenado de un array de dispositivos. Permite detener los dispositivos uno a uno esperando una confirmación por etapa, y rearmar la secuencia en sentido inverso si se retira la orden de marcha, continuando desde la última etapa alcanzada en lugar de reiniciar desde el inicio.
|
||||
|
||||
Funcionalidades principales:
|
||||
- Validación del número de dispositivos: `#NumeroDispositivos` se acota entre 1 y la constante de dimensionamiento `#N_MAX`.
|
||||
- Estado `REPOSO`: bloque en espera. Al recibir `#MarchaSecuenciaParo := TRUE` se inicializa el índice y se transita a la etapa `PARANDO`.
|
||||
- Estado `PARANDO`: avanza secuencialmente por los dispositivos de menor a mayor índice. Cada dispositivo se considera parado cuando se cumple `#ConfirmacionDisp[i] = TRUE` durante `#TiempoEntreEtapas` segundos. Al confirmar, se incrementa el índice hasta superar `#s_NumeroDispositivos`, momento en el que se transita a `FINALIZADO`. Si durante esta etapa se desactiva `#MarchaSecuenciaParo`, se invierte el sentido y se pasa a `REARMANDO` sin perder la posición alcanzada.
|
||||
- Estado `REARMANDO`: retrocede secuencialmente por los dispositivos de mayor a menor índice. Cada dispositivo se considera rearmado cuando `#ConfirmacionDisp[i] = FALSE` durante `#TiempoEntreEtapas` segundos. Al rearmar, se decrementa el índice hasta alcanzar 1, momento en el que se transita a `REPOSO`. Si durante esta etapa se vuelve a activar `#MarchaSecuenciaParo`, se invierte nuevamente el sentido y se pasa a `PARANDO` desde la posición actual.
|
||||
- Estado `FINALIZADO`: secuencia de paro completa. Al retirar `#MarchaSecuenciaParo`, se rearman los dispositivos en orden inverso empezando desde el último, transitando a `REARMANDO`.
|
||||
- Mapeado dinámico de salidas: para cada dispositivo se activa `#ParoDispositivo[i] := TRUE` si su índice es menor o igual al puntero actual y la etapa es `PARANDO`; en el resto de casos se mantiene en `FALSE`. Esto garantiza que los dispositivos ya parados en la fase actual permanezcan parados durante el rearmado inverso de los posteriores.
|
||||
- Señales de estado: `#SecReposo` indica que la secuencia está en `REPOSO` y `#SecParoFinalizada` que ha terminado (`FINALIZADO`).
|
||||
- Contadores de tiempo por etapa del tipo `ZC_TIEMPO_ETAPA` con base de tiempo en segundos (`#Pulso1Seg`).
|
||||
|
||||
> **Restricciones:** PLC serie 1200/1500.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `ZC_TIEMPO_ETAPA` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 24.05.2023 | (ABH) | Primera versión. |
|
||||
| 00.00.02 | 15.12.2023 | (HCR) | Se aumentan los dispositivos de 4 a 8. |
|
||||
| 00.00.03 | 18.12.2023 | (ABH) | Se cambia UDT tiempo etapa a `ZC_TIEMPO_ETAPA`. Se añade salida `SecReposo` para indicar que está en reposo. Se añade gestión de etapas para que, en caso de estar con orden de paro y se dé marcha, siga la secuencia donde le toque evitando tener que pararla por completo y volverla a arrancar. |
|
||||
| 01.00.00 | 03.07.2026 | (ABH) | Cambio a SCL. Se refactoriza logicas para estandarizar. Se utiliza constante N_MAX para redimensionar. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION LIMITES
|
||||
|
||||
#s_NumeroDispositivos := #NumeroDispositivos;
|
||||
|
||||
// Limite de seguridad
|
||||
IF #s_NumeroDispositivos > #N_MAX THEN
|
||||
#s_NumeroDispositivos := #N_MAX;
|
||||
ELSIF #s_NumeroDispositivos < 1 THEN
|
||||
#s_NumeroDispositivos := 1;
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION SECUENCIADOR_BIDIRECCIONAL
|
||||
|
||||
CASE #s_EtapaActual OF
|
||||
|
||||
#REPOSO:
|
||||
#s_Indice := 1;
|
||||
#s_TiempoActual := 0;
|
||||
|
||||
IF #MarchaSecuenciaParo THEN
|
||||
#s_EtapaActual := #PARANDO;
|
||||
END_IF;
|
||||
|
||||
#PARANDO:
|
||||
|
||||
// Contador de tiempo con confirmacion de dispositivo
|
||||
IF #ConfirmacionDisp[#s_Indice] AND #Pulso1Seg THEN
|
||||
#s_TiempoActual += 1;
|
||||
END_IF;
|
||||
|
||||
// Tiempo cumplido
|
||||
IF (#s_TiempoActual >= #TiempoEntreEtapas) THEN
|
||||
#s_TiempoActual := 0;
|
||||
#s_Indice += 1; // Avanzamos al siguiente dispositivo
|
||||
|
||||
// Comprobación de fin de secuencia de paro
|
||||
IF #s_Indice > #s_NumeroDispositivos THEN
|
||||
#s_EtapaActual := #FINALIZADO;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// Si se desactiva la orden de marcha de la secuencia, comenzamos el rearme inverso
|
||||
IF NOT #MarchaSecuenciaParo THEN
|
||||
#s_TiempoActual := 0;
|
||||
#s_EtapaActual := #REARMANDO;
|
||||
END_IF;
|
||||
|
||||
|
||||
#REARMANDO:
|
||||
|
||||
// Límite de seguridad inferior
|
||||
IF #s_Indice < 1 THEN
|
||||
#s_EtapaActual := #REPOSO;
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Contador de tiempo sin confirmacion de dispositivo
|
||||
IF NOT #ConfirmacionDisp[#s_Indice] AND #Pulso1Seg THEN
|
||||
#s_TiempoActual += 1;
|
||||
END_IF;
|
||||
|
||||
// Tiempo cumplido
|
||||
IF (#s_TiempoActual >= #TiempoEntreEtapas) THEN
|
||||
#s_TiempoActual := 0;
|
||||
#s_Indice -= 1; // Avanzamos al dispositivo anterior
|
||||
|
||||
IF #s_Indice < 1 THEN
|
||||
#s_EtapaActual := #REPOSO;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// Si se vuelve a dar marcha, invertimos dirección nuevamente
|
||||
IF #MarchaSecuenciaParo THEN
|
||||
#s_TiempoActual := 0;
|
||||
#s_EtapaActual := #PARANDO;
|
||||
END_IF;
|
||||
|
||||
|
||||
#FINALIZADO:
|
||||
|
||||
IF NOT #MarchaSecuenciaParo THEN
|
||||
#s_TiempoActual := 0;
|
||||
// Empezamos a rearmar desde el último dispositivo que se paro
|
||||
#s_Indice := #s_NumeroDispositivos;
|
||||
#s_EtapaActual := #REARMANDO;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
#s_EtapaActual := #REPOSO;
|
||||
END_CASE;
|
||||
|
||||
END_REGION SECUENCIADOR_BIDIRECCIONAL
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION MAPEADO_DINAMICO_DE_SALIDAS
|
||||
|
||||
#SecReposo := (#s_EtapaActual = #REPOSO);
|
||||
#SecParoFinalizada := (#s_EtapaActual = #FINALIZADO);
|
||||
|
||||
// Mapeo vectorial de comandos físicos
|
||||
FOR #for_i := 1 TO #N_MAX DO
|
||||
|
||||
// Si el índice iterativo es menor que nuestro puntero de etapa actual,
|
||||
// significa que ya hemos pasado por él en la secuencia de paro y debe estar detenido.
|
||||
IF #for_i < #s_Indice THEN
|
||||
#ParoDispositivo[#for_i] := TRUE;
|
||||
|
||||
// Si el índice coincide con el puntero y estamos parando, forzamos la salida a TRUE
|
||||
ELSIF (#for_i = #s_Indice) AND (#s_EtapaActual = #PARANDO) THEN
|
||||
#ParoDispositivo[#for_i] := TRUE;
|
||||
|
||||
// Para el resto de condiciones
|
||||
ELSE
|
||||
#ParoDispositivo[#for_i] := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION MAPEADO_DINAMICO_DE_SALIDAS
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
FUNCTION_BLOCK "FB15153_ZC_MARCHA_SEC_B_MEM"
|
||||
TITLE = FB15153_ZC_MARCHA_SEC_B_MEM
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Bloque de funcion para la gestion de activacion de las bombas de de una maquina de membranas
|
||||
VAR_INPUT
|
||||
Pulso1Seg : Bool; // Pulso de 1 segundo
|
||||
MarchaSecuencia : Bool; // Orden de marcha secuencia
|
||||
EstadoBombaPresionVF : Bool; // Estado bomba Presion (Variador)
|
||||
EstadoBombaPresion : Bool; // Estado bomba Presion
|
||||
TiempoEntreBombas : Int := 10; // SP Tiempo entre bombas
|
||||
NumeroBombasPresion : Int := 2; // Numero de bombas presion (1 o 2)
|
||||
NumeroModulos : Int := 6; // Numero de modulos
|
||||
END_VAR
|
||||
|
||||
VAR_OUTPUT
|
||||
MarchaBombaPresionVF : Bool; // Activacion bomba Presion (Variador)
|
||||
MarchaBombaPresion : Bool; // Activacion bomba Presion
|
||||
MarchaBombaModulo : Array[1..#N_MAX] of Bool; // Activacion bomba Modulo
|
||||
END_VAR
|
||||
|
||||
VAR RETAIN
|
||||
s_TonPresion { S7_SetPoint := 'False'} : Array[1..2] of "UDT_ZC_DISP_TON";
|
||||
s_TonModulos { S7_SetPoint := 'False'} : Array[1..#N_MAX] of "UDT_ZC_DISP_TON";
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_NumBombasPresion : Int; // Numero de bombas presion
|
||||
t_NumModulos : Int; // Numero de modulos
|
||||
t_BombasPresionOk : Bool; // Bombas presion arrancadas Ok
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
N_MAX : Int := 6;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2023 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Bloque de gestión de marcha secuencial de bombas de una máquina de membranas. Implementa el arranque escalonado, en cascada y temporizado, de las bombas de presión y de las bombas de los módulos de la máquina, respetando el número de bombas y módulos configurados y utilizando temporizadores individuales no retentivos.
|
||||
|
||||
Acciones detalladas:
|
||||
- Limita el número de bombas de presión activas (`t_NumBombasPresion`) al rango válido `1`–`2`, acotando la entrada `NumeroBombasPresion`.
|
||||
- Limita el número de módulos activos (`t_NumModulos`) al rango válido `1`–`N_MAX`, acotando la entrada `NumeroModulos`.
|
||||
- Traslada el setpoint de temporización `TiempoEntreBombas` a todos los temporizadores de bombas de presión (`s_TonPresion[1..2]`) y de módulos (`s_TonModulos[1..N_MAX]`).
|
||||
- Gestiona el arranque de las bombas de presión mediante dos temporizadores en cascada: primero la bomba de variador (`s_TonPresion[1]`) y, tras su confirmación y solo si hay 2 bombas configuradas, la segunda bomba de presión (`s_TonPresion[2]`).
|
||||
- Calcula el flag `t_BombasPresionOk`, que indica que el conjunto de bombas de presión requerido está en marcha: con 1 bomba exige confirmación del variador, con 2 bombas exige confirmación de ambas.
|
||||
- Arranca el módulo 1 (`s_TonModulos[1]`) directamente cuando las bombas de presión están OK.
|
||||
- Arranca los módulos `2` a `N_MAX` en cascada, de forma que cada módulo espera a la confirmación del módulo anterior y a las bombas de presión OK; los módulos no configurados se fuerzan a `FALSE` por seguridad.
|
||||
- Ejecuta los temporizadores llamando a la `FC` de temporización individual, lo que permite disponer de un `SP`, una `IN`, una salida `Q` y un tiempo transcurrido independientes por instancia.
|
||||
- Genera las salidas finales: `MarchaBombaPresionVF` (variador), `MarchaBombaPresion` (segunda bomba) y `MarchaBombaModulo[1..N_MAX]` a partir de las salidas `Q` de los temporizadores correspondientes.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC2928_ZC_TON_INDV` |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 09.05.2023 | (ABH) | Primera version. |
|
||||
| 01.00.01 | 19.05.2023 | (ABH) | Se añade parámetro de entrada para límite de número de bombas de presión. |
|
||||
| 01.00.02 | 02.10.2023 | (ABH) | Se añade `FC22028_TON_INV` para gestión de temporizadores. |
|
||||
| 01.00.03 | 02.11.2023 | (ABH) | Se añade gestión para 6 módulos. |
|
||||
| 01.00.03 | 06.07.2026 | (ABH) | Cambio a SCL. Se refactoriza numero de modulos.|
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION LIMITES
|
||||
|
||||
// Limite numero de bombas presion
|
||||
#t_NumBombasPresion := #NumeroBombasPresion;
|
||||
IF #t_NumBombasPresion < 1 THEN
|
||||
#t_NumBombasPresion := 1;
|
||||
END_IF;
|
||||
IF #t_NumBombasPresion > 2 THEN
|
||||
#t_NumBombasPresion := 2;
|
||||
END_IF;
|
||||
|
||||
// Limite numero de bombas modulos
|
||||
#t_NumModulos := #NumeroModulos;
|
||||
IF #t_NumModulos < 1 THEN
|
||||
#t_NumModulos := 1;
|
||||
END_IF;
|
||||
IF #t_NumModulos > #N_MAX THEN
|
||||
#t_NumModulos := #N_MAX;
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION TRASPASO_DE_PARAMETROS
|
||||
|
||||
// Traspaso de tiempos bomba presion
|
||||
FOR #for_i := 1 TO 2 DO
|
||||
#s_TonPresion[#for_i].SP := #TiempoEntreBombas;
|
||||
END_FOR;
|
||||
|
||||
// Traspaso de tiempos bomba modulos
|
||||
FOR #for_i := 1 TO #N_MAX DO
|
||||
#s_TonModulos[#for_i].SP := #TiempoEntreBombas;
|
||||
END_FOR;
|
||||
|
||||
END_REGION TRASPASO_DE_PARAMETROS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_BOMBAS_PRESION
|
||||
|
||||
// Temporizador bomba Presion (Variador)
|
||||
#s_TonPresion[1].IN := #MarchaSecuencia;
|
||||
|
||||
// Temporizador bomba Presion
|
||||
#s_TonPresion[2].IN :=
|
||||
(#t_NumBombasPresion = 2) AND
|
||||
#EstadoBombaPresionVF AND
|
||||
#s_TonPresion[1].Q;
|
||||
|
||||
// Bombas presion arrancadas Ok
|
||||
IF #t_NumBombasPresion = 1 THEN
|
||||
#t_BombasPresionOk := #EstadoBombaPresionVF AND #s_TonPresion[1].Q;
|
||||
ELSE
|
||||
#t_BombasPresionOk := #EstadoBombaPresion AND #s_TonPresion[2].Q;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_BOMBAS_PRESION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_BOMBAS_MODULOS
|
||||
|
||||
// El modulo 1 arranca directamente si las bombas de presion estan OK
|
||||
#s_TonModulos[1].IN := #t_BombasPresionOk;
|
||||
|
||||
// Los modulos 2 a N_MAX arrancan en cascada
|
||||
FOR #for_i := 2 TO #N_MAX DO
|
||||
|
||||
IF #for_i <= #t_NumModulos THEN
|
||||
|
||||
// Si el módulo está dentro de la configuración, evalúa la cascada (Módulo anterior Q + bombas presion Ok)
|
||||
#s_TonModulos[#for_i].IN := #s_TonModulos[#for_i - 1].Q AND #t_BombasPresionOk;
|
||||
|
||||
ELSE
|
||||
|
||||
// Forzado de seguridad a FALSE para módulos no instalados/configurados en esta máquina
|
||||
#s_TonModulos[#for_i].IN := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION GESTION_BOMBAS_MODULOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_TEMPORIZADORES
|
||||
|
||||
// Temporizadores bombas presion
|
||||
FOR #for_i := 1 TO 2 DO
|
||||
"FC2928_ZC_TON_INDV"(Pulso1seg := #Pulso1Seg,
|
||||
TON := #s_TonPresion[#for_i]);
|
||||
END_FOR;
|
||||
|
||||
// Temporizadores bombas modulos
|
||||
FOR #for_i := 1 TO #N_MAX DO
|
||||
"FC2928_ZC_TON_INDV"(Pulso1seg := #Pulso1Seg,
|
||||
TON := #s_TonModulos[#for_i]);
|
||||
END_FOR;
|
||||
|
||||
END_REGION GESTION_TEMPORIZADORES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION SALIDAS
|
||||
|
||||
// Bombas presion
|
||||
#MarchaBombaPresionVF := #s_TonPresion[1].Q;
|
||||
#MarchaBombaPresion := #s_TonPresion[2].Q;
|
||||
|
||||
// Bombas modulos
|
||||
FOR #for_i := 1 TO #N_MAX DO
|
||||
|
||||
#MarchaBombaModulo[#for_i] := #s_TonModulos[#for_i].Q;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION SALIDAS
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
@@ -0,0 +1,403 @@
|
||||
FUNCTION "FC15151_ZC_MARCHA_PARO_SEC" : Void
|
||||
TITLE = FC15151_ZC_MARCHA_PARO_SEC
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para la gestion de marcha/paro de dispositivos secuencialmente
|
||||
VAR_INPUT
|
||||
Pulso1Seg : Bool; // Pulso de 1 segundo
|
||||
Seguridad : Bool; // Estado seguridades ok
|
||||
Marcha : Bool; // Orden de marcha
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
MP_SEC : "UDT_ZC_MARCHA_PARO_SEC";
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
REPOSO : Int := 0;
|
||||
MARCHA_1 : Int := 10;
|
||||
MARCHA_2 : Int := 20;
|
||||
MARCHA_3 : Int := 30;
|
||||
MARCHA_4 : Int := 40;
|
||||
MARCHA_5 : Int := 50;
|
||||
MARCHA_6 : Int := 60;
|
||||
MARCHA_7 : Int := 70;
|
||||
MARCHA_8 : Int := 80;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2023 - 2025
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de la gestión de secuencias de arranque y parada escalonada de hasta 8 dispositivos de forma temporizada.
|
||||
|
||||
- Evaluar dinámicamente los parámetros de configuración, limitando el número de elementos de la secuencia a un rango válido entre 1 y 8 mediante la variable `NumElementos`.
|
||||
- Gestionar el traspaso del tiempo de espera entre etapas, aplicando de forma automática los parámetros `TiempoEntreMarcha` o `TiempoEntreParo` según el estado de la orden activa en la entrada `Marcha`.
|
||||
- Ejecutar una máquina de estados para la transición secuencial de las etapas de operación, controlando el tiempo de permanencia en cada fase mediante la señal base de tiempo `Pulso1Seg`.
|
||||
- Monitorizar de forma continua la señal de `Seguridad`, forzando el reinicio seguro de la máquina de estados a la etapa de reposo y limpiando los temporizadores en caso de pérdida.
|
||||
- Calcular y activar las señales de salida operativas, incluyendo los bits individuales de activación por dispositivo (`M[1]` a `M[8]`) y las confirmaciones de ciclo finalizado (`SecMarchaCompletada` y `SecParoCompletada`).
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | ´UDT_ZC_MARCHA_PARO_SEC´ |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 24.05.2023 | (ABH) | Primera version. |
|
||||
| 01.00.01 | 28.07.2023 | (ABH) | Se añade traspaso de Set Point de tiempo de paso dentro del FC. |
|
||||
| 01.00.02 | 14.03.2025 | (ABH) | Se separan los tiempos de arranque de marcha y paro. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION TRASPASO_PARAMETROS
|
||||
|
||||
// Limite de numero de elementos
|
||||
IF #MP_SEC.NumElementos < 1 THEN
|
||||
#MP_SEC.NumElementos := 1;
|
||||
END_IF;
|
||||
|
||||
IF #MP_SEC.NumElementos > 8 THEN
|
||||
#MP_SEC.NumElementos := 8;
|
||||
END_IF;
|
||||
|
||||
// Traspaso de set point tiempo etapa
|
||||
IF #Marcha THEN
|
||||
#MP_SEC.Tiempo.SetPoint := #MP_SEC.TiempoEntreMarcha;
|
||||
ELSE
|
||||
#MP_SEC.Tiempo.SetPoint := #MP_SEC.TiempoEntreParo;
|
||||
END_IF;
|
||||
|
||||
// Seguridad
|
||||
IF NOT #Seguridad THEN
|
||||
#MP_SEC.Etapa := #MP_SEC.Tiempo.Actual := 0;
|
||||
END_IF;
|
||||
|
||||
END_REGION TRASPASO_PARAMETROS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION SECUENCIA
|
||||
|
||||
CASE #MP_SEC.Etapa OF
|
||||
|
||||
// ==========================================================================================================
|
||||
#REPOSO:
|
||||
IF #Marcha AND #Seguridad THEN
|
||||
#MP_SEC.Etapa := #MARCHA_1;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
END_IF;
|
||||
|
||||
// ==========================================================================================================
|
||||
#MARCHA_1:
|
||||
|
||||
// Activacion tiempo de etapa
|
||||
#MP_SEC.Tiempo.Activar := TRUE;
|
||||
|
||||
// Con tiempo de etapa cumplido
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
|
||||
|
||||
// Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
|
||||
IF #Marcha THEN
|
||||
|
||||
IF #MP_SEC.NumElementos > 1 THEN
|
||||
#MP_SEC.Etapa := #MARCHA_2;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
ELSE
|
||||
#MP_SEC.Tiempo.Activar := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
#MP_SEC.Etapa := #REPOSO;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// ==========================================================================================================
|
||||
#MARCHA_2:
|
||||
|
||||
// Activacion tiempo de etapa
|
||||
#MP_SEC.Tiempo.Activar := TRUE;
|
||||
|
||||
// Con tiempo de etapa cumplido
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
|
||||
|
||||
// Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
|
||||
IF #Marcha THEN
|
||||
|
||||
IF #MP_SEC.NumElementos > 2 THEN
|
||||
#MP_SEC.Etapa := #MARCHA_3;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
ELSE
|
||||
#MP_SEC.Tiempo.Activar := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
#MP_SEC.Etapa := #MARCHA_1;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// ==========================================================================================================
|
||||
#MARCHA_3:
|
||||
|
||||
// Activacion tiempo de etapa
|
||||
#MP_SEC.Tiempo.Activar := TRUE;
|
||||
|
||||
// Con tiempo de etapa cumplido
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
|
||||
|
||||
// Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
|
||||
IF #Marcha THEN
|
||||
|
||||
IF #MP_SEC.NumElementos > 3 THEN
|
||||
#MP_SEC.Etapa := #MARCHA_4;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
ELSE
|
||||
#MP_SEC.Tiempo.Activar := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
#MP_SEC.Etapa := #MARCHA_2;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// ==========================================================================================================
|
||||
#MARCHA_4:
|
||||
|
||||
// Activacion tiempo de etapa
|
||||
#MP_SEC.Tiempo.Activar := TRUE;
|
||||
|
||||
// Con tiempo de etapa cumplido
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
|
||||
|
||||
// Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
|
||||
IF #Marcha THEN
|
||||
|
||||
IF #MP_SEC.NumElementos > 4 THEN
|
||||
#MP_SEC.Etapa := #MARCHA_5;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
ELSE
|
||||
#MP_SEC.Tiempo.Activar := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
#MP_SEC.Etapa := #MARCHA_3;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// ==========================================================================================================
|
||||
#MARCHA_5:
|
||||
|
||||
// Activacion tiempo de etapa
|
||||
#MP_SEC.Tiempo.Activar := TRUE;
|
||||
|
||||
// Con tiempo de etapa cumplido
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
|
||||
|
||||
// Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
|
||||
IF #Marcha THEN
|
||||
|
||||
IF #MP_SEC.NumElementos > 5 THEN
|
||||
#MP_SEC.Etapa := #MARCHA_6;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
ELSE
|
||||
#MP_SEC.Tiempo.Activar := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
#MP_SEC.Etapa := #MARCHA_4;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// ==========================================================================================================
|
||||
#MARCHA_6:
|
||||
|
||||
// Activacion tiempo de etapa
|
||||
#MP_SEC.Tiempo.Activar := TRUE;
|
||||
|
||||
// Con tiempo de etapa cumplido
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
|
||||
|
||||
// Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
|
||||
IF #Marcha THEN
|
||||
|
||||
IF #MP_SEC.NumElementos > 6 THEN
|
||||
#MP_SEC.Etapa := #MARCHA_7;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
ELSE
|
||||
#MP_SEC.Tiempo.Activar := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
#MP_SEC.Etapa := #MARCHA_5;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// ==========================================================================================================
|
||||
#MARCHA_7:
|
||||
|
||||
// Activacion tiempo de etapa
|
||||
#MP_SEC.Tiempo.Activar := TRUE;
|
||||
|
||||
// Con tiempo de etapa cumplido
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
|
||||
|
||||
// Estando en marcha, si hay mas elementos saltamos a la siguiente etapa, de lo contrario, reseteamos el tiempo de etapa
|
||||
IF #Marcha THEN
|
||||
|
||||
IF #MP_SEC.NumElementos > 7 THEN
|
||||
#MP_SEC.Etapa := #MARCHA_8;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
ELSE
|
||||
#MP_SEC.Tiempo.Activar := FALSE;
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
#MP_SEC.Etapa := #MARCHA_6;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
// ==========================================================================================================
|
||||
#MARCHA_8:
|
||||
|
||||
// Activacion tiempo de etapa
|
||||
#MP_SEC.Tiempo.Activar := TRUE;
|
||||
|
||||
// Con tiempo de etapa cumplido
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint THEN
|
||||
|
||||
// Estando en marcha, reseteamos el tiempo de etapa
|
||||
IF #Marcha THEN
|
||||
#MP_SEC.Tiempo.Activar := FALSE;
|
||||
ELSE
|
||||
#MP_SEC.Etapa := #MARCHA_7;
|
||||
#MP_SEC.Tiempo.Actual := 0;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
ELSE
|
||||
#MP_SEC.Etapa := #REPOSO;
|
||||
END_CASE;
|
||||
|
||||
|
||||
END_REGION SECUENCIA
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION TIEMPO_DE_ETAPA
|
||||
|
||||
IF #MP_SEC.Tiempo.Activar THEN
|
||||
|
||||
IF #Pulso1Seg THEN
|
||||
#MP_SEC.Tiempo.Actual += 1;
|
||||
END_IF;
|
||||
|
||||
#MP_SEC.Tiempo.Restante := #MP_SEC.Tiempo.SetPoint - #MP_SEC.Tiempo.Actual;
|
||||
|
||||
IF #MP_SEC.Tiempo.Restante <= 0 THEN
|
||||
#MP_SEC.Tiempo.Restante := 0;
|
||||
END_IF;
|
||||
|
||||
#MP_SEC.Tiempo.Activar := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION TIEMPO_DE_ETAPA
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION SALIDAS
|
||||
|
||||
// Secuencia paro completada
|
||||
#MP_SEC.SecParoCompletada := #MP_SEC.Etapa = 0;
|
||||
|
||||
// Secuencia Marcha completada
|
||||
#MP_SEC.SecMarchaCompletada := FALSE;
|
||||
CASE #MP_SEC.NumElementos OF
|
||||
1:
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 10 THEN
|
||||
#MP_SEC.SecMarchaCompletada := TRUE;
|
||||
END_IF;
|
||||
2:
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 20 THEN
|
||||
#MP_SEC.SecMarchaCompletada := TRUE;
|
||||
END_IF;
|
||||
3:
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 30 THEN
|
||||
#MP_SEC.SecMarchaCompletada := TRUE;
|
||||
END_IF;
|
||||
4:
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 40 THEN
|
||||
#MP_SEC.SecMarchaCompletada := TRUE;
|
||||
END_IF;
|
||||
5:
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 50 THEN
|
||||
#MP_SEC.SecMarchaCompletada := TRUE;
|
||||
END_IF;
|
||||
6:
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 60 THEN
|
||||
#MP_SEC.SecMarchaCompletada := TRUE;
|
||||
END_IF;
|
||||
7:
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 70 THEN
|
||||
#MP_SEC.SecMarchaCompletada := TRUE;
|
||||
END_IF;
|
||||
8:
|
||||
IF #MP_SEC.Tiempo.Actual >= #MP_SEC.Tiempo.SetPoint AND #MP_SEC.Etapa = 80 THEN
|
||||
#MP_SEC.SecMarchaCompletada := TRUE;
|
||||
END_IF;
|
||||
END_CASE;
|
||||
|
||||
// Bit marcha elementos
|
||||
#MP_SEC.M[1] := #MP_SEC.Etapa >= 10;
|
||||
#MP_SEC.M[2] := #MP_SEC.Etapa >= 20;
|
||||
#MP_SEC.M[3] := #MP_SEC.Etapa >= 30;
|
||||
#MP_SEC.M[4] := #MP_SEC.Etapa >= 40;
|
||||
#MP_SEC.M[5] := #MP_SEC.Etapa >= 50;
|
||||
#MP_SEC.M[6] := #MP_SEC.Etapa >= 60;
|
||||
#MP_SEC.M[7] := #MP_SEC.Etapa >= 70;
|
||||
#MP_SEC.M[8] := #MP_SEC.Etapa >= 80;
|
||||
|
||||
END_REGION
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
FUNCTION "FC4_ZC_ENT_DISPONIBILIDAD" : Bool
|
||||
TITLE = FC4_ZC_DISPONIBILIDAD_ENTIDAD
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para comprobar disponibilidad de las entidades.
|
||||
VAR_INPUT
|
||||
Entidad : Int; // Numero de entidad a gestionar
|
||||
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:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función encargada de evaluar y determinar la disponibilidad operativa de las entidades del sistema.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- Calcular el estado de disponibilidad de la entidad correspondiente en función del valor recibido en la entrada `Entidad`.
|
||||
- Verificar y restringir, por motivos de seguridad, el valor de la entrada `Entidad` para garantizar que no exceda los límites definidos en el array de entidades.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC4_ZC_DISPONIBILIDAD_ENTIDAD` |
|
||||
| FB | - |
|
||||
| DB | `DB6_ENTIDAD` |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 14.03.2025 | (ABH) | Primera version. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_DISPONIBILIDAD
|
||||
|
||||
// Comprobacion de limites de la entrada Entidad. En caso de estar fuera de indices, devolvemos un FALSE.
|
||||
// En caso de estar dentro de limites, devolvemos el estado de la entidad
|
||||
IF #Entidad < 1 OR #Entidad > "N_MAX_ENTIDAD" THEN
|
||||
#FC4_ZC_ENT_DISPONIBILIDAD := FALSE;
|
||||
ELSE
|
||||
#FC4_ZC_ENT_DISPONIBILIDAD := "DB6_ENTIDAD".ENT[#Entidad].Estado.Disponible;
|
||||
END_IF;
|
||||
|
||||
END_REGION GESTION_DISPONIBILIDAD
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,280 @@
|
||||
FUNCTION "FC6_ZC_ENT_ESTADO" : Void
|
||||
TITLE = FC6_ZC_ESTADO_ENTIDAD
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : AketzaBarragues
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Funcion para gestion de estados de entidades.
|
||||
VAR_INPUT
|
||||
Entidad : Int; // Numero de entidad a gestionar
|
||||
TipoProceso : Int; // Tipo de proceso
|
||||
CodigoProducto : Int; // Codigo de producto
|
||||
END_VAR
|
||||
|
||||
VAR_OUTPUT
|
||||
TipoError : Int; // 1= Error / 2= Manual
|
||||
DispNumero : Int; // Numero de dispositivo HMI
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_DispError : Bool;
|
||||
t_DispManual : Bool;
|
||||
t_DispNumero : Int;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
DISP_V : Int := 1;
|
||||
DISP_M : Int := 2;
|
||||
DISP_M_VF : Int := 3;
|
||||
DISP_M_SINA : Int := 4;
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2020 - 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 para la gestión integral de estados, disponibilidad y supervisión de los dispositivos asociados a una entidad.
|
||||
|
||||
Las tareas que realiza son las siguientes:
|
||||
|
||||
- **Supervisión de dispositivos:** Escaneo cíclico de los dispositivos vinculados a la entidad (Válvulas, Motores, Variadores y Sinamics) mediante un bucle `FOR`.
|
||||
- Verificación de alarmas generales (`Alarmas_General`) y estados de mando manual (`Estado_AutoMan`) en cada equipo.
|
||||
- Identificación del tipo de incidencia en las salidas `TipoError` (1 para Error, 2 para Manual) y reporte del índice del dispositivo afectado en `DispNumero`.
|
||||
- **Cálculo de disponibilidad:** Determinación del estado `Disponible` basándose en la ausencia de alarmas, mandos manuales, capturas activas y estados de proceso (Producción, CIP, SIP, Standby).
|
||||
- Actualización del estado `Capturada` si la entidad tiene una asignación distinta de cero.
|
||||
- **Gestión de códigos de estado:** Asignación dinámica del código numérico `CodEstado` según la fase de operación actual (Producción: 1000, CIP: 2000, SIP: 3000, Standby: 4000).
|
||||
- Refinamiento del código según el contenido detectado (Producto: +10, Agua: +20, Vacío: +30).
|
||||
- Registro de estados de limpieza (Sucia: 10000, Limpia: 11000, Esterilizada: 12000).
|
||||
- **Sincronización de producto:** Actualización de la variable `Producto` con el valor de entrada `CodigoProducto` siempre que la entidad tenga un estado activo.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | - |
|
||||
| FB | - |
|
||||
| DB | `DB2010_V`, `DB2015_M`, `DB2016_M_VF`, `DB2017_M_SINA`, `DB6_ENTIDAD` |
|
||||
| UDT | - |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 15.10.2020 | (ABH) | Primera version. |
|
||||
| 00.00.02 | 02.02.2021 | (ABH) | Modificado para uso como funcion. Se elimina bucle `FOR` para revisar solamente la entidad que se pasa como entrada. |
|
||||
| 00.00.03 | 02.12.2022 | (ABH) | Se modifica el UDT para estandarizacion. |
|
||||
| 00.00.01 | 15.10.2025 | (ABH) | Se añade gestion de codigo de estado. |
|
||||
| 00.00.05 | 10.03.2025 | (ABH) | Se añade gestion de codigo de producto a las entidades. |
|
||||
| 00.00.06 | 24.04.2025 | (HCR) | Se añade gestion de idioma. |
|
||||
| 00.00.07 | 11.09.2025 | (ABH) | Se eliminan las constantes de idioma dentro del `FC`. Se utilizan constantes globales. |
|
||||
| 01.00.00 | 26.03.2026 | (ABH) | Se elimina idioma. Se añaden constantes de tipo de dispositivo. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_ENTIDADES
|
||||
|
||||
IF "DB6_ENTIDAD".ENT[#Entidad].Habilitar THEN
|
||||
|
||||
// Asignacion de estado entidad capturada
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.Capturada := "DB6_ENTIDAD".ENT[#Entidad].Asignacion <> 0;
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION COMPROBACION_DISPOSITIVOS
|
||||
|
||||
// Reset de estados
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Alarma.Dispositivo := "DB6_ENTIDAD".ENT[#Entidad].Alarma.Manual := #t_DispError := #t_DispManual := FALSE;
|
||||
|
||||
// Comprobacion de estado de dispositivo declarados dentro de la entidad
|
||||
FOR #for_i := 1 TO "N_MAX_ENTIDAD_DISPOSITIVOS" DO
|
||||
|
||||
// Se revisan solamente las entidades declaradas
|
||||
IF "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Tipo <> 0 AND "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num <> 0 THEN
|
||||
|
||||
CASE "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Tipo OF
|
||||
|
||||
#DISP_V:
|
||||
// ==========================================================================================================
|
||||
REGION VALVULA
|
||||
|
||||
IF "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num <= "N_MAX_DISP_V" THEN
|
||||
|
||||
// Comprobacion de errores o dispositivo en manual
|
||||
#t_DispError := "DB2010_V".V["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Alarmas_General;
|
||||
#t_DispManual := "DB2010_V".V["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Estado_AutoMan;
|
||||
|
||||
IF #t_DispError OR #t_DispManual THEN
|
||||
#t_DispNumero := (#DISP_V * 1000) + "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION VALVULA
|
||||
|
||||
|
||||
#DISP_M:
|
||||
// ==========================================================================================================
|
||||
REGION MOTOR
|
||||
|
||||
IF "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num <= "N_MAX_DISP_M" THEN
|
||||
|
||||
// Comprobacion de errores o dispositivo en manual
|
||||
#t_DispError := "DB2015_M".M["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Alarmas_General;
|
||||
#t_DispManual := "DB2015_M".M["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Estado_AutoMan;
|
||||
|
||||
IF #t_DispError OR #t_DispManual THEN
|
||||
#t_DispNumero := (#DISP_M * 1000) + "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION MOTOR
|
||||
|
||||
|
||||
#DISP_M_SINA:
|
||||
// ==========================================================================================================
|
||||
REGION MOTOR_SINAMICS
|
||||
|
||||
IF "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num <= "N_MAX_DISP_M_SINA" THEN
|
||||
|
||||
// Comprobacion de errores o dispositivo en manual
|
||||
#t_DispError := "DB2017_M_SINA".M_SINA["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Alarmas_General;
|
||||
#t_DispManual := "DB2017_M_SINA".M_SINA["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Estado_AutoMan;
|
||||
|
||||
IF #t_DispError OR #t_DispManual THEN
|
||||
#t_DispNumero := (#DISP_M_SINA * 1000) + "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION MOTOR_SINAMICS
|
||||
|
||||
|
||||
#DISP_M_VF:
|
||||
// ==========================================================================================================
|
||||
REGION MOTOR_VARIADOR
|
||||
|
||||
IF "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num <= "N_MAX_DISP_M_VF" THEN
|
||||
|
||||
// Comprobacion de errores o dispositivo en manual
|
||||
#t_DispError := "DB2016_M_VF".M_VF["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Alarmas_General;
|
||||
#t_DispManual := "DB2016_M_VF".M_VF["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Estado_AutoMan;
|
||||
|
||||
IF #t_DispError OR #t_DispManual THEN
|
||||
#t_DispNumero := (#DISP_M_VF * 1000) + "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num;
|
||||
END_IF;
|
||||
|
||||
END_IF;
|
||||
END_REGION MOTOR_VARIADOR
|
||||
|
||||
|
||||
ELSE
|
||||
#t_DispError := #t_DispManual := FALSE;
|
||||
END_CASE;
|
||||
|
||||
END_IF;
|
||||
|
||||
|
||||
|
||||
IF #t_DispError THEN
|
||||
|
||||
// Activacion de estado en error
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Alarma.Dispositivo := TRUE;
|
||||
#TipoError := 1;
|
||||
#DispNumero := #t_DispNumero;
|
||||
EXIT;
|
||||
|
||||
ELSIF #t_DispManual THEN
|
||||
|
||||
// Activacion de estado en manual
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Alarma.Manual := TRUE;
|
||||
#TipoError := 2;
|
||||
#DispNumero := #t_DispNumero;
|
||||
EXIT;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION COMPROBACION_DISPOSITIVOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION ASIGNACION_ESTADOS
|
||||
|
||||
// Asignacion de estado disponible
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.Disponible :=
|
||||
("DB6_ENTIDAD".ENT[#Entidad].Asignacion = 0)
|
||||
AND NOT "DB6_ENTIDAD".ENT[#Entidad].Alarma.Dispositivo
|
||||
AND NOT "DB6_ENTIDAD".ENT[#Entidad].Alarma.Manual
|
||||
AND NOT "DB6_ENTIDAD".ENT[#Entidad].Estado.EnProduccion
|
||||
AND NOT "DB6_ENTIDAD".ENT[#Entidad].Estado.EnCIP
|
||||
AND NOT "DB6_ENTIDAD".ENT[#Entidad].Estado.EnSIP
|
||||
AND NOT "DB6_ENTIDAD".ENT[#Entidad].Estado.EnStandby
|
||||
AND NOT "DB6_ENTIDAD".ENT[#Entidad].Estado.Capturada;
|
||||
|
||||
// Asignacion de codigo de estado
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 0;
|
||||
IF "DB6_ENTIDAD".ENT[#Entidad].Estado.EnProduccion THEN
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 1000;
|
||||
ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.EnCIP THEN
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 2000;
|
||||
ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.EnSIP THEN
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 3000;
|
||||
ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.EnStandby THEN
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 4000;
|
||||
ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.Sucia THEN
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 10000;
|
||||
ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.Limpia THEN
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 11000;
|
||||
ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.Esterilizada THEN
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 12000;
|
||||
END_IF;
|
||||
|
||||
IF (*ENT[#Entidad].Estado.CodEstado >= 1000 AND *)"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado <= 4999 THEN
|
||||
IF "DB6_ENTIDAD".ENT[#Entidad].Estado.ConProducto THEN
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado + 10;
|
||||
ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.ConAgua THEN
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado + 20;
|
||||
ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.Vacia THEN
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado + 30;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// Asignacion de codigo de producto
|
||||
IF "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado <> 0 THEN
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.Producto := #CodigoProducto;
|
||||
ELSE
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 0;
|
||||
END_IF;
|
||||
|
||||
END_REGION ASIGNACION_ESTADOS
|
||||
|
||||
ELSE
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Estado.Disponible := FALSE;
|
||||
"DB6_ENTIDAD".ENT[#Entidad].Asignacion := 0;
|
||||
|
||||
END_IF;
|
||||
|
||||
|
||||
END_REGION GESTION_ENTIDADES
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+4323
File diff suppressed because it is too large
Load Diff
+1382
File diff suppressed because it is too large
Load Diff
+3452
File diff suppressed because it is too large
Load Diff
+7528
File diff suppressed because it is too large
Load Diff
+8434
File diff suppressed because it is too large
Load Diff
+7521
File diff suppressed because it is too large
Load Diff
+8434
File diff suppressed because it is too large
Load Diff
+8224
File diff suppressed because it is too large
Load Diff
+7435
File diff suppressed because it is too large
Load Diff
+8434
File diff suppressed because it is too large
Load Diff
+7221
File diff suppressed because it is too large
Load Diff
+4421
File diff suppressed because it is too large
Load Diff
+4843
File diff suppressed because it is too large
Load Diff
+10008
File diff suppressed because it is too large
Load Diff
+8697
File diff suppressed because it is too large
Load Diff
+6867
File diff suppressed because it is too large
Load Diff
+8509
File diff suppressed because it is too large
Load Diff
+3947
File diff suppressed because it is too large
Load Diff
+6851
File diff suppressed because it is too large
Load Diff
+3947
File diff suppressed because it is too large
Load Diff
+2959
File diff suppressed because it is too large
Load Diff
+3817
File diff suppressed because it is too large
Load Diff
+3947
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,135 @@
|
||||
FUNCTION "FC17_ZC_GEST_ALM" : Void
|
||||
TITLE = FC17_ZC_GEST_ALM
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
VAR_INPUT
|
||||
PrimerCiclo : Bool; // Marca de primer ciclo de arranque de la CPU
|
||||
FechaHora {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
Usuario : String; // Usuario actual
|
||||
PInt : Array[*] of "UDT_ZC_PINT"; // Array de parametro entero
|
||||
IndexTraza : Int; // Indice de texto parametro para trazabilidad
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
ValorAnterior : Array[*] of Int; // Array de valores anteriores
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : DInt; // Variable para bucles FOR
|
||||
t_IndiceSuperior : DInt; // Indice superior del array
|
||||
t_IndiceInferior : DInt; // Indice inferior del array
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2026 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** DB Optimizado.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Función principal para la gestión de trazabilidad de los parámetros **enteros** del proceso.
|
||||
|
||||
Su objetivo principal es detectar cambios de valor en el array de parámetros y lanzar un registro de traza cuando esto sucede.
|
||||
|
||||
El bloque opera de la siguiente manera:
|
||||
|
||||
1. Calcula dinámicamente los límites superior e inferior del array de entrada.
|
||||
2. Si es el primer ciclo de ejecución de la CPU, inicializa los valores "anteriores" con los valores "actuales" para evitar falsos registros de traza iniciales.
|
||||
3. En ciclos normales, compara el valor actual de cada parámetro con su valor guardado en el ciclo anterior.
|
||||
4. Si detecta una diferencia, llama a la función `FC8_ZC_TRAZA_REGISTRO` para registrar el cambio y actualiza el valor anterior.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC8_ZC_TRAZA_REGISTRO` |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_PINT` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 2026-03-20 | (ABH) | Primera version. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION CALCULO_LIMITES_ARRAY
|
||||
|
||||
// Calculo de los limites del array, ya que la entrada del array de parametros es variable.
|
||||
#t_IndiceInferior := LOWER_BOUND(ARR := #PInt, DIM := 1);
|
||||
#t_IndiceSuperior := UPPER_BOUND(ARR := #PInt, DIM := 1);
|
||||
|
||||
END_REGION CALCULO_LIMITES_ARRAY
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION PRIMER_ARRANQUE
|
||||
|
||||
// En el primer arranque de la CPU, recorremos el array completo y almacenamos los valores actuales como valores anteriores en el arranque de la CPU.
|
||||
// Esto se realiza ya que los valores anteriores no son remanentes, para optimizar la memoria del PLC.
|
||||
IF #PrimerCiclo THEN
|
||||
|
||||
FOR #for_i := #t_IndiceInferior TO #t_IndiceSuperior DO
|
||||
#ValorAnterior[#for_i] := #PInt[#for_i].Valor;
|
||||
END_FOR;
|
||||
|
||||
// Salimos inmediatamente de la funcion, para realizar la gestion de los parametros con la CPU arrancada
|
||||
RETURN;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION PRIMER_ARRANQUE
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_PARAMETROS
|
||||
|
||||
// Gestion de los cambios de valor de los parametros. Si detecta un cambio, lanza la traza
|
||||
// y actualiza el valor anterior.
|
||||
FOR #for_i := #t_IndiceInferior TO #t_IndiceSuperior DO
|
||||
|
||||
// En caso de detectar cambio de valor
|
||||
IF #PInt[#for_i].Valor <> #ValorAnterior[#for_i] THEN
|
||||
|
||||
// Lanzamos la trazabilidad
|
||||
"FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHora,
|
||||
Registrar := 1,
|
||||
Categoria := "TRZ_CAT_26_PINT",
|
||||
User := #Usuario,
|
||||
CodInt_1 := #IndexTraza + DINT_TO_INT(#for_i - 1),
|
||||
CodInt_2 := "TRZ_SYS_PAR_VAL_ANT",
|
||||
CodInt_3 := "TRZ_SYS_PAR_VAL_NUE",
|
||||
CodInt_4 := 0,
|
||||
CodInt_5 := 0,
|
||||
CodReal_1 := #ValorAnterior[#for_i],
|
||||
CodReal_2 := #PInt[#for_i].Valor);
|
||||
|
||||
// Actualizamos el valor anterior
|
||||
#ValorAnterior[#for_i] := #PInt[#for_i].Valor;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_FOR;
|
||||
|
||||
END_REGION GESTION_PARAMETROS
|
||||
|
||||
|
||||
END_FUNCTION
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
DATA_BLOCK "DB11_INF"
|
||||
TITLE = DB11_INFORMES
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
NON_RETAIN
|
||||
VAR RETAIN
|
||||
Gestion { S7_SetPoint := 'False'} : "UDT_ZC_INF_GESTION";
|
||||
Buffer { S7_SetPoint := 'False'} : Array[0.."N_MAX_INF_BUFFER"] of "UDT_ZC_INF_DATOS";
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
Gestion.HabilitacionGeneral := TRUE;
|
||||
Gestion.EstadoConexion := TRUE;
|
||||
Gestion.OrdenIniciar := FALSE;
|
||||
Gestion.Etapa := 0;
|
||||
Gestion.SP_Tiempo := 10;
|
||||
Gestion.TiempoActual := 0;
|
||||
Gestion.NumeroMaxIntentos := 3;
|
||||
|
||||
END_DATA_BLOCK
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
FUNCTION_BLOCK "FB15051_ZC_INF_CPR"
|
||||
TITLE = FB15051_ZC_INF_CPR
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
VAR_INPUT
|
||||
GuardarDatos : Bool; // Orden guardar datos
|
||||
FinGuardarDatos : Bool; // Orden finalizar guardar datos
|
||||
FechaActual {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL; // Fecha y hora actual
|
||||
TipoProceso : Int; // Tipo de proceso
|
||||
Destino : Int; // Destino
|
||||
Producto : Int; // Producto
|
||||
Producto1Destino : Int; // Producto 1 en destino
|
||||
Producto2Destino : Int; // Producto 2 en destino
|
||||
Nombre : String[40]; // Nombre
|
||||
Matricula : String[10]; // Matricula
|
||||
LetraQ : String[10]; // Letra Q
|
||||
KilosSP : Real; // Kilos SP
|
||||
KilosDescargados : Real; // Cantidad
|
||||
DensidadMedia : LReal; // Densidad Media
|
||||
TempMediaDescarga : LReal; // Temperatura media en descarga
|
||||
TempMediaEnfriamiento : LReal; // Temperatura media enfriamiento
|
||||
EmpujeRealizado : Bool; // Empuje realizado
|
||||
AclaradoRealizado : Bool; // Aclarado realizado
|
||||
END_VAR
|
||||
|
||||
VAR_OUTPUT
|
||||
GuardarSQL : Bool;
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
Mux : "UDT_ZC_MUX"; // Variable Mux
|
||||
Informe : Array[*] of "UDT_ZC_INF_CPR_PROD"; // Informes de compacto
|
||||
END_VAR
|
||||
|
||||
VAR RETAIN
|
||||
s_OrdenGuardarDatos : Bool; // Orden adquirir datos de informes
|
||||
s_OrdenGuardarFechaInicio : Bool; // Orden guardar fecha de inicio y dezplazar informes
|
||||
END_VAR
|
||||
VAR
|
||||
s_OrdenGuardarFechaFin : Bool; // Orden guardar fecha de fin
|
||||
s_OrdenBorrarInforme : Bool; // Orden borrar informe
|
||||
s_NumeroBorrado : Int; // -1= Todos / Valor= Numero de registro
|
||||
END_VAR
|
||||
VAR RETAIN
|
||||
s_P_Trig_TomarFechaInicio : Bool; // Pulso
|
||||
s_P_Trig_TomarFechaFin : Bool; // Pulso
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int; // Variable para bucles FOR
|
||||
t_dummyInt : Int;
|
||||
t_IndiceSuperior : Int; // Indice superior del array
|
||||
t_IndiceInferior : Int; // Indice inferior del array
|
||||
t_InformeVacio : "UDT_ZC_INF_CPR_PROD";
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
ACTUAL : Int := 1;
|
||||
TIPO_DESCARGA_PARCIAL : Int := 1; // TIPO DE PROCESO DESCARGA PARCIAL
|
||||
TIPO_DESCARGA_TOTAL : Int := 2; // TIPO DE PROCESO DESCARGA TOTAL
|
||||
END_VAR
|
||||
|
||||
|
||||
BEGIN
|
||||
REGION DESCRIPCION
|
||||
(*
|
||||
###### (C)Copyright ZeusControl 2023 - 2026
|
||||
|
||||
---
|
||||
### Información del Sistema
|
||||
| Hardware Compatible | Entorno de Ingeniería |
|
||||
|---------------------|-----------------------|
|
||||
| PLC serie 1200/1500 | TIA Portal 18 |
|
||||
|
||||
---
|
||||
> **Restricciones:** Ninguna.
|
||||
|
||||
---
|
||||
### Descripción Funcional
|
||||
|
||||
Bloque de funcion para la gestión de informes de descargas de compacto de recepcion.
|
||||
|
||||
En ella se realizan las siguientes acciones:
|
||||
|
||||
- Cálculo dinámico de indices de array de informes.
|
||||
- Gestion de ordenes de inicio y fin informe.
|
||||
- Desplazamiento y captura de datos de informe.
|
||||
- Borrado de informes.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC15005_ZC_DTL_TO_ZC_FECHA` |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_MUX`, `UDT_ZC_INF_CPR_PROD` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 00.00.01 | 01.08.2023 | (HCR) | Primera version. |
|
||||
| 00.00.02 | 16.04.2024 | (ABH) | Se cambian los nombre a variables para estandarizar. |
|
||||
| 01.00.02 | 13.07.2026 | (ABH) | Cambio a SCL. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION LIMITES_Y_MULTIPLEXADO
|
||||
|
||||
// Calculo limites array de informes
|
||||
#t_IndiceInferior := DINT_TO_INT(LOWER_BOUND(ARR := #Informe, DIM := 1));
|
||||
#t_IndiceSuperior := DINT_TO_INT(UPPER_BOUND(ARR := #Informe, DIM := 1));
|
||||
|
||||
// Si no hay informes configurados, salimos inmediatamente.
|
||||
IF #t_IndiceInferior <= 0 THEN
|
||||
#Mux.Index := 0;
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
// Limites multiplexado
|
||||
IF #Mux.Index < 1 THEN
|
||||
#Mux.Index := 0;
|
||||
END_IF;
|
||||
IF #Mux.Index > #t_IndiceSuperior THEN
|
||||
#Mux.Index := #t_IndiceSuperior;
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES_Y_MULTIPLEXADO
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION ORDEN_INICIO_FIN
|
||||
|
||||
// Orden de inicio
|
||||
IF #GuardarDatos AND NOT #s_P_Trig_TomarFechaInicio THEN
|
||||
#s_OrdenGuardarFechaInicio := TRUE;
|
||||
#s_OrdenGuardarDatos := TRUE;
|
||||
END_IF;
|
||||
|
||||
// Orden de fin
|
||||
#GuardarSQL := FALSE;
|
||||
IF #FinGuardarDatos AND NOT #s_P_Trig_TomarFechaFin THEN
|
||||
#s_OrdenGuardarFechaFin := TRUE;
|
||||
#GuardarSQL := TRUE;
|
||||
END_IF;
|
||||
|
||||
// Estados anteriores
|
||||
#s_P_Trig_TomarFechaInicio := #GuardarDatos;
|
||||
#s_P_Trig_TomarFechaFin := #FinGuardarDatos;
|
||||
|
||||
END_REGION ORDEN_INICIO_FIN
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION ADQUISICION_DE_DATOS
|
||||
|
||||
// Con flanco de guardar datos fecha de inicio, desplazamos los registros y almacenamos la fecha de inicio
|
||||
IF #s_OrdenGuardarFechaInicio THEN
|
||||
|
||||
// Desplazamiento de datos
|
||||
#t_dummyInt := MOVE_BLK_VARIANT(SRC := #Informe, COUNT := INT_TO_UDINT(#t_IndiceSuperior - 1), SRC_INDEX := 0, DEST_INDEX := 1, DEST => #Informe);
|
||||
|
||||
// Tomar valor de fecha de inicio
|
||||
#Informe[#ACTUAL].FechaInicio := "FC15005_ZC_DTL_TO_ZC_FECHA"(#FechaActual);
|
||||
#s_OrdenGuardarFechaInicio := FALSE;
|
||||
END_IF;
|
||||
|
||||
// Tomar datos
|
||||
IF #s_OrdenGuardarDatos THEN
|
||||
#Informe[#ACTUAL].Descarga.TipoProceso := #TipoProceso;
|
||||
#Informe[#ACTUAL].Descarga.Destino := #Destino;
|
||||
IF #TipoProceso = #TIPO_DESCARGA_PARCIAL OR #TipoProceso = #TIPO_DESCARGA_TOTAL THEN
|
||||
#Informe[#ACTUAL].Descarga.Producto := #Producto;
|
||||
#Informe[#ACTUAL].Descarga.Producto1Destino := #Producto1Destino;
|
||||
#Informe[#ACTUAL].Descarga.Producto2Destino := #Producto2Destino;
|
||||
#Informe[#ACTUAL].Descarga.KilosSP := #KilosSP;
|
||||
#Informe[#ACTUAL].Descarga.KilosDescargados := #KilosDescargados;
|
||||
#Informe[#ACTUAL].Descarga.DensidadMedia := #DensidadMedia;
|
||||
#Informe[#ACTUAL].Descarga.TemperaturaMediaDescarga := #TempMediaDescarga;
|
||||
#Informe[#ACTUAL].Descarga.TemperaturaMediaEnfriamiento := #TempMediaEnfriamiento;
|
||||
#Informe[#ACTUAL].Descarga.Nombre := #Nombre;
|
||||
#Informe[#ACTUAL].Descarga.Matricula := #Matricula;
|
||||
#Informe[#ACTUAL].Descarga.LetraQ := #LetraQ;
|
||||
END_IF;
|
||||
#Informe[#ACTUAL].Descarga.EmpujeRealizado := #EmpujeRealizado;
|
||||
#Informe[#ACTUAL].Descarga.AclaradoRealizado := #AclaradoRealizado;
|
||||
END_IF;
|
||||
|
||||
// Con flanco de guardar datos fecha de fin almacenamos la fecha de fin y resetemos guardar datos
|
||||
IF #s_OrdenGuardarFechaFin THEN
|
||||
#Informe[#ACTUAL].FechaFin := "FC15005_ZC_DTL_TO_ZC_FECHA"(#FechaActual);
|
||||
#s_OrdenGuardarDatos := FALSE;
|
||||
#s_OrdenGuardarFechaFin := FALSE;
|
||||
END_IF;
|
||||
|
||||
END_REGION ADQUISICION_DE_DATOS
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION BORRADO_INFORMES
|
||||
|
||||
// Borrado de todos los registros
|
||||
IF #s_OrdenBorrarInforme THEN
|
||||
IF #s_NumeroBorrado = -1 OR #s_NumeroBorrado = 0 THEN
|
||||
|
||||
// Borrado total
|
||||
FOR #for_i := 1 TO #t_IndiceSuperior DO
|
||||
#Informe[#for_i] := #t_InformeVacio;
|
||||
END_FOR;
|
||||
|
||||
ELSIF #s_NumeroBorrado >= 1 AND #s_NumeroBorrado < #t_IndiceSuperior THEN
|
||||
|
||||
// Borrado registro especifico
|
||||
#Informe[#s_NumeroBorrado] := #t_InformeVacio;
|
||||
|
||||
// Desplazamiento de datos
|
||||
#t_dummyInt := MOVE_BLK_VARIANT(SRC := #Informe,
|
||||
COUNT := INT_TO_UDINT(#t_IndiceSuperior - #s_NumeroBorrado),
|
||||
SRC_INDEX := #s_NumeroBorrado,
|
||||
DEST_INDEX := #s_NumeroBorrado - 1,
|
||||
DEST => #Informe);
|
||||
|
||||
// Borrado del ultimo registro
|
||||
#Informe[#t_IndiceSuperior] := #t_InformeVacio;
|
||||
|
||||
ELSIF #s_NumeroBorrado = #t_IndiceSuperior THEN
|
||||
|
||||
// Borrado de ultimo registro
|
||||
#Informe[#s_NumeroBorrado] := #t_InformeVacio;
|
||||
|
||||
END_IF;
|
||||
|
||||
#s_OrdenBorrarInforme := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
|
||||
END_REGION BORRADO_INFORMES
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
FUNCTION_BLOCK "FB15052_ZC_INF_PROD_MEM"
|
||||
TITLE = FB15052_ZC_INF_PROD_MEM
|
||||
{ S7_Optimized_Access := 'TRUE' }
|
||||
AUTHOR : ABH
|
||||
FAMILY : ZeusControl
|
||||
VERSION : 1.0
|
||||
//Bloque de gestion para adquisicion de datos para informe de produccion maquina membranas
|
||||
VAR_INPUT
|
||||
OrdenInicioInforme { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool; // Orden inicio informe
|
||||
OrdenFinInforme : Bool; // Orden fin informe
|
||||
EnProduccion : Bool; // En produccion
|
||||
FechaHoraActual {InstructionName := 'DTL'; LibVersion := '1.0'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : DTL; // Fecha y hora actual
|
||||
Producto : Int; // Producto
|
||||
DestinoConcentrado : Int; // Destino concentrado
|
||||
DestinoPermeado : Int; // Destino permeado
|
||||
LitrosEntrada : LReal; // Totalizador litros Entrada
|
||||
LitrosConcentrado : LReal; // Totalizador litros Concentrado
|
||||
Brix : LReal; // Media Brix en produccion
|
||||
Fcv : Real; // Media FCV En produccion
|
||||
TempEntrada : LReal; // Media temperatura entrada
|
||||
TempConcentrado : LReal; // Media temperatura concentrado
|
||||
TempPermeado : LReal; // Media temperatura permeado
|
||||
TiempoProduccion : "UDT_ZC_CONTADOR_TIEMPO"; // Tiempo Produccion
|
||||
END_VAR
|
||||
|
||||
VAR_IN_OUT
|
||||
Informe : Array[*] of "UDT_ZC_INF_PROD_MEM";
|
||||
END_VAR
|
||||
|
||||
VAR
|
||||
s_OrdenInicioInforme { S7_SetPoint := 'True'} : Bool; // Orden inicio informe
|
||||
s_OrdenFinInforme { S7_SetPoint := 'True'} : Bool; // Orden fin informe
|
||||
END_VAR
|
||||
VAR RETAIN
|
||||
s_oldInicio { S7_SetPoint := 'True'} : Bool; // Estado anterior inicio
|
||||
s_oldFin { S7_SetPoint := 'True'} : Bool; // Estado anterior fin
|
||||
END_VAR
|
||||
VAR
|
||||
s_OrdenBorrarInforme : Bool; // Orden borrar informe
|
||||
s_NumeroBorrado : Int; // -1= Todos / Valor= Numero de registro
|
||||
END_VAR
|
||||
|
||||
VAR_TEMP
|
||||
for_i : Int;
|
||||
t_dummyInt : Int;
|
||||
t_IndiceSuperior : Int; // Indice superior del array
|
||||
t_IndiceInferior : Int; // Indice inferior del array
|
||||
t_InformeVacio : "UDT_ZC_INF_PROD_MEM";
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
ACTUAL : Int := 1;
|
||||
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
|
||||
Bloque de funcion que implementa la gestión de los datos de informe de producción de una máquina de membranas, manteniendo un histórico de hasta `#N_REGISTROS` producciones con todos los datos relevantes del proceso (volúmenes, Brix, FCV, temperaturas, tiempos, destinos y producto) para su trazabilidad y consulta desde el sistema de supervisión.
|
||||
|
||||
Funcionalidades principales:
|
||||
- Detección de flanco ascendente en las órdenes `#OrdenInicioInforme` y `#OrdenFinInforme` mediante las variables estáticas `#s_P_Trig_Inicio` y `#s_P_Trig_Fin`, generando los pulsos internos `#s_OrdenInicioInforme` y `#s_OrdenFinInforme`.
|
||||
- Inicialización de informe: al recibir `#s_OrdenInicioInforme` se desplazan los informes existentes una posición hacia abajo mediante `MOVE_BLK_VARIANT`, se reinicializan los campos del nuevo informe activo (`#Informe[#ACTUAL]`: fechas, tiempo de producción, destinos, producto, litros, Brix, FCV y temperaturas) y se almacena la fecha/hora de inicio mediante la conversión realizada por `FC15005_ZC_DTL_TO_ZC_FECHA`.
|
||||
- Datos en curso: mientras `#EnProduccion` está activo, se copian en `#Informe[#ACTUAL]` los valores de proceso en tiempo real: tiempo de producción, destinos de concentrado y permeado, código de producto, litros (entrada, concentrado y permeado por diferencia), Brix, FCV y las tres temperaturas (concentrado, permeado y entrada), aplicando `LREAL_TO_REAL` para adaptar la precisión al tipo de dato del UDT.
|
||||
- Fin de informe: al detectar `#s_OrdenFinInforme` se registra la fecha/hora de fin en `#Informe[#ACTUAL].FechaFin`.
|
||||
- Borrado masivo: la entrada `#s_Borrar` permite limpiar completamente todos los registros del array, inicializando fechas, tiempos, litros, Brix, FCV, temperatura de concentrado y código de producto a sus valores neutros. La propia variable de orden se autodesactiva tras la operación.
|
||||
|
||||
> **Restricciones:** PLC serie 1200/1500.
|
||||
|
||||
---
|
||||
### Dependencias Requeridas
|
||||
| Tipo | Elementos |
|
||||
|------|-----------|
|
||||
| FC | `FC15005_ZC_DTL_TO_ZC_FECHA` |
|
||||
| FB | - |
|
||||
| DB | - |
|
||||
| UDT | `UDT_ZC_CONTADOR_TIEMPO`, `UDT_ZC_INF_PROD_MEM` |
|
||||
|
||||
---
|
||||
### Historial de Cambios
|
||||
| Versión | Fecha | Técnico | Cambios |
|
||||
|----------|------------|---------|---------|
|
||||
| 01.00.00 | 24.05.2023 | (ABH) | Primera versión. |
|
||||
| 01.00.01 | 16.02.2024 | (ABH) | Cambios en datos de REAL a LREAL para coincidir con UDT. |
|
||||
| 01.00.02 | 23.05.2024 | (HCR) | Se añaden temperaturas de entrada, destinos concentrado y destinos permeado. |
|
||||
| 01.00.03 | 03.07.2026 | (ABH) | Cambio a SCL. |
|
||||
*)
|
||||
END_REGION DESCRIPCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION LIMITES
|
||||
|
||||
// Calculo limites array de informes
|
||||
#t_IndiceInferior := DINT_TO_INT(LOWER_BOUND(ARR := #Informe, DIM := 1));
|
||||
#t_IndiceSuperior := DINT_TO_INT(UPPER_BOUND(ARR := #Informe, DIM := 1));
|
||||
|
||||
// Si no hay informes configurados, salimos inmediatamente.
|
||||
IF #t_IndiceInferior <= 0 THEN
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
END_REGION LIMITES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION GESTION_ORDENES
|
||||
|
||||
// Orden de inicio
|
||||
#s_OrdenInicioInforme := #OrdenInicioInforme AND NOT #s_oldInicio;
|
||||
|
||||
// Orden de fin
|
||||
#s_OrdenFinInforme := #OrdenFinInforme AND NOT #s_oldFin;
|
||||
|
||||
// Estados anteriores
|
||||
#s_oldInicio := #OrdenInicioInforme;
|
||||
#s_oldFin := #OrdenFinInforme;
|
||||
|
||||
END_REGION GESTION_ORDENES
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION INICIALIZACION
|
||||
|
||||
// Con flanco de inicio informe, desplazamos los registros, reinicializamos los datos y almacenamos la fecha y hora de inicio, todo en la poisicion 1
|
||||
IF #s_OrdenInicioInforme THEN
|
||||
|
||||
// Desplazamiento de datos
|
||||
#t_dummyInt := MOVE_BLK_VARIANT(SRC := #Informe, COUNT := INT_TO_UDINT(#t_IndiceSuperior - 1), SRC_INDEX := 0, DEST_INDEX := 1, DEST => #Informe);
|
||||
|
||||
// Reinicializacion de los datos
|
||||
#Informe[#ACTUAL] := #t_InformeVacio;
|
||||
|
||||
// Guardado de fecha y hora actual
|
||||
#Informe[#ACTUAL].FechaInicio := "FC15005_ZC_DTL_TO_ZC_FECHA"(FechaDTL := #FechaHoraActual);
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION INICIALIZACION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION DATOS_DURANTE_PRODUCCION
|
||||
|
||||
// Se guardan los datos durante la produccion
|
||||
IF #EnProduccion THEN
|
||||
|
||||
#Informe[#ACTUAL].TiempoProduccion.Hora := #TiempoProduccion.Hora;
|
||||
#Informe[#ACTUAL].TiempoProduccion.Minuto := #TiempoProduccion.Minuto;
|
||||
#Informe[#ACTUAL].TiempoProduccion.Segundo := #TiempoProduccion.Segundo;
|
||||
|
||||
#Informe[#ACTUAL].DestinoConcentrado := #DestinoConcentrado;
|
||||
#Informe[#ACTUAL].DestinoPermeado := #DestinoPermeado;
|
||||
#Informe[#ACTUAL].Producto := #Producto;
|
||||
|
||||
#Informe[#ACTUAL].LitrosEntrada := LREAL_TO_REAL(#LitrosEntrada);
|
||||
#Informe[#ACTUAL].LitrosConcentrado := LREAL_TO_REAL(#LitrosConcentrado);
|
||||
#Informe[#ACTUAL].LitrosPermeado := LREAL_TO_REAL(#LitrosEntrada - #LitrosConcentrado);
|
||||
|
||||
#Informe[#ACTUAL].Brix := LREAL_TO_REAL(#Brix);
|
||||
#Informe[#ACTUAL].FCV := #Fcv;
|
||||
|
||||
#Informe[#ACTUAL].TempConcentrado := LREAL_TO_REAL(#TempConcentrado);
|
||||
#Informe[#ACTUAL].TempPermeado := LREAL_TO_REAL(#TempPermeado);
|
||||
#Informe[#ACTUAL].TempEntrada := LREAL_TO_REAL(#TempEntrada);
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION DATOS_DURANTE_PRODUCCION
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION FIN_INFORME
|
||||
|
||||
// Se guardan los datos durante la produccion
|
||||
IF #s_OrdenFinInforme THEN
|
||||
|
||||
// Guardado de fecha y hora actual
|
||||
#Informe[#ACTUAL].FechaFin := "FC15005_ZC_DTL_TO_ZC_FECHA"(FechaDTL := #FechaHoraActual);
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION FIN_INFORME
|
||||
|
||||
|
||||
// ==========================================================================================================
|
||||
REGION BORRADO_DATOS
|
||||
|
||||
// Borrado de todos los registros
|
||||
IF #s_OrdenBorrarInforme THEN
|
||||
IF #s_NumeroBorrado = -1 OR #s_NumeroBorrado = 0 THEN
|
||||
|
||||
FOR #for_i := 1 TO #t_IndiceSuperior DO
|
||||
#Informe[#for_i] := #t_InformeVacio;
|
||||
END_FOR;
|
||||
|
||||
ELSIF #s_NumeroBorrado >= 1 AND #s_NumeroBorrado < #t_IndiceSuperior THEN
|
||||
|
||||
// Borrado registro especifico
|
||||
#Informe[#s_NumeroBorrado] := #t_InformeVacio;
|
||||
|
||||
// Desplazamiento de datos
|
||||
#t_dummyInt := MOVE_BLK_VARIANT(SRC := #Informe,
|
||||
COUNT := INT_TO_UDINT(#t_IndiceSuperior - #s_NumeroBorrado),
|
||||
SRC_INDEX := #s_NumeroBorrado,
|
||||
DEST_INDEX := #s_NumeroBorrado - 1,
|
||||
DEST => #Informe);
|
||||
|
||||
// Borrado del ultimo registro
|
||||
#Informe[#t_IndiceSuperior] := #t_InformeVacio;
|
||||
|
||||
ELSIF #s_NumeroBorrado = #t_IndiceSuperior THEN
|
||||
|
||||
// Borrado de ultimo registro
|
||||
#Informe[#s_NumeroBorrado] := #t_InformeVacio;
|
||||
|
||||
END_IF;
|
||||
|
||||
#s_OrdenBorrarInforme := FALSE;
|
||||
|
||||
END_IF;
|
||||
|
||||
END_REGION BORRADO_DATOS
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user