Overview: Totalizing Reheating Furnace Gas Flow on S7-400
For a reheating furnace application, the goal is to totalize a continuous 4-20mA flow signal into a cumulative consumption value (volume or mass) that the supervisory control system can display, log, and convert to cost. The Siemens S7-400 series provides all the necessary primitives: a high-resolution analog input module (SM 431), the standardized FC105 SCALE function, cyclic interrupt organization blocks (OB35), and 64-bit IEEE 754 double precision floating point (LREAL) for drift-free long-term accumulation.
This reference walks through the engineering of a robust totalizer function block (FB) that avoids the most common failure mode in long-duration integration: rounding error collapse in 32-bit REAL arithmetic, where the addition of a small incremental volume to a large accumulated total is silently discarded because the result cannot be represented at the current exponent.
System Architecture and Signal Flow
The signal chain follows a deterministic path from the field transmitter to the SCADA layer. Each stage has a defined responsibility, and the data type must be chosen carefully at the boundary between scaling and accumulation.
Stage 1 - Field: Thermal mass flow meter or vortex meter outputs 4-20mA proportional to instantaneous gas flow. The 4mA "live zero" is a fault-detection feature; values below 3.6mA or above 21mA should be flagged as invalid by the AI module diagnostics.
Stage 2 - Analog Input (SM 431): The SM 431 module (e.g., 6ES7 431-1KF20-0AB0) converts the 4-20mA current loop into a raw integer value in the S7 data word. For unipolar current input with 16-bit resolution, the nominal range is 0 to 27648 counts. The 4mA endpoint maps to 0 counts and 20mA to 27648 counts. The module provides channel-level diagnostics (wire break, overflow) that must be wired into the totalizer's validity logic.
Stage 3 - Scaling (FC105): The FC105 SCALE function normalizes the raw integer to engineering units. Output is a 32-bit REAL (0.0 to HI_LIM engineering units).
Stage 4 - Integration Trigger (OB35): A cyclic interrupt organization block provides a deterministic timebase. The default period is 1000ms (1 second), configurable down to 1ms in HW Config.
Stage 5 - Totalizer (Custom FB): A user-defined FB samples the scaled flow at each OB35 trigger, computes the incremental volume chunk, and adds it to a persistent 64-bit LREAL accumulator.
Stage 6 - Display Conversion: A separate routine truncates the 64-bit LREAL total to 32-bit REAL for HMI/SCADA display, while the LREAL remains the authoritative long-term value.
Prerequisites: Hardware and Software Stack
| Component | Specification | Notes |
|---|---|---|
| S7-400 CPU | 6ES7 412/414/416/417-xX | LREAL support requires CPU firmware ≥ V4.x; verify in CPU properties |
| Analog Input Module | SM 431 (6ES7 431-1KFxx) | Configure channel for 4-wire current, 4-20mA range; 0-20mA also possible |
| Flow Transmitter | 4-20mA, HART optional | Engineering unit range must match the application (Nm³/h typical) |
| STEP 7 | V5.5 SP4 or later | Or TIA Portal V15+ for newer CPU firmware projects |
| Programming Language | LAD, FBD, or SCL/ST | SCL recommended for the totalizer FB for readability and LREAL support |
| Retentive Memory Budget | 8 bytes per totalizer instance | LREAL tag plus surrounding context; confirm against CPU retentive area |
Analog Input Scaling with FC105
FC105 is the standard scaling function in the STEP 7 Standard Library under "TI-S7 Converting Blocks." It maps a raw integer input to a floating-point engineering range with explicit handling of unipolar and bipolar signal modes. Refer to the STEP 7 V5.5 Standard Functions reference manual for the full parameter specification.
FC105 Parameter Mapping
| Parameter | Type | Description | Example Value |
|---|---|---|---|
| IN | INT | Raw input from AI module (e.g., IW512) | 13824 (= 50% of 20mA) |
| HI_LIM | REAL | Engineering value at 20mA | 1000.0 (Nm³/h) |
| LO_LIM | REAL | Engineering value at 4mA | 0.0 (Nm³/h) |
| BIPOLAR | BOOL | 0 = unipolar (0..27648), 1 = bipolar (-27648..+27648) | FALSE (unipolar) |
| OUT | REAL | Scaled engineering value | 500.0 (Nm³/h) |
| RET_VAL | WORD | Error code (W#16#0000 = OK) | W#16#0000 |
FC105 RET_VAL Error Codes
| Code | Meaning | Action |
|---|---|---|
| W#16#0000 | No error | OUT is valid |
| W#16#0008 | HI_LIM = LO_LIM | Correct configuration |
| W#16#8101 | Specified input is not an INT | Verify IN tag type |
| W#16#8103 | BIPOLAR is not BOOL or input out of range | Check BIPOLAR and IN value |
LAD/FBD Call Example
IW512 0.0E+00 1000.0 FALSE MD100 MW110
| | | | | |
|----------|----------|---------|------------|------------|
| FC105 |
| "SCALE" |
|____________________________________________________|
After FC105 executes (typically in OB1 or OB35), MD100 contains the scaled flow in engineering units, e.g., 500.0 Nm³/h for a half-scale 4-20mA input. Note that FC105 returns a 32-bit REAL; this is the bottleneck point that the field report flags - subsequent accumulation must not use this 32-bit value for long-term storage.
Choosing the Right Data Type: LREAL vs DINT Accumulation
32-bit IEEE 754 single-precision REAL provides approximately 7 decimal digits of precision. For a totalizer running over months on a process gas line that can reach peak flows of 1000 Nm³/h, the accumulated total can easily exceed 10⁹ Nm³. At that magnitude, the smallest representable increment is on the order of 100 Nm³ - any addition smaller than that is silently dropped by the floating-point unit.
| Data Type | Size | Range | Precision | Suitability |
|---|---|---|---|---|
| REAL (32-bit) | 4 bytes | ±3.4 × 10³⁸ | ~7 digits | NOT recommended for long-term totals; use only for display conversion |
| LREAL (64-bit) | 8 bytes | ±1.8 × 10³⁰⁸ | ~15-17 digits | Preferred for the persistent accumulator |
| DINT (32-bit signed) | 4 bytes | -2,147,483,648 to +2,147,483,647 | Exact (integer) | Suitable for chunk-and-add methods or scaled-integer totals |
| LINT (64-bit signed) | 8 bytes | ±9.2 × 10¹⁸ | Exact (integer) | Alternative integer accumulator when scaled to 0.001 Nm³ resolution |
Strategy 1 - Direct LREAL accumulation: Convert the scaled REAL flow to LREAL once, multiply by the OB35 timebase (Δt in hours), and add to an LREAL total. This is the simplest and most readable approach but requires CPU firmware support for LREAL.
Strategy 2 - DINT chunk-and-add: Multiply the scaled flow by Δt to get a fractional volume chunk, round to DINT precision (e.g., 0.001 Nm³ resolution), and add to a DINT total. The rounding error per chunk is at most half the resolution, so for a 1-second chunk at 0.001 Nm³ resolution, the maximum drift per chunk is bounded and predictable.
OB35 Cyclic Interrupt as Integration Timebase
OB35 is the standard cyclic interrupt organization block in S7-400. It runs at a fixed, hardware-driven interval independent of OB1 cycle time, providing a deterministic timebase for periodic tasks such as PID control and flow integration.
| Parameter | Default | Configurable Range | Note |
|---|---|---|---|
| OB35 Cycle Time | 1000 ms (1 s) | 1 ms to 60000 ms | Set in HW Config → CPU Properties → Cyclic Interrupts |
| Phase Offset | 0 ms | 0 ms to cycle time | Used to distribute multiple OBs across the cycle |
| Priority | 12 | 2-26 (CPU-dependent) | Higher than OB1 priority (1) |
| Watchdog | 2x cycle time | CPU-dependent | OB35 time-out fires if OB body runs beyond this window |
For a 1-second OB35 period, the incremental volume per cycle is:
V_increment [Nm³] = Q_flow [Nm³/h] × Δt [s] / 3600
For a 1000 Nm³/h flow, the per-second increment is 0.2778 Nm³. This is well within the precision of LREAL but will be the rounding boundary for a DINT chunk-and-add implementation.
Implementing the Totalizer Function Block (FB)
The totalizer is implemented as a re-entrant FB with a multi-instance DB so the persistent total is retained across CPU restarts (when the DB is configured as non-volatile / retentive). The FB exposes inputs for flow, validity, and reset, and outputs for the LREAL total and a 32-bit display value.
FB Interface Definition
| Name | Type | Direction | Description |
|---|---|---|---|
| i_Flow_R | REAL | Input | Scaled instantaneous flow (Nm³/h) |
| i_FlowValid | BOOL | Input | AI channel quality flag (TRUE = good data) |
| i_ResetTotal | BOOL | Input | Edge-triggered reset command |
| i_DeltaT_h | REAL | Input | Integration timebase in hours (e.g., 2.7778e-4 for 1s) |
| q_TotalLR | LREAL | Output | Persistent cumulative total (Nm³) |
| q_TotalDisplay | REAL | Output | 32-bit REAL for SCADA display |
| q_Running | BOOL | Output | TRUE while integration is active |
SCL Implementation (call from OB35)
FUNCTION_BLOCK FB_FlowTotalizer
VAR
s_TotalLR : LREAL; // Persistent total
s_LastReset: BOOL; // Edge detection for reset
END_VAR
BEGIN
// Edge-triggered reset (single rising edge only)
IF i_ResetTotal AND NOT s_LastReset THEN
s_TotalLR := 0.0;
END_IF;
s_LastReset := i_ResetTotal;
// Integrate only when input is valid
IF i_FlowValid THEN
s_TotalLR := s_TotalLR + LREAL(i_Flow_R) * i_DeltaT_h;
q_Running := TRUE;
ELSE
q_Running := FALSE;
END_IF;
// Output assignment
q_TotalLR := s_TotalLR;
// 32-bit display conversion with safe clamp
IF s_TotalLR > 1.0E+30 THEN
q_TotalDisplay := 1.0E+30;
ELSIF s_TotalLR < -1.0E+30 THEN
q_TotalDisplay := -1.0E+30;
ELSE
q_TotalDisplay := REAL(s_TotalLR);
END_IF;
END_FUNCTION_BLOCK
OB35 Call Site
// In OB35 (priority 12, 1000ms cycle)
"CALL FB_FlowTotalizer"(
i_Flow_R := "DB_Scale".Flow_Nm3h, // From FC105
i_FlowValid := "DB_Scale".QualityOK, // AI channel OK
i_ResetTotal := "DB_Control".ResetTotal,
i_DeltaT_h := 2.7777778e-4, // 1.0 / 3600.0
q_TotalLR => "DB_Output".TotalLR,
q_TotalDisplay => "DB_Output".TotalDisplay,
q_Running => "DB_Output".Running
);
Engineering Unit Conversion for Gas Flow
Flow transmitters used in furnace applications typically output a normalized flow in one of several unit systems. The totalizer must convert the per-hour flow to a per-cycle increment using a consistent unit basis. Reference conditions for normal (Nm³) flow are 0°C and 101.325 kPa unless otherwise specified by the transmitter or gas contract.
| Transmitter Unit | Conversion to Nm³/h | Note |
|---|---|---|
| Nm³/h (metric normal) | Direct | Reference conditions: 0°C, 101.325 kPa |
| m³/h (actual) | × (P_actual × T_ref) / (P_ref × T_actual) | Compressibility corrections may apply for high-pressure lines |
| kg/h (mass) | × (1 / ρ_gas) | ρ_gas ≈ 0.717 kg/Nm³ for pure methane, 0.7-0.85 kg/Nm³ for natural gas |
| SCFM | × 1.6990 | Standard cubic feet per minute to Nm³/h (60°F, 14.696 psia) |
| lb/h | × 0.4536 / ρ_gas | Pounds mass to Nm³/h |
For a transmitter already configured for Nm³/h, the integration is direct. For a transmitter in mass flow (kg/h), the engineering unit range passed to FC105 should be set in Nm³/h equivalent by dividing the maximum kg/h by the gas density, or the FC105 output can be post-divided before being passed to the totalizer.
From Totalized Volume to Gas Cost
Once the LREAL total is updated, downstream calculations can convert cumulative volume to energy and cost. The energy content of natural gas is typically expressed as a higher heating value (HHV) or lower heating value (LHV) depending on the metering convention used by the gas supplier.
| Parameter | Typical Value | Unit | Note |
|---|---|---|---|
| Natural Gas HHV | 37.3 - 39.1 | MJ/Nm³ | Varies by composition; supplier-supplied value preferred |
| Natural Gas LHV | 33.5 - 35.2 | MJ/Nm³ | Used for combustion efficiency calculations |
| Energy conversion | 1 kWh = 3.6 | MJ | Standard SI conversion |
| Typical industrial tariff | 0.02 - 0.12 | USD/kWh | Region and contract dependent |
E_MJ = V_Nm3 × HHV_MJ_per_Nm3
E_kWh = E_MJ / 3.6
Cost = V_Nm3 × Tariff_per_Nm3 // volumetric billing
= E_kWh × Tariff_per_kWh // energy billing
These calculations can be performed in a separate FB (e.g., FB_CostCalc) that consumes q_TotalLR from the totalizer and updates a daily, weekly, and monthly cost register for SCADA display. The HHV value should be loaded from a configurable operator tag so it can be updated when the gas chromatograph report is issued.
Verification and Commissioning
Before connecting to the live process, validate the totalizer chain with a known input and a measured duration. The following procedure confirms scaling, integration, validity handling, and display behavior.
- Force the AI raw input (e.g., IW512) to a value representing 50% of range, e.g., 13824 counts for a 4-20mA/0-1000 Nm³/h transmitter. Verify FC105 output reads 500.0 Nm³/h in MD100 and RET_VAL = W#16#0000.
- Confirm OB35 is triggered at 1 Hz by monitoring the call counter or a local tag incremented inside the FB. Use a watch table with 1-second cyclic polling.
- Run the system for 3600 cycles (3600 seconds = 1 hour) at constant 50% input and verify the LREAL total reads 500.0 Nm³. Expected increment per cycle: 0.1389 Nm³ (500 / 3600).
- Force the AI input to 0 (0 Nm³/h) and verify the total does not change. Then set i_FlowValid = FALSE and verify the integration halts.
- Force the AI input above range (e.g., 28000 counts) and verify FC105 RET_VAL returns an error code; verify the totalizer freezes integration when validity is wired correctly.
- Test the reset command via the SCADA and verify the total returns to 0.0 LREAL on the rising edge of i_ResetTotal. Verify the reset is edge-triggered (not level-triggered) by holding the input high.
- Run the loop for 24 hours at constant 50% input and verify the LREAL total reads 12000.0 Nm³. The 32-bit display value should match to 7 significant digits; any divergence indicates a scaling or unit conversion error.
- Cycle power on the S7-400 and confirm the LREAL total is retained. If the total resets, the instance DB is not configured as retentive.
Troubleshooting Matrix
| Symptom | Likely Cause | Diagnostic | Corrective Action |
|---|---|---|---|
| Total does not increment | OB35 not running or FB not called | Monitor OB35 call counter; check CPU diagnostic buffer for OB35 time errors | Confirm OB35 is configured in HW Config with a non-zero period; verify the FB call is in OB35, not OB1 |
| Total increments but reads wrong magnitude | FC105 HI_LIM/LO_LIM swapped or scaled to wrong unit | Check FC105 RET_VAL; verify scaling direction with a known input | Swap HI_LIM and LO_LIM if negative slope transmitter; confirm FC105 error code W#16#0008 (HI_LIM = LO_LIM) |
| Total correct for first hour, then freezes | OB35 overflow (OB35 not finished before next trigger) | CPU diagnostic buffer reports OB35 time error | Extend OB35 period (e.g., 2000ms) or reduce OB35 workload; check for nested interrupt issues |
| Total drifts significantly over 24h | 32-bit REAL used for accumulator | Inspect accumulator data type in the FB instance | Migrate to LREAL; if CPU does not support LREAL, implement DINT chunk-and-add with bounded rounding |
| Total resets unexpectedly | FB instance DB is being overwritten or downloaded | Check online/offline DB consistency; review download logs | Mark DB as retentive; avoid downloading during operation; use password protection on the DB |
| Total shows 0 after CPU restart | Instance DB is not configured as retentive | Open DB properties → Retain attribute | Set the total tag as retentive in the DB properties; verify in the CPU's retentive memory configuration |
| Display shows garbage or NaN | LREAL conversion to REAL exceeds display range | Check q_TotalDisplay value in the VAT | Add explicit clamping (e.g., 1.0E+30 max) before casting to REAL; investigate upstream overflow |
| Wire break alarm from AI but total keeps incrementing | Validity flag not wired to the FB | Monitor i_FlowValid in the FB instance | Wire SM 431 channel diagnostic (e.g., PIW quality byte) to i_FlowValid; freeze integration on bad quality |
| Total grows faster than expected | Wrong Δt_h value (mismatch with OB35 period) | Compare actual OB35 period with i_DeltaT_h input | Recompute i_DeltaT_h as OB35_period_ms / 3600000.0; expose as configurable tag |
Common Pitfalls and Field-Engineered Caveats
Pressure and temperature compensation: Most industrial flow transmitters used for gas measurement internally compensate for line pressure and temperature to output a "normal" (Nm³/h) flow. If the transmitter outputs actual (m³/h) flow, the totalizer should be configured for actual volume, and the energy calculation should apply a separate pressure-temperature correction. Mixing reference conditions produces systematic 5-15% errors that are difficult to detect without an independent reference meter.
Density assumption for mass-flow transmitters: If the transmitter is configured for mass flow (kg/h) but the totalizer is set up for volumetric accumulation, the conversion must use the actual line density (or standard density at reference conditions) rather than a hard-coded methane density. Natural gas density varies from 0.7 to 0.85 kg/Nm³ depending on composition and supplier.
Time base consistency: The integration timebase i_DeltaT_h must be kept in sync with the OB35 period. If the OB35 period is changed in HW Config (e.g., from 1000ms to 500ms), i_DeltaT_h must be updated accordingly. A common implementation error is to hardcode 1.0/3600.0 and forget that the OB35 period is configurable per project.
Counter behavior during transient conditions: During a startup transient, the flow can briefly exceed the transmitter's calibrated range. The AI module will saturate at 27648 counts, and FC105 will clamp to HI_LIM. The totalizer will integrate the clamped value, which is the correct behavior - the alternative (ignoring the saturated value) would under-report consumption. Verify that the HI_LIM value matches the transmitter's maximum calibrated flow, not the normal operating flow.
Retentive behavior on power loss: S7-400 CPUs retain DB contents across power cycles only if the DB is configured as retentive in the CPU's memory configuration. Without retentive configuration, the totalizer will reset to 0 on every power cycle, which is a serious concern for billing applications. Verify retentive memory sizing in the CPU properties - the LREAL accumulator requires 8 bytes per instance, plus any other retentive tags in the same DB.
Endianness and STEP 7 / TIA Portal consistency: LREAL values stored in DBs follow IEEE 754 byte order. If you migrate the project from STEP 7 V5.x to TIA Portal, verify that the DB interface descriptions match exactly - a mismatched interface can corrupt the LREAL accumulator on the first cycle after migration. Always perform a controlled restart with manual verification of the totalizer after any project migration.
Multiple concurrent totalizers: When the project has more than one totalizer (e.g., multiple burners, multiple flow streams), allocate separate FB instance DBs and confirm each has its own retentive area. Sharing a single DB across multiple totalizer instances is supported by S7-400 multi-instance model but complicates retentive tag management.
OB35 starvation under high cyclic load: If OB1 cycle time approaches the OB35 period, OB35 can be delayed or skipped. Monitor the CPU scan time and the OB35 start time stamp; if OB35 is being delayed, increase the OB35 period or move non-time-critical code out of OB35 into OB1.
Which Siemens block converts a 4-20mA signal to engineering units for a flow totalizer on the S7-400?
FC105 SCALE in the STEP 7 Standard Library "TI-S7 Converting Blocks." Wire the AI raw input (e.g., IW512) to IN, set BIPOLAR = FALSE for 0-20mA or 4-20mA unipolar operation, define HI_LIM and LO_LIM as the engineering unit range (e.g., 0.0 to 1000.0 Nm³/h), and read the scaled REAL from OUT. RET_VAL returns W#16#0000 on success.
Why is 32-bit REAL not recommended for long-term flow totalization on the S7-400?
32-bit IEEE 754 REAL provides only about 7 decimal digits of precision. When the accumulated total grows large (e.g., 10⁹ Nm³), the smallest representable increment becomes hundreds of Nm³, and the addition of a small per-cycle volume chunk (e.g., 0.3 Nm³) is silently discarded by the FPU because n + a = n at that exponent. Use LREAL (64-bit, ~15-17 digits) for the persistent accumulator, or implement a DINT chunk-and-add strategy with bounded rounding.
What is the correct OB to use for a 1-second flow totalizer update on the S7-400?
OB35, the standard cyclic interrupt organization block, configured with a period of 1000ms. The period is set in HW Config under CPU Properties → Cyclic Interrupts. A typical flow integration uses OB35 priority 12 and a 1000ms period, giving a per-cycle increment of Q_flow × (1/3600) in Nm³ per second.
How do I keep the totalizer value after a CPU power cycle?
Configure the FB instance DB as retentive in the CPU properties (Retentive Memory settings) so the LREAL total tag is preserved across power-down/power-up cycles. Without retentive configuration, the total resets to 0.0 on every restart. For S7-400, the retentive area is configured per DB in the CPU's Memory tab; ensure the LREAL tag is included in the retentive byte range.
How do I convert totalized Nm³ of natural gas to kWh and cost?
Multiply the total Nm³ by the gas higher heating value (HHV) supplied by the gas utility (typical 37.3 to 39.1 MJ/Nm³ for pipeline natural gas) to get energy in MJ, then divide by 3.6 to convert to kWh. Apply the per-Nm³ or per-kWh tariff to get cost. For accurate billing, use the actual HHV from the gas supplier's chromatograph report rather than a generic value.