S7-1200 Peak Detection: Finding Max Values from Analog Sensors

David Krause16 min read
S7-1200SiemensTutorial / 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

S7-1200 Peak Detection: Finding Max Values from Analog Sensors

Capturing the maximum value reached by an analog sensor on a SIMATIC S7-1200 PLC is a recurring requirement in machine building: an accelerometer measuring peak shock on a press, a load cell capturing spike forces on a stamping die, a pressure sensor recording water hammer, or a vibration sensor monitoring bearing health. This reference covers three engineering-grade approaches - native MAX instruction, the LGF SearchMinMax function block, and a slope-based transient peak detector FB - together with the analog scaling, filtering, and cycle-time decisions that determine whether the recorded peak is real or noise.

1. Overview

An S7-1200 CPU (firmware V4.2 or higher for full SCL feature set, V4.4+ recommended) running TIA Portal V17 or V18 exposes three building blocks for peak detection:

  • MAX / MIN instructions in the "Basic instructions > Comparator operations" folder - scalar comparators that return the larger of two REAL or INT values per scan.
  • LGF_SearchMinMax from the official Siemens Library of General Functions (LGF) for S7-1200/S7-1500 - a parameterizable FB that scans an ARRAY[*] OF REAL and returns the minimum, maximum, and the array index where each occurred.
  • Custom FB using slope (first derivative) analysis - a three-sample window detects the apex of a transient that may last only a few milliseconds, which a single-scan MAX may miss entirely.

The choice between them is driven by the signal class: slowly varying process values (level, temperature, position) suit MAX; windowed/buffered measurement histories suit LGF_SearchMinMax; impulsive events (acceleration, pressure spikes, strain bursts) require a slope detector plus a fast cyclic interrupt OB.

2. Prerequisites

Item Specification Notes
CPU S7-1200, firmware V4.4 or higher V4.4 adds enhanced trace and runtime diagnostics
Engineering software TIA Portal V17 Update 4 or V18 Update 2 Required for LGF V3.0.x compatibility
Analog input module SM 1231 (6ES7231-4HF32-0XB0) or AI in signal board SB 1231 12-bit basic, 16-bit on HF/HS variants
Sensor Accelerometer (IEPE/±10 V/4-20 mA), load cell, pressure, or any 0-10 V / ±10 V / 4-20 mA source IEPE needs external conditioning (e.g., 6AT8002)
LGF library Siemens LGF V3.0.0 or later (TIA V17/V18 build) Distributed as .alp archive via Siemens Industry Online Support
Documentation Siemens Industry Online Support Search "LGF SearchMinMax" and "S7-1200 System Manual"
Wiring note. For accelerometers delivering IEPE (constant-current 4-20 mA with bias), connect a 4-20 mA SM 1231 channel and provide a 2-wire IEPE-compatible signal conditioner. Connecting an IEPE source directly to a 0-10 V SM 1231 input will not bias the internal amplifier and will yield near-zero readings.

3. Analog Input Signal Conditioning on the S7-1200

The SM 1231 module presents the raw input as an INT in the process image. The standard range is:

Sensor signal Raw INT range (S7-1200) Resolution (16-bit HF)
Unipolar voltage 0-10 V 0 to 27648 ~153 µV / count
Bipolar voltage ±10 V -27648 to +27648 ~305 µV / count
Current 4-20 mA 0 to 27648 ~0.58 µA / count
Current 0-20 mA 0 to 27648 ~0.72 µA / count

Convert raw to engineering units using the dedicated SCALE_X and NORM_X instructions in TIA Portal under Basic instructions > Converter operations:

// SCL - call SCALE_X in a function block
#EngineeringValue := SCALE_X(
    MIN   := 0,                // Engineering low  (e.g. 0.0 g)
    MAX   := 50.0,             // Engineering high (e.g. 50.0 g)
    VALUE := NORM_X(
        MIN := 0,              // Raw low  = 0
        MAX := 27648,          // Raw high = 27648
        VALUE := %IW64         // SM 1231 channel 0
    )
);
Bipolar sensor warning. If the sensor is bipolar (±10 V accelerometer), set MIN := -27648 and MAX := 27648 in NORM_X. Failing to do this produces a sign-locked output and a peak detector that reports only positive halves of the waveform.

