S7-1200 Lookup Table for Non-Linear Analog Input Mapping
This reference describes how to convert a 4–20 mA field input into a non-linear engineering value on a SIMATIC S7-1200 using a lookup table implemented in Structured Control Language (SCL). It covers signal conditioning, table storage in a Data Block (DB), piecewise linear interpolation for sparsely sampled tables, full table index lookup for densely sampled tables, and display of the result on a SIMATIC HMI Basic Panel or Unified Comfort Panel.
Use this document when the relationship between the measured process variable (mA in) and the desired display value is documented as a discrete table of breakpoints (for example, a vendor-supplied tank-strapping table, a non-linear transducer curve, or a vendor flow vs. differential pressure curve) and cannot be represented accurately with the standard NORM_X / SCALE_X linear conversion.
ARRAY[..] OF REAL and use direct indexed access. For full polynomial fits use Modular PID Control block NONLIN instead of a hand-written table.1. Reference Architecture
2. Prerequisites
- CPU: SIMATIC S7-1200, firmware V4.2 or later (recommended V4.4 or V4.5 for unified SCL extensions). CPUs covered: 6ES7211-1AE40-0XB0 (1211C), 6ES7212-1AE40-0XB0 (1212C), 6ES7214-1AG40-0XB0 (1214C), 6ES7215-1AG40-0XB0 (1215C), 6ES7217-1AG40-0XB0 (1217C).
- Analog input: SM 1231 signal module. Common catalog numbers: 6ES7231-4HF32-0XB0 (4 AI, 13-bit + sign), 6ES7231-5ND32-0XB0 (4 AI, 16-bit), 6ES7231-5PA40-0XB0 (2 AI RTD), 6ES7231-5QF32-0XB0 (8 AI TC), 6ES7231-5PB32-0XB0 (2 AI TC).
- Engineering: TIA Portal V17 or later. SCL is the recommended language for the interpolation function; LAD/FBD are usable for the block call.
- HMI: SIMATIC KTP700 Basic (6AV2123-2GB03-0AX0) or higher, or SIMATIC Unified Comfort (MTP / TP series).
- Table data: Vendor calibration sheet, tank strapping table, or non-linear transfer function expressed as ≤ 1024 (X, Y) pairs.
Reference documentation:
- SIMATIC S7-1200 Programmable Controller – System Manual
- S7-1200 / S7-1500 SCL Programming and Operating Manual
- Modular PID Control – Function Manual
- SM 1231 Analog Input Module – Equipment Manual
3. Step 1 – Configure the Analog Input Channel
- In the device view of the S7-1200, select the SM 1231 channel that the transmitter is wired to (default channel 0).
- Open Properties → Analog inputs → Channel 0.
- Set Measurement type = Current, Current range = 4…20 mA.
- Set Smoothing = None for table-driven applications (filter would distort the index calculation).
- Set Overflow / underflow behavior to Diagnostic interrupt + substitute value 0 to avoid out-of-range table reads.
After loading the hardware configuration, the raw input word %IW64 (example) returns an integer in the range 0 to 27648. 0 = 0 mA (or open circuit), 27648 = 20 mA. Siemens documents this linearization in the S7-1200 System Manual, Chapter "Analog value representation".
4. Step 2 – Build the Lookup Data Block
Create a Global DB named DB_Lookup with the following structure:
DATA_BLOCK "DB_Lookup"
{ S7_Optimized_Access := 'TRUE' ; S7_Setpoint := 'FALSE' }
VERSION : 0.1
NON_RETAIN
STRUCT
X_BP : ARRAY[1..32] OF REAL; // 32 X breakpoints, monotonically increasing
Y_BP : ARRAY[1..32] OF REAL; // 32 corresponding Y values
N : INT := 32; // active breakpoint count
Xmin : REAL := 4.0; // input range low (mA)
Xmax : REAL := 20.0; // input range high (mA)
Ymin : REAL := 0.0; // output low (engineering units)
Ymax : REAL := 100.0; // output high (engineering units)
LastIdx : INT := 1; // last segment index (HMI tag)
RawIn : INT := 0; // raw AI word (debug)
END_STRUCT;
END_DATA_BLOCK
i := LIMIT(1, RawIn, 27648) * N / 27648. This eliminates the search loop.Populate X_BP and Y_BP from the vendor calibration sheet. Ensure monotonic increase in X (the routine will not work correctly with a non-monotonic table). Store the values in engineering units – never mA – so the HMI can display directly.
4.1 Worked example – pH probe inverse curve
| i | X_BP (mA) | Y_BP (pH) |
|---|---|---|
| 1 | 4.00 | 0.00 |
| 2 | 5.60 | 1.00 |
| 3 | 7.20 | 2.00 |
| 4 | 8.80 | 3.00 |
| 5 | 10.40 | 4.00 |
| 6 | 12.00 | 5.00 |
| 7 | 13.60 | 6.00 |
| 8 | 15.20 | 7.00 |
| 9 | 16.80 | 8.00 |
| 10 | 18.40 | 9.00 |
| 11 | 20.00 | 10.00 |
The mA span is 4–20, the pH span is 0–10, but the curve is non-linear near the endpoints (steeper in the neutral range). Linear scaling with SCALE_X would introduce ±0.4 pH error at pH = 7.
5. Step 3 – Normalize the Raw Input
Convert %IW64 (0–27648) to a real number in the X domain (4–20 mA) using the standard Siemens conversion functions. Place this in OB1 or a Cyclic Interrupt OB (OB30–OB38) to get a deterministic 100 ms scan.
// LAD / FBD equivalent
NORM_X (EN := TRUE,
MIN := 0,
VALUE := %IW64,
MAX := 27648,
RET_VAL := rNorm);
SCALE_X (EN := TRUE,
MIN := 4.0,
VALUE := rNorm,
MAX := 20.0,
RET_VAL := rXmA);
After this block, rXmA is in mA. NORM_X and SCALE_X are documented in the SCL Programming Manual.
6. Step 4 – SCL Function Block for Piecewise Linear Interpolation
Create FB_LookupTable in SCL. The block performs a linear search through the breakpoint table, identifies the bracketing pair, and performs a one-line linear interpolation. Boundary handling clamps the output to the first and last Y_BP entries.
FUNCTION_BLOCK "FB_LookupTable"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 1.0
VAR_INPUT
X : REAL; // input value (e.g. mA)
TableDB : DB_ANY; // reference to DB_Lookup
END_VAR
VAR_OUTPUT
Y : REAL; // interpolated output
SegmentIdx : INT; // active segment (1..N-1)
Status : WORD; // 16#0000 OK, 16#8001 below range, 16#8002 above range
END_VAR
VAR
N : INT;
Xmin : REAL;
Xmax : REAL;
i : INT;
xLo : REAL;
xHi : REAL;
yLo : REAL;
yHi : REAL;
slope : REAL;
END_VAR
BEGIN
// Read table parameters from referenced DB
N := "DB_Lookup".N;
Xmin := "DB_Lookup".Xmin;
Xmax := "DB_Lookup".Xmax;
Status := 16#0000;
// 1. Clamp / detect under/over-range
IF X <= "DB_Lookup".X_BP[1] THEN
Y := "DB_Lookup".Y_BP[1];
SegmentIdx := 1;
Status := 16#8001;
RETURN;
END_IF;
IF X >= "DB_Lookup".X_BP[N] THEN
Y := "DB_Lookup".Y_BP[N];
SegmentIdx := N - 1;
Status := 16#8002;
RETURN;
END_IF;
// 2. Linear search – acceptable for N <= 32
i := 1;
WHILE i < N DO
IF X <= "DB_Lookup".X_BP[i + 1] THEN
EXIT;
END_IF;
i := i + 1;
END_WHILE;
SegmentIdx := i;
// 3. Linear interpolation between [i] and [i+1]
xLo := "DB_Lookup".X_BP[i];
xHi := "DB_Lookup".X_BP[i + 1];
yLo := "DB_Lookup".Y_BP[i];
yHi := "DB_Lookup".Y_BP[i + 1];
slope := (yHi - yLo) / (xHi - xLo);
Y := yLo + slope * (X - xLo);
END_FUNCTION_BLOCK
NONLIN (supports up to 21 breakpoints and maintains derivative continuity).6.1 Performance notes
- For N = 32, the linear search executes in < 60 µs on a CPU 1215C, well inside the 1 ms OB1 budget.
- For N = 256, switch to a binary search: replace the
WHILEloop with a 7-step binary split. Complexity drops from O(N) to O(log2 N). - For dense tables (N = 1024), bypass the search entirely and use direct array access
Y := DB.Y_BP[idx]withidx := REAL_TO_INT(X * 51.2)for 4–20 mA / 0–10 V normalization.
7. Step 5 – Use Modular PID Control NONLIN (Alternative)
If the option package Modular PID Control is licensed on the S7-1200 (article number 6ES7860-1AA10-0YX0 for V14 onward, see Modular PID Control – Function Manual), the NONLIN function block implements a 21-point piecewise non-linear function block. Configuration steps:
- Drag
FB NONLINfrom the Modular PID library into a cyclic OB. - Open the block instance DB and set
X[1..21]andY[1..21]breakpoints in engineering units. - Wire the input variable (after
NORM_X/SCALE_X) toX_IN. - Wire the output
Y_OUTdirectly to the HMI tag. - Set
GAIN = 1.0andOFFSET = 0.0for direct pass-through.
NONLIN automatically handles the boundary clamping and supports a derivative-continuous polynomial interpolation, which is useful when the curve includes a sensor manufacturer's polynomial coefficients.
8. Step 6 – Configure the HMI Tag and Display
- In TIA Portal, add a tag to the HMI connection, name
ProcessValue, datatypeREAL, point to"DB_Lookup".Y(the FB output). - Add a tag
SegmentIdxof typeINTfor diagnostic display (HMI shows which segment is active during commissioning). - Insert an IO field on the screen. Mode = Output. Format pattern =
999.99(or appropriate). - For diagnostic, add a bar graph with Min =
Ymin, Max =Ymax. - Configure a limit-value observation: yellow when
Status = 16#8001(under-range, wire break), red whenStatus = 16#8002(over-range, sensor short).
9. Step 7 – OB1 Wiring and Cycle Discipline
For a 100 ms refresh (typical for display purposes), call the FB in a cyclic interrupt:
// In OB30 (Cyclic interrupt, 100 ms)
// "MyLookupInst" is the instance DB of FB_LookupTable
// 1. Convert raw AI to mA (0..27648 → 4..20 mA)
NORM_X (MIN := 0, VALUE := %IW64, MAX := 27648, RET_VAL => rNorm);
SCALE_X(MIN := 4.0, VALUE := rNorm, MAX := 20.0, RET_VAL => rXmA);
// 2. Run lookup
"MyLookupInst"(X := rXmA, TableDB := "DB_Lookup");
// 3. Y and SegmentIdx are written to instance DB and displayed on HMI
For closed-loop control, move the call to OB1 with a 10 ms cycle, and feed the result directly to the PID_Compact input Setpoint or Input.
10. Verification Procedure
- Apply a calibrated 4.000 mA source from a precision calibrator (Beamex MC6 or similar) and read
Yfrom the watch table. ExpectY = 0.00,Status = 16#8001if below first breakpoint, otherwise Y = first Y_BP. - Step the input to 12.000 mA. Expect the breakpoint pair (12.0, 5.0) to be hit –
Y = 5.00,SegmentIdx = 6. - Step the input to 19.000 mA. The interpolated value should be
Y = 9.00 + ((19.0 - 18.4) / (20.0 - 18.4)) * (10.0 - 9.0) = 9.375.SegmentIdx = 10. - Open-circuit the input (0 mA). Expect
Y = 0.00,Status = 16#8001, and the SM 1231 to raise diagnostic interrupt SF LED on the module. - Inject 22 mA (over-range). Expect
Y = 10.00,Status = 16#8002. - Verify continuity at all breakpoints:
Y(X_BP[i]) == Y_BP[i]to within 1 × 10⁻⁶. - Confirm cycle time in OB30: TIA Portal Online & Diagnostics → Cycle time. Should remain under 50 % of the OB phase time.
11. Sampling-Rate and Resolution Constraints
| SM 1231 variant | Resolution | Integration time | Throughput | Recommended for |
|---|---|---|---|---|
| 6ES7231-4HF32-0XB0 (4 AI) | 12-bit + sign | 12.17 ms @ 60 Hz | ~80 Hz per channel | Slow temperature, level |
| 6ES7231-5ND32-0XB0 (4 AI) | 16-bit | Configurable 1.25–20 ms | Up to 400 Hz per channel | Flow, pressure, fast level |
| Built-in AI on CPU 1215C/1217C | 12-bit | 10 ms | 100 Hz | Cost-sensitive |
Resolution directly limits the achievable table density. A 12-bit converter over 4–20 mA produces 4096 discrete codes; a 16-bit converter produces 65536. A table with more entries than ADC codes wastes memory and adds no accuracy.
12. Direct Indexed Access for Dense Tables
When the breakpoint count equals the ADC count (e.g. 1024 points across 0–27648), replace the search with a single array lookup. This is the most accurate and fastest method for vendor-supplied full-range tables.
// In OB30
iRaw := LIMIT_INT(0, %IW64, 27648);
idx := REAL_TO_INT(INT_TO_REAL(iRaw) * 1024.0 / 27648.0) + 1;
idx := LIMIT_INT(1, idx, 1024);
ProcessValue := "DB_Lookup".Y_BP[idx];
This approach runs in < 8 µs on a CPU 1215C and eliminates all interpolation error – the table is the truth.
13. Diagnostic Tags and HMI Alarm Wiring
| Status word | Meaning | HMI indication | Recommended action |
|---|---|---|---|
| 16#0000 | OK | Green dot | None |
| 16#8001 | Under-range / wire break | Yellow warning | Check loop, check transmitter |
| 16#8002 | Over-range / short | Red alarm | Verify range, check sensor |
| 16#0001 | Table not monotonic | Yellow (commissioning only) | Re-enter X_BP in ascending order |
| 16#0002 | DB not loaded | Red (system) | Recompile, re-download DB |
Add the following ProDiag supervision to the S7-1200 to log the lookup overflow to the diagnostic buffer:
// Inside FB_LookupTable, after each RETURN
IF Status <> 16#0000 THEN
WRMSG (EV_ID := 1, // arbitrary event ID
INFO := 1, // text ID from project text list
STATUS := Status);
END_IF;
14. Common Pitfalls and Field Notes
-
Mixing up byte order.
SM 1231 4AI(6ES7231-4HF32) returns 12-bit values in the lower 12 bits of the input word; the upper bits are sign-extended. Always letNORM_Xhandle the scaling rather than reading%IW64directly. -
Non-monotonic X_BP. The linear search in
FB_LookupTableassumesX_BP[1] < X_BP[2] < ... < X_BP[N]. Insert a one-pass monotonicity check at startup and setStatus = 16#0001if violated. - Uninitialized DB after download. When downloading a new DB to a running CPU, retain-mode values may reset. Mark the lookup arrays as Non-retain only if a download is expected; otherwise use Retain and back up with the recipe functionality of the HMI.
- Filtering on the AI. Hardware filtering smooths the input but also desensitizes the lookup. For tables with steep slopes, set Smoothing = None and implement a software moving average in the FB if needed.
- Cold-junction compensation. For thermocouple inputs on SM 1231-5PB32 / 5QF32, the lookup must operate on the linearized °C value, not the raw mV. The compensation is automatic but must be enabled per channel.
- HMI refresh rate. A 100 ms OB30 cycle is faster than the human eye can resolve; setting a 1 s update on the HMI reduces PROFINET traffic by 90 %.
15. Memory and CPU Utilization
| Item | Footprint (CPU 1215C V4.4) | Notes |
|---|---|---|
| DB_Lookup (32 breakpoints, 2 arrays) | 272 bytes | 2 × 32 × 4 + 32 bytes overhead |
| FB_LookupTable instance | ~80 bytes | Local stack of 8 REALs + 1 INT |
| Cycle time in OB30 | ~ 0.06 ms | Linear search, 32 elements |
| Work memory used by SCL block | ~ 6 kB | Compile-time, released after download |
| Modular PID NONLIN (alternative) | ~ 24 kB work, 1.2 kB instance | Requires license |
16. Migration Notes for S7-1500 / ET 200SP
The same FB_LookupTable compiles and runs unchanged on S7-1500 CPUs (firmware V2.5 or later). For ET 200SP, use the AI 4×I 2-/4-wire ST module (6ES7134-6GD01-0BA1, 16-bit) or AI 8×I 2-wire HS (6ES7134-6HB00-0DA1, 16-bit, 1 ms conversion). The diagnostic interrupt behavior is identical; only the device catalog numbers differ.
17. FAQ
How many breakpoints can a S7-1200 lookup table hold?
Practically 1024 breakpoints in a single optimized DB on a CPU 1215C (4 kB DB size limit per data block with optimized access, expandable to 64 kB with standard access). For 21 breakpoints with derivative continuity, use the Modular PID NONLIN block instead of a custom FB.
Why does my HMI display the wrong value at 4 mA even though the transmitter is correct?
Either the SM 1231 channel is configured for 0–20 mA instead of 4–20 mA, or the X_BP[1] entry in DB_Lookup is not exactly 4.000. Verify with the watch table that %IW64 reads 0 at 4 mA. If it reads 5530 the channel is in 0–20 mA mode; reconfigure the channel properties.
Can I edit the lookup table at runtime from the HMI without re-downloading the PLC?
Yes. Mark the X_BP and Y_BP arrays as Non-optimized in the DB properties, expose them to the HMI, and create a recipe view on the panel. A 32-point table uploads/downloads in < 200 ms over PROFINET.
What is the fastest way to convert a 4–20 mA signal to a non-linear value?
Use direct indexed access (Section 12) when the table has one entry per ADC code. This eliminates the search loop and runs in < 8 µs on a CPU 1215C. For smaller tables (≤ 64 points) the linear search is fast enough and the code is simpler to maintain.
How do I detect a broken 4–20 mA loop using only the lookup result?
Configure the SM 1231 channel for wire-break detection (Diagnostics → Wire break = enabled). When the input drops below 3.6 mA the module raises a diagnostic interrupt and forces the input word to 0. The FB_LookupTable will then return Y = Y_BP[1] and Status = 16#8001; use the Status word to drive a red HMI alarm rather than the value itself.
Is the Modular PID NONLIN function faster or more accurate than a hand-written lookup?
NONLIN uses a piecewise polynomial with C1 continuity, so accuracy is typically better at the segment boundaries. Speed is comparable: ~ 0.07 ms per call. The disadvantage is the licensing cost (article 6ES7860-1AA10-0YX0) and the 21-point cap.