Building a Lookup Table in Siemens S7 STEP 7 and TIA Portal

David Krause12 min read
SiemensTIA PortalTutorial / 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

A lookup table maps an input value (in this case a temperature) to a pre-computed output value (a corresponding setpoint, density, viscosity, pH compensation, or similar process constant). On a Siemens SIMATIC S7-300, S7-400, S7-1200, or S7-1500 controller you implement this as either:

  • An SCL array indexed by a fixed index range, with linear or binary search logic in a function block.
  • A STEP 7 data block of REAL values accessed by pointer arithmetic in LAD/FBD/STL (classic STEP 7 V5.x).
  • The TBL_FIND instruction from the S7-300/S7-400 extended instruction set, which searches a source range for a pattern match.
  • The POLYGON function from the Siemens application examples, which linearly interpolates between adjacent table points when the input value falls between two tabulated keys.

This article covers all four approaches for a 40-point temperature table. The first three return an exact match (or no match); the fourth is the correct choice when the process variable can fall between two tabulated values and you need an interpolated output.

Prerequisites

  • STEP 7 V5.7 (classic) or TIA Portal V16/V17/V18/V19/V20/V21 with S7-300, S7-400, S7-1200, or S7-1500 CPU firmware compatible with the installed TIA Portal version. See the Siemens TIA Portal version compatibility list.
  • S7-SCL compiler license installed (S7-SCL V5.7 for STEP 7 V5.x, or the SCL option integrated in TIA Portal).
  • For S7-300/S7-400: the Extended Instructions package containing the table functions (TBL_FIND, Table instructions). The catalog is part of the standard STEP 7 installation; no separate license is required.
  • An S7 program in which the analog input is already normalized to engineering units (REAL) and the output is wired to a destination tag that can receive the looked-up REAL value.
  • Optional: the OSCAT open-source library (free, no Siemens license) for a pre-built X-Y curve block. Verify the license terms before production deployment.
Engineering rule: Always use REAL for both the input key and the output value, even if the process variable is an integer temperature. Indexing with INT/DINT is fine for the search loop counter, but never store temperatures in WORD or BOOL.

Method Comparison

Method CPU families Matches exact key only Interpolates between keys Sort requirement Typical scan time (40 points)
SCL array with linear scan S7-1200, S7-1500, S7-300/400 Yes No (extend to interpolation) No (unsorted works) ~80-200 µs (S7-1500)
SCL array with binary search S7-1200, S7-1500, S7-300/400 Yes No Yes, ascending by key ~30-60 µs (S7-1500)
STEP 7 classic DB + pointer S7-300, S7-400 Yes No No ~150-400 µs (S7-400)
TBL_FIND (LAD/FBD) S7-300, S7-400 Yes (pattern match) No No ~120-300 µs (S7-400)
POLYGON (interpolation) S7-300, S7-400, S7-1200, S7-1500 N/A Yes (linear between points) Yes, strictly ascending by key ~100-250 µs (S7-1500)

Method 1: SCL Array Lookup (TIA Portal)

This is the most maintainable solution on S7-1200 and S7-1500. Define a global data block with two parallel arrays (or one array of a user-defined struct) of length 40, and search by index.

Step 1: Create the data block

In TIA Portal, add a new global DB named DB_Lookup. Inside, declare a structure that holds the input keys (temperatures) and the output values:

DATA_BLOCK "DB_Lookup"
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : EngAuto
FAMILY : Lookup
VERSION : 0.1
  STRUCT
    Key   : ARRAY[1..40] OF REAL;   // Temperature in °C
    Value : ARRAY[1..40] OF REAL;   // Lookup result (engineering units)
  END_STRUCT;
END_DATA_BLOCK

Step 2: Populate the table in a startup OB

Use OB100 (warm restart) or OB101 (hot restart) to load the 40 pairs from the project or from a recipe DB. For fixed tables, hard-code them in OB100:

"DB_Lookup".Key[1]   :=   0.0;  "DB_Lookup".Value[1]  :=   1.000;
"DB_Lookup".Key[2]   :=   5.0;  "DB_Lookup".Value[2]  :=   0.998;
"DB_Lookup".Key[3]   :=  10.0;  "DB_Lookup".Value[3]  :=   0.996;
// ... continue for all 40 points ...
"DB_Lookup".Key[40]  := 195.0;  "DB_Lookup".Value[40] :=   0.879;

Step 3: Implement the lookup function block in SCL

