FAL and FSC — Loop Over an Array

FAL and FSC in rungs.dev run one expression once per array element. FAL stores each answer; FSC stops at the first element that passes. Use them to scale a batch or find a value.

FAL

Control

control

(DN)

Length

length

(ER)

Position

position

Mode

mode

Dest

dest

Expression

expression

Works out an expression once for every element of an array and stores each answer, with the control tag counting the elements off.

FSC

Control

control

(DN)

Length

length

(ER)

Position

position

Mode

mode

Expression

expression

Tests an expression against each element of an array in turn and stops at the first one that passes.

What they do

Every other array instruction does one fixed job: copy, fill, sort, average. FAL and FSC let you write the job yourself.

FAL is "do this to every element": scale every raw count into engineering units, add an offset to a whole recipe, square every deviation.

FSC is "find the first element where this is true": the first alarm still active, the first free slot in a table, the first reading over a limit.

Both write the element number they are on into .POS as they go, and your expression reads it back to pick the element. That is the whole idea:

FAL(Ctl, ?, ?, ALL, Scaled[Ctl.POS], Raw[Ctl.POS] * 2)

with Ctl.LEN set to 5 on the tag. On the first pass Ctl.POS is 0, so this is Scaled[0] := Raw[0] * 2. Then 1, then 2, and so on. The control tag does the counting.

Operands

FAL

NameTypeNotes
controlCONTROLCounts the elements off
lengthnumberHow many elements to work through
positionnumberWhich element to start at. Usually 0
modeALL, INC, or a numberHow many per scan — see below
destDINT, INT, SINT, REALWhere each answer goes. Usually indexed
expressionan expressionWorked out once per element

FSC

The same first four, then expression. There is no destination — the answer decides whether the search stops, and .FD reports whether it found anything.

mode takes a keyword or a number. Start typing and a short list offers ALL and INC; type a digit instead and the list steps aside, because a count is a number you write rather than one you pick. It can never be a tag — the controller refuses one there, so Studio does not offer it.

Mode — how many per scan

ModeWhat happens
ALLThe whole run, in one scan, on the rising edge
INCOne element per rising edge — one pulse, one element
a numberThat many per scan, every scan, until done — even after the rung goes false

ALL is what you want most of the time. Reach for a number when the array is long enough that doing it all in one scan would stretch the scan time; the run then finishes over several scans on its own.

A numerical run keeps going after the rung drops

That is deliberate: it is how a long job finishes without you having to hold the rung true for it. .EN stays on while the run is in progress and clears the moment it finishes.

The expression

FAL's expression is the same one CPT takes: arithmetic, brackets, the bitwise operators, and the maths functions. No comparisons — it has to produce a number to store.

FSC's is the same one CMP takes: it adds the comparisons and the logical operators. An element passes when the answer is anything other than zero, so a plain sum works as well as a comparison — Src[Ctl.POS] + 1 passes on every element except the one holding -1.

See Expressions in Ladder for the full operator table.

How It Works

EventWhat happens
Rung goes trueStarts from the current .POS and works forward
The last element is done.DN turns on, .POS stays on that element
Rung stays trueNothing more, unless the mode is a number
Rung false after .DN.POS and every bit go back to 0
FSC finds a match.FD and .IN turn on, .POS is the matching element

.POS always names the last element worked on, so a finished run leaves it at .LEN - 1, not .LEN.

When FSC matches it sets .IN, which parks the search — a held rung and a false rung both leave it exactly where it stopped. Clear .IN from your logic and the search carries on from the next element:

0

FindNext

SearchCtl.IN

U

A pass that reaches the end without a match clears .FD and sets .DN.

Example — Scale a Whole Batch

0

NewBatch

FAL

Control

ScaleCtl

(DN)

Length

10

(ER)

Position

0

Mode

ALL

Dest

Scaled[ScaleCtl.POS]

Expression

Raw[ScaleCtl.POS] * 4

Example — Find the First Reading Over Limit

0

Check

FSC

Control

FindCtl

(DN)

Length

10

(ER)

Position

0

Mode

ALL

Expression

Readings[FindCtl.POS] > Limit

1

FindCtl.FD

OverLimit

When it finds one, FindCtl.POS is the element number — read it to know which reading was over.

Common Mistakes

  • Forgetting Ctl.POS in the expression. Without it, every pass reads and writes the same element.
  • Looking for a way to put a tag in the Mode row. There isn't one — it is a pick list.
  • Expecting FSC to keep searching after a match. It parks on .IN; clear it to carry on.
  • Reading .POS as a count. It is an index — one less than the number done.
  • Setting .LEN longer than the array. The subscript stops the program part-way through, and the elements before it are already written.

On this page