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.
BSL
Array
array
Control
control
Source Bit
sourceBit
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
Array
array
Control
control
Source Bit
sourceBit
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.
What a shift register is
A shift register is a row of bits that all move along together, one place at a time. Think of a conveyor with a station every metre: each time the belt advances one station, whatever was at station 1 is now at station 2, station 2 moves to station 3, and a fresh reading enters at station 1.
BSL (Bit Shift Left) moves the bits toward the high end and feeds the new bit in at bit 0. BSR (Bit Shift Right) moves them toward bit 0 and feeds the new bit in at bit length − 1.
Both work on a DINT array and keep their state in a CONTROL tag, the way a timer keeps its state in a TIMER. Give each shift instruction its own control tag, even a BSL and a BSR on the same array: the bit that falls off the end is reported in the control's .UL, and a second instruction on the same control overwrites it.
Operands
| Name | Type | Notes |
|---|---|---|
array | DINT[] | Where the region starts — Buf or Buf[2] |
control | CONTROL | Holds the length, position and status bits |
sourceBit | BOOL | The bit fed in at the near end |
length | number | How many bits long the register is. A plain number, 1 or more |
length is typed as a number, not a tag, and it is stored on the control tag as its .LEN — the box shows the tag's value there, the way a timer shows its preset. The instruction reads .LEN from the tag on every run, so logic can change it.
How It Works
Both instructions act on the rising edge — the scan where the rung goes from false to true. Holding the rung true shifts once and no more.
| Event | What happens |
|---|---|
| Rung goes true | One shift. .EN and .DN turn on, .POS becomes .LEN |
| Rung stays true | Nothing more |
| Rung false | .EN, .DN, .ER and .POS go to 0 — but .UL is kept |
.LEN below zero | .ER turns on and nothing shifts |
RES on the tag | .POS and every status bit go to 0; .LEN is kept |
Which bit falls out
.UL is a copy of the bit that left the register — bit length − 1 for BSL, bit 0 for BSR. It is a copy, not a removal: the bit still moves along inside the register as well.
.UL survives a false rung
Every other status bit is cleared when the rung goes false. .UL is not. That is deliberate — it is how you read the bit that just fell off the end on a later scan, after the rung has already dropped.
Example — Conveyor Tracker
A part sensor at the head of a conveyor, and an ejector 8 stations later. Each pulse of Advance moves the whole picture along one station.
0
Advance
BSL
Array
Stations
Control
Track
Source Bit
PartPresent
Length
8
1
Stations[0].7
Eject
Stations[0].7 is bit 7 — the eighth station. When a part reaches it, the ejector fires.
The shift covers whole words
A DINT is 32 bits, and all 32 move
A length of 8 does not mean only 8 bits move. The instruction shifts whole DINT words: a length of 1 to 32 shifts one word, 33 to 64 shifts two, and so on. Bits above length − 1 inside that word move as well, and a bit pushed off the top of the last word is thrown away.
So if you use bit 20 of a register declared with a length of 8, it will drift. Keep anything you want left alone out of the array the shift register lives in.
The same rule decides how much array the instruction needs. A length of 40 needs two DINT elements, so BSL(Buf[1], …, 40) on a DINT[2] has only one element left to work with, and the overrun stops the program with a major fault.
Common Mistakes
- Adding an
ONSin front — unnecessary.BSLandBSRalready act on the rising edge. - Expecting only
lengthbits to move. See the callout above — the shift is by whole words. - Reading
.ULas "the bit was taken out". It was copied; it also moved along. - Writing
.LENfrom logic and forgetting the array has to be long enough for it.
Related
- Array instructions overview — the
CONTROLmembers and where.LENcomes from - RES — clears
.POSand the status bits, keeps.LEN - Arrays — declaring the
DINTarray a shift register lives in
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.
FFL and FFU — FIFO Queue
FFL and FFU in rungs.dev build a first-in first-out queue in an array — load a value at one end, take the oldest out at the other. Use them to track parts waiting their turn.