4. Approach 1 - Native MAX / MIN Instructions

The simplest peak latcher is a feedback loop: compare the current scaled value with a retained maximum and overwrite the retained value whenever the current value is higher. Because the retained value must survive across scan cycles, the logic must live in a function block (FB) with a static PeakValue variable - never in an FC.

FUNCTION_BLOCK "FB_PeakLatch_R"
{ S7_Optimized_Access := 'TRUE' }
VAR
    PeakValue : REAL := 0.0;          // Static, retained
    SampleCnt : DINT;                 // Number of samples examined
END_VAR
VAR_INPUT
    Reset     : BOOL;                 // TRUE clears PeakValue
    Enable    : BOOL;                 // FALSE freezes the latch
    Input     : REAL;                 // Scaled engineering value
END_VAR
BEGIN
    IF #Reset THEN
        #PeakValue := 0.0;
        #SampleCnt := 0;
    ELSIF #Enable THEN
        IF #Input > #PeakValue THEN
            #PeakValue := #Input;
        END_IF;
        #SampleCnt := #SampleCnt + 1;
    END_IF;
END_FUNCTION_BLOCK

Call the FB in OB1 (or in a cyclic interrupt OB - see Section 7):

// OB1 - cyclic call from main program
"FB_PeakLatch_R_DB"(
    Reset  := "HMI".ResetPeak OR "StartupFirstScan",
    Enable := TRUE,
    Input  := "ScaleAccel".Output   // scaled g value
);
"HMI".PeakValue := "FB_PeakLatch_R_DB".PeakValue;

Limitations of pure MAX latching:

  • No time stamp of the peak - you know the value but not when it occurred.
  • If the scan period is slower than the transient (e.g., 50 ms OB1 scanning a 5 ms pulse), the peak may be missed entirely between samples.
  • No valley / minimum recording - extend the FB symmetrically if needed.

5. Approach 2 - LGF SearchMinMax Function Block

The Siemens LGF provides LGF_SearchMinMax (V3.0.0+), a parameterizable FB that scans an array of samples in one call and returns the minimum, maximum, and their indices. This is the correct choice when you want the peak over a defined measurement window (e.g., the last 1000 samples, or the samples taken between Start and Stop inputs).

Import the LGF into TIA Portal via Options > Global libraries > Open library, then drag the FB into your project. The interface of LGF_SearchMinMax is:

Direction Name Type Description
INPUT execute BOOL Rising edge starts the scan
INPUT arrayOfReal ARRAY[*] OF REAL Source buffer (slice or full array)
INPUT mode INT 0=min, 1=max, 2=min&max
OUTPUT minValue REAL Minimum value in array
OUTPUT maxValue REAL Maximum value in array
OUTPUT minIndex DINT Index where min occurred
OUTPUT maxIndex DINT Index where max occurred
OUTPUT error BOOL 1 = parameter error
OUTPUT status WORD 0 = OK, non-zero = error code

Typical use - capture the peak in a 1-second window at 100 Hz (100 samples):

// Cyclic OB30 every 10 ms, with 100-element ring buffer
"LGF_SearchMinMax_DB"(
    execute    := "Trigger".OneSecondTick,   // 1 Hz pulse
    arrayOfReal := "DataLog".Buffer,         // 100 x REAL ring buffer
    mode       := 2,                          // 0=min, 1=max, 2=both
    minValue   => "HMI".WindowMin,
    maxValue   => "HMI".WindowMax,
    minIndex   => "HMI".WindowMinIdx,
    maxIndex   => "HMI".WindowMaxIdx,
    error      => "Diag".LgfErr,
    status     => "Diag".LgfStatus
);

Advantages over a single MAX instruction:

  • Returns index, so a peak can be correlated with the time stamp stored in a parallel array.
  • Detects both extremes from one scan, useful for closed-loop valves that need to know max and min over a stroke.
  • Battle-tested FB with documented status codes from the LGF manual.
LGF version note. LGF V2.0.x targets S7-1500 only; for S7-1200 you must use LGF V3.0.0 or later published by Siemens for the S7-1200/S7-1500 family. Check the library's ReadMe for firmware compatibility - V3.0.0 declares minimum S7-1200 firmware V4.2.

6. Approach 3 - Slope-Based Transient Peak Detection

