Siemens S7-300 Mixing Vessel: FB, DB, and Alarm Programming

David Krause19 min read
S7-300SiemensTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Overview

This tutorial implements a three-tank mixing vessel batch process on a Siemens SIMATIC S7-300 PLC using STEP 7 (Classic) and the standard programming model. The process fills Tank 1 (600 L), transfers 200 L to Tank 2 (300 L) for mixing and heating with metered recipe injection, then discharges to Tank 3 (600 L). The cycle repeats until Tank 3 reaches its high-level setpoint, at which point Tank 3 is emptied to downstream packaging.

The program is decomposed into four Function Blocks (FBs) for tank, alarm, recipe, and timer logic, supported by a single shared instance Data Block (DB) plus dedicated Data Blocks for the recipe and the timer preset values, all sequenced in OB1. A Variable Table (VAT) exposes every IN/OUT parameter for live commissioning and HMI-style monitoring on the PG/PC, exactly the view the trainer's brief requires.

Reference platform: SIMATIC S7-300 with CPU 314C-2 PN/DP or CPU 315-2 PN/DP, STEP 7 V5.5 or STEP 7 Professional (TIA Portal V15.1+ with S7-300 add-on). The sample code below uses STEP 7 V5.5 STL/FBD syntax for portability. See the SIMATIC S7-300 CPU 31xC and CPU 31x: Technical specifications manual for hardware limits.

Prerequisites

  1. STEP 7 V5.5 SP2 (or TIA Portal V15.1 with S7-300 add-on) installed and licensed on the engineering PC.
  2. SIMATIC S7-300 station with a CPU 31x, one SM 321 DI 16x24 VDC input module, one SM 322 DO 16x24 VDC/0.5 A output module, and one SM 331 AI 8x12-bit analog input module for the level transmitters.
  3. Three 4-20 mA level transmitters scaled to the tank working volumes (Tank 1: 0-600 L, Tank 2: 0-300 L, Tank 3: 0-600 L).
  4. Two transfer pumps (P1: Tank 1 to Tank 2, P2: Tank 2 to Tank 3), one delivery valve for recipe (V_RCP), and one discharge valve (V_T3_OUT).
  5. A 24 VDC signal tower or HMI panel connected via MPI/PROFINET to surface HIHI/LOLO alarms and run status.
  6. Functional understanding of FB multi-instance capability, instance DBs, and OB1 cyclic execution. Review the Programming with STEP 7 manual chapter on FBs before starting.

System Architecture and I/O Assignment

Map all field devices to fixed I/O addresses. The addresses below are conventional; adapt them to the slot/byte layout of your actual hardware configuration in HW Config.

Tag Address Type Function
T1_LT_AI PIW 272 Analog in (4-20 mA) Tank 1 level transmitter (0-600 L)
T2_LT_AI PIW 274 Analog in (4-20 mA) Tank 2 level transmitter (0-300 L)
T3_LT_AI PIW 276 Analog in (4-20 mA) Tank 3 level transmitter (0-600 L)
START_PB I 0.0 Digital in Process start pushbutton (NO)
STOP_PB I 0.1 Digital in Process stop pushbutton (NC)
ACK_PB I 0.2 Digital in Alarm acknowledge pushbutton
ESTOP_OK I 0.3 Digital in Emergency stop healthy (NC loop)
P1_RUN Q 4.0 Digital out Pump 1 (Tank 1 to Tank 2) command
P2_RUN Q 4.1 Digital out Pump 2 (Tank 2 to Tank 3) command
V_RCP Q 4.2 Digital out Recipe delivery valve (10 s pulse)
V_T3_OUT Q 4.3 Digital out Tank 3 discharge valve
HEATER Q 4.4 Digital out Tank 2 immersion heater contactor
MIXER_RUN Q 4.5 Digital out Tank 2 mixer contactor
HORN Q 4.6 Digital out Audible alarm horn
BEACON_R Q 4.7 Digital out Red beacon (process fault)
Addressing rule: on S7-300, analog values are addressed as Process-Image Words (PIW/PQW). Always read analog inputs in OB1, OB35 (cyclic interrupt), or in the FB with consistent read via L PIW ... at the top of the network. Refer to the S7-300 Module Data manual for slot-to-address mapping.

