Configuring S7_String_0 Text References in PCS 7 FBD Blocks

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

In SIMATIC PCS 7, the OS compiler generates two special STRING[16]-typed tags on most operator-controllable blocks: *String_0 and *String_1. These tags are the bridge between the AS-side block (e.g. an interlock, a motor block, or a custom FB) and the WinCC text library on the OS. They carry a text reference (TextID) that the OS resolves at runtime to a language-switchable message in the WinCC text list.

When you build the AS in CFC, PCS 7 exposes the strings as editable fields on the block I/O. You can type a different message for every block instance directly in the chart. When you switch the AS to FBD or STL, the strings are still created on compile, but the start values are locked to whatever the block type defines. To get the same per-instance behavior in FBD/STL you must re-declare the strings as IN_OUT parameters of your FB and feed them from a calling FC. This article documents that exact pattern, the AS-OS transfer, and the WinCC text-library side.

How S7_String_0 and S7_String_1 Work

During OS compilation (the AS-OS transfer), PCS 7 walks the S7 program and, for every block instance, generates a *String_0 and a *String_1 tag in the WinCC tag management. The content of those tags is a numeric TextID that points into a WinCC text list. The text list entry itself lives in the WinCC text library and can be exported/imported per language.

Tag Type Direction Purpose
*String_0 STRING[16] AS -> OS Primary text reference, e.g. operator prompt or status text.
*String_1 STRING[16] AS -> OS Secondary text reference, e.g. command text or interlock label.
The asterisk prefix is not a wildcard - it is the literal character that PCS 7 prepends to text-reference tags so the OS compiler can identify them during the AS-OS transfer. Do not rename or strip the prefix.

Data Type STRING in STEP 7: Layout and Limits

STEP 7 stores a STRING[n] in two parts: a 2-byte header containing the maximum length and the actual length, followed by n bytes of character data. For STRING[16] the total memory footprint is 18 bytes.

Offset Size Field Value (for "PUMP_01")
0 1 byte Max length 16 (0x10)
1 1 byte Actual length 7 (0x07)
2..17 16 bytes Character payload 'P','U','M','P','_','0','1',0x00,...

Anything beyond byte 17 is truncated. The 16-character cap is the reason the AS compiler always uses STRING[16] for the text reference: it is enough to hold the 14-character TextID plus the two header bytes, but never the human-readable text itself. The text itself is stored in WinCC.

Prerequisites

  • PCS 7 V9.0 SP2 or later (the same pattern works in PCS 7 V8.2 with SIMATIC Manager and STEP 7 V5.6).
  • STEP 7 / TIA Portal with the S7-300/400 FBD editor or the SCL/ST editor. The FBD language mechanics are documented in the official Function Block Diagram (FBD) for S7-300 and S7-400 Programming manual and the TIA Portal FBD reference.
  • A PCS 7 master data library that contains your custom FB type (e.g. FB1089 "INTERLOCK").
  • WinCC Explorer with a project that has a text list (default name: TextList).
  • An AS-OS transfer license (Comfort or higher) so the OS compiler can build the operator screens.

Step 1: Declare the Strings as IN_OUT in the FB Interface

Open the FB in the FBD/STL editor. In the interface table, add two IN_OUT variables of type STRING[16]:

Name Declaration Type Initial value Comment
strText0 IN_OUT STRING[16] '' Text reference 0 (TextID as ASCII digits)
strText1 IN_OUT STRING[16] '' Text reference 1 (TextID as ASCII digits)
bIn INPUT BOOL FALSE Binary value to interlock
bOut OUTPUT BOOL FALSE Interlocked result

Why IN_OUT and not INPUT? The PCS 7 OS compiler must be able to write the start value into the string from outside the FB. IN_OUT parameters are passed by reference (a pointer in the instance DI), so the calling FC can assign a per-instance value. INPUT parameters in STEP 7 are passed by value for elementary types and the OS compiler cannot resolve the start value back to the calling block.

Step 2: Map the IN_OUT to the Standard Names

The OS compiler looks for tag names String_0 and String_1 on the block I/O. Because you used custom names, you must tell the compiler which inputs map to which standard text reference. Open the block properties (right-click the FB -> Object Properties) and go to the Texts tab. Under OS text references enter:

String_0 <- strText0
String_1 <- strText1

Alternatively, in the FBD body, simply connect the strText0 input to a network whose output symbol is named String_0 in the symbol table. The compiler accepts either mapping.

Step 3: Build the Multi-Instance FB Body

The interlock logic itself is trivial; the FBD body looks like this:

NETWORK 1  // Interlock
      bIn --[ AND ]-- bOut
             ^
             |
          bEnable

The interesting work is in network 2 where the strings are formatted. Use an ST-language FB instead of pure FBD if you need string formatting, because the FBD language in S7-300/400 does not have a native block for converting an integer TextID to a STRING. The standard pattern is to use the I_STRING function from the IEC library:

