FlipFlop
FlipFlop holds a true/false state that is flipped by holding its input true for a configured time.6 minute read
FlipFlop holds a true/false state that is flipped by holding its input
true for a configured time. It also reports when the input rises and falls.
Use it to turn a held button into a latched mode, without the state flickering on a brief or bouncing contact.
flowchart LR
i1(["input"]) --> B["FlipFlop"]
i2(["reset"]) --> B
p1(["setTimer"]) --> B
B --> o1(["output"])
B --> o2(["triggerRisingEdge"])
B --> o3(["triggerFallingEdge"])
The output toggles; it does not follow the input. Hold the input true for
setTimerseconds and the output flips to the opposite of whatever it was. Hold it again and it flips back. One flip per press, however long you hold.
triggerRisingEdgeandtriggerFallingEdgereport the input, not the output. They are true for a single cycle when the input changes.
Signals
Inputs
| Path | Unit | Range | Description |
|---|---|---|---|
input |
- | true or false | Hold it true for setTimer seconds to flip the output. Releasing before then flips nothing and arms the next attempt. This is a level, held for as long as you want it read. |
reset |
- | true or false | Forces output false and restarts the timer. The block clears it back to false once acted on, so it is a pulse. It does not stick while input is still held — the timer restarts and the output flips true again after setTimer seconds. Release input first. |
Outputs
| Path | Unit | Description |
|---|---|---|
output |
- | The latched state. Survives a controller restart — it is not cleared at startup. |
triggerRisingEdge |
- | True for one cycle when input goes from false to true. |
triggerFallingEdge |
- | True for one cycle when input goes from true to false. |
Parameters
| Path | Unit | Default | Range | Effect |
|---|---|---|---|---|
setTimer |
s | one task period | above 0 | How long input must be held true before output flips. Values of 0 or below are replaced by one task period and written back, so this is also the shortest usable setting. Set it above the longest contact bounce you expect. |
It is persistent and survives a controller restart. No parameters exist below this block.
Setup
- Connect your button, sensor or condition to
input. - Set
setTimerto how long the condition must hold before it counts — 50 ms is a reasonable first value for a physical button. - Hold
inputtrue and watchoutputflip after that time. - Release, hold again, and confirm
outputflips back. One flip per press. - Tap
inputbriefly and confirmoutputdoes not change. - Pulse
resetwithinputreleased, and confirmoutputgoes false and stays false.
This block only latches a flag. It does not move anything and cannot be made
to — but whatever your output enables downstream will act the moment it
flips.
Tuning
- There is one number here:
setTimer. Everything else is wiring. - Trace
inputwhile the operator does what you want to detect. Look at how long the signal is genuinely held, and how long any bounce or glitch lasts. - Set
setTimerabove the longest glitch and comfortably below the shortest real press. For a physical button those are usually milliseconds and hundreds of milliseconds respectively, so there is a wide margin. - Confirm a real press flips the output and a glitch does not.
- If a real press sometimes fails to register,
setTimeris too long, or the input is dropping out mid-press. TracetriggerFallingEdge— a pulse there during the press means the input dropped and the timer restarted. - If glitches still get through,
setTimeris shorter than the glitch. Lengthen it. setTimeris in seconds, so a task-rate change does not move it — but the lower bound of one task period does change with the rate.
The delay between each input rise and the matching output change is setTimer.
| Symptom | Cause | Action |
|---|---|---|
| The output follows the input instead of latching | It never did — this block toggles on a held input | Read the callout at the top |
| A press did nothing | It was shorter than setTimer, or the input dropped out mid-press |
Trace triggerFallingEdge during the press |
| The output flipped when I wanted it set | Expected: every completed hold flips it | Check output before acting, or use reset to force it false |
| A reset did not stick | Expected: input was still held, so the timer restarted |
Release input first, then reset |
| The output was still set after a restart | Expected: the latch is not cleared at startup | Pulse reset in your own startup logic |
| Glitches are getting through | setTimer is shorter than the glitch |
Lengthen it |
| Real presses are being missed | setTimer is longer than the press |
Shorten it |
setTimer reads back as a tiny number |
Expected: 0 and negatives are replaced by one task period | Write a positive value |
| The block never flips, whatever I do | setTimer is not a valid number |
Rewrite it |
triggerRisingEdge was true for only one cycle |
Expected: both trigger outputs are one cycle wide | Latch it yourself if you need it longer |
| The trigger outputs do not match the output | Expected: they report the input, not the output | Watch output for the output’s changes |
A reset write disappeared |
Expected: the block clears it once acted on | Read output to confirm the reset took |
| The hold time changed after a task-rate change | Only if setTimer was at its lower bound of one task period |
Set it explicitly |
| I need several of these | Not possible — this block is single channel | Use one instance per signal |
| I need to disable it | Not possible — there is no enable | Hold input false in your own logic |
A starting point for a physical button on a 1 ms task:
setTimer = 0.05
Limits and errors
| Limit | Set by | What happens | Reported |
|---|---|---|---|
| Hold time | setTimer |
The output flips exactly once, setTimer seconds after the input rises |
output |
| Repeated flips | Fixed | One flip per press. Holding longer changes nothing; release and hold again to flip back | output |
| Short presses | setTimer |
Anything shorter is ignored entirely | triggerRisingEdge still pulses |
setTimer at 0 or below |
Checked | Replaced by one task period and written back | Read the value back |
setTimer not a valid number |
Nothing | Not checked. The timer never advances and the block never flips, silently | Not reported |
reset while input is held |
Nothing | The output clears, then flips true again after setTimer. A reset only sticks with the input released |
Not reported |
| Startup state | Fixed | output is not cleared at startup and carries across a restart |
Not reported |
| Trigger width | Fixed | Both trigger outputs are exactly one cycle wide | Not reported |
| Trigger source | Fixed | Both report the input’s edges, despite their names | Not reported |
| 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).