1. Problem Definition and Engineering Context
Many process sensors (pH probes, conductivity cells, ultrasonic level transmitters, capacitive pressure sensors, damped humidity probes, vortex flowmeters, and certain Coriolis density meters) produce a 4-20 mA output that is intentionally non-linear with respect to the measured variable. The sensor manufacturer publishes a calibration table where each integer raw count (after the S7-1200 analog input is normalized from 0-27648 to 0-20 mA, or from 5530-27648 to 4-20 mA) maps to a specific engineering value. When the table contains 100-300 points, hand-coding each block of IF...THEN statements or each comparison ladder rung becomes impractical and creates a maintenance burden.
The recommended engineering pattern on the S7-1200 platform is to store the engineering values in an ARRAY contained inside a dedicated FUNCTION_BLOCK, expose a single input (raw integer) and output (REAL engineering value) and search the table from a cyclic organization block (OB1 or OB30..OB38 depending on cycle time). Using SCL (Structured Control Language) instead of ladder keeps the lookup logic compact, version-controlled, and portable between CPU firmware V4.x and V5.x.
2. Prerequisites and S7-1200 Hardware Selection
Before writing a line of SCL, confirm that the hardware and firmware meet the following minimum requirements.
| Component | Minimum Requirement | Recommended |
|---|---|---|
| CPU | CPU 1212C DC/DC/DC (6ES7212-1AE40-0XB0), FW V4.2 | CPU 1214C DC/DC/DC (6ES7214-1AG40-0XB0), FW V4.4 or V4.5 |
| Signal Module | SM 1231 AI4 x 13 bit (6ES7231-4HD32-0XB0) | SM 1231 AI4 x 16 bit (6ES7231-5ND32-0XB0) for higher resolution |
| Work Memory | 50 KB free after program load | 100 KB free to allow table growth |
| TIA Portal | V15.1 with S7-1200 HSP | V17/V18 with installed S7-1200 System Manual, edition 06/2024 |
| SCL Compiler | SCL V15.1 | SCL V18 (bundled in TIA Portal) |
| Step 7 Basic License | Step 7 Basic V15 | Step 7 Professional V18 (allows SCL blocks) |
The S7-1200 part-numbering logic follows the pattern 6ES7 2xx-yyy40-0XB0 for the fourth-generation 121xC family. Always cross-reference the MLFB against the SIMATIC S7-1200 Programmable Controller System Manual before ordering, because certain suffixes indicate conformal coating, extended temperature range, or different analog resolutions.
3. SCL Programming Environment Setup
- Open TIA Portal and select the project tree PLC_x > Program blocks.
- Right-click Program blocks > Add new block, choose Function Block, language SCL, name
FB_SensorLUT, number100. Enable the option Multi-instance capable. - In Project tree > PLC_x > Properties > Protection, set the know-how protection only if the FB will be reused commercially; otherwise leave it open for service.
- Add a global DB named
DB_LUT_Data(DB number 200) that will hold the engineering values. The DB is normally generated automatically as part of the FB instance, but having a global copy simplifies CSV export/import via the watch table mechanism described in section 7. - Confirm that the SCL editor is set to IEC 61131-3 strict mode (TIA Portal default). This avoids implicit type conversions that can truncate raw integers.
4. Defining the Lookup Data Structure
The correct IEC 61131-3 data type for a fixed-size lookup table on the S7-1200 is an ARRAY of REAL. Historically, engineers on the older S7-200 and S7-300 platforms used separate WORD or REAL tags in a DB and addressed them by absolute name (e.g., DB100.DBD0, DB100.DBD4). On the S7-1200, this approach still works but is error-prone because the compiler does not check array bounds.
Declare the lookup array inside the FB static section:
FUNCTION_BLOCK FB_SensorLUT
{ S7_Optimized_Access := 'TRUE' }
VERSION : 1.0
VAR_INPUT
iRawValue : INT; // 4-20 mA normalized to 5530..27648
bExecute : BOOL; // Rising edge triggers one lookup
END_VAR
VAR_OUTPUT
rEngValue : REAL; // Engineering value in physical unit
bValid : BOOL; // TRUE when raw input lies inside the table
bOverflowLo : BOOL; // TRUE when raw input < first point
bOverflowHi : BOOL; // TRUE when raw input > last point
END_VAR
VAR
aRaw : ARRAY[1..300] OF INT; // Sorted ascending raw counts
aEng : ARRAY[1..300] OF REAL; // Engineering values
iCount : INT := 300; // Active number of points
END_VAR
VAR_TEMP
iLow : INT;
iHigh : INT;
iMid : INT;
rFrac : REAL;
END_VAR
The optimized bit access attribute (S7_Optimized_Access := 'TRUE') is the S7-1200 default from firmware V4.2 and stores the array in a way that the symbolic name is preserved in the watch table. Symbolic access is mandatory if the lookup table has to be loaded from a CSV file using the TIA Portal "Export/Import" wizard.
BLOCK_DB belongs to the legacy S7-300/400 STL world. On the S7-1200 use only the IEC 61131-3 generic keywords BOOL, INT, DINT, REAL, ARRAY, STRUCT. If you need to pass a DB to a function, use VARIANT instead.5. SCL Lookup Function Block Implementation
The fastest deterministic lookup for a 300-point sorted table is a binary search with eight iterations (2^8 = 256, 2^9 = 512). SCL syntax for the algorithm is shown below. The block runs in well under 100 microseconds on a CPU 1214C, easily fitting into any OB1 cycle.
BEGIN
// ---- 1. Boundary checks -------------------------------------------------
IF iRawValue < aRaw[1] THEN
rEngValue := aEng[1];
bValid := FALSE;
bOverflowLo := TRUE;
bOverflowHi := FALSE;
RETURN;
END_IF;
IF iRawValue > aRaw[iCount] THEN
rEngValue := aEng[iCount];
bValid := FALSE;
bOverflowLo := FALSE;
bOverflowHi := TRUE;
RETURN;
END_IF;
// ---- 2. Binary search for bracketing indices ---------------------------
iLow := 1;
iHigh := iCount;
WHILE (iHigh - iLow) > 1 DO
iMid := (iLow + iHigh) DIV 2;
IF iRawValue > aRaw[iMid] THEN
iLow := iMid;
ELSE
iHigh := iMid;
END_IF;
END_WHILE;
// ---- 3. Linear interpolation between iLow and iHigh --------------------
IF aRaw[iHigh] = aRaw[iLow] THEN
rFrac := 0.0; // Avoid divide-by-zero on duplicate entries
ELSE
rFrac := (INT_TO_REAL(iRawValue - aRaw[iLow])) /
(INT_TO_REAL(aRaw[iHigh] - aRaw[iLow]));
END_IF;
rEngValue := aEng[iLow] + (aEng[iHigh] - aEng[iLow]) * rFrac;
bValid := TRUE;
bOverflowLo := FALSE;
bOverflowHi := FALSE;
END_FUNCTION_BLOCK
The algorithm guarantees O(log n) execution time and is constant across the entire input range. With 300 points the loop executes at most nine times. Because aRaw is declared as ARRAY[1..300] inside the FB static area, the compiler places it in the instance DB (DB100) and the IEC check Array bounds option can be enabled for early debugging.
6. Linear Interpolation Between Sample Points
If the calibration certificate gives only 100 points but the engineering tolerance is ±0.5 percent of span, interpolation between the bracketing points is essential. The interpolation factor rFrac computed in section 5 is dimensionless and clamped implicitly by the boundary checks. For monotonic curves this yields sub-LSB accuracy between the discrete calibration points.
For curves that are very steep at the low end (e.g., pH sensors where 4 mA = pH 0 and 5 mA = pH 2), use logarithmic interpolation by transforming both raw and engineering values to log space before the lookup:
// Pre-compute in the initialization section (OB100) once per warm restart
FOR i := 1 TO 300 DO
aLogRaw[i] := LN(INT_TO_REAL(aRaw[i]));
aLogEng[i] := LN(aEng[i]);
END_FOR;
// Then run the binary search on aLogRaw and exponentiate the result
rEngValue := EXP(aLogEng[iLow] + (aLogEng[iHigh] - aLogEng[iLow]) * rFrac);
Logarithmic interpolation is also the correct choice for level sensors where the 4-20 mA output represents a non-linear function of the tank geometry (sphere, horizontal cylinder, or inverted cone).
7. Loading the 300-Point Table Efficiently
Manually typing 300 pairs of integers and REALs into the FB instance DB is the single largest time sink. Three practical methods are supported on the S7-1200 firmware.
7.1 CSV Import via TIA Portal
- In the project tree, right-click Program blocks > FB_SensorLUT (FB100) > Instance DB > DB100 and choose Export to CSV.
- Open the CSV in Microsoft Excel. Columns A (Index), B (Raw), C (Eng). Sort ascending by raw count.
- Save as
FB100_DB100.csvusing File > Save As > CSV UTF-8. - Right-click the instance DB and choose Import from CSV. The import wizard validates the row count and flags any raw value that is not strictly increasing.
7.2 Watch Table Fill via Initial Value Download
A watch table with 50 or fewer entries is fully supported by the S7-1200 web server according to the SIMATIC S7-1200 Web Server Watch Tables documentation. Larger tables must be split across multiple watch tables or, preferably, downloaded as the initial values of the instance DB during the program download.
7.3 Recipe Data Block (Recipe DB)
For applications where the calibration changes when a different sensor is connected (e.g., a test rig with swappable probes), store the table in a separate global DB DB_Recipe and use the PLC recipe functions of TIA Portal. The recipe function generates the READ_DBL and WRIT_DBL SCL calls automatically and writes the data block directly to load memory.
8. Calling the Lookup FB from a Cyclic OB
Wire the FB in OB1 (or in OB30 if the sensor is read at 100 ms). The instance DB is generated automatically on first download.
// OB1 - Main program sweep
"FB_SensorLUT_DB"(iRawValue := "iw_AI0_Norm",
bExecute := TRUE,
rEngValue => "rPressure_bar",
bValid => "bPressure_OK",
bOverflowLo => "bPressure_Under",
bOverflowHi => "bPressure_Over");
// Scale the raw AI to 5530..27648 in OB1 before the call
"iw_AI0_Norm" := "Scale_AI_To_0_27648"("iw_AI0_Raw");
The S7-1200 analog input module SM 1231 returns 0-27648 for a 0-20 mA signal or 0-27648 with clipping at 5530 for 4-20 mA (overrange to 0 and 27648 if the channel is configured for current, not voltage). Always confirm the channel configuration is Current 4-wire or Current 2-wire in the device configuration; a voltage configuration on a current-output sensor will produce negative raw counts and immediately trip bOverflowLo.
9. Commissioning with Watch Tables and the Web Server
- Connect the CPU to the engineering station via Profinet or the integrated Ethernet port.
- Open Online & Diagnostics > Watch tables and create a watch table named
WT_Pressure_Cal. Add the symbolic tags"iw_AI0_Norm","rPressure_bar","bPressure_OK","bPressure_Under", and"bPressure_Over". - Enable the S7-1200 web server (CPU properties > Web server > Activate web server on this module). The web server watch tables then become accessible from any browser at
http://<cpu-ip>/under Watch tables, which is invaluable when a tablet or a phone is the only available HMI on site. - Force a known reference signal (e.g., a Druck DPI 880 calibrator at 12.000 mA) and verify that the resulting raw count and engineering value match the calibration certificate within ±0.1 percent.
10. Verification and Calibration Checks
Verification consists of a five-point up-scale and down-scale calibration. Use the following acceptance criteria.
| Calibration Point | Reference mA | Expected Raw Count | Expected Eng Value | Pass Criterion |
|---|---|---|---|---|
| 0 percent | 4.000 | 5530 | 1.000 bar (example) | ± 1 LSB raw, ± 0.05 bar eng |
| 25 percent | 8.000 | 11060 | per certificate | ± 2 LSB raw |
| 50 percent | 12.000 | 16589 | per certificate | ± 2 LSB raw |
| 75 percent | 16.000 | 22118 | per certificate | ± 2 LSB raw |
| 100 percent | 20.000 | 27648 | per certificate | ± 1 LSB raw |
Record the up-scale and down-scale values in a calibration log. A hysteresis larger than 0.3 percent of span indicates a sensor issue, not a PLC scaling issue.
11. Troubleshooting Matrix
| Symptom | Likely Root Cause | Diagnostic Step | Fix |
|---|---|---|---|
| Compiler error "Invalid data type BLOCK_DB" | Legacy STL keyword used in SCL | Search source for BLOCK_DB | Replace with VARIANT or remove type declaration |
| All values return the first array element | aRaw not sorted ascending | Open watch table, sort aRaw[1..300] | Re-import CSV sorted by raw count |
| rEngValue jumps erratically | Duplicate raw count entries | Watch table search for duplicates | Remove duplicate row, re-import |
| bOverflowLo always TRUE | Channel configured for voltage instead of current | Device configuration > AI channel > Signal type | Change to Current 4-wire |
| SF (System Fault) LED on CPU | OB121 not loaded and array out-of-bounds occurred | Online & Diagnostics > Diagnostic buffer | Download OB121 and verify array bounds |
| Compile error "Array index out of user range" | Index variable type mismatch (SINT vs INT) | Check iMid, iLow, iHigh declarations | Declare all loop variables as INT |
| Web server watch table missing tags | More than 50 entries in a single watch table | Count entries in WT | Split into multiple watch tables per S7-1200 Web Server documentation |
| CPU goes STOP with "IO access error" | SM 1231 not inserted in device configuration | Device view > compare to physical rack | Add SM 1231, download HW config |
12. Performance, Memory, and Optimization Notes
- Code size: The compiled SCL binary for a 300-point lookup FB occupies roughly 8-12 KB of work memory on a CPU 1214C. Verified against the S7-1200 resource tables in the System Manual.
- Execution time: Binary search + interpolation requires < 100 microseconds on a CPU 1214C DC/DC/DC at firmware V4.4. This is well inside the OB1 minimum cycle of 1 ms.
- Memory layout: Two arrays of 300 elements each cost 600 * 4 bytes = 2400 bytes of work memory for REAL, plus 600 * 2 bytes = 1200 bytes for INT. The remaining memory is available for additional program blocks.
-
Optimization: If the sensor curve is polynomial of degree 3 or 4, replacing the table with a Horner-evaluated polynomial (
rEngValue := K0 + X * (K1 + X * (K2 + X * K3))) shrinks the memory footprint by 99 percent at the cost of small fitting error. Use polynomial only when the manufacturer provides certified polynomial coefficients (common for Pt100/Pt1000 and thermocouples). - Multi-sensor scenarios: For more than four sensors of the same family, instantiate the FB four times with the multi-instance flag. The total instance DB size scales linearly with the number of sensors and remains inside the work memory of a CPU 1215C (125 KB).
13. Frequently Asked Questions
What is the maximum number of array elements I can declare in an S7-1200 SCL FB?
The S7-1200 supports arrays with index range -32768 to 32767. Practical limits depend on work memory; a 300-element ARRAY of REAL plus a parallel 300-element ARRAY of INT uses about 3.6 KB, which fits in any CPU 1212C or higher. The S7-1200 System Manual lists exact work memory per array element in section "Data types".
Why does my SCL block compile with "Invalid data type BLOCK_DB" on the S7-1200?
The keyword BLOCK_DB is an S7-300/400 STL remnant and is not part of the IEC 61131-3 grammar accepted by the S7-1200 SCL compiler. Replace it with VARIANT if a DB pointer is needed, or remove the explicit type declaration entirely if the FB is called directly with a symbolic instance DB name.
Can the web server display watch tables with more than 50 entries?
The S7-1200 web server documentation explicitly states that watch tables with 50 or fewer entries are fully displayed. Larger watch tables must be split into multiple tables of at most 50 entries each. Refer to the S7-1200 web server watch tables page for the exact behavior.
How do I import a 300-row sensor calibration file into the instance DB?
Export the instance DB to CSV (right-click the DB > Export to CSV), edit the columns in Excel sorted ascending by raw count, save as CSV UTF-8, then right-click the DB and choose Import from CSV. The wizard validates the row count and flags duplicate or non-monotonic raw values.
Does linear interpolation between lookup points satisfy typical process accuracy requirements?
For most process-grade 4-20 mA sensors with a published calibration table of 100-300 points, linear interpolation between bracketing samples delivers sub-LSB accuracy of 0.05 percent to 0.1 percent of span, which meets ISA RP 7.7 for typical measurement loops. For higher accuracy, switch to logarithmic interpolation in the FB initialization as shown in section 6.