Configuring Productivity Suite Structured Text Tasks

Brian Holt8 min read
AutomationDirectOther TopicTutorial / 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

Red underlines, failed compiles, unexpected timer behavior, and long scans are the common signs that a Productivity Suite Structured Text task needs correction. Start with the task type and syntax, then check tags, function blocks, loops, and arrays in that order. Get the task running with the smallest valid change, then correct naming and structure before returning it to normal service.

Reject the quick fixes first

Do not keep editing around a structural problem. Several common quick fixes either cannot work or hide the fault without correcting it.

Symptom or attempted fix Why it fails Next check
Trying to convert an existing Ladder task to Structured Text A task cannot be converted between Ladder and Structured Text after creation. Create a new task with Task Type set to Structured Text.
Removing code until the red underline disappears The actual problem may be an undefined tag, missing semicolon, incomplete control structure, or invalid tag name. Read the marked statement and validate the complete task.
Changing := to = everywhere := performs assignment. A condition uses a comparison expression, as shown by Tag1 = 1. Classify each expression as an assignment or condition.
Calling a timer repeatedly inside a loop Time-based functions such as TON, TOF, and TP may not behave as expected inside FOR, WHILE, or REPEAT loops. Move the time-based call to scan-level logic and use the loop only for non-time-based processing.
Looking for a compile error after division by zero Division by zero does not generate a compile error in this environment; the result is 0. Guard the divisor explicitly and test the result path.
Declaring a temporary variable inside the ST code Productivity Suite does not support local variable declaration in ST code. Create the tag in the Tag Database or through the editor.

Check 1: Confirm the task type

Read the task type in the Task Management panel. If it is already Structured Text, continue to syntax inspection. If it is Ladder, stop editing that task as though it were ST; its type cannot be changed.

Create the correct task as follows:

  1. In the Task Management panel, right-click the required task folder, such as Run Every Scan.
  2. Select New Task.
  3. Enter the task name.
  4. Under Task Type, select Structured Text instead of Ladder.
  5. Select OK.

New projects create an ST task by default, but confirm its folder and execution context before placing logic in it. Task placement determines when the code runs. For an advanced call, @CALL runs a task in the Run When Called folder; configure that instruction through Edit Instruction by right-clicking or pressing Shift + Space.

Check 2: Clear syntax faults in order

Read the first red-underlined statement, not the last one. One missing terminator or closing keyword can make later lines appear faulty even when those lines are correct.

  1. Confirm that every complete statement ends with a semicolon.
  2. Match every control-flow opening keyword with its full closing structure, such as IF with END_IF.
  3. Confirm that assignments use :=.
  4. Add parentheses where an expression mixes operators. Operators have defined precedence, equal-precedence operators evaluate from left to right, and parentheses make the intended order explicit.
  5. Use the ST editor toolbar to insert a complete control structure when rebuilding a damaged block.

A statement or an entire control-flow structure may span multiple lines. Line breaks do not replace statement terminators:

IF
    Tag1 = 1
THEN
    Tag2 := 5;
END_IF;

For branching logic, use the form that makes the selection unambiguous:

IF condition THEN
    statements;
ELSIF condition THEN
    statements;
ELSE
    statements;
END_IF;

CASE variable OF
    1: statement;
    2, 3, 11: statement;
    5..10: statement;
ELSE
    statement;
END_CASE;

If the first error clears and the next line remains red, repeat the same check there. If an otherwise valid statement still fails, move to tag resolution.

Check 3: Resolve tags and identifiers

Read the identifier underlined in red. If the tag is undefined, create it in the Tag Database or directly from the editor. After syntax errors are cleared, select Validate or press Shift + F8; the Define Tags dialog opens for new tags.

Normal ST tag names cannot contain:

  • Operator symbols such as +, -, =, *, /, \, #, @, ^, %, <, or >
  • Spaces
  • Brackets or braces
  • Semicolons
  • Reserved keywords such as IF, THEN, PI, or TRUE

Some existing tags, including system tags, contain characters that ordinary ST identifiers do not permit. Reference those tags with a dollar sign and curly braces. The system tag named 2 Second Bit becomes:

${2 Second Bit}

Do not rename a required system tag merely to remove the spaces. Use the supported escaped form. For user-created tags, adopt meaningful legal names so later faults can be traced without decoding abbreviations.

Check 4: Verify assignments and function-block instances

Read every left-hand tag and the value being assigned. A basic assignment stores the result of the right-hand expression:

counter := counter + 1;
speed := RPM * 0.1047;

Multiple assignments on one line are allowed when the data types match:

int3 := int2 := int1 + 5;

If that statement fails, verify the participating tag definitions and data types instead of splitting the line and assuming the syntax caused the fault. Splitting it can still be useful during diagnosis because it exposes which assignment fails, but the final chained form is valid when the types match.

