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.
Prerequisites
- STEP 7 V5.5 SP2 (or TIA Portal V15.1 with S7-300 add-on) installed and licensed on the engineering PC.
- 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.
- 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).
- 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).
- A 24 VDC signal tower or HMI panel connected via MPI/PROFINET to surface HIHI/LOLO alarms and run status.
- 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) |
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
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
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) |
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:
- Tank 1 HIHI (>= 525 L): stop Tank 1 fill and the entire process.
- Tank 1 LOLO (<= 95 L): stop Tank 1 fill and the entire process.
- 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
- Compile and download all blocks. Use PLC > Download in STEP 7. Run the CPU in RUN mode after clearing any SF/BF faults.
- Open VAT_1, switch to "Monitor/Modify" and confirm
Lvl_T1, Lvl_T2, Lvl_T3track the simulated tank levels. - Force
START_PB = 1in the VAT and verifyStepincrements 0 to 1 to 2 etc. as the simulated levels cross the setpoints. - Force
Lvl_T1 = 530to 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. - Confirm
CycleCountincrements only when the full procedure completes and Tank 3 drains to LO. - Use the PLC > Monitor/Modify > Data Block view on DB101 to change
SV_MixHeatat 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.