For impulsive events - the peak g of a stamping press, the water-hammer spike in a hydraulic line, the impact force of a tool engaging a workpiece - a single comparator misses the apex unless the scan period is shorter than the event itself. The robust solution is a three-sample slope detector that flags a peak when the signal was rising on the previous sample and falling on the current one.

FUNCTION_BLOCK "FB_PeakDetector_Transient"
{ S7_Optimized_Access := 'TRUE' }
VAR
    x_n0 : REAL;    // current sample
    x_n1 : REAL;    // previous sample
    x_n2 : REAL;    // pre-previous sample
    ts   : DINT;    // peak time stamp (ms since PLC start)
END_VAR
VAR_INPUT
    Input        : REAL;     // scaled engineering value
    Threshold    : REAL := 0.001;  // min rise/fall slope
    Enable       : BOOL;
    Reset        : BOOL;
END_VAR
VAR_OUTPUT
    PeakDetected : BOOL;
    PeakValue    : REAL;
    PeakTime_ms  : DINT;
END_VAR
VAR_TEMP
    slopeUp   : BOOL;
    slopeDown : BOOL;
END_VAR
BEGIN
    IF #Reset THEN
        #PeakValue := 0.0;
        #PeakDetected := FALSE;
        #x_n0 := #Input;
        #x_n1 := #Input;
        #x_n2 := #Input;
        RETURN;
    END_IF;

    IF NOT #Enable THEN RETURN; END_IF;

    // Shift history
    #x_n2 := #x_n1;
    #x_n1 := #x_n0;
    #x_n0 := #Input;

    // Rising then falling = peak
    #slopeUp   := (#x_n0 - #x_n1) >  #Threshold;
    #slopeDown := (#x_n1 - #x_n2) >  #Threshold;

    IF #slopeUp AND #slopeDown THEN
        #PeakValue    := #x_n1;          // apex is the middle sample
        #PeakTime_ms  := TIME_TCK();     // system tick in ms
        #PeakDetected := TRUE;            // sticky flag for HMI
    END_IF;
END_FUNCTION_BLOCK

Why three samples? Two samples tell you the slope direction now; the third sample lets you know what the slope was previously. The combination up then down is a local maximum. Setting Threshold above the noise floor (use 3-5× the standard deviation of the resting signal) prevents the detector from firing on quantisation noise. TIME_TCK() returns a 100 ns tick; divide by 10,000 to convert to milliseconds.

7. Cycle Time and Sampling Considerations

The S7-1200 default scan in OB1 is 10-50 ms. A 5 ms accelerometer pulse will be aliased or missed. To sample fast, move the peak logic into a cyclic interrupt OB:

OB Name Configurable interval Typical use
OB1 Main Scan-driven (10-50 ms) Slow process values
OB30 Cyclic interrupt 0 1 ms to 60 s Fast control loops, vibration, peak detect
OB31 Cyclic interrupt 1 1 ms to 60 s Independent loop
OB40 Hardware interrupt On threshold/limit Edge-triggered capture

For a 1 kHz vibration sample, set the OB30 time to 1 ms. The S7-1200 hardware filters the analog input to ~50 Hz on most SM 1231 channels, so a 1 kHz event is heavily attenuated - a true 1 kHz capture requires an external sample-and-hold or a third-party IEPE digitiser. For press-impact peaks of ~10-50 ms duration, a 1 ms OB30 is more than sufficient.

Anti-aliasing. The SM 1231 modules integrate a 1st-order low-pass filter at ~25 Hz. If the signal contains frequency content above the cycle-rate, the CPU will see a smoothed waveform - which is actually beneficial for peak detection because it suppresses the noise that would otherwise cause false triggers. Verify the actual bandwidth of your specific SM 1231 article number in the S7-1200 System Manual.

8. Filtering the Sensor Signal

Three filter strategies are commonly used before peak detection, each available as either a Siemens standard instruction or a hand-rolled SCL block:

8.1 Moving Average (N-tap FIR)

// 8-tap moving average ring buffer
IF #Index > 7 THEN #Index := 0; END_IF;
#Sum := #Sum - #Buf[#Index] + #Input;
#Buf[#Index] := #Input;
#Index := #Index + 1;
#Average := #Sum / 8.0;

