Array Instructions Overview
Reference for the Ladder Logic array instructions in rungs.dev — BSL, BSR, FFL, FFU, LFL, LFU, COP, CPS, FLL, AVE, SRT, STD, SIZE, FAL and FSC — and the CONTROL tag structure.
Most instructions work on one value at a time. The array instructions work on a run of
elements: a stretch of a DINT array, a whole buffer, a window inside a longer array.
They all need to remember two things between scans — how many elements they are working
through, and which one they are on. That is what a CONTROL tag holds, the way a TIMER tag
holds a timer's preset and accumulator.
Available Array Instructions
| Instruction | Symbol | Purpose |
|---|---|---|
| BSL | BSL Array array (DN) Control control (ER) Source Bit sourceBit (UL) Length length | Shifts every bit of a DINT array one place toward the high end on each rising edge, feeding the source bit in at bit 0. |
| BSR | BSR Array array (DN) Control control (ER) Source Bit sourceBit (UL) Length length | Shifts every bit of a DINT array one place toward the low end on each rising edge, feeding the source bit in at the far end. |
| FFL | FFL Source source (DN) Array array (EM) Control control Length length Position position | Puts a value into the next free slot of a queue on each rising edge, and stops once the queue holds .LEN of them. |
| FFU | FFU Array array (DN) Destination destination (EM) Control control Length length Position position | Takes the oldest value out of a queue on each rising edge, shifting the rest down one place. |
| LFL | LFL Source source (DN) Array array (EM) Control control Length length Position position | Puts a value on top of a stack on each rising edge, and stops once the stack holds .LEN of them. |
| LFU | LFU Array array (DN) Destination destination (EM) Control control Length length Position position | Takes the newest value off the top of a stack on each rising edge, leaving the others where they are. |
| COP | COP Source source Dest dest Length length | Copies a run of elements from one array into another, stopping at whichever array runs out first. |
| CPS | CPS Source source Dest dest Length length | Copies a run of elements the way COP does, holding the copy so nothing else can change the data part-way through. |
| FLL | FLL Source source Dest dest Length length | Writes one value into every element of a run of an array. |
| AVE | AVE Array array (DN) Dimension dimension (ER) Dest dest Control control Length length Position position | Adds up a run of array elements and stores their average in a tag. |
| SRT | SRT Array array (DN) Dimension dimension (ER) Control control Length length Position position | Sorts a run of array elements into ascending order, in place. |
| STD | STD Array array (DN) Dimension dimension (ER) Dest dest Control control Length length Position position | Works out how spread out a run of array elements is and stores the result in a REAL tag. |
| SIZE | SIZE Array array Dimension dimension Destination destination | Counts the elements of an array and stores the count in the destination tag. |
| FAL | 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 | 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. |
CONTROL Tag Members
Every CONTROL tag exposes the same fields. Access them with a dot (MyControl.POS).
| Member | Type | Meaning |
|---|---|---|
.LEN | DINT | Length — how many elements to work through |
.POS | DINT | Position — which element the instruction is on |
.EN | BOOL | Enable — 1 while a loading or shifting rung is true |
.EU | BOOL | Enable unload — 1 while an FFU or LFU rung is true |
.DN | BOOL | Done — 1 when the instruction has worked through .LEN elements |
.EM | BOOL | Empty — 1 when the buffer holds nothing |
.ER | BOOL | Error — 1 when .LEN or .POS is out of range |
.UL | BOOL | Unload — the bit BSL or BSR shifted out |
.IN | BOOL | Inhibit — 1 while an FSC search is paused |
.FD | BOOL | Found — 1 when an FSC search matched |
Not every instruction uses every bit — and four of them use no control at all.
| Instruction | Control | Bits it uses |
|---|---|---|
BSL, BSR | yes | .EN .DN .ER .UL |
FFL, LFL | yes | .EN .DN .EM |
FFU, LFU | yes | .EU .DN .EM |
AVE, STD, SRT | yes | .EN .DN .ER |
FAL, FSC | yes | .EN .DN .ER .UL .IN .FD |
COP, CPS, FLL, SIZE | no | none — they keep no state |
.IN and .FD belong to FSC: .FD says it found a match and .IN parks the search there
until you clear it.
.DN and .EM are results, not switches: the load and unload instructions work them out
again from .POS every time they run, so writing one yourself changes nothing.
Reference these members as contacts, the same way you would a timer's:
0
Track.DN
Light
Once per edge, or every scan
The two halves of the family differ on when they run, and mixing them up is the commonest surprise:
- Once per rising edge —
BSL,BSR,FFL,FFU,LFL,LFU,AVE,STD,SRT, andFAL/FSCinALLorINCmode. Holding the rung true does the job once. To do it again, let the rung go false first. - Spread over several scans —
FALandFSCwith a numerical mode. They keep going on every scan until the run finishes, even after the rung goes false. - Every scan the rung is true —
COP,CPS,FLL,SIZE. Leave one of these on a permanently true rung and it runs on every scan, overwriting whatever else touched the destination.
Where the Length comes from
The length you type into the box is a starting value, not something the instruction reads
each scan. It is written into .LEN once, when the program starts, and after that the
instruction reads .LEN from the control tag.
So writing Track.LEN := 4 from your logic changes how many elements the instruction works
through on its next run, even though the box still shows the number you typed. That is
deliberate — it is how you make a buffer that grows and shrinks while the program runs.
The array has to be long enough for .LEN
Studio checks the number you type against the array's declared size and tells you in the
editor if it does not fit. It cannot check a .LEN your logic writes, because the value only
exists while the program runs — so an over-long .LEN stops the program with a major fault
instead.
Starting Part-Way Along
The array operand names where the region starts, so both of these are valid:
BSL(Samples, …)— start at element 0BSL(Samples[4], …)— start at element 4
Elements before the start are never touched.
Sharing a control
One buffer's load and its unload are meant to share a control tag — that is how they agree
on how full it is. Every other array instruction needs a control of its own. A BSL and a
BSR do not cooperate through theirs: each one writes its own .UL there, so sharing one
means the second shift overwrites what the first reported. Studio warns when it sees that.
Related
- BSL and BSR — the bit shift instructions
- FFL and FFU — a first-in first-out queue
- LFL and LFU — a last-in first-out stack
- COP and CPS — copy a run of elements
- FLL — write one value into every element
- AVE and STD — average and spread
- SRT — sort a run in place
- SIZE — how many elements an array has
- FAL and FSC — run your own expression over every element
- CONTROL tags — declaring one
- RES — clears
.POSand the status bits, keeps.LEN - Arrays — declaring an array tag
LIMIT — Range Check
LIMIT in rungs.dev passes power when a test value is inside [lowLimit, highLimit]; if lowLimit is greater than highLimit, the bounds reverse to outside-the-band.
BSL and BSR — Bit Shift
BSL and BSR in rungs.dev move every bit of a DINT array one place along on each rising edge, feeding a new bit in at one end. Use them to track parts down a conveyor.