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
Length
length
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
Length
length
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
| Name | Type | Notes |
|---|---|---|
control | CONTROL | Counts the elements off |
length | number | How many elements to work through |
position | number | Which element to start at. Usually 0 |
mode | ALL, INC, or a number | How many per scan — see below |
dest | DINT, INT, SINT, REAL | Where each answer goes. Usually indexed |
expression | an expression | Worked 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
| Mode | What happens |
|---|---|
ALL | The whole run, in one scan, on the rising edge |
INC | One element per rising edge — one pulse, one element |
| a number | That 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
| Event | What happens |
|---|---|
| Rung goes true | Starts from the current .POS and works forward |
| The last element is done | .DN turns on, .POS stays on that element |
| Rung stays true | Nothing 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.
Resuming an FSC search
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
A pass that reaches the end without a match clears .FD and sets .DN.
Example — Scale a Whole Batch
0
NewBatch
FAL
Control
ScaleCtl
Length
10
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
Length
10
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.POSin 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
FSCto keep searching after a match. It parks on.IN; clear it to carry on. - Reading
.POSas a count. It is an index — one less than the number done. - Setting
.LENlonger than the array. The subscript stops the program part-way through, and the elements before it are already written.
Related
- Array instructions overview
- CPT and CMP — the same two expression grammars, on one value
- Expressions in Ladder — the operator table
SRT — Sort
SRT in rungs.dev sorts a run of array elements into ascending order, in place. Use it to find a median, rank readings, or order a batch before working through it.
NOP / AFI — No Operation and Always False
NOP and AFI in rungs.dev — NOP is a placeholder that does nothing, AFI forces the rest of its rung false. Both are used while building and debugging programs, not in finished logic.