LevelSwitch

LevelSwitch compares one signal against one level and publishes two complementary flags.
3.30–3.34

LevelSwitch compares one signal against one level and publishes two complementary flags. A deadband holds the decision while the signal sits near the level, so the output does not chatter on noise.

Use it to raise a flag when a pressure, a speed or a position crosses a threshold.

flowchart LR
    i1(["input"]) --> B["LevelSwitch"]
    p1(["switchLevel"]) --> B
    p2(["deadband"]) --> B
    B --> o1(["isLower"])
    B --> o2(["isHigher"])

isHigher is always the exact opposite of isLower. Read whichever reads better in your logic; they can never disagree.

The deadband is split either side of the level. A deadband of 2 around a level of 5 switches to high at 6 and back to low at 4. Size it from the noise on your signal, not from the level.

Signals

Inputs

Path Unit Range Description
input signal unit unbounded The signal to compare. Compared as-is, with no filtering — feed it a filtered signal if it is noisy beyond what the deadband can absorb.

Outputs

Path Unit Description
isLower - True while the input is below the level. Starts true, before the first comparison has run.
isHigher - True while the input is above the level. Always the complement of isLower.

Parameters

Path Unit Default Range Effect
switchLevel signal unit 0.0 unbounded The level to compare against. The output switches high at switchLevel + deadband/2 and back low at switchLevel - deadband/2.
deadband signal unit 0.0 0 upward Total width of the hold region, split either side of the level. With 0 the output switches exactly at the level and will chatter on any noise. A negative value removes the hysteresis and is not rejected.

Both are persistent and survive a controller restart. No parameters exist below this block.

Setup

  1. Connect the signal you want to watch to input.
  2. Set switchLevel to the value you want to detect.
  3. Leave deadband at 0 for a first look, and watch isHigher while the signal crosses the level.
  4. If isHigher flickers at the crossing, the signal is noisy — go to Tuning.
  5. Confirm isLower and isHigher are always opposite. They are computed to be, so a disagreement means you are reading two different cycles.

This block only reads a signal and raises a flag. It does not move anything and cannot be made to.

Tuning

  1. Trace input while the machine does what you want to detect, and note how far the signal wanders when it is sitting still near the level.
  2. Set deadband to about twice that wander. That is the whole tuning.
  3. Check the crossing again. isHigher should switch once, cleanly, in each direction.
  4. If it still chatters, the deadband is smaller than the noise. Double it.
  5. If the flag now arrives too late, the deadband is too wide — remember it delays the switch by half its width in each direction.
  6. If you cannot get both, the signal needs filtering upstream rather than a wider deadband here. A wider deadband costs you accuracy in both directions; a filter costs you a little delay in one.
  7. Nothing here depends on the task rate, so none of this needs re-checking after a rate change.

As the input sweeps up through the level and back down, a zero deadbandswitches at the level itself, while a deadband of 4 switches two units above onthe way up and two below on the waydown.

The gap between the two switching points is the deadband.

Symptom Cause Action
The flag chatters at the crossing deadband is smaller than the noise on the signal Widen it, or filter the input
The flag chatters with deadband set The signal is noisier than you measured Trace the input at rest near the level and re-measure
The flag arrives later than expected Expected: the deadband delays the switch by half its width Narrow it, or move switchLevel down by half the deadband
The flag never switches The signal never reaches switchLevel ± deadband/2 Check the level, and check the input is actually connected
The hysteresis disappeared deadband is negative, which is not rejected Write a positive value
isHigher reads true at exactly the level Expected with a zero deadband: the tie goes to high Set a deadband
isLower read true before anything ran Expected: it starts true until the first cycle Ignore the outputs until the controller is running
Both flags read the same Not possible in one cycle You are comparing readings from different cycles
The flag did not update after a restart Expected: the previous decision is held for one cycle Ignore the first cycle
A NaN reached the input and the flag froze The decision is held when the input is not a number Fix the upstream signal
I need to watch several signals Not possible — this block is single channel Use one instance per signal
I need to disable it Not possible — there is no enable Ignore the outputs in your own logic

A starting point for a signal that sits within ±0.5 of its value at rest:

switchLevel = <the value you want to detect>
deadband    = 2.0

Limits and errors

Limit Set by What happens Reported
Switching point switchLevel, deadband High at switchLevel + deadband/2, low at switchLevel - deadband/2 isLower, isHigher
Inside the deadband deadband The decision is held — this is the hysteresis and the reason the block exists Not reported
Exactly at the level, zero deadband Fixed Reads isHigher Not reported
deadband sign Nothing Not checked. A negative value overlaps the two thresholds and removes the hysteresis Not reported
input value Nothing Not checked. A NaN input holds the previous decision rather than switching Not reported
Initial state Fixed isLower reads true and isHigher false until the first cycle runs Not reported
Channel count Fixed One signal per instance, always Not reported
Task rate Not used The block has no time dependence at all; the decision is instantaneous Not applicable

This block logs nothing, ever. Every condition above shows as a value on a trace, or not at all.


Verified against motorcortex-control3 3.30.0 (bc348fd).