Reorganizacion de libreria.

This commit is contained in:
2026-07-20 08:15:06 +02:00
parent e0b9f4a206
commit 2b9dbc1f27
280 changed files with 9799 additions and 9398 deletions
@@ -0,0 +1,40 @@
DATA_BLOCK "DB2000_ED"
TITLE = DB2000_ED
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : HCR
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos entrada digital
VAR RETAIN
ED { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_ED"] of "UDT_ZC_DISP_ED"; // .
END_VAR
VAR
Agrup { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_AGRUP"] of "UDT_ZC_DISP_AGRUP";
NumDispositivos : Int;
END_VAR
BEGIN
ED[0].Estado_AutoMan := FALSE;
ED[0].Estado_Activado := FALSE;
ED[0].Estado_EntradaCanal := FALSE;
ED[0].Orden_ActivarManual := FALSE;
ED[0].Config_Habilitar := FALSE;
ED[0].Config_HabilitarRetardoAct := FALSE;
ED[0].Config_HabilitarRetardoDes := FALSE;
ED[0].Config_HabilitarInvertir := FALSE;
ED[0].Aux_oldActivado := FALSE;
ED[0].Aux_oldAutoMan := FALSE;
ED[0].Config_GrupoAlarma := 0;
ED[0].Config_DirEntradaByte := 0;
ED[0].Config_DirEntradaBit := 0;
ED[0].Tiempos_SPTiempoAct := 3;
ED[0].Tiempos_SPTiempoDes := 3;
ED[0].Tiempos_TiempoAct := 0;
ED[0].Tiempos_TiempoDes := 0;
Agrup[0].AlgunaEnManual := FALSE;
Agrup[0].AlgunaAlarma := FALSE;
Agrup[0].NuevaAlarma := FALSE;
END_DATA_BLOCK
@@ -0,0 +1,53 @@
DATA_BLOCK "DB2001_EA"
TITLE = DB2001_EA
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos entrada analogica
VAR RETAIN
EA { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_EA"] of "UDT_ZC_DISP_EA"; // .
END_VAR
VAR
Agrup { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_AGRUP"] of "UDT_ZC_DISP_AGRUP";
NumDispositivos : Int;
END_VAR
BEGIN
EA[0].Estado_ValorIngenieria := 0.0;
EA[0].Estado_AutoMan := FALSE;
EA[0].Alarmas_Min := FALSE;
EA[0].Alarmas_Max := FALSE;
EA[0].Alarmas_HiloRoto := FALSE;
EA[0].Alarmas_Lectura := FALSE;
EA[0].Alarmas_Parametros := FALSE;
EA[0].Alarmas_General := FALSE;
EA[0].Config_Habilitar := FALSE;
EA[0].Config_HabilitarAlarmaMin := FALSE;
EA[0].Config_HabilitarAlarmaMax := FALSE;
EA[0].Config_HisteresisTipo := FALSE;
EA[0].Aux_oldAlarma := FALSE;
EA[0].Aux_oldAutoMan := FALSE;
EA[0].Config_TipoAcceso := 0;
EA[0].Config_GrupoAlarma := 0;
EA[0].Estado_ValorTarjeta := 0;
EA[0].Estado_Lectura := 16#0000;
EA[0].Orden_ConsignaManual := 0.0;
EA[0].Config_DireccionEntradaByte := 0;
EA[0].Config_EscaladoMinTarjeta := 0;
EA[0].Config_EscaladoMaxTarjeta := 27648;
EA[0].Config_EscaladoMinIngenieria := 0.0;
EA[0].Config_EscaladoMaxIngenieria := 100.0;
EA[0].Config_EscaladoOffset := 0.0;
EA[0].Config_ErrorMinIngenieria := 0.0;
EA[0].Config_ErrorMaxIngenieria := 100.0;
EA[0].Config_ErrorMinHisteresis := 0.0;
EA[0].Config_ErrorMaxHisteresis := 0.0;
EA[0].Aux_Estado := 0;
Agrup[0].AlgunaEnManual := FALSE;
Agrup[0].AlgunaAlarma := FALSE;
Agrup[0].NuevaAlarma := FALSE;
END_DATA_BLOCK
@@ -0,0 +1,42 @@
DATA_BLOCK "DB2005_SD"
TITLE = DB2005_SD
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos salida digital
VAR RETAIN
SD { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_SD"] of "UDT_ZC_DISP_SD"; // .
END_VAR
VAR
Agrup { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_AGRUP"] of "UDT_ZC_DISP_AGRUP";
NumDispositivos : Int;
END_VAR
BEGIN
SD[0].Estado_AutoMan := FALSE;
SD[0].Estado_Activado := FALSE;
SD[0].Estado_Enclavado := FALSE;
SD[0].Orden_ActivarManual := FALSE;
SD[0].Orden_ActivarAuto := FALSE;
SD[0].Config_Habilitar := FALSE;
SD[0].Config_HabilitarRetardoAct := FALSE;
SD[0].Config_HabilitarRetardoDes := FALSE;
SD[0].Config_HabilitarInvertir := FALSE;
SD[0].Aux_oldActivado := FALSE;
SD[0].Aux_oldAutoMan := FALSE;
SD[0].Estado_SeguridadOk := TRUE;
SD[0].Config_GrupoAlarma := 0;
SD[0].Config_DireccionSalidaByte := 0;
SD[0].Config_DireccionSalidaBit := 0;
SD[0].Tiempos_SetPointTiempoAct := 3;
SD[0].Tiempos_SetPointTiempoDes := 3;
SD[0].Tiempos_TiempoAct := 0;
SD[0].Tiempos_TiempoDes := 0;
Agrup[0].AlgunaEnManual := FALSE;
Agrup[0].AlgunaAlarma := FALSE;
Agrup[0].NuevaAlarma := FALSE;
END_DATA_BLOCK
@@ -0,0 +1,51 @@
DATA_BLOCK "DB2006_SA"
TITLE = DB2006_SA
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloique de datos Salida Analogica
VAR RETAIN
SA { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_SA"] of "UDT_ZC_DISP_SA"; // .
END_VAR
VAR
Agrup { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_AGRUP"] of "UDT_ZC_DISP_AGRUP";
NumDispositivos : Int;
END_VAR
BEGIN
SA[0].Estado_AutoMan := FALSE;
SA[0].Estado_Enclavado := FALSE;
SA[0].Alarmas_Min := FALSE;
SA[0].Alarmas_Max := FALSE;
SA[0].Alarmas_Escritura := FALSE;
SA[0].Alarmas_Parametros := FALSE;
SA[0].Alarmas_General := FALSE;
SA[0].Config_Habilitar := FALSE;
SA[0].Config_HabilitarAlarmaMin := FALSE;
SA[0].Config_HabilitarAlarmaMax := FALSE;
SA[0].Aux_oldAlarma := FALSE;
SA[0].Aux_oldAutoMan := FALSE;
SA[0].Estado_SeguridadOk := TRUE;
SA[0].Config_GrupoAlarma := 0;
SA[0].Estado_ValorTarjeta := 0;
SA[0].Estado_Escritura := 16#0000;
SA[0].Orden_ConsignaManual := 0.0;
SA[0].Orden_ConsignaAuto := 0.0;
SA[0].Orden_ConsignaEnclavado := 0.0;
SA[0].Config_DireccionSalidaByte := 0;
SA[0].Config_EscaladoMinTarjeta := 0;
SA[0].Config_EscaladoMaxTarjeta := 27648;
SA[0].Config_EscaladoMinIngenieria := 0.0;
SA[0].Config_EscaladoMaxIngenieria := 0.0;
SA[0].Config_EscaladoOffset := 0.0;
SA[0].Config_ErrorMinIngenieria := 0.0;
SA[0].Config_ErrorMaxIngenieria := 0.0;
SA[0].Aux_Estado := 0;
Agrup[0].AlgunaEnManual := FALSE;
Agrup[0].AlgunaAlarma := FALSE;
Agrup[0].NuevaAlarma := FALSE;
END_DATA_BLOCK
@@ -0,0 +1,57 @@
DATA_BLOCK "DB2010_V"
TITLE = DB2010_V
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloique de datos valvula.
VAR RETAIN
V { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_V"] of "UDT_ZC_DISP_V"; // .
END_VAR
VAR
Agrup { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_AGRUP"] of "UDT_ZC_DISP_AGRUP";
NumDispositivos : Int;
END_VAR
BEGIN
V[0].Estado_AutoMan := FALSE;
V[0].Estado_Activado := FALSE;
V[0].Estado_Enclavado := FALSE;
V[0].Estado_SeguridadOk := TRUE;
V[0].Estado_EntradaRetornoReposo := FALSE;
V[0].Estado_EntradaRetornoTrabajo := FALSE;
V[0].Alarmas_Reposo := FALSE;
V[0].Alarmas_Trabajo := FALSE;
V[0].Alarmas_Mantenimiento := FALSE;
V[0].Alarmas_Doble := FALSE;
V[0].Alarmas_General := FALSE;
V[0].Orden_ActivarManual := FALSE;
V[0].Orden_ActivarAuto := TRUE;
V[0].Orden_ResetCiclos := FALSE;
V[0].Config_Habilitar := FALSE;
V[0].Config_HabilitarRetornoReposo := TRUE;
V[0].Config_HabilitarInvertirReposo := FALSE;
V[0].Config_HabilitarRetornoTrabajo := TRUE;
V[0].Config_HabilitarInvertirTrabajo := FALSE;
V[0].Config_HabilitarMantenimiento := FALSE;
V[0].Aux_oldActivado := FALSE;
V[0].Aux_oldAlarma := FALSE;
V[0].Aux_oldAutoMan := FALSE;
V[0].Config_GrupoAlarma := 0;
V[0].Config_DireccionSalidaByte := 0;
V[0].Config_DireccionSalidaBit := 0;
V[0].Config_DireccionRetReposoByte := 0;
V[0].Config_DireccionRetReposoBit := 0;
V[0].Config_DireccionRetTrabajoByte := 0;
V[0].Config_DireccionRetTrabajoBit := 0;
V[0].Tiempos_SetPointTiempoAlarma := 10;
V[0].Tiempos_Alarma := 0;
V[0].Tiempos_SetPointCiclos := 1000;
V[0].Tiempos_Ciclos := 0;
Agrup[0].AlgunaEnManual := FALSE;
Agrup[0].AlgunaAlarma := FALSE;
Agrup[0].NuevaAlarma := FALSE;
END_DATA_BLOCK
@@ -0,0 +1,56 @@
DATA_BLOCK "DB2015_M"
TITLE = DB2015_M
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos motor.
VAR RETAIN
M { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_M"] of "UDT_ZC_DISP_M"; // .
END_VAR
VAR
Agrup { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_AGRUP"] of "UDT_ZC_DISP_AGRUP";
NumDispositivos : Int;
END_VAR
BEGIN
M[0].Estado_AutoMan := FALSE;
M[0].Estado_Activado := FALSE;
M[0].Estado_Enclavado := FALSE;
M[0].Estado_SeguridadOk := TRUE;
M[0].Estado_EntradaTermico := FALSE;
M[0].Estado_EntradaConfMarcha := FALSE;
M[0].Alarmas_Termico := FALSE;
M[0].Alarmas_ConfirmacionMarcha := FALSE;
M[0].Alarmas_Mantenimiento := FALSE;
M[0].Alarmas_General := FALSE;
M[0].Orden_ActivarManual := FALSE;
M[0].Orden_ActivarAuto := FALSE;
M[0].Orden_ResetHoras := FALSE;
M[0].Config_Habilitar := FALSE;
M[0].Config_HabilitarRetornoTermico := TRUE;
M[0].Config_HabilitarInvertirTermico := FALSE;
M[0].Config_HabilitarRetornoConfMarcha := TRUE;
M[0].Config_HabilitarInvertirConfMarcha := FALSE;
M[0].Config_HabilitarMantenimiento := FALSE;
M[0].Aux_oldActivado := FALSE;
M[0].Aux_oldAlarma := FALSE;
M[0].Aux_oldAutoMan := FALSE;
M[0].Config_GrupoAlarma := 0;
M[0].Config_DireccionSalidaByte := 0;
M[0].Config_DireccionSalidaBit := 0;
M[0].Config_DireccionRetTermicoByte := 0;
M[0].Config_DireccionRetTermicoBit := 0;
M[0].Config_DireccionRetConfMarchaByte := 0;
M[0].Config_DireccionRetConfMarchaBit := 0;
M[0].Tiempos_SetPointTiempoAlarma := 10;
M[0].Tiempos_Alarma := 0;
M[0].Tiempos_SetPointMantenimiento := 2000.0;
M[0].Tiempos_Mantenimiento := 0.0;
Agrup[0].AlgunaEnManual := FALSE;
Agrup[0].AlgunaAlarma := FALSE;
Agrup[0].NuevaAlarma := FALSE;
END_DATA_BLOCK
@@ -0,0 +1,65 @@
DATA_BLOCK "DB2016_M_VF"
TITLE = DB2016_M_VF
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos motor variador.
VAR RETAIN
M_VF { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_M_VF"] of "UDT_ZC_DISP_M_VF"; // .
END_VAR
VAR
Agrup { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_AGRUP"] of "UDT_ZC_DISP_AGRUP";
NumDispositivos : Int;
END_VAR
BEGIN
M_VF[0].Estado_AutoMan := FALSE;
M_VF[0].Estado_Activado := FALSE;
M_VF[0].Estado_Enclavado := FALSE;
M_VF[0].Estado_SeguridadOk := TRUE;
M_VF[0].Estado_EntradaTermico := FALSE;
M_VF[0].Estado_EntradaConfMarcha := FALSE;
M_VF[0].Alarmas_Termico := FALSE;
M_VF[0].Alarmas_ConfirmacionMarcha := FALSE;
M_VF[0].Alarmas_Mantenimiento := FALSE;
M_VF[0].Alarmas_Escritura := FALSE;
M_VF[0].Alarmas_Parametros := FALSE;
M_VF[0].Alarmas_General := FALSE;
M_VF[0].Orden_ActivarManual := FALSE;
M_VF[0].Orden_ActivarAuto := FALSE;
M_VF[0].Orden_ResetHoras := FALSE;
M_VF[0].Config_Habilitar := FALSE;
M_VF[0].Config_HabilitarRetornoTermico := TRUE;
M_VF[0].Config_HabilitarInvertirTermico := FALSE;
M_VF[0].Config_HabilitarRetornoConfMarcha := TRUE;
M_VF[0].Config_HabilitarInvertirConfMarcha := FALSE;
M_VF[0].Config_HabilitarMantenimiento := FALSE;
M_VF[0].Config_HabilitarAlarmaEscrituraSalida := FALSE;
M_VF[0].Aux_oldActivado := FALSE;
M_VF[0].Aux_oldAlarma := FALSE;
M_VF[0].Aux_oldAutoMan := FALSE;
M_VF[0].Estado_Escritura := 16#0000;
M_VF[0].Config_GrupoAlarma := 0;
M_VF[0].Orden_ConsignaManual := 0.0;
M_VF[0].Orden_ConsignaAuto := 0.0;
M_VF[0].Config_DireccionSalidaByte := 0;
M_VF[0].Config_DireccionSalidaBit := 0;
M_VF[0].Config_DireccionRetTermicoByte := 0;
M_VF[0].Config_DireccionRetTermicoBit := 0;
M_VF[0].Config_DireccionRetConfMarchaByte := 0;
M_VF[0].Config_DireccionRetConfMarchaBit := 0;
M_VF[0].Config_DireccionSalidaAnalogicaByte := 0;
M_VF[0].Config_EscaladoMinIngenieria := 0.0;
M_VF[0].Config_EscaladoMaxIngenieria := 50.0;
M_VF[0].Tiempos_SetPointAlarma := 10;
M_VF[0].Tiempos_Alarma := 0;
M_VF[0].Tiempos_SetPointMantenimiento := 2000.0;
M_VF[0].Tiempos_Mantenimiento := 0.0;
Agrup[0].AlgunaEnManual := FALSE;
Agrup[0].AlgunaAlarma := FALSE;
Agrup[0].NuevaAlarma := FALSE;
END_DATA_BLOCK
@@ -0,0 +1,62 @@
DATA_BLOCK "DB2017_M_SINA"
TITLE = DB2017_M_SINA
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Dispositivo Motor Sinamics
VAR RETAIN
M_SINA { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_M_SINA"] of "UDT_ZC_DISP_M_SINA"; // .
END_VAR
VAR
Agrup { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_AGRUP"] of "UDT_ZC_DISP_AGRUP";
NumDispositivos : Int;
END_VAR
BEGIN
M_SINA[0].Estado_AutoMan := FALSE;
M_SINA[0].Estado_Activado := FALSE;
M_SINA[0].Estado_Enclavado := FALSE;
M_SINA[0].Estado_PermisoInvertirSentido := FALSE;
M_SINA[0].Estado_RetornoTermico := FALSE;
M_SINA[0].Estado_EjeBloqueado := FALSE;
M_SINA[0].Estado_EjeHabilitado := FALSE;
M_SINA[0].Alarmas_Termico := FALSE;
M_SINA[0].Alarmas_SinaSpeed := FALSE;
M_SINA[0].Alarmas_Mantenimiento := FALSE;
M_SINA[0].Alarmas_General := FALSE;
M_SINA[0].Orden_ActivarManual := FALSE;
M_SINA[0].Orden_ActivarAuto := FALSE;
M_SINA[0].Orden_ResetHoras := FALSE;
M_SINA[0].Orden_ResetFallos := FALSE;
M_SINA[0].Orden_SeleccionInverso := FALSE;
M_SINA[0].Config_Habilitar := FALSE;
M_SINA[0].Config_HabilitarRetornoTermico := TRUE;
M_SINA[0].Config_HabilitarInvertirTermico := TRUE;
M_SINA[0].Config_HabilitarMantenimiento := FALSE;
M_SINA[0].Aux_oldActivado := FALSE;
M_SINA[0].Aux_oldAlarma := FALSE;
M_SINA[0].Aux_oldAutoMan := FALSE;
M_SINA[0].Estado_SeguridadOk := TRUE;
M_SINA[0].Config_GrupoAlarma := 0;
M_SINA[0].Estado_VelocidadSalida := 0.0;
M_SINA[0].Estado_Estado := 16#0000;
M_SINA[0].Estado_CodigoFallo := 16#0000;
M_SINA[0].Orden_ConsignaManual := 0.0;
M_SINA[0].Orden_ConsignaAuto := 0.0;
M_SINA[0].Config_DireccionRetTermicoByte := 0;
M_SINA[0].Config_DireccionRetTermicoBit := 0;
M_SINA[0].Config_VelocidadMin := 0.0;
M_SINA[0].Config_VelocidadMax := 0.0;
M_SINA[0].Config_K_Velocidad := 50.0;
M_SINA[0].Tiempos_SetPointTiempoAlarma := 10;
M_SINA[0].Tiempos_Alarma := 0;
M_SINA[0].Tiempos_SetPointMantenimiento := 2000.0;
M_SINA[0].Tiempos_Mantenimiento := 0.0;
Agrup[0].AlgunaEnManual := TRUE;
Agrup[0].AlgunaAlarma := FALSE;
Agrup[0].NuevaAlarma := FALSE;
END_DATA_BLOCK
@@ -0,0 +1,47 @@
DATA_BLOCK "DB2025_TOT"
TITLE = DB2025_TOT
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos de totalizadores.
VAR RETAIN
TOT { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_TOT"] of "UDT_ZC_DISP_TOT"; // .
END_VAR
VAR
TiempoCiclo { S7_SetPoint := 'False'} : "UDT_ZC_TIEMPO_CICLO";
NumDispositivos : Int;
END_VAR
BEGIN
TOT[0].Hmi_Estado := 0;
TOT[0].Estado_Pulso := FALSE;
TOT[0].Estado_Valor := 0.0;
TOT[0].Orden_Activar := FALSE;
TOT[0].Orden_ResetParcial := FALSE;
TOT[0].Orden_ResetTotal := FALSE;
TOT[0].Orden_ResetProceso := FALSE;
TOT[0].Config_Habilitar := FALSE;
TOT[0].Config_Tipo := FALSE;
TOT[0].Config_IncrDecr := FALSE;
TOT[0].Aux_oldActivado := FALSE;
TOT[0].Aux_oldAlarma := FALSE;
TOT[0].Estado_DesbordeTotal := 0;
TOT[0].Estado_DesbordeParcial := 0;
TOT[0].Config_DireccionEntradaByte := 0;
TOT[0].Config_DireccionEntradaBit := 0;
TOT[0].Config_LitroXPulso := 0.0;
TOT[0].Aux_AcuTiempo := 0.0;
TOT[0].Estado_Total := 0.0;
TOT[0].Estado_Parcial := 0.0;
TOT[0].Estado_Proceso := 0.0;
TOT[0].Aux_TotalizadorMem := 0.0;
TiempoCiclo.Actual := 28.50767;
TiempoCiclo.Min := 150.0;
TiempoCiclo.Max := 0.0;
TiempoCiclo.auxMem := 3.12728198846045E-308;
TiempoCiclo.Reset := FALSE;
END_DATA_BLOCK
@@ -0,0 +1,17 @@
DATA_BLOCK "DB2026_FF"
TITLE = DB2026_FF
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
NON_RETAIN
//Bloque de datos dispositivo Flip Flop
VAR RETAIN
FF { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_FF"] of "UDT_ZC_DISP_FF";
END_VAR
BEGIN
END_DATA_BLOCK
@@ -0,0 +1,17 @@
DATA_BLOCK "DB2027_FF_SEC"
TITLE = DB2027_FF_SEC
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
NON_RETAIN
//Bloque de datos de Flip Flop secuencial.
VAR RETAIN
FF_SEC { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_FF_SEC"] of "UDT_ZC_DISP_FF_SEC";
END_VAR
BEGIN
END_DATA_BLOCK
@@ -0,0 +1,19 @@
DATA_BLOCK "DB2028_TEMP"
TITLE = DB2028_TEMP
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Dispositivos temporizadores TON, TOF, TONR y TP
VAR RETAIN
TON { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_TON"] of "UDT_ZC_DISP_TON"; // TON
TOF { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_TOF"] of "UDT_ZC_DISP_TOF"; // TOF
TONR { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_TONR"] of "UDT_ZC_DISP_TONR"; // TONR
TP { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_TP"] of "UDT_ZC_DISP_TP"; // TP
END_VAR
BEGIN
END_DATA_BLOCK
@@ -0,0 +1,56 @@
DATA_BLOCK "DB2035_PID"
TITLE = DB2035_PID
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : AketzaBarragues
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos dispositivo PID
VAR RETAIN
PID { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_PID"] of "UDT_ZC_DISP_PID"; // .
Agrup : Array[0.."N_MAX_DISP_AGRUP"] of "UDT_ZC_DISP_AGRUP";
END_VAR
VAR
NumDispositivos : Int;
END_VAR
BEGIN
PID[0].Estado_AutoMan := TRUE;
PID[0].Estado_ModeActivate := FALSE;
PID[0].Orden_Forzar := FALSE;
PID[0].Orden_ActivarAuto := FALSE;
PID[0].Orden_Ack := FALSE;
PID[0].Orden_Reset := FALSE;
PID[0].Alarmas_Error := FALSE;
PID[0].Config_InvertirControl := FALSE;
PID[0].Config_TipoEntrada := FALSE;
PID[0].Aux_oldForzar := FALSE;
PID[0].Estado_PV := 0.0;
PID[0].Estado_ValorSalida := 0.0;
PID[0].Estado_PV_0_100 := 0.0;
PID[0].Estado_SP_0_100 := 0.0;
PID[0].Estado_Error_SP_PV_0_100 := 0.0;
PID[0].Estado_Mode := 3;
PID[0].Estado_EstadoPID := 3;
PID[0].Orden_ConsignaAuto := 0.0;
PID[0].Orden_ConsignaForzado := 0.0;
PID[0].Alarmas_ErrorBits := 16#0000_0000;
PID[0].Config_Gain := 0.15;
PID[0].Config_Ti := 3.0;
PID[0].Config_Td := 0.0;
PID[0].Config_LimiteSuperiorSalida := 100.0;
PID[0].Config_LimiteInferiorSalida := 0.0;
PID[0].Config_LimiteSuperiorEntrada := 15000.0;
PID[0].Config_LimiteInferiorEntrada := 0.0;
PID[0].Aux_oldMode := 3;
PID[0].Aux_SP_Manual := 0.0;
PID[0].Aux_SP_Auto := 0.0;
PID[0].Aux_oldGain := 0.15;
PID[0].Aux_oldTi := 3.0;
PID[0].Aux_oldTd := 0.0;
Agrup[0].AlgunaEnManual := TRUE;
Agrup[0].AlgunaAlarma := FALSE;
Agrup[0].NuevaAlarma := FALSE;
END_DATA_BLOCK
@@ -0,0 +1,17 @@
DATA_BLOCK "DB2037_MEDIA"
TITLE = DB2037_MEDIA
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
NON_RETAIN
//Bloque de datos medias
VAR RETAIN
MEDIA { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_MEDIA"] of "UDT_ZC_DISP_MEDIA";
END_VAR
BEGIN
END_DATA_BLOCK
@@ -0,0 +1,17 @@
DATA_BLOCK "DB2038_MEDIA_VOL"
TITLE = DB2038_MEDIA_VOLUMEN
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
NON_RETAIN
//Bloque de datos medias en funcion del caudal/volumen
VAR RETAIN
MEDIA_VOL { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_MEDIA_VOLUMEN"] of "UDT_ZC_DISP_MEDIA_VOLUMEN";
END_VAR
BEGIN
END_DATA_BLOCK
@@ -0,0 +1,24 @@
DATA_BLOCK "DB2040_TQ"
TITLE = DB2040_TQ
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : HCR
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos dispositivo TQ.
VAR RETAIN
TQ { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_TQ"] of "UDT_ZC_DISP_TQ"; // .
END_VAR
VAR
Agrup { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_AGRUP"] of "UDT_ZC_DISP_AGRUP";
NumDispositivos : Int;
END_VAR
BEGIN
TQ[0].Config_HabilitarControlTemp := TRUE;
TQ[0].Config_HabilitarAgitador := TRUE;
TQ[0].Tiempo_RetTanqueVacio.SP := 5;
Agrup[0].AlgunaEnManual := FALSE;
END_DATA_BLOCK
@@ -0,0 +1,56 @@
DATA_BLOCK "DB2041_TQ_AE"
TITLE = DB2041_TQ_AE
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : HCR
FAMILY : ZeusControl
VERSION : 1.0
VAR RETAIN
TQ_AE { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_TQ_AE"] of "UDT_ZC_DISP_TQ_AE"; // .
END_VAR
VAR
Agrup { S7_SetPoint := 'False'} : Array[0.."N_MAX_DISP_AGRUP"] of "UDT_ZC_DISP_AGRUP";
NumDispositivos : Int;
END_VAR
BEGIN
TQ_AE[0].Estado_AutoMan := FALSE;
TQ_AE[0].Orden_Manual := FALSE;
TQ_AE[0].Orden_CIP := FALSE;
TQ_AE[0].Orden_Produccion := FALSE;
TQ_AE[0].Orden_Vaciado := FALSE;
TQ_AE[0].Alarma_PresionAlta := FALSE;
TQ_AE[0].Alarma_PresionBaja := FALSE;
TQ_AE[0].Alarma_Configuracion := FALSE;
TQ_AE[0].Salida_ValvulaVenteo := FALSE;
TQ_AE[0].Salida_ValvulaEsteril := FALSE;
TQ_AE[0].Salida_ValvulaDucha := FALSE;
TQ_AE[0].Aux_DuchaFlipActivo := FALSE;
TQ_AE[0].Aux_DuchaFlopActivo := TRUE;
TQ_AE[0].Aux_DuchaFlanco := FALSE;
TQ_AE[0].Aux_DuchaSalidaFlip := FALSE;
TQ_AE[0].Aux_DuchaSalidaFlop := FALSE;
TQ_AE[0].Config_Habilitar := FALSE;
TQ_AE[0].Config_HabilitarAlarmas := FALSE;
TQ_AE[0].Aux_oldOrdenManual := FALSE;
TQ_AE[0].Aux_oldAutoMan := FALSE;
TQ_AE[0].Config_GrupoAlarma := 0;
TQ_AE[0].Estado_ValorPresion := 0.0;
TQ_AE[0].Config_PresionMaxTrabajo := 0.0;
TQ_AE[0].Config_PresionMinTrabajo := 0.0;
TQ_AE[0].Config_PresionMaxAlarma := 0.0;
TQ_AE[0].Config_PresionMinAlarma := 0.0;
TQ_AE[0].Tiempos_SetPointAlarmaMaxPresion := 0;
TQ_AE[0].Tiempos_SetPointAlarmaMinPresion := 0;
TQ_AE[0].Tiempos_AlarmaMaxPresion := 0;
TQ_AE[0].Tiempos_AlarmaMinPresion := 0;
TQ_AE[0].Tiempos_SetPointFlipDucha := 0;
TQ_AE[0].Tiempos_SetPointFlopDucha := 0;
TQ_AE[0].Tiempos_DuchaTiempoFlip := 0;
TQ_AE[0].Tiempos_DuchaTiempoFlop := 0;
Agrup[0].AlgunaEnManual := TRUE;
Agrup[0].AlgunaAlarma := FALSE;
Agrup[0].NuevaAlarma := FALSE;
END_DATA_BLOCK
@@ -0,0 +1,37 @@
DATA_BLOCK "DB2717_INST_M_SINA"
TITLE = DB2717_INST_M_SINA
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
NON_RETAIN
//Instancia bloque de funcion FB2017_M_SINA
"FB2017_ZC_M_SINA"
BEGIN
Pulso1seg := FALSE;
Simulacion := FALSE;
Ack := FALSE;
SeguridadesOK := TRUE;
HWIDSTW[0] := 0;
HWIDZSW[0] := 0;
SinaSpeed[0].EnableAxis := FALSE;
SinaSpeed[0].AckError := FALSE;
SinaSpeed[0].SpeedSp := 0.0;
SinaSpeed[0].RefSpeed := 0.0;
SinaSpeed[0].ConfigAxis := 16#003F;
SinaSpeed[0].HWIDSTW := 0;
SinaSpeed[0].HWIDZSW := 0;
SinaSpeed[0].AxisEnabled := FALSE;
SinaSpeed[0].Lockout := FALSE;
SinaSpeed[0].ActVelocity := 0.0;
SinaSpeed[0].Error := FALSE;
SinaSpeed[0].Status := 16#0000;
SinaSpeed[0].DiagId := 16#0000;
SinaSpeed[0].STW1 := 16#0000;
SinaSpeed[0].VelocitySP := 16#0000;
SinaSpeed[0].ZSW1 := 16#0000;
SinaSpeed[0].VelocityAV := 16#0000;
END_DATA_BLOCK
@@ -0,0 +1,19 @@
DATA_BLOCK "DB2800_ED_MUX"
TITLE = DB2800_ED_MUX
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : HCR
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos multiplexado entrada digital
STRUCT
Mux : Struct
NumDispositivos : Int;
Scada { S7_SetPoint := 'False'} : Array[0.."N_MAX_SCADA"] of "UDT_ZC_DISP_MUX_ED"; // .
END_STRUCT;
END_STRUCT;
BEGIN
END_DATA_BLOCK
@@ -0,0 +1,19 @@
DATA_BLOCK "DB2801_EA_MUX"
TITLE = DB2801_EA_MUX
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos multiplexado entrada analogica
STRUCT
Mux : Struct
NumDispositivos : Int;
Scada { S7_SetPoint := 'False'} : Array[0.."N_MAX_SCADA"] of "UDT_ZC_DISP_MUX_EA"; // .
END_STRUCT;
END_STRUCT;
BEGIN
END_DATA_BLOCK
@@ -0,0 +1,41 @@
DATA_BLOCK "DB2805_SD_MUX"
TITLE = DB2805_SD_MUX
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos multiplexado salida digital
STRUCT
Mux : Struct
NumDispositivos : Int;
Scada { S7_SetPoint := 'False'} : Array[0.."N_MAX_SCADA"] of "UDT_ZC_DISP_MUX_SD"; // .
END_STRUCT;
END_STRUCT;
BEGIN
Mux.Scada[0].Habilitar := TRUE;
Mux.Scada[0].Index := 0;
Mux.Scada[0].oldIndex := 0;
Mux.Scada[0].SD.Estado_AutoMan := FALSE;
Mux.Scada[0].SD.Estado_Activado := FALSE;
Mux.Scada[0].SD.Estado_Enclavado := FALSE;
Mux.Scada[0].SD.Orden_ActivarManual := FALSE;
Mux.Scada[0].SD.Orden_ActivarAuto := FALSE;
Mux.Scada[0].SD.Config_Habilitar := FALSE;
Mux.Scada[0].SD.Config_HabilitarRetardoAct := FALSE;
Mux.Scada[0].SD.Config_HabilitarRetardoDes := FALSE;
Mux.Scada[0].SD.Config_HabilitarInvertir := FALSE;
Mux.Scada[0].SD.Aux_oldActivado := FALSE;
Mux.Scada[0].SD.Aux_oldAutoMan := FALSE;
Mux.Scada[0].SD.Estado_SeguridadOk := TRUE;
Mux.Scada[0].SD.Config_GrupoAlarma := 0;
Mux.Scada[0].SD.Config_DireccionSalidaByte := 0;
Mux.Scada[0].SD.Config_DireccionSalidaBit := 0;
Mux.Scada[0].SD.Tiempos_SetPointTiempoAct := 3;
Mux.Scada[0].SD.Tiempos_SetPointTiempoDes := 3;
Mux.Scada[0].SD.Tiempos_TiempoAct := 0;
Mux.Scada[0].SD.Tiempos_TiempoDes := 0;
END_DATA_BLOCK
@@ -0,0 +1,19 @@
DATA_BLOCK "DB2806_SA_MUX"
TITLE = DB2806_SA_MUX
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloique de datos multiplexado Salida Analogica
STRUCT
Mux : Struct
NumDispositivos : Int;
Scada { S7_SetPoint := 'False'} : Array[0.."N_MAX_SCADA"] of "UDT_ZC_DISP_MUX_SA"; // .
END_STRUCT;
END_STRUCT;
BEGIN
END_DATA_BLOCK
@@ -0,0 +1,19 @@
DATA_BLOCK "DB2810_V_MUX"
TITLE = DB2810_V_MUX
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloique de datos multiplexado valvula.
STRUCT
Mux : Struct
NumDispositivos : Int;
Scada { S7_SetPoint := 'False'} : Array[0.."N_MAX_SCADA"] of "UDT_ZC_DISP_MUX_V"; // .
END_STRUCT;
END_STRUCT;
BEGIN
END_DATA_BLOCK
@@ -0,0 +1,55 @@
DATA_BLOCK "DB2815_M_MUX"
TITLE = DB2815_M_MUX
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos multiplexado motor.
STRUCT
Mux : Struct
NumDispositivos : Int;
Scada { S7_SetPoint := 'False'} : Array[0.."N_MAX_SCADA"] of "UDT_ZC_DISP_MUX_M"; // .
END_STRUCT;
END_STRUCT;
BEGIN
Mux.Scada[0].Habilitar := TRUE;
Mux.Scada[0].Index := 43;
Mux.Scada[0].oldIndex := 43;
Mux.Scada[0].M.Estado_AutoMan := FALSE;
Mux.Scada[0].M.Estado_Activado := FALSE;
Mux.Scada[0].M.Estado_Enclavado := FALSE;
Mux.Scada[0].M.Estado_SeguridadOk := TRUE;
Mux.Scada[0].M.Estado_EntradaTermico := FALSE;
Mux.Scada[0].M.Estado_EntradaConfMarcha := FALSE;
Mux.Scada[0].M.Alarmas_Termico := FALSE;
Mux.Scada[0].M.Alarmas_ConfirmacionMarcha := FALSE;
Mux.Scada[0].M.Alarmas_Mantenimiento := FALSE;
Mux.Scada[0].M.Alarmas_General := FALSE;
Mux.Scada[0].M.Orden_ActivarManual := FALSE;
Mux.Scada[0].M.Orden_ActivarAuto := FALSE;
Mux.Scada[0].M.Orden_ResetHoras := FALSE;
Mux.Scada[0].M.Config_Habilitar := TRUE;
Mux.Scada[0].M.Config_HabilitarRetornoTermico := FALSE;
Mux.Scada[0].M.Config_HabilitarInvertirTermico := FALSE;
Mux.Scada[0].M.Config_HabilitarRetornoConfMarcha := TRUE;
Mux.Scada[0].M.Config_HabilitarInvertirConfMarcha := FALSE;
Mux.Scada[0].M.Config_HabilitarMantenimiento := FALSE;
Mux.Scada[0].M.Aux_oldActivado := FALSE;
Mux.Scada[0].M.Aux_oldAlarma := FALSE;
Mux.Scada[0].M.Aux_oldAutoMan := FALSE;
Mux.Scada[0].M.Config_GrupoAlarma := 4;
Mux.Scada[0].M.Config_DireccionSalidaByte := 501;
Mux.Scada[0].M.Config_DireccionSalidaBit := 0;
Mux.Scada[0].M.Config_DireccionRetTermicoByte := 0;
Mux.Scada[0].M.Config_DireccionRetTermicoBit := 0;
Mux.Scada[0].M.Config_DireccionRetConfMarchaByte := 501;
Mux.Scada[0].M.Config_DireccionRetConfMarchaBit := 5;
Mux.Scada[0].M.Tiempos_SetPointTiempoAlarma := 10;
Mux.Scada[0].M.Tiempos_Alarma := 0;
Mux.Scada[0].M.Tiempos_SetPointMantenimiento := 2000.0;
Mux.Scada[0].M.Tiempos_Mantenimiento := 18.71946;
END_DATA_BLOCK
@@ -0,0 +1,64 @@
DATA_BLOCK "DB2816_M_VF_MUX"
TITLE = DB2816_M_VF
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos motor multiplexado variador.
STRUCT
Mux : Struct
NumDispositivos : Int;
Scada { S7_SetPoint := 'False'} : Array[0.."N_MAX_SCADA"] of "UDT_ZC_DISP_MUX_M_VF"; // .
END_STRUCT;
END_STRUCT;
BEGIN
Mux.Scada[0].Habilitar := TRUE;
Mux.Scada[0].Index := 5;
Mux.Scada[0].oldIndex := 5;
Mux.Scada[0].M_VF.Estado_AutoMan := FALSE;
Mux.Scada[0].M_VF.Estado_Activado := FALSE;
Mux.Scada[0].M_VF.Estado_Enclavado := FALSE;
Mux.Scada[0].M_VF.Estado_SeguridadOk := TRUE;
Mux.Scada[0].M_VF.Estado_EntradaTermico := FALSE;
Mux.Scada[0].M_VF.Estado_EntradaConfMarcha := FALSE;
Mux.Scada[0].M_VF.Alarmas_Termico := FALSE;
Mux.Scada[0].M_VF.Alarmas_ConfirmacionMarcha := FALSE;
Mux.Scada[0].M_VF.Alarmas_Mantenimiento := FALSE;
Mux.Scada[0].M_VF.Alarmas_Escritura := FALSE;
Mux.Scada[0].M_VF.Alarmas_Parametros := FALSE;
Mux.Scada[0].M_VF.Alarmas_General := FALSE;
Mux.Scada[0].M_VF.Orden_ActivarManual := FALSE;
Mux.Scada[0].M_VF.Orden_ActivarAuto := FALSE;
Mux.Scada[0].M_VF.Orden_ResetHoras := FALSE;
Mux.Scada[0].M_VF.Config_Habilitar := TRUE;
Mux.Scada[0].M_VF.Config_HabilitarRetornoTermico := TRUE;
Mux.Scada[0].M_VF.Config_HabilitarInvertirTermico := TRUE;
Mux.Scada[0].M_VF.Config_HabilitarRetornoConfMarcha := TRUE;
Mux.Scada[0].M_VF.Config_HabilitarInvertirConfMarcha := FALSE;
Mux.Scada[0].M_VF.Config_HabilitarMantenimiento := FALSE;
Mux.Scada[0].M_VF.Config_HabilitarAlarmaEscrituraSalida := TRUE;
Mux.Scada[0].M_VF.Aux_oldActivado := FALSE;
Mux.Scada[0].M_VF.Aux_oldAlarma := FALSE;
Mux.Scada[0].M_VF.Aux_oldAutoMan := FALSE;
Mux.Scada[0].M_VF.Estado_Escritura := 16#0000;
Mux.Scada[0].M_VF.Config_GrupoAlarma := 0;
Mux.Scada[0].M_VF.Orden_ConsignaManual := 31.75312;
Mux.Scada[0].M_VF.Orden_ConsignaAuto := 0.0;
Mux.Scada[0].M_VF.Config_DireccionSalidaByte := 100;
Mux.Scada[0].M_VF.Config_DireccionSalidaBit := 6;
Mux.Scada[0].M_VF.Config_DireccionRetTermicoByte := 101;
Mux.Scada[0].M_VF.Config_DireccionRetTermicoBit := 3;
Mux.Scada[0].M_VF.Config_DireccionRetConfMarchaByte := 101;
Mux.Scada[0].M_VF.Config_DireccionRetConfMarchaBit := 2;
Mux.Scada[0].M_VF.Config_DireccionSalidaAnalogicaByte := 2110;
Mux.Scada[0].M_VF.Config_EscaladoMinIngenieria := 0.0;
Mux.Scada[0].M_VF.Config_EscaladoMaxIngenieria := 100.0;
Mux.Scada[0].M_VF.Tiempos_SetPointAlarma := 10;
Mux.Scada[0].M_VF.Tiempos_Alarma := 0;
Mux.Scada[0].M_VF.Tiempos_SetPointMantenimiento := 2000.0;
Mux.Scada[0].M_VF.Tiempos_Mantenimiento := 12.90666;
END_DATA_BLOCK
@@ -0,0 +1,61 @@
DATA_BLOCK "DB2817_M_SINA_MUX"
TITLE = DB2817_M_SINA_MUX
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos multiplexado dispositivo Motor Sinamics
STRUCT
Mux : Struct
NumDispositivos : Int;
Scada { S7_SetPoint := 'False'} : Array[0.."N_MAX_SCADA"] of "UDT_ZC_DISP_MUX_M_SINA"; // .
END_STRUCT;
END_STRUCT;
BEGIN
Mux.Scada[0].Habilitar := FALSE;
Mux.Scada[0].Index := 0;
Mux.Scada[0].oldIndex := 0;
Mux.Scada[0].M_SINA.Estado_AutoMan := FALSE;
Mux.Scada[0].M_SINA.Estado_Activado := FALSE;
Mux.Scada[0].M_SINA.Estado_Enclavado := FALSE;
Mux.Scada[0].M_SINA.Estado_PermisoInvertirSentido := FALSE;
Mux.Scada[0].M_SINA.Estado_RetornoTermico := FALSE;
Mux.Scada[0].M_SINA.Estado_EjeBloqueado := FALSE;
Mux.Scada[0].M_SINA.Estado_EjeHabilitado := FALSE;
Mux.Scada[0].M_SINA.Alarmas_Termico := FALSE;
Mux.Scada[0].M_SINA.Alarmas_SinaSpeed := FALSE;
Mux.Scada[0].M_SINA.Alarmas_Mantenimiento := FALSE;
Mux.Scada[0].M_SINA.Alarmas_General := FALSE;
Mux.Scada[0].M_SINA.Orden_ActivarManual := FALSE;
Mux.Scada[0].M_SINA.Orden_ActivarAuto := FALSE;
Mux.Scada[0].M_SINA.Orden_ResetHoras := FALSE;
Mux.Scada[0].M_SINA.Orden_ResetFallos := FALSE;
Mux.Scada[0].M_SINA.Orden_SeleccionInverso := FALSE;
Mux.Scada[0].M_SINA.Config_Habilitar := FALSE;
Mux.Scada[0].M_SINA.Config_HabilitarRetornoTermico := TRUE;
Mux.Scada[0].M_SINA.Config_HabilitarInvertirTermico := TRUE;
Mux.Scada[0].M_SINA.Config_HabilitarMantenimiento := FALSE;
Mux.Scada[0].M_SINA.Aux_oldActivado := FALSE;
Mux.Scada[0].M_SINA.Aux_oldAlarma := FALSE;
Mux.Scada[0].M_SINA.Aux_oldAutoMan := FALSE;
Mux.Scada[0].M_SINA.Estado_SeguridadOk := TRUE;
Mux.Scada[0].M_SINA.Config_GrupoAlarma := 0;
Mux.Scada[0].M_SINA.Estado_VelocidadSalida := 0.0;
Mux.Scada[0].M_SINA.Estado_Estado := 16#0000;
Mux.Scada[0].M_SINA.Estado_CodigoFallo := 16#0000;
Mux.Scada[0].M_SINA.Orden_ConsignaManual := 0.0;
Mux.Scada[0].M_SINA.Orden_ConsignaAuto := 0.0;
Mux.Scada[0].M_SINA.Config_DireccionRetTermicoByte := 0;
Mux.Scada[0].M_SINA.Config_DireccionRetTermicoBit := 0;
Mux.Scada[0].M_SINA.Config_VelocidadMin := 0.0;
Mux.Scada[0].M_SINA.Config_VelocidadMax := 0.0;
Mux.Scada[0].M_SINA.Config_K_Velocidad := 50.0;
Mux.Scada[0].M_SINA.Tiempos_SetPointTiempoAlarma := 10;
Mux.Scada[0].M_SINA.Tiempos_Alarma := 0;
Mux.Scada[0].M_SINA.Tiempos_SetPointMantenimiento := 2000.0;
Mux.Scada[0].M_SINA.Tiempos_Mantenimiento := 0.0;
END_DATA_BLOCK
@@ -0,0 +1,44 @@
DATA_BLOCK "DB2825_TOT_MUX"
TITLE = DB2825_TOT_MUX
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos multiplexado de totalizadores.
STRUCT
Mux : Struct
NumDispositivos : Int;
Scada { S7_SetPoint := 'False'} : Array[0.."N_MAX_SCADA"] of "UDT_ZC_DISP_MUX_TOT"; // .
END_STRUCT;
END_STRUCT;
BEGIN
Mux.Scada[0].Habilitar := TRUE;
Mux.Scada[0].Index := 44;
Mux.Scada[0].oldIndex := 44;
Mux.Scada[0].TOT.Hmi_Estado := 0;
Mux.Scada[0].TOT.Estado_Pulso := TRUE;
Mux.Scada[0].TOT.Estado_Valor := 7.595486;
Mux.Scada[0].TOT.Orden_Activar := FALSE;
Mux.Scada[0].TOT.Orden_ResetParcial := FALSE;
Mux.Scada[0].TOT.Orden_ResetTotal := FALSE;
Mux.Scada[0].TOT.Orden_ResetProceso := FALSE;
Mux.Scada[0].TOT.Config_Habilitar := TRUE;
Mux.Scada[0].TOT.Config_Tipo := FALSE;
Mux.Scada[0].TOT.Config_IncrDecr := FALSE;
Mux.Scada[0].TOT.Aux_oldActivado := TRUE;
Mux.Scada[0].TOT.Aux_oldAlarma := FALSE;
Mux.Scada[0].TOT.Estado_DesbordeTotal := 0;
Mux.Scada[0].TOT.Estado_DesbordeParcial := 0;
Mux.Scada[0].TOT.Config_DireccionEntradaByte := 609;
Mux.Scada[0].TOT.Config_DireccionEntradaBit := 7;
Mux.Scada[0].TOT.Config_LitroXPulso := 1.0;
Mux.Scada[0].TOT.Aux_AcuTiempo := 1.0;
Mux.Scada[0].TOT.Estado_Total := 3129.0;
Mux.Scada[0].TOT.Estado_Parcial := 3129.0;
Mux.Scada[0].TOT.Estado_Proceso := 250.0;
Mux.Scada[0].TOT.Aux_TotalizadorMem := 3127.0;
END_DATA_BLOCK
@@ -0,0 +1,56 @@
DATA_BLOCK "DB2835_PID_MUX"
TITLE = DB2835_PID_MUX
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : AketzaBarragues
FAMILY : ZeusControl
VERSION : 1.0
NON_RETAIN
//Bloque de datos multiplexado dispositivo PID
STRUCT
Mux : Struct
NumDispositivos : Int;
Scada { S7_SetPoint := 'False'} : Array[0.."N_MAX_SCADA"] of "UDT_ZC_DISP_MUX_PID"; // .
END_STRUCT;
END_STRUCT;
BEGIN
Mux.Scada[0].Habilitar := TRUE;
Mux.Scada[0].Index := 0;
Mux.Scada[0].oldIndex := 0;
Mux.Scada[0].PID.Estado_AutoMan := TRUE;
Mux.Scada[0].PID.Estado_ModeActivate := FALSE;
Mux.Scada[0].PID.Orden_Forzar := FALSE;
Mux.Scada[0].PID.Orden_ActivarAuto := FALSE;
Mux.Scada[0].PID.Orden_Ack := FALSE;
Mux.Scada[0].PID.Orden_Reset := FALSE;
Mux.Scada[0].PID.Alarmas_Error := FALSE;
Mux.Scada[0].PID.Config_InvertirControl := FALSE;
Mux.Scada[0].PID.Config_TipoEntrada := FALSE;
Mux.Scada[0].PID.Aux_oldForzar := FALSE;
Mux.Scada[0].PID.Estado_PV := 0.0;
Mux.Scada[0].PID.Estado_ValorSalida := 0.0;
Mux.Scada[0].PID.Estado_PV_0_100 := 0.0;
Mux.Scada[0].PID.Estado_SP_0_100 := 0.0;
Mux.Scada[0].PID.Estado_Error_SP_PV_0_100 := 0.0;
Mux.Scada[0].PID.Estado_Mode := 3;
Mux.Scada[0].PID.Estado_EstadoPID := 3;
Mux.Scada[0].PID.Orden_ConsignaAuto := 0.0;
Mux.Scada[0].PID.Orden_ConsignaForzado := 0.0;
Mux.Scada[0].PID.Alarmas_ErrorBits := 16#0000_0000;
Mux.Scada[0].PID.Config_Gain := 0.15;
Mux.Scada[0].PID.Config_Ti := 3.0;
Mux.Scada[0].PID.Config_Td := 0.0;
Mux.Scada[0].PID.Config_LimiteSuperiorSalida := 100.0;
Mux.Scada[0].PID.Config_LimiteInferiorSalida := 0.0;
Mux.Scada[0].PID.Config_LimiteSuperiorEntrada := 15000.0;
Mux.Scada[0].PID.Config_LimiteInferiorEntrada := 0.0;
Mux.Scada[0].PID.Aux_oldMode := 3;
Mux.Scada[0].PID.Aux_SP_Manual := 0.0;
Mux.Scada[0].PID.Aux_SP_Auto := 0.0;
Mux.Scada[0].PID.Aux_oldGain := 0.15;
Mux.Scada[0].PID.Aux_oldTi := 3.0;
Mux.Scada[0].PID.Aux_oldTd := 0.0;
END_DATA_BLOCK
@@ -0,0 +1,23 @@
DATA_BLOCK "DB2840_TQ_MUX"
TITLE = DB2840_TQ_MUX
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : HCR
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos multiplexado dispositivo TQ.
STRUCT
Mux : Struct
NumDispositivos : Int;
Scada { S7_SetPoint := 'False'} : Array[0.."N_MAX_SCADA"] of "UDT_ZC_DISP_MUX_TQ"; // .
END_STRUCT;
END_STRUCT;
BEGIN
Mux.Scada[0].Habilitar := TRUE;
Mux.Scada[0].TQ.Config_HabilitarControlTemp := TRUE;
Mux.Scada[0].TQ.Config_HabilitarAgitador := TRUE;
Mux.Scada[0].TQ.Tiempo_RetTanqueVacio.SP := 5;
END_DATA_BLOCK
@@ -0,0 +1,56 @@
DATA_BLOCK "DB2841_TQ_AE_MUX"
TITLE = DB2841_TQ_AE_MUX
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : HCR
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de datos multiplexado tanque aire esteril
STRUCT
Mux : Struct
NumDispositivos : Int;
Scada { S7_SetPoint := 'False'} : Array[0.."N_MAX_SCADA"] of "UDT_ZC_DISP_MUX_TQ_AE"; // .
END_STRUCT;
END_STRUCT;
BEGIN
Mux.Scada[0].Habilitar := TRUE;
Mux.Scada[0].Index := 0;
Mux.Scada[0].oldIndex := 0;
Mux.Scada[0].TQ_AE.Estado_AutoMan := FALSE;
Mux.Scada[0].TQ_AE.Orden_Manual := FALSE;
Mux.Scada[0].TQ_AE.Orden_CIP := FALSE;
Mux.Scada[0].TQ_AE.Orden_Produccion := FALSE;
Mux.Scada[0].TQ_AE.Orden_Vaciado := FALSE;
Mux.Scada[0].TQ_AE.Alarma_PresionAlta := FALSE;
Mux.Scada[0].TQ_AE.Alarma_PresionBaja := FALSE;
Mux.Scada[0].TQ_AE.Alarma_Configuracion := FALSE;
Mux.Scada[0].TQ_AE.Salida_ValvulaVenteo := FALSE;
Mux.Scada[0].TQ_AE.Salida_ValvulaEsteril := FALSE;
Mux.Scada[0].TQ_AE.Salida_ValvulaDucha := FALSE;
Mux.Scada[0].TQ_AE.Aux_DuchaFlipActivo := FALSE;
Mux.Scada[0].TQ_AE.Aux_DuchaFlopActivo := TRUE;
Mux.Scada[0].TQ_AE.Aux_DuchaFlanco := FALSE;
Mux.Scada[0].TQ_AE.Aux_DuchaSalidaFlip := FALSE;
Mux.Scada[0].TQ_AE.Aux_DuchaSalidaFlop := FALSE;
Mux.Scada[0].TQ_AE.Config_Habilitar := FALSE;
Mux.Scada[0].TQ_AE.Config_HabilitarAlarmas := FALSE;
Mux.Scada[0].TQ_AE.Aux_oldOrdenManual := FALSE;
Mux.Scada[0].TQ_AE.Aux_oldAutoMan := FALSE;
Mux.Scada[0].TQ_AE.Config_GrupoAlarma := 0;
Mux.Scada[0].TQ_AE.Estado_ValorPresion := 0.0;
Mux.Scada[0].TQ_AE.Config_PresionMaxTrabajo := 0.0;
Mux.Scada[0].TQ_AE.Config_PresionMinTrabajo := 0.0;
Mux.Scada[0].TQ_AE.Config_PresionMaxAlarma := 0.0;
Mux.Scada[0].TQ_AE.Config_PresionMinAlarma := 0.0;
Mux.Scada[0].TQ_AE.Tiempos_SetPointAlarmaMaxPresion := 0;
Mux.Scada[0].TQ_AE.Tiempos_SetPointAlarmaMinPresion := 0;
Mux.Scada[0].TQ_AE.Tiempos_AlarmaMaxPresion := 0;
Mux.Scada[0].TQ_AE.Tiempos_AlarmaMinPresion := 0;
Mux.Scada[0].TQ_AE.Tiempos_SetPointFlipDucha := 0;
Mux.Scada[0].TQ_AE.Tiempos_SetPointFlopDucha := 0;
Mux.Scada[0].TQ_AE.Tiempos_DuchaTiempoFlip := 0;
Mux.Scada[0].TQ_AE.Tiempos_DuchaTiempoFlop := 0;
END_DATA_BLOCK
@@ -1,321 +0,0 @@
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
@@ -1,355 +0,0 @@
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
@@ -1,317 +0,0 @@
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
@@ -1,354 +0,0 @@
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
@@ -1,391 +0,0 @@
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
@@ -1,385 +0,0 @@
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
@@ -1,432 +0,0 @@
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
@@ -1,412 +0,0 @@
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
@@ -1,318 +0,0 @@
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
@@ -1,387 +0,0 @@
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
@@ -1,539 +0,0 @@
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
@@ -1,321 +0,0 @@
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,74 @@
DATA_BLOCK "DB6_ENTIDAD"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
STRUCT
ENT { S7_SetPoint := 'False'} : Array[0.."N_MAX_ENTIDAD"] of "UDT_ZC_PRO_ENTIDAD";
END_STRUCT;
BEGIN
ENT[0].Habilitar := TRUE;
ENT[0].ID := 0;
ENT[0].Asignacion := 0;
ENT[0].Estado.Disponible := FALSE;
ENT[0].Estado.Capturada := FALSE;
ENT[0].Estado.EnProduccion := FALSE;
ENT[0].Estado.EnCIP := FALSE;
ENT[0].Estado.EnSIP := FALSE;
ENT[0].Estado.EnStandby := FALSE;
ENT[0].Estado.Limpia := FALSE;
ENT[0].Estado.Sucia := FALSE;
ENT[0].Estado.Esterilizada := FALSE;
ENT[0].Estado.ConProducto := FALSE;
ENT[0].Estado.ConAgua := FALSE;
ENT[0].Estado.Vacia := FALSE;
ENT[0].Estado.R_Bool_12 := FALSE;
ENT[0].Estado.R_Bool_13 := FALSE;
ENT[0].Estado.R_Bool_14 := FALSE;
ENT[0].Estado.R_Bool_15 := FALSE;
ENT[0].Estado.Producto := 0;
ENT[0].Estado.CodEstado := 0;
ENT[0].Alarma.Dispositivo := FALSE;
ENT[0].Alarma.Manual := FALSE;
ENT[0].Alarma.R_Bool_3 := FALSE;
ENT[0].Alarma.R_Bool_4 := FALSE;
ENT[0].Alarma.R_Bool_5 := FALSE;
ENT[0].Alarma.R_Bool_6 := FALSE;
ENT[0].Alarma.R_Bool_7 := FALSE;
ENT[0].Alarma.R_Bool_8 := FALSE;
ENT[0].Dispositivo[1].Tipo := 0;
ENT[0].Dispositivo[1].Num := 0;
ENT[1].Habilitar := TRUE;
ENT[1].ID := 1;
ENT[1].Asignacion := 0;
ENT[1].Estado.Disponible := TRUE;
ENT[1].Estado.Capturada := FALSE;
ENT[1].Estado.EnProduccion := FALSE;
ENT[1].Estado.EnCIP := FALSE;
ENT[1].Estado.EnSIP := FALSE;
ENT[1].Estado.EnStandby := FALSE;
ENT[1].Estado.Limpia := TRUE;
ENT[1].Estado.Sucia := FALSE;
ENT[1].Estado.Esterilizada := FALSE;
ENT[1].Estado.ConProducto := FALSE;
ENT[1].Estado.ConAgua := FALSE;
ENT[1].Estado.Vacia := FALSE;
ENT[1].Estado.R_Bool_12 := FALSE;
ENT[1].Estado.R_Bool_13 := FALSE;
ENT[1].Estado.R_Bool_14 := FALSE;
ENT[1].Estado.R_Bool_15 := FALSE;
ENT[1].Estado.Producto := 0;
ENT[1].Estado.CodEstado := 11000;
ENT[1].Alarma.Dispositivo := FALSE;
ENT[1].Alarma.Manual := FALSE;
ENT[1].Alarma.R_Bool_3 := FALSE;
ENT[1].Alarma.R_Bool_4 := FALSE;
ENT[1].Alarma.R_Bool_5 := FALSE;
ENT[1].Alarma.R_Bool_6 := FALSE;
ENT[1].Alarma.R_Bool_7 := FALSE;
ENT[1].Alarma.R_Bool_8 := FALSE;
ENT[1].Dispositivo[1].Tipo := 0;
ENT[1].Dispositivo[1].Num := 0;
END_DATA_BLOCK
File diff suppressed because it is too large Load Diff
@@ -147,7 +147,7 @@ BEGIN
END_FOR;
// Numero maximo de dispositivos para limitar en HMI/Scada
"DB2017_M_SINA".Mux.NumDispositivos := "N_MAX_DISP_M_SINA";
"DB2017_M_SINA".NumDispositivos := "N_MAX_DISP_M_SINA";
REGION COMPROBACION_N_MAX
@@ -89,7 +89,7 @@ BEGIN
END_FOR;
// Numero maximo de dispositivos para limitar en HMI/Scada
"DB2000_ED".Mux.NumDispositivos := "N_MAX_DISP_ED";
"DB2000_ED".NumDispositivos := "N_MAX_DISP_ED";
REGION COMPROBACION_N_MAX
@@ -106,7 +106,7 @@ BEGIN
END_FOR;
// Numero maximo de dispositivos para limitar en HMI/Scada
"DB2001_EA".Mux.NumDispositivos := "N_MAX_DISP_EA";
"DB2001_EA".NumDispositivos := "N_MAX_DISP_EA";
REGION COMPROBACION_N_MAX
@@ -95,7 +95,7 @@ BEGIN
END_FOR;
// Numero maximo de dispositivos para limitar en HMI/Scada
"DB2005_SD".Mux.NumDispositivos := "N_MAX_DISP_SD";
"DB2005_SD".NumDispositivos := "N_MAX_DISP_SD";
REGION COMPROBACION_N_MAX
@@ -102,7 +102,7 @@ BEGIN
END_FOR;
// Numero maximo de dispositivos para limitar en HMI/Scada
"DB2006_SA".Mux.NumDispositivos := "N_MAX_DISP_SA";
"DB2006_SA".NumDispositivos := "N_MAX_DISP_SA";
REGION COMPROBACION_N_MAX
@@ -103,7 +103,7 @@ BEGIN
END_FOR;
// Numero maximo de dispositivos para limitar en HMI/Scada
"DB2010_V".Mux.NumDispositivos := "N_MAX_DISP_V";
"DB2010_V".NumDispositivos := "N_MAX_DISP_V";
REGION COMPROBACION_N_MAX
@@ -101,7 +101,7 @@ BEGIN
END_FOR;
// Numero maximo de dispositivos para limitar en HMI/Scada
"DB2015_M".Mux.NumDispositivos := "N_MAX_DISP_M";
"DB2015_M".NumDispositivos := "N_MAX_DISP_M";
REGION COMPROBACION_N_MAX
@@ -109,7 +109,7 @@ BEGIN
END_FOR;
// Numero maximo de dispositivos para limitar en HMI/Scada
"DB2016_M_VF".Mux.NumDispositivos := "N_MAX_DISP_M_VF";
"DB2016_M_VF".NumDispositivos := "N_MAX_DISP_M_VF";
REGION COMPROBACION_N_MAX
@@ -87,7 +87,7 @@ BEGIN
REGION LOGICA_DEL_DISPOSITIVO
// Numero maximo de dispositivos para limitar en HMI/Scada
"DB2025_TOT".Mux.NumDispositivos := "N_MAX_DISP_TOT";
"DB2025_TOT".NumDispositivos := "N_MAX_DISP_TOT";
REGION COMPROBACION_N_MAX
@@ -86,7 +86,7 @@ BEGIN
END_FOR;
// Numero maximo de dispositivos para limitar en HMI/Scada
"DB2041_TQ_AE".Mux.NumDispositivos := "N_MAX_DISP_TQ_AE";
"DB2041_TQ_AE".NumDispositivos := "N_MAX_DISP_TQ_AE";
REGION COMPROBACION_N_MAX
@@ -83,7 +83,7 @@ BEGIN
REGION TRASPASO_DE_PARAMETROS
// Numero maximo de dispositivos para limitar en HMI/Scada
"DB2035_PID".Mux.NumDispositivos := "N_MAX_DISP_PID";
"DB2035_PID".NumDispositivos := "N_MAX_DISP_PID";
// ===============================================================================================================
// TRASPASO DE PARAMETROS A PID COMPACT
@@ -115,7 +115,7 @@ BEGIN
REGION LOGICA_DEL_DISPOSITIVO
// Numero maximo de dispositivos para limitar en HMI/Scada
"DB2040_TQ".Mux.NumDispositivos := "N_MAX_DISP_TQ";
"DB2040_TQ".NumDispositivos := "N_MAX_DISP_TQ";
// Cambio de estado desde HMI/SCADA
IF "DB2040_TQ".TQ[#NumeroTanque].Orden_CambioEstado THEN
@@ -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
"DB2800_ED_MUX".Mux.Scada[#for_mux].Index :=
"DB2800_ED_MUX".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 "DB2800_ED_MUX".Mux.Scada[#for_mux].Index < 0 THEN
"DB2800_ED_MUX".Mux.Scada[#for_mux].Index := 0;
END_IF;
IF "DB2800_ED_MUX".Mux.Scada[#for_mux].Index > "N_MAX_DISP_ED" THEN
"DB2800_ED_MUX".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 := "DB2800_ED_MUX".Mux.Scada[#for_mux].Index;
#t_oldIndex := "DB2800_ED_MUX".Mux.Scada[#for_mux].oldIndex;
END_REGION INDICES
IF "DB2800_ED_MUX".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
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED := "DB2000_ED".ED[#t_Index];
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED := "DB2000_ED".ED[#t_Index];
// ===========================================================================================================
// Valor anterior del indice
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldIndex := #t_Index;
END_IF;
END_REGION CARGA_INICIAL
REGION DATOS_LECTURA
// ===========================================================================================================
// Movimiento de datos gestionados en FC
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Hmi_Estado := "DB2000_ED".ED[#t_Index].Hmi_Estado;
IF NOT "DB2000_ED".ED[#t_Index].Estado_AutoMan THEN
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Orden_ActivarManual := "DB2000_ED".ED[#t_Index].Orden_ActivarManual;
END_IF;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Estado_Activado := "DB2000_ED".ED[#t_Index].Estado_Activado;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Estado_EntradaCanal := "DB2000_ED".ED[#t_Index].Estado_EntradaCanal;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Aux_oldActivado := "DB2000_ED".ED[#t_Index].Aux_oldActivado;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Aux_oldAutoMan := "DB2000_ED".ED[#t_Index].Aux_oldAutoMan;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Tiempos_TiempoAct := "DB2000_ED".ED[#t_Index].Tiempos_TiempoAct;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Tiempos_TiempoDes := "DB2000_ED".ED[#t_Index].Tiempos_TiempoDes;
"DB2800_ED_MUX".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 <> "DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Estado_AutoMan THEN
// Cambio desde HMI
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Estado_AutoMan := "DB2000_ED".ED[#t_Index].Estado_AutoMan;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Estado_AutoMan := "DB2000_ED".ED[#t_Index].Estado_AutoMan;
ELSIF "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Estado_AutoMan <> "DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Estado_AutoMan THEN
// Cambio desde Multiplexado
"DB2000_ED".ED[#t_Index].Estado_AutoMan := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Estado_AutoMan;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Estado_AutoMan := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Estado_AutoMan;
END_IF;
// ===========================================================================================================
// Orden Activar Manual
IF "DB2000_ED".ED[#t_Index].Orden_ActivarManual <> "DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Orden_ActivarManual THEN
// Cambio desde HMI
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Orden_ActivarManual := "DB2000_ED".ED[#t_Index].Orden_ActivarManual;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Orden_ActivarManual := "DB2000_ED".ED[#t_Index].Orden_ActivarManual;
ELSIF "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Orden_ActivarManual <> "DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Orden_ActivarManual THEN
// Cambio desde Multiplexado
"DB2000_ED".ED[#t_Index].Orden_ActivarManual := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Orden_ActivarManual;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Orden_ActivarManual := "DB2800_ED_MUX".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 :=
("DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_DirEntradaBit <> "DB2000_ED".ED[#t_Index].Config_DirEntradaBit)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_DirEntradaByte <> "DB2000_ED".ED[#t_Index].Config_DirEntradaByte)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_Habilitar <> "DB2000_ED".ED[#t_Index].Config_Habilitar)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_HabilitarInvertir <> "DB2000_ED".ED[#t_Index].Config_HabilitarInvertir)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoAct <> "DB2000_ED".ED[#t_Index].Config_HabilitarRetardoAct)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoDes <> "DB2000_ED".ED[#t_Index].Config_HabilitarRetardoDes)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_TipoAcceso <> "DB2000_ED".ED[#t_Index].Config_TipoAcceso)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoAct <> "DB2000_ED".ED[#t_Index].Tiempos_SPTiempoAct)
OR ("DB2800_ED_MUX".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 :=
("DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_DirEntradaBit <> "DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_DirEntradaBit)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_DirEntradaByte <> "DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_DirEntradaByte)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_Habilitar <> "DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_Habilitar)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_HabilitarInvertir <> "DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_HabilitarInvertir)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoAct <> "DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoAct)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoDes <> "DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoDes)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_TipoAcceso <> "DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_TipoAcceso)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoAct <> "DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoAct)
OR ("DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoDes <> "DB2800_ED_MUX".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
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Estado_AutoMan := "DB2000_ED".ED[#t_Index].Estado_AutoMan;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Orden_ActivarManual := "DB2000_ED".ED[#t_Index].Orden_ActivarManual;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_DirEntradaBit := "DB2000_ED".ED[#t_Index].Config_DirEntradaBit;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_DirEntradaByte := "DB2000_ED".ED[#t_Index].Config_DirEntradaByte;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_Habilitar := "DB2000_ED".ED[#t_Index].Config_Habilitar;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_HabilitarInvertir := "DB2000_ED".ED[#t_Index].Config_HabilitarInvertir;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoAct := "DB2000_ED".ED[#t_Index].Config_HabilitarRetardoAct;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoDes := "DB2000_ED".ED[#t_Index].Config_HabilitarRetardoDes;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_TipoAcceso := "DB2000_ED".ED[#t_Index].Config_TipoAcceso;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoAct := "DB2000_ED".ED[#t_Index].Tiempos_SPTiempoAct;
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoDes := "DB2000_ED".ED[#t_Index].Tiempos_SPTiempoDes;
// Actualizamos el estado original para configuraciones
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Estado_AutoMan := "DB2000_ED".ED[#t_Index].Estado_AutoMan;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Orden_ActivarManual := "DB2000_ED".ED[#t_Index].Orden_ActivarManual;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_DirEntradaBit := "DB2000_ED".ED[#t_Index].Config_DirEntradaBit;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_DirEntradaByte := "DB2000_ED".ED[#t_Index].Config_DirEntradaByte;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_Habilitar := "DB2000_ED".ED[#t_Index].Config_Habilitar;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_HabilitarInvertir := "DB2000_ED".ED[#t_Index].Config_HabilitarInvertir;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoAct := "DB2000_ED".ED[#t_Index].Config_HabilitarRetardoAct;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoDes := "DB2000_ED".ED[#t_Index].Config_HabilitarRetardoDes;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_TipoAcceso := "DB2000_ED".ED[#t_Index].Config_TipoAcceso;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoAct := "DB2000_ED".ED[#t_Index].Tiempos_SPTiempoAct;
"DB2800_ED_MUX".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 := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Estado_AutoMan;
"DB2000_ED".ED[#t_Index].Orden_ActivarManual := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Orden_ActivarManual;
"DB2000_ED".ED[#t_Index].Config_DirEntradaBit := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_DirEntradaBit;
"DB2000_ED".ED[#t_Index].Config_DirEntradaByte := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_DirEntradaByte;
"DB2000_ED".ED[#t_Index].Config_Habilitar := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_Habilitar;
"DB2000_ED".ED[#t_Index].Config_HabilitarInvertir := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_HabilitarInvertir;
"DB2000_ED".ED[#t_Index].Config_HabilitarRetardoAct := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoAct;
"DB2000_ED".ED[#t_Index].Config_HabilitarRetardoDes := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoDes;
"DB2000_ED".ED[#t_Index].Config_TipoAcceso := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_TipoAcceso;
"DB2000_ED".ED[#t_Index].Tiempos_SPTiempoAct := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoAct;
"DB2000_ED".ED[#t_Index].Tiempos_SPTiempoDes := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoDes;
// Actualizamos el estado original para configuraciones
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Estado_AutoMan := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Estado_AutoMan;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Orden_ActivarManual := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Orden_ActivarManual;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_DirEntradaBit := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_DirEntradaBit;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_DirEntradaByte := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_DirEntradaByte;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_Habilitar := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_Habilitar;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_HabilitarInvertir := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_HabilitarInvertir;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoAct := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoAct;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_HabilitarRetardoDes := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_HabilitarRetardoDes;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Config_TipoAcceso := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Config_TipoAcceso;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoAct := "DB2800_ED_MUX".Mux.Scada[#for_mux].ED.Tiempos_SPTiempoAct;
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED.Tiempos_SPTiempoDes := "DB2800_ED_MUX".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.
"DB2800_ED_MUX".Mux.Scada[#for_mux].ED := "DB2000_ED".ED[0];
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldED := "DB2000_ED".ED[0];
// Actualizacion de estado anterior
"DB2800_ED_MUX".Mux.Scada[#for_mux].oldIndex := 0;
END_IF;
ELSE
// Multiplexado no habilitado
"DB2800_ED_MUX".Mux.Scada[#for_mux].Index :=
"DB2800_ED_MUX".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
"DB2801_EA_MUX".Mux.Scada[#for_mux].Index :=
"DB2801_EA_MUX".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 "DB2801_EA_MUX".Mux.Scada[#for_mux].Index < 0 THEN
"DB2801_EA_MUX".Mux.Scada[#for_mux].Index := 0;
END_IF;
IF "DB2801_EA_MUX".Mux.Scada[#for_mux].Index > "N_MAX_DISP_EA" THEN
"DB2801_EA_MUX".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 := "DB2801_EA_MUX".Mux.Scada[#for_mux].Index;
#t_oldIndex := "DB2801_EA_MUX".Mux.Scada[#for_mux].oldIndex;
END_REGION INDICES
IF "DB2801_EA_MUX".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
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA := "DB2001_EA".EA[#t_Index];
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA := "DB2001_EA".EA[#t_Index];
END_IF;
// ===========================================================================================================
// Valor anterior del indice
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldIndex := #t_Index;
END_REGION CARGA_INICIAL
REGION DATOS_LECTURA
// ===========================================================================================================
// Movimiento de datos gestionados en FC
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Hmi_Estado := "DB2001_EA".EA[#t_Index].Hmi_Estado;
IF NOT "DB2001_EA".EA[#t_Index].Estado_AutoMan THEN
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Orden_ConsignaManual := "DB2001_EA".EA[#t_Index].Orden_ConsignaManual;
END_IF;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Estado_ValorIngenieria := "DB2001_EA".EA[#t_Index].Estado_ValorIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Estado_ValorTarjeta := "DB2001_EA".EA[#t_Index].Estado_ValorTarjeta;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Alarmas_General := "DB2001_EA".EA[#t_Index].Alarmas_General;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Alarmas_HiloRoto := "DB2001_EA".EA[#t_Index].Alarmas_HiloRoto;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Alarmas_Lectura := "DB2001_EA".EA[#t_Index].Alarmas_Lectura;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Alarmas_Max := "DB2001_EA".EA[#t_Index].Alarmas_Max;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Alarmas_Min := "DB2001_EA".EA[#t_Index].Alarmas_Min;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Alarmas_Parametros := "DB2001_EA".EA[#t_Index].Alarmas_Parametros;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Aux_Estado := "DB2001_EA".EA[#t_Index].Aux_Estado;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Aux_oldAlarma := "DB2001_EA".EA[#t_Index].Aux_oldAlarma;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Aux_oldAutoMan := "DB2001_EA".EA[#t_Index].Aux_oldAutoMan;
"DB2801_EA_MUX".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 <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Estado_AutoMan THEN
// Cambio desde HMI
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Estado_AutoMan := "DB2001_EA".EA[#t_Index].Estado_AutoMan;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Estado_AutoMan := "DB2001_EA".EA[#t_Index].Estado_AutoMan;
ELSIF "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Estado_AutoMan <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Estado_AutoMan THEN
// Cambio desde Multiplexado
"DB2001_EA".EA[#t_Index].Estado_AutoMan := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Estado_AutoMan;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Estado_AutoMan := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Estado_AutoMan;
END_IF;
// ===========================================================================================================
// Orden Activar Manual
IF "DB2001_EA".EA[#t_Index].Orden_ConsignaManual <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Orden_ConsignaManual THEN
// Cambio desde HMI
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Orden_ConsignaManual := "DB2001_EA".EA[#t_Index].Orden_ConsignaManual;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Orden_ConsignaManual := "DB2001_EA".EA[#t_Index].Orden_ConsignaManual;
ELSIF "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Orden_ConsignaManual <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Orden_ConsignaManual THEN
// Cambio desde Multiplexado
"DB2001_EA".EA[#t_Index].Orden_ConsignaManual := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Orden_ConsignaManual;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Orden_ConsignaManual := "DB2801_EA_MUX".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 :=
("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_DireccionEntradaByte <> "DB2001_EA".EA[#t_Index].Config_DireccionEntradaByte)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxHisteresis <> "DB2001_EA".EA[#t_Index].Config_ErrorMaxHisteresis)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxIngenieria <> "DB2001_EA".EA[#t_Index].Config_ErrorMaxIngenieria)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMinHisteresis <> "DB2001_EA".EA[#t_Index].Config_ErrorMinHisteresis)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMinIngenieria <> "DB2001_EA".EA[#t_Index].Config_ErrorMinIngenieria)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxIngenieria <> "DB2001_EA".EA[#t_Index].Config_EscaladoMaxIngenieria)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxTarjeta <> "DB2001_EA".EA[#t_Index].Config_EscaladoMaxTarjeta)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinIngenieria <> "DB2001_EA".EA[#t_Index].Config_EscaladoMinIngenieria)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinTarjeta <> "DB2001_EA".EA[#t_Index].Config_EscaladoMinTarjeta)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoOffset <> "DB2001_EA".EA[#t_Index].Config_EscaladoOffset)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_Habilitar <> "DB2001_EA".EA[#t_Index].Config_Habilitar)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMax <> "DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMax)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMin <> "DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMin)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_TipoAcceso <> "DB2001_EA".EA[#t_Index].Config_TipoAcceso)
OR ("DB2801_EA_MUX".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 :=
("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_DireccionEntradaByte <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_DireccionEntradaByte)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMaxHisteresis <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxHisteresis)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMaxIngenieria <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxIngenieria)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMinHisteresis <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMinHisteresis)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMinIngenieria <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMinIngenieria)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMaxIngenieria <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxIngenieria)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMaxTarjeta <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxTarjeta)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMinIngenieria <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinIngenieria)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMinTarjeta <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinTarjeta)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoOffset <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoOffset)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_Habilitar <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_Habilitar)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMax <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMax)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMin <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMin)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_TipoAcceso <> "DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_TipoAcceso)
OR ("DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_HisteresisTipo <> "DB2801_EA_MUX".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
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Estado_AutoMan := "DB2001_EA".EA[#t_Index].Estado_AutoMan;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Orden_ConsignaManual := "DB2001_EA".EA[#t_Index].Orden_ConsignaManual;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_DireccionEntradaByte := "DB2001_EA".EA[#t_Index].Config_DireccionEntradaByte;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMaxHisteresis := "DB2001_EA".EA[#t_Index].Config_ErrorMaxHisteresis;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMaxIngenieria := "DB2001_EA".EA[#t_Index].Config_ErrorMaxIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMinHisteresis := "DB2001_EA".EA[#t_Index].Config_ErrorMinHisteresis;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMinIngenieria := "DB2001_EA".EA[#t_Index].Config_ErrorMinIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMaxIngenieria := "DB2001_EA".EA[#t_Index].Config_EscaladoMaxIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMaxTarjeta := "DB2001_EA".EA[#t_Index].Config_EscaladoMaxTarjeta;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMinIngenieria := "DB2001_EA".EA[#t_Index].Config_EscaladoMinIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMinTarjeta := "DB2001_EA".EA[#t_Index].Config_EscaladoMinTarjeta;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoOffset := "DB2001_EA".EA[#t_Index].Config_EscaladoOffset;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_Habilitar := "DB2001_EA".EA[#t_Index].Config_Habilitar;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMax := "DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMax;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMin := "DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMin;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_TipoAcceso := "DB2001_EA".EA[#t_Index].Config_TipoAcceso;
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_HisteresisTipo := "DB2001_EA".EA[#t_Index].Config_HisteresisTipo;
// Actualizamos el estado original para configuraciones
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_DireccionEntradaByte := "DB2001_EA".EA[#t_Index].Config_DireccionEntradaByte;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxHisteresis := "DB2001_EA".EA[#t_Index].Config_ErrorMaxHisteresis;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxIngenieria := "DB2001_EA".EA[#t_Index].Config_ErrorMaxIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMinHisteresis := "DB2001_EA".EA[#t_Index].Config_ErrorMinHisteresis;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMinIngenieria := "DB2001_EA".EA[#t_Index].Config_ErrorMinIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxIngenieria := "DB2001_EA".EA[#t_Index].Config_EscaladoMaxIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxTarjeta := "DB2001_EA".EA[#t_Index].Config_EscaladoMaxTarjeta;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinIngenieria := "DB2001_EA".EA[#t_Index].Config_EscaladoMinIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinTarjeta := "DB2001_EA".EA[#t_Index].Config_EscaladoMinTarjeta;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoOffset := "DB2001_EA".EA[#t_Index].Config_EscaladoOffset;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_Habilitar := "DB2001_EA".EA[#t_Index].Config_Habilitar;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMax := "DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMax;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMin := "DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMin;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_TipoAcceso := "DB2001_EA".EA[#t_Index].Config_TipoAcceso;
"DB2801_EA_MUX".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 := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Estado_AutoMan;
"DB2001_EA".EA[#t_Index].Orden_ConsignaManual := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Orden_ConsignaManual;
"DB2001_EA".EA[#t_Index].Config_DireccionEntradaByte := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_DireccionEntradaByte;
"DB2001_EA".EA[#t_Index].Config_ErrorMaxHisteresis := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMaxHisteresis;
"DB2001_EA".EA[#t_Index].Config_ErrorMaxIngenieria := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMaxIngenieria;
"DB2001_EA".EA[#t_Index].Config_ErrorMinHisteresis := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMinHisteresis;
"DB2001_EA".EA[#t_Index].Config_ErrorMinIngenieria := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMinIngenieria;
"DB2001_EA".EA[#t_Index].Config_EscaladoMaxIngenieria := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMaxIngenieria;
"DB2001_EA".EA[#t_Index].Config_EscaladoMaxTarjeta := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMaxTarjeta;
"DB2001_EA".EA[#t_Index].Config_EscaladoMinIngenieria := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMinIngenieria;
"DB2001_EA".EA[#t_Index].Config_EscaladoMinTarjeta := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMinTarjeta;
"DB2001_EA".EA[#t_Index].Config_EscaladoOffset := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoOffset;
"DB2001_EA".EA[#t_Index].Config_Habilitar := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_Habilitar;
"DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMax := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMax;
"DB2001_EA".EA[#t_Index].Config_HabilitarAlarmaMin := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMin;
"DB2001_EA".EA[#t_Index].Config_TipoAcceso := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_TipoAcceso;
"DB2001_EA".EA[#t_Index].Config_HisteresisTipo := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_HisteresisTipo;
// Actualizamos el estado original para configuraciones
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_DireccionEntradaByte := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_DireccionEntradaByte;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxHisteresis := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMaxHisteresis;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMaxIngenieria := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMaxIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMinHisteresis := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMinHisteresis;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_ErrorMinIngenieria := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_ErrorMinIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxIngenieria := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMaxIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMaxTarjeta := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMaxTarjeta;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinIngenieria := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMinIngenieria;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoMinTarjeta := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoMinTarjeta;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_EscaladoOffset := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_EscaladoOffset;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_Habilitar := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_Habilitar;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMax := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMax;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_HabilitarAlarmaMin := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_HabilitarAlarmaMin;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_TipoAcceso := "DB2801_EA_MUX".Mux.Scada[#for_mux].EA.Config_TipoAcceso;
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA.Config_HisteresisTipo := "DB2801_EA_MUX".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.
"DB2801_EA_MUX".Mux.Scada[#for_mux].EA := "DB2001_EA".EA[0];
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldEA := "DB2001_EA".EA[0];
// Actualizacion de estado anterior
"DB2801_EA_MUX".Mux.Scada[#for_mux].oldIndex := 0;
END_IF;
ELSE
// Multiplexado no habilitado
"DB2801_EA_MUX".Mux.Scada[#for_mux].Index :=
"DB2801_EA_MUX".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
"DB2805_SD_MUX".Mux.Scada[#for_mux].Index :=
"DB2805_SD_MUX".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 "DB2805_SD_MUX".Mux.Scada[#for_mux].Index < 0 THEN
"DB2805_SD_MUX".Mux.Scada[#for_mux].Index := 0;
END_IF;
IF "DB2805_SD_MUX".Mux.Scada[#for_mux].Index > "N_MAX_DISP_SD" THEN
"DB2805_SD_MUX".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 := "DB2805_SD_MUX".Mux.Scada[#for_mux].Index;
#t_oldIndex := "DB2805_SD_MUX".Mux.Scada[#for_mux].oldIndex;
END_REGION INDICES
IF "DB2805_SD_MUX".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
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD := "DB2005_SD".SD[#t_Index];
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD := "DB2005_SD".SD[#t_Index];
// ===========================================================================================================
// Valor anterior del indice
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldIndex := #t_Index;
END_IF;
END_REGION CARGA_INICIAL
REGION DATOS_LECTURA
// ===========================================================================================================
// Movimiento de datos gestionados en FC
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Hmi_Estado := "DB2005_SD".SD[#t_Index].Hmi_Estado;
IF NOT "DB2005_SD".SD[#t_Index].Estado_AutoMan THEN
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Orden_ActivarManual := "DB2005_SD".SD["DB2805_SD_MUX".Mux.Scada[#for_mux].Index].Orden_ActivarManual;
END_IF;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Estado_Activado := "DB2005_SD".SD[#t_Index].Estado_Activado;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Estado_Enclavado := "DB2005_SD".SD[#t_Index].Estado_Enclavado;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Estado_Salida := "DB2005_SD".SD[#t_Index].Estado_Salida;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Estado_SeguridadOk := "DB2005_SD".SD[#t_Index].Estado_SeguridadOk;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Orden_ActivarAuto := "DB2005_SD".SD[#t_Index].Orden_ActivarAuto;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Tiempos_TiempoAct := "DB2005_SD".SD[#t_Index].Tiempos_TiempoAct;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Tiempos_TiempoDes := "DB2005_SD".SD[#t_Index].Tiempos_TiempoDes;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Aux_oldActivado := "DB2005_SD".SD[#t_Index].Aux_oldActivado;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Aux_oldAutoMan := "DB2005_SD".SD[#t_Index].Aux_oldAutoMan;
"DB2805_SD_MUX".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 <> "DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Estado_AutoMan THEN
// Cambio desde HMI
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Estado_AutoMan := "DB2005_SD".SD[#t_Index].Estado_AutoMan;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Estado_AutoMan := "DB2005_SD".SD[#t_Index].Estado_AutoMan;
ELSIF "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Estado_AutoMan <> "DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Estado_AutoMan THEN
// Cambio desde Multiplexado
"DB2005_SD".SD[#t_Index].Estado_AutoMan := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Estado_AutoMan;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Estado_AutoMan := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Estado_AutoMan;
END_IF;
// ===========================================================================================================
// Orden Activar Manual
IF "DB2005_SD".SD[#t_Index].Orden_ActivarManual <> "DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Orden_ActivarManual THEN
// Cambio desde HMI
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Orden_ActivarManual := "DB2005_SD".SD[#t_Index].Orden_ActivarManual;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Orden_ActivarManual := "DB2005_SD".SD[#t_Index].Orden_ActivarManual;
ELSIF "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Orden_ActivarManual <> "DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Orden_ActivarManual THEN
// Cambio desde Multiplexado
"DB2005_SD".SD[#t_Index].Orden_ActivarManual := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Orden_ActivarManual;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Orden_ActivarManual := "DB2805_SD_MUX".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 :=
("DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaBit <> "DB2005_SD".SD[#t_Index].Config_DireccionSalidaBit)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaByte <> "DB2005_SD".SD[#t_Index].Config_DireccionSalidaByte)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_Habilitar <> "DB2005_SD".SD[#t_Index].Config_Habilitar)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_HabilitarInvertir <> "DB2005_SD".SD[#t_Index].Config_HabilitarInvertir)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoAct <> "DB2005_SD".SD[#t_Index].Config_HabilitarRetardoAct)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoDes <> "DB2005_SD".SD[#t_Index].Config_HabilitarRetardoDes)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_TipoAcceso <> "DB2005_SD".SD[#t_Index].Config_TipoAcceso)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoAct <> "DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoAct)
OR ("DB2805_SD_MUX".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 :=
("DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_DireccionSalidaBit <> "DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaBit)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_DireccionSalidaByte <> "DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaByte)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_Habilitar <> "DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_Habilitar)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_HabilitarInvertir <> "DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_HabilitarInvertir)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoAct <> "DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoAct)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoDes <> "DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoDes)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_TipoAcceso <> "DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_TipoAcceso)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoAct <> "DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoAct)
OR ("DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoDes <> "DB2805_SD_MUX".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
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Estado_AutoMan := "DB2005_SD".SD[#t_Index].Estado_AutoMan;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Orden_ActivarManual := "DB2005_SD".SD[#t_Index].Orden_ActivarManual;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_DireccionSalidaBit := "DB2005_SD".SD[#t_Index].Config_DireccionSalidaBit;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_DireccionSalidaByte := "DB2005_SD".SD[#t_Index].Config_DireccionSalidaByte;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_Habilitar := "DB2005_SD".SD[#t_Index].Config_Habilitar;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_HabilitarInvertir := "DB2005_SD".SD[#t_Index].Config_HabilitarInvertir;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoAct := "DB2005_SD".SD[#t_Index].Config_HabilitarRetardoAct;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoDes := "DB2005_SD".SD[#t_Index].Config_HabilitarRetardoDes;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_TipoAcceso := "DB2005_SD".SD[#t_Index].Config_TipoAcceso;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoAct := "DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoAct;
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoDes := "DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoDes;
// Actualizamos el estado original para configuraciones
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaBit := "DB2005_SD".SD[#t_Index].Config_DireccionSalidaBit;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaByte := "DB2005_SD".SD[#t_Index].Config_DireccionSalidaByte;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_Habilitar := "DB2005_SD".SD[#t_Index].Config_Habilitar;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_HabilitarInvertir := "DB2005_SD".SD[#t_Index].Config_HabilitarInvertir;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoAct := "DB2005_SD".SD[#t_Index].Config_HabilitarRetardoAct;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoDes := "DB2005_SD".SD[#t_Index].Config_HabilitarRetardoDes;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_TipoAcceso := "DB2005_SD".SD[#t_Index].Config_TipoAcceso;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoAct := "DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoAct;
"DB2805_SD_MUX".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 := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Estado_AutoMan;
"DB2005_SD".SD[#t_Index].Orden_ActivarManual := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Orden_ActivarManual;
"DB2005_SD".SD[#t_Index].Config_DireccionSalidaBit := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_DireccionSalidaBit;
"DB2005_SD".SD[#t_Index].Config_DireccionSalidaByte := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_DireccionSalidaByte;
"DB2005_SD".SD[#t_Index].Config_Habilitar := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_Habilitar;
"DB2005_SD".SD[#t_Index].Config_HabilitarInvertir := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_HabilitarInvertir;
"DB2005_SD".SD[#t_Index].Config_HabilitarRetardoAct := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoAct;
"DB2005_SD".SD[#t_Index].Config_HabilitarRetardoDes := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoDes;
"DB2005_SD".SD[#t_Index].Config_TipoAcceso := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_TipoAcceso;
"DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoAct := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoAct;
"DB2005_SD".SD[#t_Index].Tiempos_SetPointTiempoDes := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoDes;
// Actualizamos el estado original para configuraciones
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaBit := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_DireccionSalidaBit;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_DireccionSalidaByte := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_DireccionSalidaByte;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_Habilitar := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_Habilitar;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_HabilitarInvertir := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_HabilitarInvertir;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoAct := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoAct;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_HabilitarRetardoDes := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_HabilitarRetardoDes;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Config_TipoAcceso := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Config_TipoAcceso;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoAct := "DB2805_SD_MUX".Mux.Scada[#for_mux].SD.Tiempos_SetPointTiempoAct;
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD.Tiempos_SetPointTiempoDes := "DB2805_SD_MUX".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.
"DB2805_SD_MUX".Mux.Scada[#for_mux].SD := "DB2005_SD".SD[0];
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldSD := "DB2005_SD".SD[0];
// Actualizacion de estado anterior
"DB2805_SD_MUX".Mux.Scada[#for_mux].oldIndex := 0;
END_IF;
ELSE
"DB2805_SD_MUX".Mux.Scada[#for_mux].Index :=
"DB2805_SD_MUX".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
"DB2806_SA_MUX".Mux.Scada[#for_mux].Index :=
"DB2806_SA_MUX".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 "DB2806_SA_MUX".Mux.Scada[#for_mux].Index < 0 THEN
"DB2806_SA_MUX".Mux.Scada[#for_mux].Index := 0;
END_IF;
IF "DB2806_SA_MUX".Mux.Scada[#for_mux].Index > "N_MAX_DISP_SA" THEN
"DB2806_SA_MUX".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 := "DB2806_SA_MUX".Mux.Scada[#for_mux].Index;
#t_oldIndex := "DB2806_SA_MUX".Mux.Scada[#for_mux].oldIndex;
END_REGION INDICES
IF "DB2806_SA_MUX".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
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA := "DB2006_SA".SA[#t_Index];
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA := "DB2006_SA".SA[#t_Index];
// ===========================================================================================================
// Valor anterior del indice
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldIndex := #t_Index;
END_IF;
END_REGION CARGA_INICIAL
REGION DATOS_LECTURA
// ===========================================================================================================
// Movimiento de datos gestionados en FC
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Hmi_Estado := "DB2006_SA".SA[#t_Index].Hmi_Estado;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Estado_SeguridadOk := "DB2006_SA".SA[#t_Index].Estado_SeguridadOk;
IF NOT "DB2006_SA".SA[#t_Index].Estado_AutoMan THEN
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaManual := "DB2006_SA".SA[#t_Index].Orden_ConsignaManual;
END_IF;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Estado_ValorActual := "DB2006_SA".SA[#t_Index].Estado_ValorActual;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Estado_ValorTarjeta := "DB2006_SA".SA[#t_Index].Estado_ValorTarjeta;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Estado_Enclavado := "DB2006_SA".SA[#t_Index].Estado_Enclavado;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Alarmas_Escritura := "DB2006_SA".SA[#t_Index].Alarmas_Escritura;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Alarmas_General := "DB2006_SA".SA[#t_Index].Alarmas_General;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Alarmas_Max := "DB2006_SA".SA[#t_Index].Alarmas_Max;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Alarmas_Min := "DB2006_SA".SA[#t_Index].Alarmas_Min;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Alarmas_Parametros := "DB2006_SA".SA[#t_Index].Alarmas_Parametros;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaAuto := "DB2006_SA".SA[#t_Index].Orden_ConsignaAuto;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Aux_Estado := "DB2006_SA".SA[#t_Index].Aux_Estado;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Aux_oldAlarma := "DB2006_SA".SA[#t_Index].Aux_oldAlarma;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Aux_oldAutoMan := "DB2006_SA".SA[#t_Index].Aux_oldAutoMan;
"DB2806_SA_MUX".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 <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Estado_AutoMan THEN
// Cambio desde HMI
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Estado_AutoMan := "DB2006_SA".SA[#t_Index].Estado_AutoMan;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Estado_AutoMan := "DB2006_SA".SA[#t_Index].Estado_AutoMan;
ELSIF "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Estado_AutoMan <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Estado_AutoMan THEN
// Cambio desde Multiplexado
"DB2006_SA".SA[#t_Index].Estado_AutoMan := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Estado_AutoMan;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Estado_AutoMan := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Estado_AutoMan;
END_IF;
// ===========================================================================================================
// Orden Consigna Manual
IF "DB2006_SA".SA[#t_Index].Orden_ConsignaManual <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Orden_ConsignaManual THEN
// Cambio desde HMI
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaManual := "DB2006_SA".SA[#t_Index].Orden_ConsignaManual;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Orden_ConsignaManual := "DB2006_SA".SA[#t_Index].Orden_ConsignaManual;
ELSIF "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaManual <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Orden_ConsignaManual THEN
// Cambio desde Multiplexado
"DB2006_SA".SA[#t_Index].Orden_ConsignaManual := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaManual;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Orden_ConsignaManual := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaManual;
END_IF;
// ===========================================================================================================
// Orden Consigna enclavado
IF "DB2006_SA".SA[#t_Index].Orden_ConsignaEnclavado <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Orden_ConsignaEnclavado THEN
// Cambio desde HMI
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaEnclavado := "DB2006_SA".SA[#t_Index].Orden_ConsignaEnclavado;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Orden_ConsignaEnclavado := "DB2006_SA".SA[#t_Index].Orden_ConsignaEnclavado;
ELSIF "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaEnclavado <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Orden_ConsignaEnclavado THEN
// Cambio desde Multiplexado
"DB2006_SA".SA[#t_Index].Orden_ConsignaEnclavado := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaEnclavado;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Orden_ConsignaEnclavado := "DB2806_SA_MUX".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 :=
("DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_DireccionSalidaByte <> "DB2006_SA".SA[#t_Index].Config_DireccionSalidaByte)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_ErrorMaxIngenieria <> "DB2006_SA".SA[#t_Index].Config_ErrorMaxIngenieria)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_ErrorMinIngenieria <> "DB2006_SA".SA[#t_Index].Config_ErrorMinIngenieria)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxIngenieria <> "DB2006_SA".SA[#t_Index].Config_EscaladoMaxIngenieria)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxTarjeta <> "DB2006_SA".SA[#t_Index].Config_EscaladoMaxTarjeta)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinIngenieria <> "DB2006_SA".SA[#t_Index].Config_EscaladoMinIngenieria)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinTarjeta <> "DB2006_SA".SA[#t_Index].Config_EscaladoMinTarjeta)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoOffset <> "DB2006_SA".SA[#t_Index].Config_EscaladoOffset)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_Habilitar <> "DB2006_SA".SA[#t_Index].Config_Habilitar)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMax <> "DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMax)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMin <> "DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMin)
OR ("DB2806_SA_MUX".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 :=
("DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_DireccionSalidaByte <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_DireccionSalidaByte)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_ErrorMaxIngenieria <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_ErrorMaxIngenieria)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_ErrorMinIngenieria <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_ErrorMinIngenieria)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMaxIngenieria <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxIngenieria)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMaxTarjeta <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxTarjeta)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMinIngenieria <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinIngenieria)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMinTarjeta <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinTarjeta)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoOffset <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoOffset)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_Habilitar <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_Habilitar)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMax <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMax)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMin <> "DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMin)
OR ("DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_TipoAcceso <> "DB2806_SA_MUX".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
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Estado_AutoMan := "DB2006_SA".SA[#t_Index].Estado_AutoMan;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaManual := "DB2006_SA".SA[#t_Index].Orden_ConsignaManual;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaEnclavado := "DB2006_SA".SA[#t_Index].Orden_ConsignaEnclavado;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_DireccionSalidaByte := "DB2006_SA".SA[#t_Index].Config_DireccionSalidaByte;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_ErrorMaxIngenieria := "DB2006_SA".SA[#t_Index].Config_ErrorMaxIngenieria;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_ErrorMinIngenieria := "DB2006_SA".SA[#t_Index].Config_ErrorMinIngenieria;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMaxIngenieria := "DB2006_SA".SA[#t_Index].Config_EscaladoMaxIngenieria;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMaxTarjeta := "DB2006_SA".SA[#t_Index].Config_EscaladoMaxTarjeta;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMinIngenieria := "DB2006_SA".SA[#t_Index].Config_EscaladoMinIngenieria;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMinTarjeta := "DB2006_SA".SA[#t_Index].Config_EscaladoMinTarjeta;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoOffset := "DB2006_SA".SA[#t_Index].Config_EscaladoOffset;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_Habilitar := "DB2006_SA".SA[#t_Index].Config_Habilitar;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMax := "DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMax;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMin := "DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMin;
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_TipoAcceso := "DB2006_SA".SA[#t_Index].Config_TipoAcceso;
// Actualizamos el estado original para configuraciones
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_DireccionSalidaByte := "DB2006_SA".SA[#t_Index].Config_DireccionSalidaByte;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_ErrorMaxIngenieria := "DB2006_SA".SA[#t_Index].Config_ErrorMaxIngenieria;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_ErrorMinIngenieria := "DB2006_SA".SA[#t_Index].Config_ErrorMinIngenieria;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxIngenieria := "DB2006_SA".SA[#t_Index].Config_EscaladoMaxIngenieria;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxTarjeta := "DB2006_SA".SA[#t_Index].Config_EscaladoMaxTarjeta;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinIngenieria := "DB2006_SA".SA[#t_Index].Config_EscaladoMinIngenieria;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinTarjeta := "DB2006_SA".SA[#t_Index].Config_EscaladoMinTarjeta;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoOffset := "DB2006_SA".SA[#t_Index].Config_EscaladoOffset;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_Habilitar := "DB2006_SA".SA[#t_Index].Config_Habilitar;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMax := "DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMax;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMin := "DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMin;
"DB2806_SA_MUX".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 := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Estado_AutoMan;
"DB2006_SA".SA[#t_Index].Orden_ConsignaManual := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaManual;
"DB2006_SA".SA[#t_Index].Orden_ConsignaEnclavado := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Orden_ConsignaEnclavado;
"DB2006_SA".SA[#t_Index].Config_DireccionSalidaByte := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_DireccionSalidaByte;
"DB2006_SA".SA[#t_Index].Config_ErrorMaxIngenieria := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_ErrorMaxIngenieria;
"DB2006_SA".SA[#t_Index].Config_ErrorMinIngenieria := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_ErrorMinIngenieria;
"DB2006_SA".SA[#t_Index].Config_EscaladoMaxIngenieria := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMaxIngenieria;
"DB2006_SA".SA[#t_Index].Config_EscaladoMaxTarjeta := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMaxTarjeta;
"DB2006_SA".SA[#t_Index].Config_EscaladoMinIngenieria := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMinIngenieria;
"DB2006_SA".SA[#t_Index].Config_EscaladoMinTarjeta := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMinTarjeta;
"DB2006_SA".SA[#t_Index].Config_EscaladoOffset := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoOffset;
"DB2006_SA".SA[#t_Index].Config_Habilitar := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_Habilitar;
"DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMax := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMax;
"DB2006_SA".SA[#t_Index].Config_HabilitarAlarmaMin := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMin;
"DB2006_SA".SA[#t_Index].Config_TipoAcceso := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_TipoAcceso;
// Actualizamos el estado original para configuraciones
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_DireccionSalidaByte := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_DireccionSalidaByte;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_ErrorMaxIngenieria := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_ErrorMaxIngenieria;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_ErrorMinIngenieria := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_ErrorMinIngenieria;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxIngenieria := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMaxIngenieria;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMaxTarjeta := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMaxTarjeta;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinIngenieria := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMinIngenieria;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoMinTarjeta := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoMinTarjeta;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_EscaladoOffset := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_EscaladoOffset;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_Habilitar := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_Habilitar;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMax := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMax;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_HabilitarAlarmaMin := "DB2806_SA_MUX".Mux.Scada[#for_mux].SA.Config_HabilitarAlarmaMin;
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA.Config_TipoAcceso := "DB2806_SA_MUX".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.
"DB2806_SA_MUX".Mux.Scada[#for_mux].SA := "DB2006_SA".SA[0];
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldSA := "DB2006_SA".SA[0];
// Actualizacion de estado anterior
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldIndex := 0;
END_IF;
ELSE
// Multiplexado no habilitado
"DB2806_SA_MUX".Mux.Scada[#for_mux].Index :=
"DB2806_SA_MUX".Mux.Scada[#for_mux].oldIndex := 0;
END_IF;
END_FOR;
END_REGION MULTIPLEXADO
END_FUNCTION

Some files were not shown because too many files have changed in this diff Show More