Before calling a function block, create a tag instance of its tag structure. A timer instance uses IN for its enable input, PT for preset time, ET for elapsed time, and Q for the done indication when ET >= PT:

timer1(IN := timer1_enable, PT := timer1_preset);

If the call is red-underlined, first confirm that timer1 exists as the correct function-block instance. Then confirm that the input tags exist and have compatible definitions. Use formal parameter lists such as IN := and PT := for longer calls; they show which value feeds each parameter and reduce errors caused by positional reading.

Advanced functions require an @ prefix. For example, @CALL calls a configured task and @UDI instantiates a User Defined Instruction. Configure either through Edit Instruction rather than guessing a call signature.

Check 5: Bound loops and keep timers outside them

Read the loop condition, index limits, and exit path. If a FOR loop has a finite intended range, express that range directly:

FOR i := 1 TO 10 BY 1 DO
    statements;
END_FOR;

For a condition-controlled loop, verify that something inside the loop can make the condition false:

WHILE condition DO
    statements;
END_WHILE;

Use EXIT inside a FOR, WHILE, or REPEAT loop when a detected condition must end execution early. An unbounded or unexpectedly large loop keeps the CPU in that task longer during the scan. Structured Text control commands including IF, FOR, WHILE, REPEAT, and CASE can consume more processing time than equivalent Ladder logic, particularly for simple logic.

Do not use repeated loop iterations as a substitute for elapsed time. A PLC loop executes within a scan; it does not create a reliable time base. Place TON, TOF, and TP calls where each instance executes in the intended scan context, then let the loop process data rather than repeatedly advancing time-based logic.

If scan behavior changes after adding ST, temporarily reduce the loop workload to the smallest useful range and measure the PLC scan indication available in the project diagnostics. If the scan returns to its former range, inspect the iteration count and per-iteration logic before restoring the full workload.

Check 6: Correct array bounds and guarded arithmetic

Read every array subscript before testing the values. Productivity Suite ST arrays use one-based indexing, matching Ladder: the first element is index 1, not 0.

1D_array[1] := 100;
2D_array[3,2] := 50;

The first statement writes the first element of 1D_array. The second writes row 3, column 2 of 2D_array. If logic was copied from a zero-based language, audit initial index values, loop limits, and every calculated subscript before operating the machine.

Guard divisors before executing arithmetic. A divide-by-zero expression compiles and returns 0, so successful validation does not prove that the calculation is meaningful:

IF divisor = 0 THEN
    calculation_valid := FALSE;
ELSE
    result := numerator / divisor;
    calculation_valid := TRUE;
END_IF;

The tag names in this pattern are illustrative and must be created in the Tag Database with data types appropriate to the calculation. Drive downstream behavior from an explicit validity indication rather than treating a zero result as proof that the input value was genuinely zero.

Validate, test, and return the task to service

  1. Correct the earliest red-underlined syntax error.
  2. Confirm semicolons, closing keywords, assignments, and parentheses.
  3. Select Validate or press Shift + F8.
  4. Define each legitimate undefined tag through the Define Tags dialog; correct illegal names rather than creating near-duplicates.
  5. Confirm that every function block has a tag instance and every advanced function uses its required @ prefix.
  6. Audit all arrays for one-based indexes and all loops for finite bounds or a reachable exit condition.
  7. Move time-based function calls out of loops.
  8. Add an explicit zero-divisor branch wherever division is performed.
  9. Compile again. Incorrect syntax or undefined tags must no longer block the compile.
  10. Test each branch with controlled input values. Observe assignment results, CASE selections, array targets, timer ET and Q, loop exit behavior, and the PLC scan indication.

Keep related logic in structured blocks, indent nested paths, comment complex decisions, and use formal parameter lists in complex instructions. Editor colors, backgrounds, and font sizes can be changed under Tools > Options > Structured Text; those preferences improve readability but do not correct syntax or execution.

FAQ

Can I convert a Productivity Suite Ladder task to Structured Text?

No. After creation, a task cannot be converted between Ladder and Structured Text. Create a new task, select Structured Text under Task Type, and move or rewrite only the required logic.

Does Productivity Suite Structured Text use array index 0?

No. Array indexing is one-based, so index 1 is the first element. Audit copied zero-based loops before using them with Productivity Suite arrays.

Can I keep troubleshooting after the task validates but runs incorrectly?

Continue only while controlled tests show bounded loops, valid array indexes, acceptable scan behavior, and predictable outputs. Stop if the task type, function signature, CPU behavior, or project diagnostics cannot be reconciled with Productivity Suite Help topics P343, P346, P345, or P082. Preserve the project and diagnostic details, then escalate through AutomationDirect's official support channel.

Back to blog