// In an SCL/ST source for FB1089 "INTERLOCK"
strText0 := INT_TO_STRING(1000 + iInstanceID);  // -> "1001"
IF bIn THEN
  strText1 := INT_TO_STRING(2000 + iInstanceID); // -> "2001"
ELSE
  strText1 := INT_TO_STRING(2999);
END_IF;

The TextID is a number that points into the WinCC text list. Convention is to use the block number family: 1xxx for String_0, 2xxx for String_1. The actual text for ID 1001 lives in WinCC, not on the AS.

Step 4: Call the FB from a Higher-Level FC

To get per-instance texts, you call the FB from an FC and supply a different TextID at each call site. Create FC900 "CallInterlocks" in STL or SCL:

// FC900 in STL
      CALL  "INTERLOCK" , "DI_IL_1"
      strText0 := '1001'         // -> "1001" (TextID for pump 1)
      strText1 := '2001'
      bIn      := I0.0
      bOut     := Q8.0

      CALL  "INTERLOCK" , "DI_IL_2"
      strText0 := '1002'         // -> "1002" (TextID for pump 2)
      strText1 := '2002'
      bIn      := I0.1
      bOut     := Q8.1

Every call site gets its own TextID, and the OS compiler generates a separate *String_0 and *String_1 per instance. The same FB type is reused, just like a CFC chart with multiple block instances.

Because the strings are IN_OUT, the literal '1001' is loaded into the instance DI at call time. If you change a TextID later, you only edit the FC; you do not have to recompile the FB type.

Step 5: Compile the OS (AS-OS Transfer)

  1. In the S7 program, right-click the chart and choose Compile OS.
  2. Select the target OS server. PCS 7 will run the OS compiler and push the new tags into WinCC.
  3. Open the WinCC Tag Management and verify that <chart>_DI_IL_1.String_0 and <chart>_DI_IL_1.String_1 are present, one pair per instance.
  4. Trigger a Full compilation of the OS, not an incremental one, the first time you set up text references. Incremental compiles sometimes miss the text-reference tag generation in mixed CFC/FBD programs.

Step 6: Populate the WinCC Text Library

On the OS side, open WinCC Explorer, expand Text and Graphic Lists, and select your text list (default: TextList). For every TextID that the AS uses, add an entry:

TextID English German French
1001 Interlock Pump 1 Verriegelung Pumpe 1 Verrouillage Pompe 1
1002 Interlock Pump 2 Verriegelung Pumpe 2 Verrouillage Pompe 2
2001 Start Pump 1 Pumpe 1 starten Démarrer Pompe 1
2002 Start Pump 2 Pumpe 2 starten Démarrer Pompe 2

Import/export uses the WinCC text library CSV format. The columns are ID,English,German,French,... - one column per configured runtime language. The runtime resolves the current language from the OS user settings.

Step 7: Bind the Strings to a Block Icon

Open the faceplate or the screen where the interlock block icon lives. On the icon's Output field, configure a text output and bind it to <chart>_DI_IL_1.String_0. Set the Output type to Text from text list. WinCC will read the string content (e.g. "1001"), convert it to an integer, and look up the entry in the text list. The displayed text changes automatically when the user switches runtime language.

For more complex scenarios where you need to embed a dynamic value into a parameterized text (e.g. "Pumpe %d gesperrt"), use a WinCC dynamic dialog with a text list output and pass the value through the text reference field of the block icon configuration.

Converting Between Strings and Other Types

PCS 7's FBD library does not include the rich set of string conversion blocks found in Schneider Electric's Control Expert (formerly Unity Pro). The STRING_TO_x family in Control Expert handles STRING to BOOL, INT, REAL, etc. and is documented in the official Schneider Electric FAQ FA213383 - Example of the STRING_TO_x block in FBD using Control Expert. On the Siemens side, the equivalent conversions live in the standard IEC library as STRING_TO_INT, STRING_TO_REAL, INT_TO_STRING, REAL_TO_STRING, and the more tolerant STRNG_ variants in the "TI-S7 Converting Blocks" library. For TextID round-tripping, STRING_TO_INT is the only function you need - it returns 0 for non-numeric content, so wrap it with an error flag if you expect user input.

Troubleshooting Matrix

Symptom Probable cause Fix
*String_0 tag is missing on the OS The block I/O name does not match the standard. PCS 7 looks for the literal name String_0. Map the custom IN_OUT to String_0 in the block properties (Texts tab).
Same TextID on every instance The strings are INPUT (passed by value) or are assigned inside the FB body instead of from the calling FC. Change the declaration to IN_OUT and assign at the call site in the FC.
OS shows a numeric value instead of text WinCC text list entry for the TextID is missing or the TextID is zero. Add the missing entries to the text list. Confirm with the WinCC text list diagnostics tool.
Question marks or U+FFFD (EF BF BD) in the OS text The TextID was typed as raw characters in the wrong code page, or the source CSV was saved as UTF-16 and read as ANSI. Re-export the text list as UTF-8. Strip any non-ASCII bytes from the TextID payload on the AS side - TextIDs must be pure ASCII digits.
OS compile aborts with "tag too long" Custom IN_OUT declared as STRING[32] or larger. OS compiler only handles STRING[16] for text references. Resize the IN_OUT to exactly STRING[16].
Texts do not switch with runtime language The text list has no entry for the active language, or the language is not enabled in the OS project. Add a column for every language in the text list. Enable all languages in Computer Properties -> Parameters -> Languages.
Instance data of the FB overwrites the string at every cycle The FB body writes to the IN_OUT unconditionally, ignoring the value passed in. Use the IN_OUT only to read by default; only write to it during the first scan (IF bFirstScan THEN ... END_IF;) or remove the writes entirely.