FUNCTION_BLOCK FB_Lookup_Exact
{ S7_Optimized_Access := 'TRUE' }
VAR_INPUT
    iSearchValue : REAL;       // Temperature in °C
END_VAR
VAR_OUTPUT
    oResult      : REAL;       // Value from table
    oIndex       : INT;        // Index of the match (0 = no match)
    oFound       : BOOL;       // TRUE if exact match
END_VAR
VAR
    i            : INT;
END_VAR
BEGIN
    oFound := FALSE;
    oIndex := 0;
    oResult := 0.0;
    // Linear scan; switch to FOR loop with EXIT for early termination
    FOR i := 1 TO 40 DO
        IF "DB_Lookup".Key[i] = iSearchValue THEN
            oResult := "DB_Lookup".Value[i];
            oIndex  := i;
            oFound  := TRUE;
            RETURN;
        END_IF;
    END_FOR;
END_FUNCTION_BLOCK

Step 4: Use a tolerance for noisy analog inputs

If the temperature comes from an RTD or thermocouple module, exact equality is rare. Wrap the comparison in a ±0.5 °C window:

IF ABS("DB_Lookup".Key[i] - iSearchValue) <= 0.5 THEN

For better noise immunity, average the AI input in the analog input driver block (e.g., 16-sample moving average) before calling the lookup.

Method 2: Classic STEP 7 DB Lookup (S7-300/S7-400, V5.x)

On STEP 7 V5.7 with an S7-300 or S7-400, you can build the table in a shared DB and use pointer arithmetic in STL to walk the entries.

Data block

DATA_BLOCK DB 100
TITLE = Temperature Lookup
STRUCT
    Key   : ARRAY[1..40] OF REAL;
    Value : ARRAY[1..40] OF REAL;
END_STRUCT;
BEGIN
    Key[1]   := 0.0;    Value[1]   := 1.000;
    // ... populate all 40 entries ...
END

STL scan

// In OB1, searchKey = MD100 (REAL), result -> MD104
      L     40
      T     LW 0                  // Loop counter
      L     P#DBX 0.0             // Pointer to Key[1]
      T     LD 2
LOOP: L     DBD [LD 2]            // Load Key[i]
      L     MD 100                // Load searchKey
      ==R
      JC    FOUND
      L     P#8.0                 // Increment pointer by 8 bytes (REAL)
      +D
      T     LD 2
      L     LW 0
      LOOP LOOP
      L     0.0
      T     MD 104                // No match -> 0.0
      JU    DONE