Program Structure Overview

The block container in STEP 7 contains the following blocks. Multi-instance FBs are used so a single instance DB holds all per-tank state, which the trainer's brief requires for IN/OUT visibility.

Block Type Purpose
OB1 Organization block Cyclic main; calls FBs in sequence and holds the step chain (networks NW1-NW12)
OB100 Warm restart Resets all instance DBs and outputs to a defined cold start state
FB100 Function block Generic tank FB (level scaling, HI/LO/HIHI/LOLO compare, pump/valve control, run status)
FB101 Function block Recipe injection FB (scales 0.1 L per 100 L of fluid in Tank 2, fires 10 s pulse on V_RCP)
FB102 Function block Mix and heat FB (runs mixer + heater for 10 minutes, uses on-delay timer with SV from DB)
FB103 Function block Alarm FB (HIHI, LOLO, latch, acknowledge, beacon/horn)
DB100 Instance DB Multi-instance container for three calls of FB100 (Tank 1/2/3) and calls of FB101/102/103
DB101 Shared DB Timer preset values, recipe constants, step number, cycle counter
DB102 Shared DB HMI-tag mirror: scaled levels, valve/pump status, alarms, run state (exposed to VAT)
VAT_1 Variable table Online monitoring: levels, outputs, alarms, step

FB100 - Generic Tank Level, Pump, and Valve Control

FB100 is the workhorse. It scales the 4-20 mA raw value into engineering units (litres), compares it to four setpoints (HI, LO, HIHI, LOLO), and provides an output structure with pump run request, valve commands, and a level-reached bit. The block uses a multi-instance declaration so three independent tank instances (one per call) share the same code but hold private static data.

FUNCTION_BLOCK FB100
// ============================================================
// Generic Tank FB - level scaling, setpoint compare, run cmd
// ============================================================
VAR_INPUT
  i_Raw         : INT;     // 0-27648 from AI module
  i_HI          : REAL;    // HI setpoint (litres)
  i_LO          : REAL;    // LO setpoint (litres)
  i_HIHI        : REAL;    // HIHI setpoint (litres)
  i_LOLO        : REAL;    // LOLO setpoint (litres)
  i_UseLOLO     : BOOL;    // FALSE disables LOLO logic for Tank 3
  i_Enable      : BOOL;    // Master enable from sequence step
  i_Reset       : BOOL;    // Acknowledge / reset from OB1
END_VAR

VAR_OUTPUT
  o_Lvl_L       : REAL;    // Scaled level in litres
  o_bHI         : BOOL;    // Level >= HI
  o_bLO         : BOOL;    // Level <= LO
  o_bHIHI       : BOOL;    // Level >= HIHI (latched to FB103)
  o_bLOLO       : BOOL;    // Level <= LOLO (latched to FB103)
  o_bRun        : BOOL;    // Pump/valve run command from this FB
  o_bReady      : BOOL;    // TRUE when level is inside the working band
END_VAR

VAR
  s_Lvl_L       : REAL;    // Static: filtered level for hysteresis
END_VAR

BEGIN
// --- Scale 4-20 mA (0-27648 counts) to 0..i_MaxLitres ----
// Use the calibrated span below; for Tank 1/3 use 600 L max, Tank 2 use 300 L
// FB100 itself stays generic - caller passes i_MaxL via static or computes externally
// In this exercise we expose raw litre scale via a scaling FB not shown.
// Simplified scaling assuming i_Raw already normalised 0..100% into o_Lvl_L:

  o_Lvl_L := INT_TO_REAL(i_Raw) / 27648.0 * 600.0;   // adjust max per tank

