19 KiB
Sistema DAR – Diet as Regular
SAE452 · Mixer Sidel con CPU S7-317
1. Objetivo
- Reducir pérdidas de jarabe (syrup) durante los cambios de producto.
- Compensar la dilución y la variabilidad de °Brix del jarabe Diet, tratándolo como Regular:
- Al inicio: detectar la llegada real de jarabe y comenzar la carga del tanque TP301 sin arrastrar agua.
- Al final: detectar la desaparición del jarabe y drenar sólo el volumen mínimo necesario.
2. Alcance de este documento
Step 0 / Step 1 del proyecto DAR: lectura de instrumentos, detección de interfaces agua/jarabe y alarmas de conductividad.
La autocorrección de mezcla (Step 2) y el control refinado con UR29 no se detallan aquí.
3. Arquitectura de instrumentación añadida
Etiqueta | Instrumento | Función principal | Interface PLC |
---|---|---|---|
UR62 – QTM306 | Refractómetro Maselli (Ø 2″) | Detección rápida de paso agua → jarabe y jarabe → agua en la línea de llegada «Syrup Line» | 4-20 mA ó TCP (seleccionable)HMI_Instrument.QTM306 |
UR29 – QTM307 | Refractómetro Maselli alta precisión (stream jarabe) | Medición precisa de °Brix para futura autocorrección (Step 2) | 4-20 mA/TCPHMI_Instrument.QTM307 |
CTS306 | Conductivímetro Knick 2405 | Comprobar dureza (µS/cm) del agua de proceso; generar alarmas fuera de rango | 4-20 mAHMI_Instrument.CTS306 |
Diagrama simplificado:
[ Water In ]--CTS306----┐
│
(purge) +--┴--Drain
|
Syrup Tanks --Pump--UR62(QTM306)-----> Mixer pipe ---> UR29(QTM307) ---> TP301
4. Fases operativas
-
Priming / Syrup Line Preparation
- La sala de jarabe envía agua para purga inicial.
UR62
lee °Brix. MientrasBrix_UR62
sea menor que el umbral_BrixCutUR62
, la válvula AVS347/348 permanece abierta a drenaje y se descartan los litros contados en la tabla histórica según el tanque origen.- Cuando
Brix_UR62 ≥ _BrixCutUR62
(filtro TON 0,5 s) ⇒- Se cierra drenaje, se abre ruta a TP301 y se inicia el totalizador de jarabe.
-
Carga de TP301 (Producción)
- El control de caudal se basa en los medidores FTP302 (masa jarabe) y FTN301 (agua).
UR29
todavía puede monitorizar, pero no interviene en Step 1.
-
Final de producción (Run-out)
- El set point de corte es el mismo principio pero inverso: cuando
Brix_UR62
cae por debajo de_BrixCutUR62
se considera fin de jarabe y se conmuta a agua.
- El set point de corte es el mismo principio pero inverso: cuando
-
Alarmas de conductividad
CTS306.PVFiltered
se compara con los límites (_Water_Conduct_Min
y_Water_Conduct_Max
) configurados en la receta:- Bajo límite ⇒
Alarm084
- Sobre límite ⇒
Alarm085
- Bajo límite ⇒
5. Algoritmo de corte °Brix
Variable receta: Recipe__XX.Actual_Recipe_Parameters._BrixCutUR62
SyrBrix_Threshold = SyrBrix_Recipe * _BrixCutUR62
La recomendación inicial (Step 1) es 50 % del °Brix nominal del jarabe.
El valor es configurable por receta para adaptar distintas formulaciones.
Condición lógica (extracto de idea):
IF UR62_Brix ≥ SyrBrix_Threshold THEN
SyrupLoaded := TRUE // comienza carga TP301
ELSE
SyrupLoaded := FALSE // continúa drenaje
6. Implementación en el PLC
6.1 Lectura analógica vs digital
Bloque Maselli_ADAM_Read
o_Brix := … // conversión 4-20 mA → °Brix
o_Alarm_Present := CurrentErrorCode <> 0
En DAR_Logic
se selecciona la fuente según parámetro READ_MASELLI_DIGITAL
:
FALSE
⇒ Vía IM155 (PEW) yMaselli_ADAM_Read
TRUE
⇒ Comunicación TCP (MaselliTCP_DB_UR62
,MaselliTCP_DB_UR29
)
6.2 Variables clave
Variable | Descripción |
---|---|
HMI_Instrument.QTM306.PVFiltered |
°Brix filtrado de UR62 |
HMI_Instrument.QTM307.PVFiltered |
°Brix filtrado de UR29 |
HMI_Instrument.CTS306.PVFiltered |
Conductividad agua |
Recipe..._Water_Conduct_Min/Max |
Límites de alarma |
_BrixCutUR62 |
% de corte sobre °Brix jarabe |
6.3 Lógica de alarmas (fragmento)
IF CTS306.PVFiltered < _Water_Conduct_Min THEN Alarm084 := TRUE;
IF CTS306.PVFiltered > _Water_Conduct_Max THEN Alarm085 := TRUE;
6.4 Tabla de litros por tanque (legacy)
Mientras se afina el disparo por °Brix, el programa sigue disponiendo de la matriz de volúmenes históricos para cada tanque de origen. Esta tabla se encuentra en los datos persistentes de la sala Syrup y se usa como respaldo.
7. Calibración y puesta en marcha
-
Parametrizar en cada receta:
- °Brix jarabe (
_SyrupBrix
) _BrixCutUR62
(empíricamente 0,5)- Límites de conductividad agua.
- °Brix jarabe (
-
Verificar offset ADC-DAC (
i_Offset_ADC_DAC
) enMaselli_ADAM_Read
(≈ 0,025 mA medido). -
Comprobar IP de los gateways digitales (líneas 22-27 de
DAR_Logic
). -
Ejecutar pruebas de paso agua→jarabe y jarabe→agua para cada línea/tanque y ajustar
_BrixCutUR62
si aparecen falsos disparos.
8. Mejoras previstas (Step 2)
- Uso de
UR29
para autocorrección del ratio agua/jarabe (SyrBrix_Autocorrection.scl
). - Cierre automático según
Brix_UR29
en Storage TM301. - Sustitución completa de tabla de litros por detección 100 % basada en °Brix.
9. Referencias de código
source/DAR_Logic.scl
– Funciones principales de lectura y alarmas.source/Maselli_ADAM_Read.scl
– Conversión 4-20 mA → °Brix.source/HMI_Instrument.scl
– DB de proceso con variables de los instrumentos.source/Syrup_Line_MFM_Prep_DAR.scl
– Secuencia automática de purga/carga (FC 1813 propuesto).source/Recipe__XX.scl
– Parámetros de receta (_BrixCutUR62, conductividad, etc.).
10. Anexo – Tabla rápida de códigos de error Maselli_ADAM_Read
Código | Significado | Rango mA |
---|---|---|
0 | OK | 3,9 – 20,1 |
1 | Maselli sin datos | ≈ 1,5 ± 0,1 |
2 | Alarma Maselli | ≈ 2,0 ± 0,1 |
3 | Sobre-rango alto | 20,1 – 22,8 |
4 | Overflow | > 22,8 |
5 | Sub-rango general | — |
6 | Crítico (< 1,185 mA) | < 1,185 |
11. Detalle operativo actual de cálculo de litros y criterios de corte
11.1 Inicio – Priming de la línea Syrup
- Al iniciar la secuencia
FTP302Line_Preparation
se copia el totalizador instantáneo del caudalímetro de jarabe FTP302:
gSyrLinePrepCountInit := Profibus_Variables.gFTP302_Tot
- En cada ciclo se calcula el volumen realmente desplazado desde ese instante:
TP301SyrupPrimingCount = Profibus_Variables.gFTP302_Tot - gSyrLinePrepCountInit
- Umbral volumétrico:
Aux_Somma_Lt = _SyrupRunOutLiters + DB784
(DB784 es un ajuste dinámico calculado por la lógica fuzzy-net).WaterCountAcheaved = TP301SyrupPrimingCount ≥ Aux_Somma_Lt
- Umbral de °Brix (ver §5):
UR62_Brix ≥ SyrBrix_Threshold
- Condiciones de fin de priming (se deben cumplir ambas):
WaterCountAcheaved = TRUE
AND UR62_Brix ≥ SyrBrix_Threshold
Cuando esto ocurre, la FB Syrup_Line_MFM_Prep_Seq
libera el paso a TP301 y pone
Procedure_Variables.FTP302Line_Preparation.LinePrepared := TRUE
.
@startuml
title 11.1 Priming – Syrup Line to TP301
hide footbox
skinparam ArrowHeadColor none
skinparam NoteBackgroundColor #F0F0F0
skinparam NoteBorderColor #999999
skinparam ParticipantPadding 20
skinparam BoxPadding 6
skinparam WrapWidth 250
!pragma teoz true
' ==== Estilos reutilizables (tomados del ejemplo) ====
!define VAR(x) <back:#F0F0F0><color:#7F6000><b>x</b></color></back>
!define SIG(x) <back:#F0F0F0><color:#005A9E><b>x</b></color></back>
!define FROM(x) <back:#FFAAAA><color:#000000><b>x</b></color></back>
!define TO(x) <back:#AAFFFF><color:#000000><b> x</b></color></back>
!definelong Nota($donde, $text)
note over $donde
$text
end note
!enddefinelong
participant "Sala Syrup" as SR
participant "Pump P2" as P2
participant "UR62\nQTM306" as UR62
participant PLC as PLC
participant "Drain Valve\nAVS347/348" as DV
participant "MFM FTP302" as FTP302
participant "Tank TP301" as TP301
== Inicio purga ==
SR -> P2 : FROM(Start purge – water)
PLC -> DV : FROM(Open drain)
loop Purga (agua)
UR62 -> PLC : SIG(Brix) ≈ 0
PLC -> FTP302 : SIG(Read Tot)
Nota(PLC, "Brix < _BrixCutUR62\nContando litros purga")
end
UR62 -> PLC : SIG(Brix) ≥ VAR(Threshold)
PLC -> PLC : TO(WaterCountAcheaved := TRUE)
== Fin priming ==
PLC -> DV : TO(Close drain)
PLC -> TP301 : TO(Route syrup to TP301)
Nota(PLC, "LinePrepared := TRUE\nSyrup loading starts")
@enduml
@startuml
' Activity Diagram – Priming Syrup Line (New Syntax)
' PlantUML activity-beta
title 11.1 Priming – Syrup Line to TP301 (Activity)
skinparam wrapWidth 240
skinparam maxMessageSize 120
start
:Iniciar purga de agua\n(Pump P2 ON, AVS347/348 OPEN);
repeat
:Medir Brix con UR62\n`Brix_UR62`;
if (¿Brix ≥ Threshold?) then (sí)
break
else (no)
:Contar litros purga\n`TP301SyrupPrimingCount += ΔFTP302`;
endif
repeat while (Brix < Threshold)
if (¿Litros ≥ Aux_Somma_Lt?) then (sí)
:WaterCountAcheaved := TRUE;
else (no)
:Seguir purgando;
goto repeat
endif
:Cerrar drenaje AVS347/348;
:Redirigir flujo a TP301;
:LinePrepared := TRUE;
stop
@enduml
11.2 Fin de producción – Empuje del producto en la tubería (Product Pipe Run-Out)
El objetivo es vaciar el tramo de tubería comprendido entre el mezclador y la llenadora sin desperdiciar producto.
Modo seleccionado mediante bits HMI:
Bit | Método de empuje | Descripción de cálculo |
---|---|---|
ProdPipeRunOutWaterCount |
Conteo volumétrico | Igual que en priming, usando la suma de totalizadores FTN301 + FTP302 . |
ProdPipeRunOutFillerBott |
Conteo de botellas | Más preciso cuando hay contador de botellas de la llenadora. |
a) Conteo volumétrico
Prod_Pipe_RunOut.Push_Count_Init := Prod_Pipe_RunOut.Totalizer // al arrancar
Prod_Pipe_RunOut.Push_Count := TotalizerActual - Push_Count_Init
ProdPushDone := Push_Count > ProdPipeRunOutProdAmount // valor receta
b) Conteo de botellas
VolumenTubing_litros = FillerBottleCount * Bottle_Size_Liters
Prod_Pipe_RunOut.Push_Count_Init := VolumenTubing_litros // al arrancar
Prod_Pipe_RunOut.Push_Count := VolumenTubing_litros - Push_Count_Init
ProdPushDone := Push_Count > ProdPipeRunOutProdAmount
Bottle_Size_Liters
se toma de Filling_Time_Tranfer_DB.Bottle_Size_Litters
y ProdPipeRunOutProdAmount
representa el volumen que cabe entre ambas máquinas, incluyendo colectores y válvulas.
c) Condición de final
La FB ProductPipeRunOut_Seq
finaliza cuando:
ProdPushDone = TRUE // volumen/botellas empujado
OR LastbottleDone = TRUE // señal In_Flr_LastContainer recibida
En ese momento:
System_RunOut_Variables.ProdPipe_RunOut.Done := TRUE
- Se habilita la carga de la siguiente receta o se inicia el enjuague, según configuración.
@startuml
title 11.2 Product Pipe Run-Out – Empuje a llenadora
hide footbox
skinparam ArrowHeadColor none
skinparam NoteBackgroundColor #F0F0F0
skinparam NoteBorderColor #999999
skinparam ParticipantPadding 20
skinparam BoxPadding 6
skinparam WrapWidth 250
!pragma teoz true
' ==== Estilos reutilizables ====
!define VAR(x) <back:#F0F0F0><color:#7F6000><b>x</b></color></back>
!define SIG(x) <back:#F0F0F0><color:#005A9E><b>x</b></color></back>
!define FROM(x) <back:#FFAAAA><color:#000000><b>x</b></color></back>
!define TO(x) <back:#AAFFFF><color:#000000><b> x</b></color></back>
!definelong Nota($donde, $text)
note over $donde
$text
end note
!enddefinelong
participant PLC as PLC
participant "MFM FTN301" as FTN301
participant "MFM FTP302" as FTP302
participant "Filler" as FILL
participant "Prod Pipe" as PIPE
== Solicitud Run-Out ==
FILL -> PLC : FROM(ProdPipe_RunOut.Request)
PLC -> PLC : TO(Init Push_Count_Init)
Nota(PLC, "Modo seleccionado:\n• WaterCount o\n• FillerBottleCount")
== Empuje de producto ==
loop Mientras Push_Count < Objetivo
FTP302 -> PLC : SIG(ΔTot Syrup)
FTN301 -> PLC : SIG(ΔTot Water)
FILL -> PLC : SIG(BottleCounter)
PLC -> PLC : TO(Calcula Push_Count)
end
Nota(PLC, "ProdPushDone = TRUE")
== Final Run-Out ==
PLC -> PIPE : TO(Cerrar válvulas / aislar producto)
PLC -> PLC : TO(ProdPipe_RunOut.Done := TRUE)
FILL -> PLC : SIG(LastBottleDone)
Nota(PLC, "Si LastBottleDone o PushDone -> Done\nCarga siguiente receta / CIP")
@enduml
@startuml
title DAR Priming & RunOut States
hide footbox
skinparam ArrowHeadColor none
skinparam NoteBackgroundColor #F0F0F0
skinparam NoteBorderColor #999999
skinparam ParticipantPadding 100
skinparam BoxPadding 6
skinparam WrapWidth 250
!pragma teoz true
' ==== Estilos reutilizables del ejemplo ====
!define VAR(x) <back:#F0F0F0><color:#7F6000><b>x</b></color></back>
!define SIG(x) <back:#F0F0F0><color:#005A9E><b>x</b></color></back>
!define FROM(x) <back:#FFAAAA><color:#000000><b>x</b></color></back>
!define TO(x) <back:#AAFFFF><color:#000000><b> x</b></color></back>
!definelong Nota($donde, $text)
note over $donde
$text
end note
!enddefinelong
!definelong NotaParalela($donde, $text)
/ note over $donde
$text
end note
!enddefinelong
!definelong Variable($donde, $text)
hnote right $donde #AAFFFF
$text
end note
!enddefinelong
!definelong VariableRojo($donde, $text)
hnote right $donde #FFBBBB
$text
end note
!enddefinelong
!definelong VariableIzquierda($donde, $text)
hnote left $donde #AAFFFF
$text
end note
!enddefinelong
!definelong VariableCentro($donde, $text)
hnote over $donde #AAFFFF
$text
end note
!enddefinelong
state "DAR System" as System {
[*] --> Idle : System startup
state "Idle" as Idle {
Idle : System ready
Idle : Monitoring instruments
}
note right of Idle #AAFFFF
UR62, UR29, CTS306
Online monitoring
end note
state "Priming Process" as Priming {
state "Init Priming" as InitPriming {
InitPriming : <back:#FFAAAA><color:#000000><b>CMD_FTP302Line_Prep</b></color></back>
InitPriming : Operator request
}
state "Purging Water" as PurgingWater {
PurgingWater : Open drain valve
PurgingWater : Start Pump P2
}
note right of PurgingWater #FFBBBB
UR62_Brix < Threshold
Volume < Aux_Somma_Lt
end note
state "Syrup Detected" as SyrupDetected {
SyrupDetected : <back:#AAFFFF><color:#000000><b> BrixCutReached = TRUE</b></color></back>
SyrupDetected : <back:#AAFFFF><color:#000000><b> WaterCountAcheaved = TRUE</b></color></back>
}
note right of SyrupDetected #AAFFFF
UR62_Brix ≥ SyrBrix_Threshold
Volume ≥ Aux_Somma_Lt
end note
state "Line Prepared" as LinePrepared {
LinePrepared : Close drain valve
LinePrepared : Route to TP301
}
note right of LinePrepared #AAFFFF
LinePrepared := TRUE
Syrup loading starts
end note
InitPriming --> PurgingWater : <back:#F0F0F0><color:#7F6000><b>Start purge</b></color></back>
PurgingWater --> SyrupDetected : <back:#F0F0F0><color:#005A9E><b>Brix & Volume OK</b></color></back>
SyrupDetected --> LinePrepared : <back:#AAFFFF><color:#000000><b> Conditions met</b></color></back>
LinePrepared --> [*] : Priming complete
}
state "Production Mode" as Production {
Production : Normal blending
Production : Recipe execution
}
note top of Production #AAFFFF
Stable operation
UR29 monitoring
end note
state "RunOut Process" as RunOut {
state "Init RunOut" as InitRunOut {
InitRunOut : <back:#FFAAAA><color:#000000><b>ProdPipe_RunOut.Request</b></color></back>
InitRunOut : <back:#FFAAAA><color:#000000><b>TM301_RunOut.Done</b></color></back>
}
note right of InitRunOut #AAFFFF
Push_Count_Init
method selection
end note
state "Method Selection" as MethodSelection {
MethodSelection : Choose counting method
state "Water Count Mode" as WaterCount {
WaterCount : Volumetric counting
}
state "Bottle Count Mode" as BottleCount {
BottleCount : Filler bottle counting
}
note left of WaterCount #AAFFFF
FTN301_Tot + FTP302_Tot
end note
note right of BottleCount #AAFFFF
FillerBottleCount
× Bottle_Size
end note
MethodSelection --> WaterCount : <back:#F0F0F0><color:#7F6000><b>ProdPipeRunOutWaterCount</b></color></back>
MethodSelection --> BottleCount : <back:#F0F0F0><color:#7F6000><b>ProdPipeRunOutFillerBott</b></color></back>
}
state "Product Pushing" as Pushing {
Pushing : Monitor push progress
Pushing : Count volume/bottles
}
note right of Pushing #FFBBBB
Push_Count < Target
NOT LastbottleDone
end note
state "RunOut Complete" as RunOutComplete {
RunOutComplete : <back:#AAFFFF><color:#000000><b> ProdPipe_RunOut.Done = TRUE</b></color></back>
RunOutComplete : Close product valves
}
note right of RunOutComplete #AAFFFF
ProdPushDone = TRUE
OR LastbottleDone
end note
InitRunOut --> MethodSelection : <back:#F0F0F0><color:#005A9E><b>Request received</b></color></back>
WaterCount --> Pushing : <back:#AAFFFF><color:#000000><b> Method selected</b></color></back>
BottleCount --> Pushing : <back:#AAFFFF><color:#000000><b> Method selected</b></color></back>
Pushing --> RunOutComplete : <back:#F0F0F0><color:#005A9E><b>Target reached</b></color></back>
RunOutComplete --> [*] : RunOut complete
}
state "Changeover/CIP" as Changeover {
Changeover : Load next recipe
Changeover : OR start CIP
}
note top of Changeover #AAFFFF
EnableNextRecipe
OR Rinse sequence
end note
' Main state transitions
Idle --> Priming : <back:#FFAAAA><color:#000000><b>Operator command</b></color></back>
Priming --> Production : <back:#AAFFFF><color:#000000><b> Line prepared</b></color></back>
Production --> RunOut : <back:#F0F0F0><color:#005A9E><b>End of production</b></color></back>
RunOut --> Changeover : <back:#AAFFFF><color:#000000><b> Pipeline empty</b></color></back>
Changeover --> Idle : <back:#F0F0F0><color:#005A9E><b>Sequence complete</b></color></back>
' Emergency transitions
Priming --> Idle : <back:#FFAAAA><color:#000000><b>Abort sequence</b></color></back>
Production --> Idle : <back:#FFAAAA><color:#000000><b>Emergency stop</b></color></back>
RunOut --> Idle : <back:#FFAAAA><color:#000000><b>Emergency stop</b></color></back>
}
' External notes with color coding
note top of System #F0F0F0
**Sistema DAR - Diet as Regular**
SAE452 San Giorgio in Bosco
end note
note bottom of System #AAFFFF
**Instrumentos principales:**
• UR62 (QTM306): Detección agua/jarabe
• UR29 (QTM307): Precisión alta
• CTS306: Conductividad agua
end note
@enduml