Sample Full FB in Structured Text

For engineers who want a drop-in starting point, here is the complete FB1089 "INTERLOCK" in SCL/ST with the multi-instance string pattern:

FUNCTION_BLOCK FB1089
VAR_INPUT
  bIn         : BOOL;
  iInstanceID : INT;       // unique per call, 1..N
END_VAR
VAR_OUTPUT
  bOut : BOOL;
END_VAR
VAR_IN_OUT
  strText0 : STRING[16];   // OS text reference 0
  strText1 : STRING[16];   // OS text reference 1
END_VAR
VAR
  bFirstScan : BOOL := TRUE;
END_VAR
BEGIN
  IF bFirstScan THEN
    strText0 := INT_TO_STRING(1000 + iInstanceID);
    strText1 := INT_TO_STRING(2000 + iInstanceID);
    bFirstScan := FALSE;
  END_IF;

  bOut := bIn AND NOT bFault;
END_FUNCTION_BLOCK

Caller (FC900):

FUNCTION FC900 : VOID
BEGIN
  // Pump 1
  "INTERLOCK".iInstanceID := 1;
  "INTERLOCK".strText0    := '1001';
  "INTERLOCK".strText1    := '2001';
  "INTERLOCK".bIn         := I0.0;
  "DI_IL_1"(bIn := I0.0);

  // Pump 2
  "INTERLOCK".iInstanceID := 2;
  "INTERLOCK".strText0    := '1002';
  "INTERLOCK".strText1    := '2002';
  "DI_IL_2"(bIn := I0.1);
END_FUNCTION

Verification and Acceptance Test

  1. Download the S7 program to the AS. Open the online view of the instance DB. Confirm that strText0 contains '1001' for instance 1 and '1002' for instance 2.
  2. In WinCC Explorer, open Graphics Designer and place the interlock faceplate on a test screen. Activate Runtime.
  3. Verify that the faceplate shows "Interlock Pump 1" for the first icon and "Interlock Pump 2" for the second.
  4. Switch the OS runtime language from English to German. The text should change to "Verriegelung Pumpe 1" / "Verriegelung Pumpe 2" without recompiling.
  5. In the WinCC diagnostics window, confirm there are no "tag not found" or "text list entry not found" alarms.

Common Pitfalls

  • Forgetting the asterisk. The OS tag is *String_0, not String_0. The asterisk is part of the tag name from WinCC's perspective.
  • Using INPUT instead of IN_OUT. The most common reason engineers cannot change the text per instance in FBD. There is no workaround in STEP 7 V5.x: you must use IN_OUT for the OS to be able to set a per-instance start value.
  • Reserving the wrong length. Anything other than STRING[16] breaks the OS compiler. If you need more than 16 characters, store a 4-digit (or longer) TextID and put the long text in WinCC.
  • Mixing CFC and FBD with the same FB type. The CFC chart will continue to work as before (string editable in the I/O view), but the FBD caller must use IN_OUT. Document this so the next engineer does not break it.

Why does my FBD block not expose a String_0 / String_1 I/O pin?

PCS 7 only generates text-reference tags for block I/Os whose names match the literal String_0 and String_1. Open the FB in the FBD/STL editor and rename your pins, or map them in the block properties under the Texts tab so the OS compiler can find them.

Can I change the text per instance in FBD the way CFC allows?

Yes, but only by declaring the strings as IN_OUT parameters of the FB and assigning the TextID at each call site in the calling FC. With INPUT parameters the OS compiler cannot write a per-instance start value, so every instance shows the same text.

What is the maximum length of the S7_String_0 / S7_String_1 tag?

Exactly 16 characters: a 2-byte header plus 14 usable bytes. The header holds the maximum length (16) and the actual length; the payload holds the TextID as ASCII digits. Anything longer is rejected by the OS compiler.

Why does my OS show U+FFFD (the EF BF BD replacement character) inside a text?

That byte sequence is the Unicode replacement character and almost always means the source text was saved or copied in a non-matching code page. Re-export the WinCC text list as UTF-8 and confirm the TextID payload on the AS side is pure ASCII digits - TextIDs must not contain any non-ASCII bytes.

Do I need to recompile the OS every time I change a TextID on the AS?

Yes, for the first setup. After that, you can edit the WinCC text list directly without touching the AS - the text lives in WinCC, the AS only holds the numeric TextID. Runtime language switching happens without any recompile.

Back to blog