MotionDetector
MotionDetector remembers a reference value and raises a flag when the signal drifts further than a threshold from it, in either direction.6 minute read
MotionDetector remembers a reference value and raises a flag when the signal
drifts further than a threshold from it, in either direction. The flag stays
raised until you reset it.
Use it to notice that something which should be standing still has moved — a brake slipping, a load settling, a clamped part creeping.
flowchart LR
i1(["input"]) --> B["MotionDetector"]
i2(["activate"]) --> B
i3(["reset"]) --> B
i4(["disable"]) --> B
p1(["threshold"]) --> B
p2(["enable"]) --> B
B --> o1(["isTriggered"])
B --> o2(["isEnabled"])
B --> o3(["reference"])
Pulse
resetwhenever you raiseactivate. Raisingactivateon its own does not capture a new reference — the detector keeps comparing against whateverreferencealready holds, which is 0 after a controller start.resetis what captures the current input as the reference. Always send both.
Read
referenceto see what it is actually comparing against. It is published for exactly this reason, and it is the fastest way to tell whether the reference was captured when you expected.
There is no noise filtering. A single sample past the threshold latches the flag permanently. If your signal is noisy, filter it before this block or use
WindowDetector, which has a time window.
Signals
Inputs
| Path | Unit | Range | Description |
|---|---|---|---|
input |
signal unit | unbounded | The signal being watched. |
activate |
- | true or false | Detection runs while this is true. A level, not a pulse. On its own it does not capture a reference — see the callout above. |
reset |
- | true or false | Clears the flag and captures the current input as the new reference. The block clears it for you, so it is a pulse. Holding it true holds the detector re-armed. |
disable |
- | true or false | Suspends detection. While disabled the reference tracks the input, so disabling and re-enabling is another way to re-arm cleanly. |
Outputs
| Path | Unit | Description |
|---|---|---|
isTriggered |
- | The input has drifted past the threshold. Latches until reset or disabled. |
isEnabled |
- | Detection is permitted. |
reference |
signal unit | The value the input is being compared against. Check this first when the detector behaves unexpectedly. |
Parameters
| Path | Unit | Default | Range | Effect |
|---|---|---|---|---|
threshold |
signal unit | 0.0 | above 0 | How far the input may drift from reference before the flag latches, in either direction. At the default of 0 any change at all triggers. A negative value makes it trigger immediately and permanently, and is not rejected. |
enable |
- | true | - | Turns detection on. When off, the flag is held clear and the reference follows the input. |
Both are persistent and survive a controller restart. No parameters exist below this block.
Setup
- Connect the signal you want to watch to
input. - Set
thresholdto how much movement you are willing to accept. It defaults to 0, which triggers on anything. - Bring the machine to the state you want to monitor and hold it there.
- Raise
activateand pulseresetin the same write. - Read
referenceand confirm it matches the current input. If it reads 0, the reset did not land — send it again. - Confirm
isTriggeredis false and stays false while the machine is still. - Nudge the machine past the threshold and confirm
isTriggeredlatches.
This block only watches a signal and raises a flag. It does not move anything
and cannot be made to — but whatever acts on isTriggered downstream will act
the moment it latches.
Tuning
- Trace
inputwhile the machine is in the state you want to monitor, for as long as you would normally leave it there. - Note the total spread — both the noise and any slow settling that is acceptable.
- Set
thresholdabove that spread, with margin. Too tight and you get false trips from noise; too loose and real movement goes unnoticed. - Re-arm and leave it for a realistic dwell. Confirm it does not trip.
- If it trips on noise, either widen
thresholdor filterinputupstream. Filtering is usually the better answer — a wide threshold hides real movement, whereas a filter only delays detection. - If you need to ignore short spikes rather than steady noise,
WindowDetectorwith atimeWindowis the better block, at the cost of fixed levels instead of a captured reference. - Nothing here depends on the task rate, so none of this needs re-checking after a rate change.
The flag never falls once raised. That is what makes it useful between polls.
| Symptom | Cause | Action |
|---|---|---|
| It triggered immediately after activating | reference is 0 because reset was not sent with activate |
Read reference; pulse reset |
| It triggered immediately even after a reset | threshold is 0 — the default — or negative |
Set a positive threshold |
reference reads 0 |
The reference has never been captured | Pulse reset |
reference is not what I expected |
It was captured at a different moment, or while disabled it tracked the input | Pulse reset at the moment you want captured |
| It trips on noise | There is no debounce in this block | Filter the input, or use WindowDetector |
| The flag will not clear | Expected: it latches | Pulse reset, or disable and re-enable |
| The flag cleared on its own | The block was disabled, which clears it | Check isEnabled |
| Real movement was not detected | threshold is wider than the movement |
Narrow it |
| Nothing is ever detected | activate is false, or enable is false, or disable is true |
Check isEnabled and activate |
| A dead sensor was not detected | A signal that is not a number reads as no motion here | Supervise the sensor with WindowDetector, which trips on it |
| The flag survived a restart | It is not cleared at startup, and reference returns to 0 |
Re-arm after every start |
| I need to watch several signals | Not possible — this block is single channel | Use one instance per signal |
A starting point for an axis in metres that should not move:
threshold = 0.002
enable = true
Limits and errors
| Limit | Set by | What happens | Reported |
|---|---|---|---|
| Detection band | threshold, reference |
The flag latches outside reference plus or minus threshold. Exactly at the edge does not trigger |
isTriggered |
| Reference capture | reset, and disabling |
Only reset and being disabled capture a reference. Raising activate does not |
reference |
threshold sign |
Nothing | Not checked. A negative value triggers immediately and permanently | Not reported |
threshold default |
Fixed at 0 | Any change at all triggers | Not reported |
| Debounce | None | A single sample past the threshold latches the flag | Not reported |
| Values that are not numbers | Nothing | Not checked. The flag is held, so a dead sensor reads as no motion | Not reported |
| Latching | Fixed | The flag stays raised until reset or disabled | Not reported |
| Disable | disable, enable |
Detection stops, the flag clears, and the reference tracks the input | isEnabled |
| Startup | Fixed | reference starts at 0 and the flag is not cleared |
reference |
| Channel count | Fixed | One signal per instance, always | Not reported |
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).