// --- Hysteresis: 1 litre dead-band to prevent chatter ----
  IF o_Lvl_L >= (i_HI + 1.0) THEN o_bHI := TRUE;
  ELSIF o_Lvl_L <= (i_HI - 1.0) THEN o_bHI := FALSE;
  END_IF;

  IF o_Lvl_L <= (i_LO - 1.0) THEN o_bLO := TRUE;
  ELSIF o_Lvl_L >= (i_LO + 1.0) THEN o_bLO := FALSE;
  END_IF;

  IF o_Lvl_L >= i_HIHI THEN o_bHIHI := TRUE; END_IF;
  IF i_UseLOLO AND (o_Lvl_L <= i_LOLO) THEN o_bLOLO := TRUE; END_IF;

// --- Run request: enable + not at HI + not in alarm ----
  o_bRun  := i_Enable AND NOT o_bHIHI AND NOT o_bLOLO AND (o_Lvl_L < i_HI);
  o_bReady := (o_Lvl_L > i_LO) AND (o_Lvl_L < i_HIHI);

  // Static level copy for FB103 alarm FB to read without crossing instance lines
  s_Lvl_L := o_Lvl_L;
END_FUNCTION_BLOCK

The trainer's brief specified that "FB internal addressing so that we can see IN and OUT addressing to the FB" is mandatory. By calling FB100 three times with different IN pin values and three separate instance data blocks (or a single multi-instance DB100 with three iDB_Tank1, iDB_Tank2, iDB_Tank3 static FB100 instances), the VAT can monitor every input and every output live.

FB101 - Recipe Injection FB

The recipe dose is 0.1 L per 100 L of fluid in Tank 2. The delivery valve is fixed at 10 s per 0.1 L. FB101 reads the current Tank 2 level, divides by 100, rounds up to the next integer number of doses, multiplies by 10 s, and emits a run command to V_RCP plus a Done bit when the total dose time has elapsed. Tank 2 capacity is 300 L, so a full Tank 2 needs 3 doses = 30 s of valve on-time.

FUNCTION_BLOCK FB101
VAR_INPUT
  i_Tank2_Lvl   : REAL;    // current litres in Tank 2
  i_DoseSec     : REAL;    // seconds per 0.1 L dose (default 10.0)
  i_Start       : BOOL;    // rising-edge start from sequence step
  i_Abort       : BOOL;    // abort on alarm
END_VAR

VAR_OUTPUT
  o_ValveCmd    : BOOL;    // drives V_RCP
  o_Doses       : INT;     // computed number of doses
  o_TotalSec    : REAL;    // total injection time
  o_bDone       : BOOL;
END_VAR

VAR
  s_TON         : TON;     // IEC on-delay timer
  s_StartEdge   : BOOL;
  s_Run         : BOOL;