An 8-tap moving average at 1 ms OB30 gives a flat passband to ~125 Hz with linear phase - ideal for a press-impact peak that lasts 10-50 ms.

8.2 PT1 First-Order Low-Pass

Siemens provides the standard CTRL_PT1 instruction, or use LGF_Filter_PT1 from the LGF library. Cutoff frequency fc is set by:

fc = 1 / (2π · Tconst)

For a 10 Hz cutoff: T_const = 0.0159 s.

8.3 Exponential Smoothing

#Filtered := #Alpha * #Input + (1.0 - #Alpha) * #Filtered;

With α = 0.1-0.3, exponential smoothing is computationally trivial and effective for slowly varying DC levels. It is not a true low-pass filter (no defined cutoff), but its single-coefficient footprint makes it the default on memory-constrained S7-1200 CPUs.

Filter selection rule. For transient peak capture (impacts, spikes), use a moving average because it preserves the peak amplitude. A PT1 low-pass will attenuate the peak value by 30 % or more for a 10 ms pulse - which means your recorded peak is too low.

9. FB vs FC - Choosing the Right Block Type

A function (FC) is stateless; an function block (FB) carries a static data block (DB) that retains its values between calls. The peak-detection logic must remember the previous peak value, so it cannot live in an FC unless the previous value is passed in as an IN_OUT parameter from a global variable or another FB's static memory.

Block Retains data between calls Recommended for peak detection
FC No (stateless) Only if previous peak is an IN_OUT from caller
FB Yes (instance DB) Default choice; clean encapsulation

If you convert an FB to an FC because you only want a stateless function (e.g., to read the peak out of a buffer), declare the previous peak value as VAR_IN_OUT instead of VAR_OUTPUT. The compiler will not permit a VAR (static) inside an FC.

10. HMI Display and Data Logging

Typical WinCC / HMI tag mapping for a peak detection application:

HMI tag PLC address Polling Use
PeakValue DB.PeakValue (REAL) 1 s Numeric display
PeakTime DB.PeakTime_ms (DINT) 1 s Time stamp string
ResetPeak DB.Reset (BOOL) On demand Button "Reset"
TrendValue %IW64 (raw) or scaled REAL 100 ms Trend view for live waveform
SampleCount DB.SampleCnt (DINT) 1 s Sanity check (must increase)

For archiving, use the DataLog function on a S7-1200 with a 4 GB SD card (max 32 GB supported). Open a CSV log per shift, write the peak value, timestamp, and sample count on every OB30 tick. Retention: 2-3 months at 1 s logging is feasible on a 4 GB card.

11. Verification and Commissioning

  1. Force a known input. Apply a 5.000 V reference (or a calibrated 12.000 mA current source) to the SM 1231 input. Verify the scaled value matches the expected engineering unit to within 0.1 %.
  2. Step test. Connect a function generator producing a 10 Hz, 4 Vpp square wave to the analog input. The expected peak is +2 V and -2 V (bipolar) or +2 V and 0 V (unipolar). Confirm the FB's PeakValue stabilises within 2-3 samples of the true amplitude.
  3. Burst test. Drive a single impulse (e.g., tap the accelerometer with a calibration hammer) and verify that the slope detector's PeakDetected flag pulses for one OB30 cycle and PeakValue latches at the expected g value within ±5 %.
  4. Reset verification. From the HMI, trigger Reset and confirm PeakValue returns to 0.0 (or to the configured idle value) within one OB1 cycle.
  5. Long-duration test. Log the peak value for 24 h. Drift, saturation, and noise are easier to spot in a trend than a single number.

12. Troubleshooting Matrix

Symptom Likely cause Diagnostic step Fix
PeakValue stays at 0 Sensor wired to wrong channel / polarity Monitor %IW raw in watch table Re-wire per SM 1231 pinout
PeakValue locks at 27648 Over-range (sensor > 10 V or open current loop) Check raw value vs. expected Verify sensor output range; check 4-20 mA loop current
PeakValue tracks but is too low PT1 low-pass attenuating transient Compare with moving average Replace PT1 with moving average for impacts
PeakDetected fires continuously Threshold too low, noise triggering slope View raw signal in trace Raise Threshold to 3-5× noise std-dev
PeakValue never updates FB called in wrong OB, or Enable stuck FALSE Check OB30 active bit, watch Enable Move call into OB30; verify Enable source
Bipolar sensor shows only positive peak SCALE_X / NORM_X set to unipolar range Inspect block parameters Set NORM_X MIN := -27648, MAX := 27648
LGF_SearchMinMax returns error Mode out of range, or array passed by slice wrong Inspect status word Set mode to 0/1/2; pass array as ARRAY[*] OF REAL
Peak time stamp jumps backward TIME_TCK() overflow or use of TIA system clock Check CPU diagnostic buffer Reset TIME_TCK reference, or use RD_SYS_T for absolute time