FOUND: L     DBD [LD 2]
      L     P#320.0               // Offset from Key[1] to Value[1] = 40*8
      +D
      LAR1
      L     DBD [AR1,P#0.0]       // Load Value[i]
      T     MD 104
DONE: NOP 0
Pointer math: Each REAL occupies 8 bytes. The offset from the start of Key to Value is 40 * 8 = 320 bytes. This is the single most common pointer bug in classic STEP 7 — verify it by cross-checking with the DB's offset view in the editor.

Method 3: TBL_FIND Instruction (S7-300/S7-400)

TBL_FIND (Find value in table) is in the Extended Instructions catalog under Table functions. It scans a source range (SRC) for entries that match a comparison pattern defined by CMD (1=EQ, 2=NE, 3=GT, 4=GE, 5=LT, 6=LE). The block returns the index of the first match, the number of matches, and the source/destination ranges used.

TBL_FIND interface

Parameter Type Direction Description
REQ BOOL IN Start the search on a rising edge
SRC VARIANT IN Pointer to the source range to search (must be ARRAY of BYTE/INT/DINT/REAL)
PATTERN VARIANT IN Pointer to the comparison value (single element)
CMD INT IN Comparison: 1=EQ, 2=NE, 3=GT, 4=GE, 5=LT, 6=LE
POSITION DINT OUT Index of the first match (zero-based)
COUNT DINT OUT Number of matches found
BUSY BOOL OUT 1 while the block is running
ERROR BOOL OUT 1 if the call returned an error
STATUS WORD OUT Error/status code (0x0000 = no error, 0x8220 = invalid SRC, 0x8221 = invalid PATTERN, 0x8230 = data type mismatch, 0x8231 = CMD out of range)

Wiring TBL_FIND in FBD

      +-------+--------+
      |       |  POSITION      |
      |       +--------+
      |       |  COUNT  |
      |       +--------+
REQ ---| TBL_  | BUSY  |
SRC ---| FIND  | ERROR |
PATTERN -- |       | STATUS|
CMD ------|       +--------+
      +-------+

Drive REQ with a one-shot pulse (use a rising-edge contact of your scan enable), set CMD = 1 (equal), and read POSITION. The returned index is zero-based, so add 1 to map it onto your 1..40 DB array.

Error handling checklist

STATUS Meaning Remediation
0x0000 OK Proceed; read POSITION
0x8220 Invalid SRC pointer Verify the SRC pointer references a DB/array of compatible type
0x8221 Invalid PATTERN pointer PATTERN must be a single element of the same type as SRC
0x8230 Data type mismatch SRC and PATTERN must be the same elementary type
0x8231 CMD out of range Set CMD to 1..6
Asynchronous execution: On S7-300 and S7-400, TBL_FIND may take multiple OB1 cycles. Always check BUSY before reusing the SRC/PATTERN pointers or before re-triggering with REQ. On S7-1500, TBL_FIND runs synchronously and BUSY is not used.

Method 4: Polygon Interpolation for Non-Exact Values

When the process variable can fall between two tabulated keys, exact-match lookup will frequently return "no match." Use linear interpolation between the bracketing points. The Siemens application example 8803015 provides the standard POLYGON function block.

SCL implementation of linear interpolation

FUNCTION_BLOCK FB_Lookup_Interp
{ S7_Optimized_Access := 'TRUE' }
VAR_INPUT
    iX : REAL;                 // Input (e.g., temperature)
END_VAR
VAR_OUTPUT
    oY  : REAL;                // Interpolated value
    oOK : BOOL;                // TRUE if iX is inside table range
END_VAR
VAR
    i   : INT;
    x1, x2, y1, y2 : REAL;
END_VAR
BEGIN
    oOK := FALSE;
    oY  := 0.0;
    // Clamp below first key
    IF iX <= "DB_Lookup".Key[1] THEN
        oY  := "DB_Lookup".Value[1];
        oOK := TRUE;
        RETURN;
    END_IF;
    // Clamp above last key
    IF iX >= "DB_Lookup".Key[40] THEN
        oY  := "DB_Lookup".Value[40];
        oOK := TRUE;
        RETURN;
    END_IF;
    // Find bracketing pair (Key array is assumed ascending)
    FOR i := 1 TO 39 DO
        IF (iX >= "DB_Lookup".Key[i]) AND (iX < "DB_Lookup".Key[i+1]) THEN
            x1 := "DB_Lookup".Key[i];
            x2 := "DB_Lookup".Key[i+1];
            y1 := "DB_Lookup".Value[i];
            y2 := "DB_Lookup".Value[i+1];
            // y = y1 + (y2 - y1) * (x - x1) / (x2 - x1)
            oY  := y1 + (y2 - y1) * (iX - x1) / (x2 - x1);
            oOK := TRUE;
            RETURN;
        END_IF;
    END_FOR;
END_FUNCTION_BLOCK
Sort order: The bracketing loop assumes Key[] is sorted ascending. If the table is loaded from a recipe or HMI, validate the order in OB100 and raise an alarm if not monotonic.

Performance and Memory Footprint

For 40 REAL pairs you need 40 × 8 bytes × 2 = 640 bytes of load memory. S7-1500 CPUs and S7-1200 CPUs from firmware V4.4 onward have ample work memory; on the S7-300 CPU 312 (work memory 32 KB) or the S7-400 CPU 412-1 (144 KB), 640 bytes is negligible. Watch out for:

  • Optimized vs. non-optimized access: TIA Portal defaults to optimized symbolic access on S7-1200/S7-1500, which costs a few extra cycles for array indexing versus a direct DB number. This is the correct tradeoff for maintainability.
  • Volatile vs. retentive: Mark the table DB as retentive only if you intend to modify it from the HMI at runtime. Hard-coded engineering tables should be non-retentive so a CPU restart reinitializes from OB100.
  • Cyclic load: Calling a 40-point linear scan every 1 ms on an S7-1516 is fine. On an S7-314 with 0.1 ms OB1 period, it consumes a measurable share of cycle time. Use a slower OB (e.g., OB35 at 100 ms) for the lookup call if your process allows it.

Step-by-Step Commissioning (40-Point Temperature Table)

  1. Decide whether the application needs exact match or interpolation. For setpoint conversion (e.g., RTD to density), use interpolation. For discrete process steps (e.g., recipe stage selection), use exact match.
  2. Build the source data. Export your engineering values from Excel as CSV; in TIA Portal use Tools > Data Block Generator with the CSV import to auto-fill the DB. In STEP 7 V5.x, paste values directly into the DB initial values view.
  3. Create DB_Lookup with the 40 keys and 40 values.
  4. Implement the lookup FB in SCL (exact or interpolated) and compile the SCL source.
  5. In OB100, populate the DB with your engineering values. Compile and download.
  6. In OB1 (or OB35), call the FB and wire the analog-input REAL to iSearchValue / iX.
  7. Connect a watch table to monitor oIndex, oFound, and oResult during commissioning.

Verification

Test Procedure Pass criterion
Exact match in range Force iSearchValue = 75.0 °C (a known key) oFound = TRUE, oIndex = matching index, oResult = expected value
Exact match, key not present Force 77.5 °C (not in the table) oFound = FALSE, oIndex = 0, oResult unchanged from last valid value (or 0.0 if initialized)
Interpolation mid-range Force 77.5 °C, with interpolation block oResult between Value[15] and Value[16] linearly; oOK = TRUE
Clamp below Force -5.0 °C oResult = Value[1]; oOK = TRUE
Clamp above Force 250.0 °C oResult = Value[40]; oOK = TRUE
TBL_FIND STATUS Force a bad PATTERN pointer via watch table ERROR = TRUE, STATUS = 0x8221
Cycle time Read OB1/OB35 cycle time in online > diagnostics Lookup call < 5% of total cycle time

Troubleshooting Matrix

Symptom Likely cause Remediation
Lookup always returns index 0 / not found Key values not loaded (OB100 missing), or wrong DB instance Online > Monitor > DB_Lookup — confirm Key[i] is non-zero; check OB100 wiring
Result jumps wildly Analog input not normalized, or noise larger than tolerance window Verify AI scaling in the analog input driver; widen tolerance or apply input filtering
TBL_FIND STATUS 0x8230 PATTERN and SRC differ in data type Ensure both reference the same elementary type (e.g., both REAL or both INT)
TBL_FIND STATUS 0x8220 SRC pointer is not a typed ARRAY Wrap the source DB in an ARRAY of the required type before passing to SRC
Interpolation result out of range Key array not sorted ascending Sort the DB values in OB100; add a monotonicity check that raises an alarm on violation
Compile error: "Incompatible types" on array index INT used where DINT expected (or vice versa) Match the index type to the array bounds; S7-1500 arrays can use DINT
Cycle time spike after enabling lookup Linear scan in a fast OB on a small CPU Move the call to OB35 (100 ms) or use binary search; on S7-1500, parallelize via a UDT
Download fails: "DB_Lookup is being accessed" Background HMI polling on the table Disable HMI tags pointing to the DB; redownload; re-enable

FAQ

How many entries can a single SCL ARRAY lookup hold in TIA Portal?

The maximum ARRAY size is limited by CPU work memory. S7-1500 CPUs support arrays well beyond 10 000 elements; S7-1200 from firmware V4.4 also supports multi-thousand-element arrays. The 40-point temperature table described here consumes only 640 bytes and runs on any S7-300/S7-400/S7-1200/S7-1500 CPU.

Should I use exact match or linear interpolation?

Use exact match only when the process variable is quantized to your key values (e.g., a recipe number). Use linear interpolation when the input is a continuous measurement such as temperature, pressure, or flow. Interpolation is also the correct choice when the analog input has more resolution than the table.

Is TBL_FIND available on S7-1200 or S7-1500?

TBL_FIND is documented in the Extended Instructions catalog for S7-300 and S7-400 in the Siemens TIA Portal documentation. On S7-1200 and S7-1500 the table search is usually implemented in SCL as a FOR loop, which is more compact and benefits from the faster cycle time of these CPUs.

How do I load the 40 table values from an HMI recipe?

Create a recipe DB on the HMI, expose DB_Lookup.Key and DB_Lookup.Value as symbolic tags, and write both arrays from the recipe function. Mark DB_Lookup as retentive if the values must survive a warm restart; otherwise re-download the engineering values from OB100 on every restart.

What is the fastest way to implement a 40-point lookup on an S7-314?

Use a binary search in SCL on the pre-sorted Key array. With 40 entries the search converges in at most 6 iterations, keeping the cycle time well under 100 µs on a CPU 314. Alternatively, offload the lookup to a faster S7-1500 if the project is being upgraded.

Back to blog