END_VAR
BEGIN
  // Detect rising edge on i_Start
  IF i_Start AND NOT s_StartEdge THEN
     s_Run := TRUE;
     o_bDone := FALSE;
     s_TON(IN := FALSE, PT := T#0ms);
  END_IF;
  s_StartEdge := i_Start;

  // Compute required doses: ceil(L / 100) = number of 0.1 L pulses
  o_Doses    := REAL_TO_INT((i_Tank2_Lvl / 100.0) + 0.999);
  IF o_Doses < 0 THEN o_Doses := 0; END_IF;
  o_TotalSec := INT_TO_REAL(o_Doses) * i_DoseSec;

  IF s_Run THEN
     s_TON(IN := TRUE, PT := DINT_TO_TIME(REAL_TO_DINT(o_TotalSec * 1000.0)));
     o_ValveCmd := NOT s_TON.Q;     // valve on while timer runs
     IF s_TON.Q THEN
        s_Run := FALSE;
        o_ValveCmd := FALSE;
        o_bDone := TRUE;
     END_IF;
  ELSE
     o_ValveCmd := FALSE;
  END_IF;

  IF i_Abort THEN
     s_Run := FALSE;
     s_TON(IN := FALSE);
     o_ValveCmd := FALSE;
  END_IF;
END_FUNCTION_BLOCK
IEC timer note: the TON used here is the IEC standard timer from the STEP 7 standard library (folder "System Function Blocks"). It is reset by calling with IN := FALSE. The internal DB holds the running time so OB100 cold restart must clear it; we do that by writing 0 into s_TON in OB100. See the STEP 7 programming manual chapter on IEC timers for full rules.

FB102 - Mix and Heat FB

FB102 starts the mixer and heater outputs, runs them for the preset time in DB101.SV_MixHeat (default T#10m), and signals Done. The 10-minute preset is held in DB101 so the trainer can change it from the VAT without recompiling.

FUNCTION_BLOCK FB102
VAR_INPUT
  i_PresetTime  : TIME;    // 10 minutes from DB101
  i_Start       : BOOL;
  i_Abort       : BOOL;
END_VAR

VAR_OUTPUT
  o_Mixer       : BOOL;
  o_Heater      : BOOL;
  o_bDone       : BOOL;
END_VAR

VAR
  s_TON         : TON;
  s_StartEdge   : BOOL;
  s_Run         : BOOL;
END_VAR
BEGIN
  IF i_Start AND NOT s_StartEdge THEN
     s_Run := TRUE;
     o_bDone := FALSE;
  END_IF;
  s_StartEdge := i_Start;

  IF s_Run THEN
     s_TON(IN := TRUE, PT := i_PresetTime);
     o_Mixer  := NOT s_TON.Q;
     o_Heater := NOT s_TON.Q;
     IF s_TON.Q THEN s_Run := FALSE; o_bDone := TRUE; o_Mixer := FALSE; o_Heater := FALSE; END_IF;
  ELSE
     o_Mixer := FALSE; o_Heater := FALSE;
  END_IF;

  IF i_Abort THEN
     s_Run := FALSE; s_TON(IN := FALSE);
     o_Mixer := FALSE; o_Heater := FALSE;
  END_IF;
END_FUNCTION_BLOCK

FB103 - Alarm FB (HIHI/LOLO Latch and Acknowledge)

FB103 collects HIHI and LOLO flags from each tank, latches them, and drives the beacon/horn outputs. Acknowledge is rising-edge sensitive and clears the latched fault provided the trigger condition is no longer present. This is the standard S7-300 alarm pattern; refer to the STEP 7 Standard PID Control and Alarm handling application example for additional guidance.

FUNCTION_BLOCK FB103
VAR_INPUT
  i_HIHI        : BOOL;    // any tank HIHI
  i_LOLO        : BOOL;    // any tank LOLO
  i_Ack         : BOOL;    // ack pushbutton
  i_Reset       : BOOL;    // cold restart
END_VAR

VAR_OUTPUT
  o_Beacon      : BOOL;    // red beacon
  o_Horn        : BOOL;    // audible horn, pulsed
  o_bActive     : BOOL;    // any latched alarm
  o_bHIHI       : BOOL;    // latched HIHI
  o_bLOLO       : BOOL;    // latched LOLO
END_VAR

VAR
  s_HIHI_latch  : BOOL;
  s_LOLO_latch  : BOOL;
  s_AckEdge     : BOOL;
  s_HornTON     : TON;     // 2 s horn pulse, retriggered
END_VAR
BEGIN
  // Set latches
  IF i_HIHI THEN s_HIHI_latch := TRUE; END_IF;
  IF i_LOLO THEN s_LOLO_latch := TRUE; END_IF;
  IF i_Reset THEN s_HIHI_latch := FALSE; s_LOLO_latch := FALSE; END_IF;

  // Acknowledge (rising edge) - only clears if trigger gone
  IF i_Ack AND NOT s_AckEdge THEN
     IF NOT i_HIHI THEN s_HIHI_latch := FALSE; END_IF;
     IF NOT i_LOLO THEN s_LOLO_latch := FALSE; END_IF;
  END_IF;
  s_AckEdge := i_Ack;

  o_bHIHI   := s_HIHI_latch;
  o_bLOLO   := s_LOLO_latch;
  o_bActive := s_HIHI_latch OR s_LOLO_latch;
  o_Beacon  := o_bActive;

  // Pulsed horn every 2 s while un-acked
  s_HornTON(IN := o_bActive AND NOT s_HornTON.Q, PT := T#2s);
  o_Horn := o_bActive AND s_HornTON.Q;
END_FUNCTION_BLOCK

OB1 - Main Sequence (Step Chain)

OB1 holds a simple step counter plus the call instances of the FBs. The step chain implements the procedure steps 1-9 from the trainer's brief. Because the brief says "Process run can simply be a NW in OB1", the FB instances are called from OB1 directly and the step transitions live as ladder/FBD networks alongside the calls.

ORGANIZATION_BLOCK OB1
VAR_TEMP
  t_RawT1 : INT;
  t_RawT2 : INT;
  t_RawT3 : INT;
END_VAR
BEGIN
NETWORK 1   // Read analog inputs (force consistent read on SM 331)
  t_RawT1 := PIW272;
  t_RawT2 := PIW274;
  t_RawT3 := PIW276;

NETWORK 2   // Tank 1 FB100 - fill Tank 1 to HI = 500 L
  iDB_Tank1( i_Raw := t_RawT1,
             i_HI  := 500.0, i_LO := 100.0,
             i_HIHI:= 525.0, i_LOLO := 95.0,
             i_UseLOLO := TRUE,
             i_Enable  := (Step = 1) OR (Step = 3),
             i_Reset   := OB100_OneShot );

NETWORK 3   // Tank 2 FB100 - transfer 200 L to Tank 2 (HI = 200 L)
  iDB_Tank2( i_Raw := t_RawT2,
             i_HI  := 200.0, i_LO := 0.0,
             i_HIHI:= 250.0, i_LOLO := 0.0,
             i_UseLOLO := FALSE,
             i_Enable  := (Step = 2) OR (Step = 7),
             i_Reset   := OB100_OneShot );

NETWORK 4   // Tank 3 FB100 - HI = 400 L, LOLO disabled
  iDB_Tank3( i_Raw := t_RawT3,
             i_HI  := 400.0, i_LO := 0.0,
             i_HIHI:= 525.0, i_LOLO := 0.0,
             i_UseLOLO := FALSE,
             i_Enable  := (Step = 6) OR (Step = 8),
             i_Reset   := OB100_OneShot );

NETWORK 5   // Pump 1 - Tank 1 to Tank 2 (interlocked with Tank 1 NOT HIHI and Tank 2 NOT HI)
  Q4.0 := iDB_Tank1.o_bRun AND iDB_Tank2.o_bReady
          AND NOT ALARM_ACTIVE;

NETWORK 6   // Pump 2 - Tank 2 to Tank 3
  Q4.1 := iDB_Tank2.o_bRun AND iDB_Tank3.o_bReady
          AND NOT ALARM_ACTIVE;

NETWORK 7   // Step chain - simple integer state machine
  // Step transitions: refer to procedure 1-9 in brief
  CASE Step OF
    0: IF START_PB AND ESTOP_OK AND NOT ALARM_ACTIVE THEN Step := 1; END_IF;
    1: IF iDB_Tank1.o_bHI THEN Step := 2; END_IF;        // T1 to HI = 500 L
    2: IF iDB_Tank2.o_bHI THEN Step := 3; END_IF;        // T2 reached 200 L
    3: IF iDB_Tank1.o_bHI AND NOT iDB_Tank2.o_bHI THEN
          Recipe_Done := FALSE; Step := 4;
       END_IF;
    4: FB101_Recipe(i_Tank2_Lvl := iDB_Tank2.o_Lvl_L,
                    i_DoseSec   := 10.0,
                    i_Start     := TRUE,
                    i_Abort     := ALARM_ACTIVE);
       Q4.2 := FB101_Recipe.o_ValveCmd;
       IF FB101_Recipe.o_bDone THEN Step := 5; END_IF;
    5: FB102_MixHeat(i_PresetTime := DB101.SV_MixHeat,
                     i_Start      := (Step_Old = 4 AND Step = 5),
                     i_Abort      := ALARM_ACTIVE);
       Q4.5 := FB102_MixHeat.o_Mixer;
       Q4.4 := FB102_MixHeat.o_Heater;
       IF FB102_MixHeat.o_bDone THEN Step := 6; END_IF;
    6: IF iDB_Tank2.o_bLO AND iDB_Tank1.o_bHI THEN Step := 7; END_IF;
    7: // repeat 2-7 until T3 HI
       IF iDB_Tank3.o_bHI THEN Step := 8; END_IF;
    8: IF NOT iDB_Tank2.o_bRun THEN Step := 9; END_IF;
    9: IF iDB_Tank3.o_bLO THEN Step := 0; END_IF;
  END_CASE;
  Step_Old := Step;

NETWORK 8   // Discharge valve Q4.3 active in step 8 until T3 LO
  Q4.3 := (Step = 8) AND (iDB_Tank3.o_Lvl_L > 0.0) AND NOT ALARM_ACTIVE;

NETWORK 9   // Alarm FB
  FB103_Alarm(i_HIHI := iDB_Tank1.o_bHIHI OR iDB_Tank3.o_bHIHI,
              i_LOLO := iDB_Tank1.o_bLOLO,
              i_Ack  := ACK_PB,
              i_Reset:= ColdStart);
  Q4.6 := FB103_Alarm.o_Horn;
  Q4.7 := FB103_Alarm.o_Beacon;
  ALARM_ACTIVE := FB103_Alarm.o_bActive;

NETWORK 10  // Cycle counter - increments on every return to step 0
  IF (Step_Old = 9) AND (Step = 0) THEN
     DB101.CycleCount := DB101.CycleCount + 1;
  END_IF;

NETWORK 11  // HMI mirror to DB102 (visible in VAT)
  DB102.Lvl_T1 := iDB_Tank1.o_Lvl_L;
  DB102.Lvl_T2 := iDB_Tank2.o_Lvl_L;
  DB102.Lvl_T3 := iDB_Tank3.o_Lvl_L;
  DB102.Step   := Step;
  DB102.P1     := Q4.0;
  DB102.P2     := Q4.1;
  DB102.V_RCP  := Q4.2;
  DB102.V_OUT  := Q4.3;
  DB102.Alarm  := FB103_Alarm.o_bActive;
END_ORGANIZATION_BLOCK
Step chain discipline: the brief explicitly excludes LOLO on Tank 3, so FB100 is called with i_UseLOLO := FALSE for Tank 3. The alarm FB only ever sets HIHI on Tank 3. If o_bHIHI rises on Tank 3, the process must halt transfers to that tank - this is enforced by the AND in NW5/NW6 with ALARM_ACTIVE. Refer to the Programming with STEP 7 chapter on FC/FB calls for parameter passing rules.

DB100 and DB101 - Instance and Shared Data Blocks

DB100 is the multi-instance container. Declaring iDB_Tank1, iDB_Tank2, iDB_Tank3 as FB100 static variables in DB100 plus FB101_Recipe as FB101 and FB102_MixHeat as FB102 produces a single instance DB the VAT can open and inspect.

DATA_BLOCK DB100
  STRUCT
    iDB_Tank1   : FB100;    // 200+ bytes of static data
    iDB_Tank2   : FB100;
    iDB_Tank3   : FB100;
    FB101_Recipe: FB101;
    FB102_MixHeat: FB102;
  END_STRUCT;
END_DATA_BLOCK

DB101 holds every preset value the trainee should be able to change live from the VAT - timer SV, recipe dose, hysteresis, and the cycle counter.

DATA_BLOCK DB101
  STRUCT
    SV_MixHeat   : TIME  := T#10m;     // mix + heat time
    SV_DoseSec   : REAL := 10.0;       // seconds per 0.1 L dose
    SV_HystL     : REAL := 1.0;        // hysteresis in litres
    CycleCount   : DINT := 0;          // incremented on batch end
  END_STRUCT;
END_DATA_BLOCK

DB102 is the HMI mirror populated by OB1 NW11. It contains only plain REAL and BOOL fields so the VAT can format them as decimal/boolean without the FB static structure noise.

VAT_1 - Online Monitoring

Open the VAT from the S7 program: Blocks > right-click > Insert New Object > Variable Table. Add the following symbolic names; assign the symbol table once at the project root so the VAT resolves addresses automatically.

Symbol Address Format Comment
Lvl_T1 DB102.DBD0 Floating-point Tank 1 level in litres
Lvl_T2 DB102.DBD4 Floating-point Tank 2 level in litres
Lvl_T3 DB102.DBD8 Floating-point Tank 3 level in litres
Step DB102.DBD12 DEC Current step number 0-9
P1 DB102.DBX16.0 BOOL Pump 1 running
P2 DB102.DBX16.1 BOOL Pump 2 running
V_RCP DB102.DBX16.2 BOOL Recipe valve
V_OUT DB102.DBX16.3 BOOL Discharge valve
Alarm DB102.DBX16.4 BOOL Any latched alarm active
HI_T1 DB100.iDB_Tank1.o_bHI BOOL Tank 1 reached HI
HI_T2 DB100.iDB_Tank2.o_bHI BOOL Tank 2 reached HI
HI_T3 DB100.iDB_Tank3.o_bHI BOOL Tank 3 reached HI
CycleCount DB101.DBD 0 DEC Completed batches
MixHeat_SV DB101.DBD 4 TIME Mix/heat preset (modify online)
Symbolic addressing: in the VAT, toggle the "Symbol" column on so the symbol table resolves. STEP 7 evaluates the path DB100.iDB_Tank1.o_bHI against the multi-instance declaration automatically. If the path is grayed, recompile the S7 program after saving the symbol table.

Alarm Handling and Process Interlocks

Three alarms are defined in the trainer's brief:

  1. Tank 1 HIHI (>= 525 L): stop Tank 1 fill and the entire process.
  2. Tank 1 LOLO (<= 95 L): stop Tank 1 fill and the entire process.
  3. Tank 3 HIHI (>= 525 L): stop Tank 3 fill and the entire process.

Each alarm is latched in FB103 and can only be acknowledged when the physical condition has cleared. The horn pulses every 2 s while the alarm is unacknowledged, and the beacon stays solid red. The ALARM_ACTIVE flag is used in every pump/valve command network in OB1, so an unacknowledged alarm instantly halts the field outputs while leaving the step counter intact for the operator to resume after acknowledge.

Alarm Trigger Action Reset method
T1_HIHI Lvl_T1 >= 525 L Disable P1, halt sequence Ack after level < 524 L
T1_LOLO Lvl_T1 <= 95 L Disable P1, halt sequence Ack after level > 96 L
T3_HIHI Lvl_T3 >= 525 L Disable P2, halt sequence Ack after level < 524 L

OB100 - Cold Restart Initialization

OB100 runs once after power-on or CPU restart. Use it to drive all outputs low and clear the step counter so a defined cold start is guaranteed.

ORGANIZATION_BLOCK OB100
BEGIN
  QW4   := 0;             // all digital outputs off
  Step  := 0;
  Step_Old := 0;
  Recipe_Done := FALSE;
  ALARM_ACTIVE := FALSE;
  DB101.CycleCount := 0;
  // Clear FB instance timers explicitly
  DB100.FB101_Recipe.s_TON(IN := FALSE);
  DB100.FB102_MixHeat.s_TON(IN := FALSE);
  DB100.FB103_Alarm.s_HornTON(IN := FALSE);
  OB100_OneShot := TRUE;
END_ORGANIZATION_BLOCK

Verification and Commissioning Steps

  1. Compile and download all blocks. Use PLC > Download in STEP 7. Run the CPU in RUN mode after clearing any SF/BF faults.
  2. Open VAT_1, switch to "Monitor/Modify" and confirm Lvl_T1, Lvl_T2, Lvl_T3 track the simulated tank levels.
  3. Force START_PB = 1 in the VAT and verify Step increments 0 to 1 to 2 etc. as the simulated levels cross the setpoints.
  4. Force Lvl_T1 = 530 to simulate HIHI. Verify the beacon lights, the horn pulses, and all pumps stop. Acknowledge and verify recovery only after the level drops below 524 L.
  5. Confirm CycleCount increments only when the full procedure completes and Tank 3 drains to LO.
  6. Use the PLC > Monitor/Modify > Data Block view on DB101 to change SV_MixHeat at runtime and confirm FB102 uses the new value on the next batch.

Troubleshooting Matrix

Symptom Likely cause Action
Step stays at 0 after START_PB ESTOP_OK low or ALARM_ACTIVE latched Check I0.3, clear any latched alarm via ACK_PB
Lvl_T1 reads 32767 (overrange) Sensor open circuit, AI module wiring Verify 4-20 mA loop, check SM 331 channel configuration in HW Config
Pump chatters on/off at HI Hysteresis set too low Increase DB101.SV_HystL to 2.0 L
Recipe valve never closes FB101 s_TON not reset on cold start Verify OB100 clears FB101_Recipe.s_TON
Tank 3 fills past 525 L HIHI alarm not wired to P2 interlock Verify NW6 includes AND NOT ALARM_ACTIVE
Step 7 loops forever Tank 2 never reaches LO because pump stays on Verify P2 turns off when iDB_Tank2.o_bRun = FALSE
VAT shows "Invalid address" for FB output Multi-instance path not compiled Save symbol table, recompile S7 program, re-open VAT

Extension Ideas

  • Add a recipe table (DB200) holding multiple recipes (Recipe_1, Recipe_2, Recipe_3) and select via a selector switch on the HMI.
  • Replace the on-delay timer in FB102 with a PID controller (FB41 CONT_C from the Standard PID Control library) to maintain a temperature setpoint during the mix/heat phase.
  • Add WinCC flexible or TIA Portal WinCC screens bound to DB102 to turn the VAT into a full HMI.
  • Implement a Profinet connection to a SINAMICS G120 drive for variable-speed pump control - see the SINAMICS G120 with SIMATIC S7-300/400 application example.

Why use a multi-instance DB instead of three separate instance DBs for FB100?

A multi-instance DB100 holding three FB100 instances keeps every per-tank variable in one place, simplifies the VAT address table, and reduces CPU DB count. It also exposes the o_bHI, o_bHIHI, and level outputs of all three tanks in a single "DB100" watch window.

How do I disable the LOLO alarm on Tank 3 while keeping it on Tank 1?

Call FB100 for Tank 3 with i_UseLOLO := FALSE. The FB code then never sets o_bLOLO, so the alarm FB has no LOLO input from Tank 3 to latch. The procedure's HIHI-only behavior on Tank 3 is preserved.

What scaling should I use for the 4-20 mA level transmitters?

Configure the SM 331 channel for 4-20 mA (measuring range D). The raw integer range is 0 (4 mA) to 27648 (20 mA). Multiply by the tank's max litres (600 for Tank 1/3, 300 for Tank 2) and divide by 27648 to get engineering units. A 1 L hysteresis band is sufficient for batch operation.

Why does the recipe FB compute doses using ceiling, not rounding?

Recipe injection is conservative: the brief requires 0.1 L of recipe per 100 L of fluid. A ceiling calculation guarantees the full dose is delivered even when the level sits just above a 100 L boundary, e.g. 100.001 L yields two doses.

Can I run this program on an S7-1200 or S7-1500 instead?

The logic is portable, but S7-1200/1500 use TIA Portal and the SCL/optimized-block model. Convert STL to SCL, replace multi-instance STAT with multi-instance in optimized DBs, and re-declare the IEC timers as IEC_TIMER with DB-backed instances. See the Siemens S7-1200/1500 migration guide.

Back to blog