13. Field-Proven Caveats

  • Sample-and-hold mismatch. If your OB1 cycle is 30 ms but the analog event is 5 ms, the analog read may already be returning the tail of the pulse. Insert a hardware peak-detect op-amp (e.g., a diode + capacitor with FET reset) on the analog front-end, or move the entire capture into a 1 ms OB30.
  • Retain behaviour. Mark the instance DB as Non-optimised with retain or Optimised with retain in TIA Portal if you need the peak value to survive a power cycle. Without retain, the peak resets to 0 on every restart.
  • First-scan reset. Tie the FB Reset input to FirstScan (system bit) so the latched peak does not contain a stale value from a previous run on the first cycle after PLC startup.
  • Float math overhead. REAL division on the S7-1200 takes ~6 µs of CPU time at firmware V4.4. At OB30 1 ms, a 100-tap moving average with 100 divisions/sec is well within budget (~0.6 % of cycle), but on the smaller CPU 1212C at 1 ms OB30 it can starve communication. Use DINT fixed-point if cycle time is tight.
  • Ground loops on accelerometers. If the peak value drifts at mains frequency, the accelerometer shell is not grounded. Use a shielded cable with the shield bonded at the PLC end only and an isolated signal conditioner.

14. Choosing the Approach - Quick Selection

Use case Recommended method Why
Slow process value, latch the highest reading Native MAX FB Trivial code, no buffer needed
Buffered measurement over a fixed window LGF_SearchMinMax Returns index, both extremes, validated code
Impulsive event (acceleration, water hammer, impact) Slope FB in 1 ms OB30 + moving average Catches the apex reliably with timestamp
Continuous trend, peak in last N seconds LGF_SearchMinMax on ring buffer Window-based, no missed scans
Vibration, FFT downstream Raw buffer in OB30, no peak logic FFT requires raw samples, not compressed peaks

What cycle time is required to catch an accelerometer peak on the S7-1200?

For a 10-50 ms impact (typical press shock), a 1 ms OB30 cyclic interrupt is sufficient. For sub-millisecond transients, the SM 1231 bandwidth (~25 Hz filtered) and the S7-1200 analog scan rate become the bottleneck - in that case, an external peak-hold circuit or IEPE digitiser is required before the PLC.

How do I reset the latched peak value from the HMI?

Bind a WinCC button to a BOOL tag wired to the FB's Reset input. Pulse the BOOL for one OB1 cycle, then release. The FB sets PeakValue to 0.0 and clears PeakDetected. Make the instance DB retain if you want the value to survive a power cycle.

Can the S7-1200 detect multiple peaks per second?

Yes. Use a ring buffer in a 1 ms OB30 and run LGF_SearchMinMax with mode := 1 (max only) once per cycle, or once per 100 ms if you only need a coarse peak-per-window reading. For multiple discrete peaks per second, iterate the array and detect each local maximum with the slope detector rather than scanning once.

What is the difference between the MAX instruction and LGF_SearchMinMax?

The MAX instruction compares two scalar values per call and returns the larger. LGF_SearchMinMax scans an ARRAY[*] OF REAL and returns the minimum, maximum, and the array indices where each occurred. Use MAX for point-to-point comparison, LGF_SearchMinMax for windowed/buffered analysis.

How do I handle a bipolar analog signal such as ±10 V from an accelerometer?

Configure the SM 1231 channel for ±10 V mode in the device configuration, then in your SCL set NORM_X(MIN := -27648, MAX := 27648, ...) before calling SCALE_X. The peak FB must then accept negative peaks - either declare VAR PeakValue : REAL := 0.0 with a small dead-band, or initialise PeakValue to the most negative representable value so the first rising edge is captured.

Back to blog