---
# Sistema DAR – Diet as Regular
SAE452 · Mixer Sidel con CPU S7-317
## 1. Objetivo
1. Reducir pérdidas de jarabe (syrup) durante los cambios de producto.
2. 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/TCP
`HMI_Instrument.QTM307` |
| **CTS306** | Conductivímetro Knick 2405 | Comprobar dureza (µS/cm) del agua de proceso; generar alarmas fuera de rango | 4-20 mA
`HMI_Instrument.CTS306` |
Diagrama simplificado:
```
[ Water In ]--CTS306----┐
│
(purge) +--┴--Drain
|
Syrup Tanks --Pump--UR62(QTM306)-----> Mixer pipe ---> UR29(QTM307) ---> TP301
```
## 4. Fases operativas
1. **Priming / Syrup Line Preparation**
- La sala de jarabe envía agua para purga inicial.
- `UR62` lee °Brix. Mientras `Brix_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.
2. **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.
3. **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.
4. **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`
## 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`
```SCL
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) y `Maselli_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)
```SCL
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
1. Parametrizar en cada receta:
* °Brix jarabe (`_SyrupBrix`)
* `_BrixCutUR62` (empíricamente 0,5)
* Límites de conductividad agua.
2. Verificar offset ADC-DAC (`i_Offset_ADC_DAC`) en `Maselli_ADAM_Read` (≈ 0,025 mA medido).
3. Comprobar IP de los gateways digitales (líneas 22-27 de `DAR_Logic`).
4. 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
1. Al iniciar la secuencia `FTP302Line_Preparation` se copia el totalizador instantáneo del caudalímetro de jarabe FTP302:
```pascal
gSyrLinePrepCountInit := Profibus_Variables.gFTP302_Tot
```
2. En cada ciclo se calcula el volumen realmente desplazado desde ese instante:
```pascal
TP301SyrupPrimingCount = Profibus_Variables.gFTP302_Tot - gSyrLinePrepCountInit
```
3. 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`
4. Umbral de °Brix (ver §5):
* `UR62_Brix ≥ SyrBrix_Threshold`
5. Condiciones de fin de priming (se deben cumplir ambas):
```pascal
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`.
```plantuml
@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) x
!define SIG(x) x
!define FROM(x) x
!define TO(x) x
!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
```
```plantuml
@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
```pascal
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
```pascal
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:
```pascal
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.
```plantuml
@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) x
!define SIG(x) x
!define FROM(x) x
!define TO(x) x
!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
```
```plantuml
@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) x
!define SIG(x) x
!define FROM(x) x
!define TO(x) x
!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 : CMD_FTP302Line_Prep
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 : BrixCutReached = TRUE
SyrupDetected : WaterCountAcheaved = TRUE
}
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 : Start purge
PurgingWater --> SyrupDetected : Brix & Volume OK
SyrupDetected --> LinePrepared : Conditions met
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 : ProdPipe_RunOut.Request
InitRunOut : TM301_RunOut.Done
}
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 : ProdPipeRunOutWaterCount
MethodSelection --> BottleCount : ProdPipeRunOutFillerBott
}
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 : ProdPipe_RunOut.Done = TRUE
RunOutComplete : Close product valves
}
note right of RunOutComplete #AAFFFF
ProdPushDone = TRUE
OR LastbottleDone
end note
InitRunOut --> MethodSelection : Request received
WaterCount --> Pushing : Method selected
BottleCount --> Pushing : Method selected
Pushing --> RunOutComplete : Target reached
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 : Operator command
Priming --> Production : Line prepared
Production --> RunOut : End of production
RunOut --> Changeover : Pipeline empty
Changeover --> Idle : Sequence complete
' Emergency transitions
Priming --> Idle : Abort sequence
Production --> Idle : Emergency stop
RunOut --> Idle : Emergency stop
}
' 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
```