Cambio de formato de exportacion a S7dcl.

This commit is contained in:
2026-07-20 16:03:44 +02:00
parent 350bcb6b01
commit d551a132c0
714 changed files with 44789 additions and 30182 deletions
@@ -0,0 +1,603 @@
{
S7_Author := "ABH";
S7_BlockNumber := "15148";
S7_BlockTitle := "MLC_4JF";
S7_EditorMode := "SCL";
S7_Family := "ZeusControl";
S7_IECCheck := "TRUE";
S7_Optimized := "TRUE";
S7_Version := "1.0"
}
FUNCTION_BLOCK "FB15148_ZC_SEC_MB_CLIENT"
VAR_INPUT
{ S7_MLC := "MLC_kR" }
Habilitar : Bool := FALSE;
{ S7_MLC := "MLC_3fW" }
Iniciar : Bool;
{ S7_MLC := "MLC_3En" }
Ack : Bool;
{ S7_MLC := "MLC_3Gg" }
Pulso1Seg : Bool;
{ S7_MLC := "MLC_4Nb" }
AutoDesconexion : Bool;
{ S7_MLC := "MLC_573" }
Numero : Int;
{
S7_Access := "ReadOnly := External";
S7_Visibility := "Hidden := External"
}
DONE : Array[1..8] of Bool;
{
S7_Access := "ReadOnly := External";
S7_Visibility := "Hidden := External"
}
BUSY : Array[1..8] of Bool;
{
S7_Access := "ReadOnly := External";
S7_Visibility := "Hidden := External"
}
ERROR : Array[1..8] of Bool;
{
S7_Access := "ReadOnly := External";
S7_Visibility := "Hidden := External"
}
STATUS : Array[1..8] of Word;
END_VAR
VAR_OUTPUT
{ S7_MLC := "MLC_3zW" }
Finalizado : Bool;
{ S7_MLC := "MLC_4rC" }
EnEjecuccion : Bool;
{
S7_Access := "ReadOnly := External";
S7_MLC := "MLC_3C4"
}
AlgunError : Bool := FALSE;
ErrorEnBloque : Array[1..8] of Bool := [
8(FALSE)
];
{
S7_Access := "ReadOnly := External";
S7_Visibility := "Hidden := External"
}
REQ : Array[1..8] of Bool;
{
S7_Access := "ReadOnly := External";
S7_Visibility := "Hidden := External"
}
DISCONNECT : Array[1..8] of Bool;
END_VAR
VAR RETAIN
{ S7_MLC := "MLC_4v5" }
s_Etapa : Int := #ETAPA_0_REPOSO;
END_VAR
VAR
{
S7_Access := "ReadOnly := External";
S7_MLC := "MLC_3WZ";
S7_Visibility := "Hidden := External"
}
s_AlgunError : Bool := FALSE;
{
S7_Access := "ReadOnly := External";
S7_Visibility := "Hidden := External"
}
s_NumeroActual : Int;
s_SP_TiempoEsperaBusy : Int := 20;
s_TiempoEsperaBusy : Int;
s_Error : Array[1..8] of Bool := [
8(FALSE)
];
END_VAR
VAR RETAIN
s_NumeroError : Array[1..8] of UInt;
s_NumeroDone : Array[1..8] of UInt;
END_VAR
VAR_TEMP
for_i : Int;
END_VAR
VAR CONSTANT
{ S7_MLC := "MLC_4ve" }
ETAPA_0_REPOSO : Int := 0;
{ S7_MLC := "MLC_383" }
ETAPA_10_PROCESANDO_1 : Int := 10;
{ S7_MLC := "MLC_3jm" }
ETAPA_20_PROCESANDO_2 : Int := 20;
ETAPA_30_PROCESANDO_3 : Int := 30;
ETAPA_40_PROCESANDO_4 : Int := 40;
ETAPA_50_PROCESANDO_5 : Int := 50;
ETAPA_60_PROCESANDO_6 : Int := 60;
ETAPA_70_PROCESANDO_7 : Int := 70;
ETAPA_80_PROCESANDO_8 : Int := 80;
END_VAR
{ S7_Language := "SCL" }
NETWORK
(*
ZEUS CONTROL, S.A.
(c)Copyright (2025) All Rights Reserved
--------------------------------------------------------------------------------------
Software: TIA Portal 18
Restricciones: PLC serie 1200/1500
Nombre: FB15148_ZC_SEC_MB_CLIENT
Descripcion: Bloque de funcion para gestion de comunicaciones secuenciales MODBUS.
Dependencias:
FC: -
FB: -
DB: -
UDT: -
Change log:
Version Fecha Tecnico a cargo Descripcion
01.00.00    04.07.2025  (ABH)   Primera version
//=====================================================================================
*)
REGION LIMITES
#s_NumeroActual := #Numero;
IF #s_NumeroActual > 8 THEN
#s_NumeroActual := 8;
END_IF;
IF #s_NumeroActual < 1 THEN
#s_NumeroActual := 1;
END_IF;
END_REGION
REGION ORDEN_DE_INICIO
IF NOT #Habilitar OR #Ack THEN
#s_AlgunError := FALSE;
FOR #for_i := 1 TO 8 DO
#REQ[#for_i] := FALSE;
#DISCONNECT[#for_i] := TRUE;
#s_Error[#for_i] := FALSE;
#s_NumeroDone[#for_i] := 0;
#s_NumeroError[#for_i] := 0;
END_FOR;
#s_Etapa := #ETAPA_0_REPOSO;
END_IF;
IF #Habilitar AND #s_Etapa = 0 AND #s_NumeroActual > 0 AND #Iniciar THEN
#s_AlgunError := FALSE;
#s_Etapa := #ETAPA_10_PROCESANDO_1;
// Reinicializamos las variables REQ y ERROR
FOR #for_i := 1 TO 8 DO
#REQ[#for_i] := FALSE;
#s_Error[#for_i] := FALSE;
IF #AutoDesconexion THEN
#DISCONNECT[#for_i] := TRUE;
END_IF;
END_FOR;
END_IF;
END_REGION
REGION SECUENCIA
CASE #s_Etapa OF
#ETAPA_0_REPOSO:
;
#ETAPA_10_PROCESANDO_1:
REGION MB_CLIENT_1
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[1] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 0 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[1] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[1] THEN
// Quitamos la peticion
#REQ[1] := FALSE;
#s_NumeroDone[1] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_20_PROCESANDO_2;
// En caso de error mostramos informacion
ELSIF #ERROR[1] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[1] := TRUE;
#REQ[1] := FALSE;
#s_NumeroError[1] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_20_PROCESANDO_2;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[1] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_20_PROCESANDO_2:
REGION MB_CLIENT_2
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[2] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 1 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[2] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[2] THEN
// Quitamos la peticion
#REQ[2] := FALSE;
#s_NumeroDone[2] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_30_PROCESANDO_3;
// En caso de error mostramos informacion
ELSIF #ERROR[2] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[2] := TRUE;
#REQ[2] := FALSE;
#s_NumeroError[2] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_30_PROCESANDO_3;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[2] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_30_PROCESANDO_3:
REGION MB_CLIENT_3
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[3] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 2 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[3] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[3] THEN
// Quitamos la peticion
#REQ[3] := FALSE;
#s_NumeroDone[3] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_40_PROCESANDO_4;
// En caso de error mostramos informacion
ELSIF #ERROR[3] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[3] := TRUE;
#REQ[3] := FALSE;
#s_NumeroError[3] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_40_PROCESANDO_4;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[3] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_40_PROCESANDO_4:
REGION MB_CLIENT_4
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[4] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 3 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[4] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[4] THEN
// Quitamos la peticion
#REQ[4] := FALSE;
#s_NumeroDone[4] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_50_PROCESANDO_5;
// En caso de error mostramos informacion
ELSIF #ERROR[4] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[4] := TRUE;
#REQ[4] := FALSE;
#s_NumeroError[4] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_50_PROCESANDO_5;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[4] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_50_PROCESANDO_5:
REGION MB_CLIENT_5
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[5] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 4 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[5] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[5] THEN
// Quitamos la peticion
#REQ[5] := FALSE;
#s_NumeroDone[5] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_60_PROCESANDO_6;
// En caso de error mostramos informacion
ELSIF #ERROR[5] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[5] := TRUE;
#REQ[5] := FALSE;
#s_NumeroError[5] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_60_PROCESANDO_6;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[5] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_60_PROCESANDO_6:
REGION MB_CLIENT_6
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[6] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 5 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[6] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[6] THEN
// Quitamos la peticion
#REQ[6] := FALSE;
#s_NumeroDone[6] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_70_PROCESANDO_7;
// En caso de error mostramos informacion
ELSIF #ERROR[6] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[6] := TRUE;
#REQ[6] := FALSE;
#s_NumeroError[6] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_70_PROCESANDO_7;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[6] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_70_PROCESANDO_7:
REGION MB_CLIENT_7
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[7] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 6 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[7] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[7] THEN
// Quitamos la peticion
#REQ[7] := FALSE;
#s_NumeroDone[7] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_80_PROCESANDO_8;
// En caso de error mostramos informacion
ELSIF #ERROR[7] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[7] := TRUE;
#REQ[7] := FALSE;
#s_NumeroError[7] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_80_PROCESANDO_8;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[7] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_80_PROCESANDO_8:
REGION MB_CLIENT_8
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[8] := FALSE;
// Lanzamos la orden del GET
#REQ[8] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[8] THEN
// Quitamos la peticion
#REQ[8] := FALSE;
#s_NumeroDone[8] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_0_REPOSO;
// En caso de error mostramos informacion
ELSIF #ERROR[8] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[8] := TRUE;
#REQ[8] := FALSE;
#s_NumeroError[8] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_0_REPOSO;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[8] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_REGION
ELSE
#s_Etapa := #ETAPA_0_REPOSO;
END_CASE;
END_REGION
REGION SALIDAS
#Finalizado := #s_Etapa = 0;
#EnEjecuccion := #s_Etapa <> 0;
// Gestion señales de salida de bloque
#s_AlgunError := FALSE;
FOR #for_i := 1 TO 8 DO
#ErrorEnBloque[#for_i] := #s_Error[#for_i];
IF #s_Error[#for_i] THEN
#s_AlgunError := TRUE;
END_IF;
END_FOR;
#AlgunError := #s_AlgunError;
END_REGION
END_NETWORK
END_FUNCTION_BLOCK
@@ -0,0 +1,26 @@
MultiLingualTexts:
- id: MLC_4JF
es-ES: FB15148_ZC_SEC_MB_CLIENT
- id: MLC_kR
es-ES: Habilitacion General
- id: MLC_3fW
es-ES: Iniciar secuencia
- id: MLC_3En
es-ES: Acuse general para resetear la secuencia
- id: MLC_3Gg
es-ES: Pulso de 1 segundo
- id: MLC_4Nb
es-ES: 0= Deshabilitada / 1= Habilitada
- id: MLC_573
es-ES: Numero total de bloques
- id: MLC_3zW
es-ES: Secuencia finalizada
- id: MLC_4rC
es-ES: Secuencia en ejecucion
- id: MLC_3C4
es-ES: Algun error
- id: MLC_4v5
- id: MLC_3WZ
- id: MLC_4ve
- id: MLC_383
- id: MLC_3jm
@@ -1,549 +0,0 @@
FUNCTION_BLOCK "FB15148_ZC_SEC_MB_CLIENT"
TITLE = FB15148_ZC_SEC_MB_CLIENT
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
VAR_INPUT
Habilitar : Bool := FALSE; // Habilitacion General
Iniciar : Bool; // Iniciar secuencia
Ack : Bool; // Acuse general para resetear la secuencia
Pulso1Seg : Bool; // Pulso de 1 segundo
AutoDesconexion : Bool; // 0= Deshabilitada / 1= Habilitada
Numero : Int; // Numero total de bloques
DONE { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..8] of Bool;
BUSY { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..8] of Bool;
ERROR { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..8] of Bool;
STATUS { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..8] of Word;
END_VAR
VAR_OUTPUT
Finalizado : Bool; // Secuencia finalizada
EnEjecuccion : Bool; // Secuencia en ejecucion
AlgunError { ExternalWritable := 'False'} : Bool := FALSE; // Algun error
ErrorEnBloque { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Array[1..8] of Bool := [8(FALSE)];
REQ { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..8] of Bool;
DISCONNECT { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..8] of Bool;
END_VAR
VAR RETAIN
s_Etapa : Int := #ETAPA_0_REPOSO;
END_VAR
VAR
s_AlgunError { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool := FALSE;
s_NumeroActual { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
s_SP_TiempoEsperaBusy : Int := 20;
s_TiempoEsperaBusy : Int;
s_Error : Array[1..8] of Bool := [8(FALSE)];
END_VAR
VAR RETAIN
s_NumeroError : Array[1..8] of UInt;
s_NumeroDone : Array[1..8] of UInt;
END_VAR
VAR_TEMP
for_i : Int;
END_VAR
VAR CONSTANT
ETAPA_0_REPOSO : Int := 0;
ETAPA_10_PROCESANDO_1 : Int := 10;
ETAPA_20_PROCESANDO_2 : Int := 20;
ETAPA_30_PROCESANDO_3 : Int := 30;
ETAPA_40_PROCESANDO_4 : Int := 40;
ETAPA_50_PROCESANDO_5 : Int := 50;
ETAPA_60_PROCESANDO_6 : Int := 60;
ETAPA_70_PROCESANDO_7 : Int := 70;
ETAPA_80_PROCESANDO_8 : Int := 80;
END_VAR
BEGIN
(*
ZEUS CONTROL, S.A.
(c)Copyright (2025) All Rights Reserved
--------------------------------------------------------------------------------------
Software: TIA Portal 18
Restricciones: PLC serie 1200/1500
Nombre: FB15148_ZC_SEC_MB_CLIENT
Descripcion: Bloque de funcion para gestion de comunicaciones secuenciales MODBUS.
Dependencias:
FC: -
FB: -
DB: -
UDT: -
Change log:
Version Fecha Tecnico a cargo Descripcion
01.00.00    04.07.2025  (ABH)   Primera version
//=====================================================================================
*)
REGION LIMITES
#s_NumeroActual := #Numero;
IF #s_NumeroActual > 8 THEN
#s_NumeroActual := 8;
END_IF;
IF #s_NumeroActual < 1 THEN
#s_NumeroActual := 1;
END_IF;
END_REGION
REGION ORDEN_DE_INICIO
IF NOT #Habilitar OR #Ack THEN
#s_AlgunError := FALSE;
FOR #for_i := 1 TO 8 DO
#REQ[#for_i] := FALSE;
#DISCONNECT[#for_i] := TRUE;
#s_Error[#for_i] := FALSE;
#s_NumeroDone[#for_i] := 0;
#s_NumeroError[#for_i] := 0;
END_FOR;
#s_Etapa := #ETAPA_0_REPOSO;
END_IF;
IF #Habilitar AND #s_Etapa = 0 AND #s_NumeroActual > 0 AND #Iniciar THEN
#s_AlgunError := FALSE;
#s_Etapa := #ETAPA_10_PROCESANDO_1;
// Reinicializamos las variables REQ y ERROR
FOR #for_i := 1 TO 8 DO
#REQ[#for_i] := FALSE;
#s_Error[#for_i] := FALSE;
IF #AutoDesconexion THEN
#DISCONNECT[#for_i] := TRUE;
END_IF;
END_FOR;
END_IF;
END_REGION
REGION SECUENCIA
CASE #s_Etapa OF
#ETAPA_0_REPOSO:
;
#ETAPA_10_PROCESANDO_1:
REGION MB_CLIENT_1
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[1] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 0 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[1] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[1] THEN
// Quitamos la peticion
#REQ[1] := FALSE;
#s_NumeroDone[1] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_20_PROCESANDO_2;
// En caso de error mostramos informacion
ELSIF #ERROR[1] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[1] := TRUE;
#REQ[1] := FALSE;
#s_NumeroError[1] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_20_PROCESANDO_2;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[1] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_20_PROCESANDO_2:
REGION MB_CLIENT_2
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[2] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 1 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[2] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[2] THEN
// Quitamos la peticion
#REQ[2] := FALSE;
#s_NumeroDone[2] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_30_PROCESANDO_3;
// En caso de error mostramos informacion
ELSIF #ERROR[2] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[2] := TRUE;
#REQ[2] := FALSE;
#s_NumeroError[2] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_30_PROCESANDO_3;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[2] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_30_PROCESANDO_3:
REGION MB_CLIENT_3
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[3] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 2 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[3] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[3] THEN
// Quitamos la peticion
#REQ[3] := FALSE;
#s_NumeroDone[3] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_40_PROCESANDO_4;
// En caso de error mostramos informacion
ELSIF #ERROR[3] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[3] := TRUE;
#REQ[3] := FALSE;
#s_NumeroError[3] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_40_PROCESANDO_4;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[3] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_40_PROCESANDO_4:
REGION MB_CLIENT_4
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[4] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 3 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[4] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[4] THEN
// Quitamos la peticion
#REQ[4] := FALSE;
#s_NumeroDone[4] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_50_PROCESANDO_5;
// En caso de error mostramos informacion
ELSIF #ERROR[4] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[4] := TRUE;
#REQ[4] := FALSE;
#s_NumeroError[4] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_50_PROCESANDO_5;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[4] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_50_PROCESANDO_5:
REGION MB_CLIENT_5
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[5] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 4 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[5] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[5] THEN
// Quitamos la peticion
#REQ[5] := FALSE;
#s_NumeroDone[5] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_60_PROCESANDO_6;
// En caso de error mostramos informacion
ELSIF #ERROR[5] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[5] := TRUE;
#REQ[5] := FALSE;
#s_NumeroError[5] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_60_PROCESANDO_6;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[5] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_60_PROCESANDO_6:
REGION MB_CLIENT_6
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[6] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 5 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[6] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[6] THEN
// Quitamos la peticion
#REQ[6] := FALSE;
#s_NumeroDone[6] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_70_PROCESANDO_7;
// En caso de error mostramos informacion
ELSIF #ERROR[6] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[6] := TRUE;
#REQ[6] := FALSE;
#s_NumeroError[6] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_70_PROCESANDO_7;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[6] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_70_PROCESANDO_7:
REGION MB_CLIENT_7
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[7] := FALSE;
// Comprobamos que esta configurado los datos del enlace S7
IF #s_NumeroActual = 6 THEN
// No esta configurado el enlace, Finalizamos
#s_TiempoEsperaBusy := 0;
#s_Etapa := #ETAPA_0_REPOSO;
ELSE
// Lanzamos la orden del GET
#REQ[7] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[7] THEN
// Quitamos la peticion
#REQ[7] := FALSE;
#s_NumeroDone[7] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_80_PROCESANDO_8;
// En caso de error mostramos informacion
ELSIF #ERROR[7] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[7] := TRUE;
#REQ[7] := FALSE;
#s_NumeroError[7] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_80_PROCESANDO_8;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[7] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_IF;
END_REGION
#ETAPA_80_PROCESANDO_8:
REGION MB_CLIENT_8
// Quitamos la orden de desconexion con el equipo
#DISCONNECT[8] := FALSE;
// Lanzamos la orden del GET
#REQ[8] := TRUE;
// Esperamos a que finalice correctamente el GET
IF #DONE[8] THEN
// Quitamos la peticion
#REQ[8] := FALSE;
#s_NumeroDone[8] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_0_REPOSO;
// En caso de error mostramos informacion
ELSIF #ERROR[8] OR #s_TiempoEsperaBusy >= #s_SP_TiempoEsperaBusy THEN
#s_Error[8] := TRUE;
#REQ[8] := FALSE;
#s_NumeroError[8] += 1;
#s_TiempoEsperaBusy := 0;
// Saltamos al siguiente
#s_Etapa := #ETAPA_0_REPOSO;
END_IF;
// Gestion de errores por tiempo sin respuesta
IF #BUSY[8] AND #Pulso1Seg THEN
#s_TiempoEsperaBusy += 1;
END_IF;
END_REGION
ELSE
#s_Etapa := #ETAPA_0_REPOSO;
END_CASE;
END_REGION
REGION SALIDAS
#Finalizado := #s_Etapa = 0;
#EnEjecuccion := #s_Etapa <> 0;
// Gestion señales de salida de bloque
#s_AlgunError := FALSE;
FOR #for_i := 1 TO 8 DO
#ErrorEnBloque[#for_i] := #s_Error[#for_i];
IF #s_Error[#for_i] THEN
#s_AlgunError := TRUE;
END_IF;
END_FOR;
#AlgunError := #s_AlgunError;
END_REGION
END_FUNCTION_BLOCK
@@ -0,0 +1,307 @@
{
S7_Author := "ABH";
S7_BlockComment := "MLC_44J";
S7_BlockNumber := "15150";
S7_BlockTitle := "MLC_42L";
S7_EditorMode := "SCL";
S7_Family := "ZeusControl";
S7_IECCheck := "TRUE";
S7_Optimized := "TRUE";
S7_Version := "1.0"
}
FUNCTION_BLOCK "FB15150_ZC_SEC_S7COM"
VAR_INPUT
{ S7_MLC := "MLC_4vr" }
Habilitar : Bool := FALSE;
{ S7_MLC := "MLC_38z" }
Iniciar : Bool;
{ S7_MLC := "MLC_4x4" }
Ack : Bool;
{ S7_MLC := "MLC_4Zq" }
Pulso1Seg : Bool;
{ S7_MLC := "MLC_4vy" }
NumeroBloques : Int := 1;
{ S7_MLC := "MLC_3Tv" }
TiempoEspera : Int := 10;
NDR_DONE : Array[1..#N_MAX] of Bool;
ERROR : Array[1..#N_MAX] of Bool;
END_VAR
VAR_OUTPUT
{ S7_MLC := "MLC_3m5" }
Finalizado : Bool;
{ S7_MLC := "MLC_4P8" }
EnEjecuccion : Bool;
{
S7_Access := "ReadOnly := External";
S7_MLC := "MLC_4Ba"
}
AlgunError : Bool := FALSE;
EnError : Array[1..#N_MAX] of Bool := [
8(FALSE)
];
REQ : Array[1..#N_MAX] of Bool;
END_VAR
VAR RETAIN
{
S7_Access := "ReadOnly := External";
S7_MLC := "MLC_4dP";
S7_Visibility := "Hidden := External"
}
s_Etapa : Int := #REPOSO;
END_VAR
VAR
{
S7_Access := "ReadOnly := External";
S7_MLC := "MLC_Ph";
S7_Visibility := "Hidden := External"
}
s_IndiceActual : Int;
{
S7_Access := "ReadOnly := External";
S7_MLC := "MLC_V6";
S7_Visibility := "Hidden := External"
}
s_AlgunError : Bool := FALSE;
{
S7_Access := "ReadOnly := External";
S7_MLC := "MLC_LF";
S7_Visibility := "Hidden := External"
}
s_NumeroBloques : Int;
END_VAR
VAR RETAIN
{
S7_Access := "ReadOnly := External";
S7_MLC := "MLC_4Vt";
S7_Visibility := "Hidden := External"
}
s_TiempoEsperaActual : Int;
END_VAR
VAR
{
S7_Access := "ReadOnly := External";
S7_Visibility := "Hidden := External"
}
s_Error : Array[1..#N_MAX] of Bool := [
8(FALSE)
];
END_VAR
VAR RETAIN
{
S7_Access := "ReadOnly := External";
S7_Visibility := "Hidden := External"
}
s_NumeroError : Array[1..#N_MAX] of UInt;
{
S7_Access := "ReadOnly := External";
S7_Visibility := "Hidden := External"
}
s_NumeroDone : Array[1..#N_MAX] of UInt;
END_VAR
VAR_TEMP
for_i : Int;
END_VAR
VAR CONSTANT
{ S7_MLC := "MLC_4p6" }
REPOSO : Int := 0;
{ S7_MLC := "MLC_4jG" }
PROCESANDO : Int := 10;
{ S7_MLC := "MLC_376" }
N_MAX : Int := 8;
END_VAR
{ S7_Language := "SCL" }
NETWORK
REGION DESCRIPCION
//=======================================================================
// (C)Copyright ZeusControl 2024 - 2026
//=======================================================================
(*
### Información del Sistema
| Hardware Compatible | Entorno de Ingeniería |
|---------------------|-----------------------|
| PLC serie 1200/1500 | TIA Portal 18 |
---
### Descripción Funcional
El bloque `FB15150_ZC_SEC_S7COM` implementa un gestor de comunicaciones secuenciales S7 (PUT/GET) que ejecuta, de forma ordenada y con gestión de errores, una secuencia de peticiones a otros tantos bloques de comunicación. Garantiza que las operaciones se lancen una a una, esperando a la finalización de cada una (correcta o con error) antes de continuar con la siguiente, y permite acotar el tiempo de espera por petición para detectar bloqueos de la comunicación.
Funcionalidades principales:
- Habilitación y Ack: cuando el bloque se deshabilita (`#Habilitar := FALSE`) o se activa la entrada de acuse `#Ack`, se reinicializan todas las variables internas y de salida, se vacían los flags de error, se resetea la etapa a `REPOSO` y se sale del bloque mediante `RETURN`.
- Límite de dimensionamiento: se valida `#NumeroBloques` contra la constante de dimensionamiento `#N_MAX`, acotando el valor entre 1 y `#N_MAX`.
- Arranque ordenado: cuando se recibe la entrada `#Iniciar` estando en `REPOSO`, se inicializa el índice de proceso, se limpian las peticiones y los flags de error, y se transita a la etapa `PROCESANDO`.
- Procesamiento secuencial: para cada bloque actual, se lanza la activación de `#REQ` y se monitorizan las señales de fin `#NDR_DONE` y `#ERROR`. Se avanza al siguiente bloque tanto en caso de éxito como de error.
- Control de tiempo de espera: si la petición actual no finaliza antes de cumplir `#TiempoEspera` (incrementado con `#Pulso1Seg`), se da por fallida y se avanza al siguiente bloque, contabilizándolo como error.
- Salidas de estado: `#EnEjecuccion` indica que la secuencia está en curso (`#s_Etapa <> REPOSO`) y `#Finalizado` indica que la secuencia ha concluido. Por cada bloque se expone `#EnError` y un `#AlgunError` global que se activa si cualquier petición ha fallado.
> **Restricciones:** Ninguna.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 00.00.01 | 24.05.2023 | (ABH) | Primera versión. |
| 00.00.02 | 21.09.2023 | (ABH) | Cambio a SCL. |
| 00.00.03 | 24.08.2025 | (ABH) | Se añade tiempo de espera para dar como error. |
| 01.00.00 | 02.07.2026 | (ABH) | Refactorización de lógica para estandarización. Se añade constante de dimensionamiento. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION HABILITACION
// En caso de no estar habilitado el bloque o pulsar el boton ACK, reinicializamos valores y salimos inmediatamente
IF NOT #Habilitar OR #Ack THEN
#s_AlgunError := FALSE;
FOR #for_i := 1 TO #N_MAX DO
#REQ[#for_i] := FALSE;
#s_Error[#for_i] := FALSE;
#s_NumeroDone[#for_i] := 0;
#s_NumeroError[#for_i] := 0;
#EnError[#for_i] := FALSE;
END_FOR;
#s_Etapa := #REPOSO;
#s_TiempoEsperaActual := 0;
#s_IndiceActual := 1;
#Finalizado := FALSE;
#EnEjecuccion := FALSE;
#AlgunError := FALSE;
RETURN;
END_IF;
END_REGION HABILITACION
// ==========================================================================================================
REGION LIMITES
// Traspaso de numero de bloques a variable interna
#s_NumeroBloques := #NumeroBloques;
// Limite de bloques
IF #s_NumeroBloques > #N_MAX THEN
#s_NumeroBloques := #N_MAX;
ELSIF #s_NumeroBloques < 1 THEN
#s_NumeroBloques := 1;
END_IF;
END_REGION LIMITES
// ==========================================================================================================
REGION ORDEN_DE_INICIO
IF #Habilitar AND #s_Etapa = #REPOSO AND #Iniciar THEN
#s_AlgunError := FALSE;
#s_Etapa := #PROCESANDO;
#s_IndiceActual := 1; // Apuntamos al primer BLOQUE
// Reinicializamos las variables REQ y ERROR antes de empezar
FOR #for_i := 1 TO #N_MAX DO
#REQ[#for_i] := FALSE;
#s_Error[#for_i] := FALSE;
END_FOR;
#s_TiempoEsperaActual := 0;
END_IF;
END_REGION ORDEN_DE_INICIO
// ==========================================================================================================
REGION SECUENCIA
CASE #s_Etapa OF
#REPOSO:
; // Esperando orden de inicio
#PROCESANDO:
// Verificacion de final de la secuencia
IF #s_IndiceActual > #s_NumeroBloques THEN
// Si hemos procesado todos los bloques, finalizamos la secuencia
#s_Etapa := #REPOSO;
RETURN;
END_IF;
// Procesamos
REGION GESTION_COMUNICACIONES
// Lanzamos orden request para el bloque de comunicaciones
#REQ[#s_IndiceActual] := TRUE;
// Esperamos a que finalice correctamente el bloque de comunicaciones
IF #NDR_DONE[#s_IndiceActual] THEN
#REQ[#s_IndiceActual] := FALSE;
#s_NumeroDone[#s_IndiceActual] += 1;
#s_TiempoEsperaActual := 0;
// Avanzamos al siguiente bloque de comunicaciones
#s_IndiceActual += 1;
// En caso de error o Timeout
ELSIF #ERROR[#s_IndiceActual] OR #s_TiempoEsperaActual >= #TiempoEspera THEN
#s_Error[#s_IndiceActual] := TRUE;
#REQ[#s_IndiceActual] := FALSE;
#s_NumeroError[#s_IndiceActual] += 1;
#s_TiempoEsperaActual := 0;
// Avanzamos al siguiente bloque de comunicaciones
#s_IndiceActual += 1;
END_IF;
// Contador de tiempo de Timeout
IF #Pulso1Seg THEN
#s_TiempoEsperaActual += 1;
END_IF;
END_REGION GESTION_COMUNICACIONES
ELSE
#s_Etapa := #REPOSO;
END_CASE;
END_REGION SECUENCIA
// ==========================================================================================================
REGION SALIDAS
#Finalizado := (#s_Etapa = #REPOSO);
#EnEjecuccion := (#s_Etapa <> #REPOSO);
// Gestion señales de salida de bloque
#s_AlgunError := FALSE;
FOR #for_i := 1 TO #N_MAX DO
#EnError[#for_i] := #s_Error[#for_i];
IF #s_Error[#for_i] THEN
#s_AlgunError := TRUE;
END_IF;
END_FOR;
#AlgunError := #s_AlgunError;
END_REGION SALIDAS
END_NETWORK
END_FUNCTION_BLOCK
@@ -0,0 +1,64 @@
MultiLingualTexts:
- id: MLC_42L
es-ES: FB15150_ZC_SEC_GET
- id: MLC_44J
es-ES: |-
ZEUS CONTROL, S.A.
(c)Copyright (2023) All Rights Reserved
--------------------------------------------------------------------------------------
Software: TIA Portal 16
Restricciones: PLC serie 1200/1500
Nombre: FB15150_ZC_SEC_GET
Descripcion: Bloque de funcion para gestion de comunicaciones secuenciales GET.
Dependencias:
FC: -
FB: -
DB: -
UDT: -
Change log:
Version Fecha Tecnico a cargo Descripcion
01.00.00    24.05.2023  (ABH)   Primera version
01.00.01 21.09.2023 (ABH) Cambio a SCL.
//=====================================================================================
- id: MLC_4vr
es-ES: Habilitacion General
- id: MLC_38z
es-ES: Iniciar secuencia
- id: MLC_4x4
es-ES: Acuse general para resetear la secuencia
- id: MLC_4Zq
es-ES: Pulso 1 segundo
- id: MLC_4vy
es-ES: Numero de bloques de comunicacion en la secuencia
- id: MLC_3Tv
es-ES: Tiempo espera estado bloque comunicacion
- id: MLC_3m5
es-ES: Secuencia finalizada
- id: MLC_4P8
es-ES: Secuencia en ejecucion
- id: MLC_4Ba
es-ES: Algun error
- id: MLC_4dP
es-ES: Etapa actual
- id: MLC_Ph
es-ES: Indice actual del bloque de comunicacion en ejecuccion
- id: MLC_V6
es-ES: Indicador de algun error
- id: MLC_LF
es-ES: Numero de bloques
- id: MLC_4Vt
es-ES: Tiempo de espera actual
- id: MLC_4p6
es-ES: Etapa reposo
- id: MLC_4jG
es-ES: Etapa procesando
- id: MLC_376
es-ES: Numero maximo de bloques de comunicacion
@@ -1,274 +0,0 @@
FUNCTION_BLOCK "FB15150_ZC_SEC_S7COM"
TITLE = FB15150_ZC_SEC_GET
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//ZEUS CONTROL, S.A.
//(c)Copyright (2023) All Rights Reserved
//--------------------------------------------------------------------------------------
//
//Software: TIA Portal 16
//Restricciones: PLC serie 1200/1500
//
//Nombre: FB15150_ZC_SEC_GET
//Descripcion: Bloque de funcion para gestion de comunicaciones secuenciales GET.
//
//Dependencias:
// FC: -
// FB: -
// DB: -
// UDT: -
//
//
//Change log:
//
// Version Fecha Tecnico a cargo Descripcion
//
// 01.00.00    24.05.2023  (ABH)   Primera version
// 01.00.01 21.09.2023 (ABH) Cambio a SCL.
//
////=====================================================================================
VAR_INPUT
Habilitar : Bool := FALSE; // Habilitacion General
Iniciar : Bool; // Iniciar secuencia
Ack : Bool; // Acuse general para resetear la secuencia
Pulso1Seg : Bool; // Pulso 1 segundo
NumeroBloques { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Int := 1; // Numero de bloques de comunicacion en la secuencia
TiempoEspera { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Int := 10; // Tiempo espera estado bloque comunicacion
NDR_DONE : Array[1..#N_MAX] of Bool;
ERROR : Array[1..#N_MAX] of Bool;
END_VAR
VAR_OUTPUT
Finalizado : Bool; // Secuencia finalizada
EnEjecuccion : Bool; // Secuencia en ejecucion
AlgunError { ExternalWritable := 'False'} : Bool := FALSE; // Algun error
EnError { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Array[1..#N_MAX] of Bool := [8(FALSE)];
REQ { S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Array[1..#N_MAX] of Bool;
END_VAR
VAR RETAIN
s_Etapa { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int := #REPOSO; // Etapa actual
END_VAR
VAR
s_IndiceActual { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Indice actual del bloque de comunicacion en ejecuccion
s_AlgunError { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool := FALSE; // Indicador de algun error
s_NumeroBloques { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Numero de bloques
END_VAR
VAR RETAIN
s_TiempoEsperaActual { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int; // Tiempo de espera actual
END_VAR
VAR
s_Error { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..#N_MAX] of Bool := [8(FALSE)];
END_VAR
VAR RETAIN
s_NumeroError { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..#N_MAX] of UInt;
s_NumeroDone { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..#N_MAX] of UInt;
END_VAR
VAR_TEMP
for_i : Int;
END_VAR
VAR CONSTANT
REPOSO : Int := 0; // Etapa reposo
PROCESANDO : Int := 10; // Etapa procesando
N_MAX : Int := 8; // Numero maximo de bloques de comunicacion
END_VAR
BEGIN
REGION DESCRIPCION
//=======================================================================
// (C)Copyright ZeusControl 2024 - 2026
//=======================================================================
(*
### Información del Sistema
| Hardware Compatible | Entorno de Ingeniería |
|---------------------|-----------------------|
| PLC serie 1200/1500 | TIA Portal 18 |
---
### Descripción Funcional
El bloque `FB15150_ZC_SEC_S7COM` implementa un gestor de comunicaciones secuenciales S7 (PUT/GET) que ejecuta, de forma ordenada y con gestión de errores, una secuencia de peticiones a otros tantos bloques de comunicación. Garantiza que las operaciones se lancen una a una, esperando a la finalización de cada una (correcta o con error) antes de continuar con la siguiente, y permite acotar el tiempo de espera por petición para detectar bloqueos de la comunicación.
Funcionalidades principales:
- Habilitación y Ack: cuando el bloque se deshabilita (`#Habilitar := FALSE`) o se activa la entrada de acuse `#Ack`, se reinicializan todas las variables internas y de salida, se vacían los flags de error, se resetea la etapa a `REPOSO` y se sale del bloque mediante `RETURN`.
- Límite de dimensionamiento: se valida `#NumeroBloques` contra la constante de dimensionamiento `#N_MAX`, acotando el valor entre 1 y `#N_MAX`.
- Arranque ordenado: cuando se recibe la entrada `#Iniciar` estando en `REPOSO`, se inicializa el índice de proceso, se limpian las peticiones y los flags de error, y se transita a la etapa `PROCESANDO`.
- Procesamiento secuencial: para cada bloque actual, se lanza la activación de `#REQ` y se monitorizan las señales de fin `#NDR_DONE` y `#ERROR`. Se avanza al siguiente bloque tanto en caso de éxito como de error.
- Control de tiempo de espera: si la petición actual no finaliza antes de cumplir `#TiempoEspera` (incrementado con `#Pulso1Seg`), se da por fallida y se avanza al siguiente bloque, contabilizándolo como error.
- Salidas de estado: `#EnEjecuccion` indica que la secuencia está en curso (`#s_Etapa <> REPOSO`) y `#Finalizado` indica que la secuencia ha concluido. Por cada bloque se expone `#EnError` y un `#AlgunError` global que se activa si cualquier petición ha fallado.
> **Restricciones:** Ninguna.
---
### Dependencias Requeridas
| Tipo | Elementos |
|------|-----------|
| FC | - |
| FB | - |
| DB | - |
| UDT | - |
---
### Historial de Cambios
| Versión | Fecha | Técnico | Cambios |
|----------|------------|---------|---------|
| 00.00.01 | 24.05.2023 | (ABH) | Primera versión. |
| 00.00.02 | 21.09.2023 | (ABH) | Cambio a SCL. |
| 00.00.03 | 24.08.2025 | (ABH) | Se añade tiempo de espera para dar como error. |
| 01.00.00 | 02.07.2026 | (ABH) | Refactorización de lógica para estandarización. Se añade constante de dimensionamiento. |
*)
END_REGION DESCRIPCION
// ==========================================================================================================
REGION HABILITACION
// En caso de no estar habilitado el bloque o pulsar el boton ACK, reinicializamos valores y salimos inmediatamente
IF NOT #Habilitar OR #Ack THEN
#s_AlgunError := FALSE;
FOR #for_i := 1 TO #N_MAX DO
#REQ[#for_i] := FALSE;
#s_Error[#for_i] := FALSE;
#s_NumeroDone[#for_i] := 0;
#s_NumeroError[#for_i] := 0;
#EnError[#for_i] := FALSE;
END_FOR;
#s_Etapa := #REPOSO;
#s_TiempoEsperaActual := 0;
#s_IndiceActual := 1;
#Finalizado := FALSE;
#EnEjecuccion := FALSE;
#AlgunError := FALSE;
RETURN;
END_IF;
END_REGION HABILITACION
// ==========================================================================================================
REGION LIMITES
// Traspaso de numero de bloques a variable interna
#s_NumeroBloques := #NumeroBloques;
// Limite de bloques
IF #s_NumeroBloques > #N_MAX THEN
#s_NumeroBloques := #N_MAX;
ELSIF #s_NumeroBloques < 1 THEN
#s_NumeroBloques := 1;
END_IF;
END_REGION LIMITES
// ==========================================================================================================
REGION ORDEN_DE_INICIO
IF #Habilitar AND #s_Etapa = #REPOSO AND #Iniciar THEN
#s_AlgunError := FALSE;
#s_Etapa := #PROCESANDO;
#s_IndiceActual := 1; // Apuntamos al primer BLOQUE
// Reinicializamos las variables REQ y ERROR antes de empezar
FOR #for_i := 1 TO #N_MAX DO
#REQ[#for_i] := FALSE;
#s_Error[#for_i] := FALSE;
END_FOR;
#s_TiempoEsperaActual := 0;
END_IF;
END_REGION ORDEN_DE_INICIO
// ==========================================================================================================
REGION SECUENCIA
CASE #s_Etapa OF
#REPOSO:
; // Esperando orden de inicio
#PROCESANDO:
// Verificacion de final de la secuencia
IF #s_IndiceActual > #s_NumeroBloques THEN
// Si hemos procesado todos los bloques, finalizamos la secuencia
#s_Etapa := #REPOSO;
RETURN;
END_IF;
// Procesamos
REGION GESTION_COMUNICACIONES
// Lanzamos orden request para el bloque de comunicaciones
#REQ[#s_IndiceActual] := TRUE;
// Esperamos a que finalice correctamente el bloque de comunicaciones
IF #NDR_DONE[#s_IndiceActual] THEN
#REQ[#s_IndiceActual] := FALSE;
#s_NumeroDone[#s_IndiceActual] += 1;
#s_TiempoEsperaActual := 0;
// Avanzamos al siguiente bloque de comunicaciones
#s_IndiceActual += 1;
// En caso de error o Timeout
ELSIF #ERROR[#s_IndiceActual] OR #s_TiempoEsperaActual >= #TiempoEspera THEN
#s_Error[#s_IndiceActual] := TRUE;
#REQ[#s_IndiceActual] := FALSE;
#s_NumeroError[#s_IndiceActual] += 1;
#s_TiempoEsperaActual := 0;
// Avanzamos al siguiente bloque de comunicaciones
#s_IndiceActual += 1;
END_IF;
// Contador de tiempo de Timeout
IF #Pulso1Seg THEN
#s_TiempoEsperaActual += 1;
END_IF;
END_REGION GESTION_COMUNICACIONES
ELSE
#s_Etapa := #REPOSO;
END_CASE;
END_REGION SECUENCIA
// ==========================================================================================================
REGION SALIDAS
#Finalizado := (#s_Etapa = #REPOSO);
#EnEjecuccion := (#s_Etapa <> #REPOSO);
// Gestion señales de salida de bloque
#s_AlgunError := FALSE;
FOR #for_i := 1 TO #N_MAX DO
#EnError[#for_i] := #s_Error[#for_i];
IF #s_Error[#for_i] THEN
#s_AlgunError := TRUE;
END_IF;
END_FOR;
#AlgunError := #s_AlgunError;
END_REGION SALIDAS
END_FUNCTION_BLOCK