Expand description
§Debouncr
A simple and efficient no_std
input debouncer that uses integer bit
shifting to debounce inputs. The basic algorithm can detect rising and
falling edges and only requires 1 byte of RAM for detecting up to
8 consecutive high/low states or 2 bytes of RAM for detecting up to
16 consecutive high/low states.
While the regular algorithm will detect any change from “bouncing” to “stable high/low” as an edge, there is also a variant that will only detect changes from “stable high” to “stable low” and vice versa as an edge (see section “Stateful Debouncing”).
The algorithm is based on the Ganssle Guide to Debouncing (section “An Alternative”).
§API
§Instantiate
First, decide how many consecutive states you want to detect. For example, if you poll the input pin every 5 ms and require 4 consecutive logical-high states to trigger a debounced press event, that event will happen after 20 ms.
On initialization, you also need to specify the initial state: true
for
logical-high, false
for logical-low.
use debouncr::debounce_4;
let mut debouncer = debounce_4(false); // Type: Debouncer<u8, Repeat4>
§Update
In regular intervals, call the update(pressed)
function to update the
internal state.
use debouncr::{debounce_3, Edge};
let mut debouncer = debounce_3(false);
assert_eq!(debouncer.update(poll_button()), None);
assert_eq!(debouncer.update(poll_button()), None);
assert_eq!(debouncer.update(poll_button()), Some(Edge::Rising));
The update
function will return a rising/falling edge, or None
if the
input is still bouncing.
§Query Debounced State
You can also query the current debounced state. If none of the n
recent
updates were pressed, then the debounced state will be low. If all n
recent updates were pressed, then the debounced state will be high.
use debouncr::debounce_3;
let mut debouncer = debounce_3(false);
// Initially low
assert!(debouncer.is_low());
assert!(!debouncer.is_high());
// Update, now it's neither high nor low
debouncer.update(true);
assert!(!debouncer.is_low());
assert!(!debouncer.is_high());
// After two more updates, it's high
debouncer.update(true);
debouncer.update(true);
assert!(debouncer.is_high());
§Stateful Debouncing
By default, the debouncer will report any change from “bouncing” to “stable high/low” as an edge. If instead you want to detect only changes from a stable state to the opposite stable state, use the stateful debouncer instead. It has slightly higher (but still tiny) memory overhead than the regular debouncer, because it also stores the previous state in addition to the debouncing updates.
use debouncr::{debounce_stateful_3, Edge};
let mut debouncer = debounce_stateful_3(false);
// Ensure initial low state
assert!(debouncer.is_low());
// Temporary bouncing states will not trigger an edge
assert_eq!(debouncer.update(true), None);
assert_eq!(debouncer.update(false), None);
assert_eq!(debouncer.update(false), None);
assert_eq!(debouncer.update(false), None);
// However, stable opposite states will trigger an edge
assert_eq!(debouncer.update(true), None);
assert_eq!(debouncer.update(true), None);
assert_eq!(debouncer.update(true), Some(Edge::Rising));
§Example: RTIC
If you want to debounce a pin in an RTIC project, register a resource and a timer.
use debouncr::{Debouncer, debounce_12, Edge, Repeat12};
#[app(..., monotonic = rtic::cyccnt::CYCCNT)]
const APP: () = {
struct Resources {
button: gpioa::PA11<Input<PullUp>>,
button_state: Debouncer<u16, Repeat12>,
}
#[init(spawn = [poll_button])]
fn init(ctx: init::Context) -> init::LateResources {
// ...
ctx.spawn.poll_button().unwrap();
init::LateResources {
button,
button_state: debounce_12(false),
}
}
/// Regularly called task that polls the buttons and debounces them.
#[task(
resources = [button, button_state],
spawn = [button_pressed, button_released],
schedule = [poll_button],
)]
fn poll_button(ctx: poll_button::Context) {
// Poll button
let pressed: bool = ctx.resources.button.is_low().unwrap();
// Update state
let edge = ctx.resources.button_state.update(pressed);
// Dispatch event
if edge == Some(Edge::Rising) {
ctx.spawn.button_pressed().unwrap();
} else if edge == Some(Edge::Falling) {
ctx.spawn.button_released().unwrap();
}
// Re-schedule the timer interrupt
ctx.schedule
.poll_button(ctx.scheduled + POLL_PERIOD.cycles())
.unwrap();
}
/// The button was pressed.
#[task]
fn button_pressed(ctx: button_pressed::Context) {
// Button was pressed, handle event somehow
}
/// The button was released.
#[task]
fn button_released(ctx: button_pressed::Context) {
// Button was released, handle event somehow
}
};
§Memory Consumption
Memory size of a debouncer instance:
Debouncer | Repetitions | Bytes |
---|---|---|
Debouncer | 2..8 | 1 |
DebouncerStateful | 2..8 | 2 |
Debouncer | 9..16 | 2 |
DebouncerStateful | 9..16 | 4 |
Structs§
- Debouncer
- A debouncer.
- Debouncer
Stateful - A stateful debouncer.
- Repeat2
- Detect 2 consecutive logical-high states.
- Repeat3
- Detect 3 consecutive logical-high states.
- Repeat4
- Detect 4 consecutive logical-high states.
- Repeat5
- Detect 5 consecutive logical-high states.
- Repeat6
- Detect 6 consecutive logical-high states.
- Repeat7
- Detect 7 consecutive logical-high states.
- Repeat8
- Detect 8 consecutive logical-high states.
- Repeat9
- Detect 9 consecutive logical-high states.
- Repeat10
- Detect 10 consecutive logical-high states.
- Repeat11
- Detect 11 consecutive logical-high states.
- Repeat12
- Detect 12 consecutive logical-high states.
- Repeat13
- Detect 13 consecutive logical-high states.
- Repeat14
- Detect 14 consecutive logical-high states.
- Repeat15
- Detect 15 consecutive logical-high states.
- Repeat16
- Detect 16 consecutive logical-high states.
Enums§
- Edge
- Rising or falling edge.
Functions§
- debounce_
2 - Create a new debouncer that can detect a rising or falling edge of 2 consecutive logical states.
- debounce_
3 - Create a new debouncer that can detect a rising or falling edge of 3 consecutive logical states.
- debounce_
4 - Create a new debouncer that can detect a rising or falling edge of 4 consecutive logical states.
- debounce_
5 - Create a new debouncer that can detect a rising or falling edge of 5 consecutive logical states.
- debounce_
6 - Create a new debouncer that can detect a rising or falling edge of 6 consecutive logical states.
- debounce_
7 - Create a new debouncer that can detect a rising or falling edge of 7 consecutive logical states.
- debounce_
8 - Create a new debouncer that can detect a rising or falling edge of 8 consecutive logical states.
- debounce_
9 - Create a new debouncer that can detect a rising or falling edge of 9 consecutive logical states.
- debounce_
10 - Create a new debouncer that can detect a rising or falling edge of 10 consecutive logical states.
- debounce_
11 - Create a new debouncer that can detect a rising or falling edge of 11 consecutive logical states.
- debounce_
12 - Create a new debouncer that can detect a rising or falling edge of 12 consecutive logical states.
- debounce_
13 - Create a new debouncer that can detect a rising or falling edge of 13 consecutive logical states.
- debounce_
14 - Create a new debouncer that can detect a rising or falling edge of 14 consecutive logical states.
- debounce_
15 - Create a new debouncer that can detect a rising or falling edge of 15 consecutive logical states.
- debounce_
16 - Create a new debouncer that can detect a rising or falling edge of 16 consecutive logical states.
- debounce_
stateful_ 2 - Create a new stateful debouncer that can detect stable state changes after 2 consecutive logical states.
- debounce_
stateful_ 3 - Create a new stateful debouncer that can detect stable state changes after 3 consecutive logical states.
- debounce_
stateful_ 4 - Create a new stateful debouncer that can detect stable state changes after 4 consecutive logical states.
- debounce_
stateful_ 5 - Create a new stateful debouncer that can detect stable state changes after 5 consecutive logical states.
- debounce_
stateful_ 6 - Create a new stateful debouncer that can detect stable state changes after 6 consecutive logical states.
- debounce_
stateful_ 7 - Create a new stateful debouncer that can detect stable state changes after 7 consecutive logical states.
- debounce_
stateful_ 8 - Create a new stateful debouncer that can detect stable state changes after 8 consecutive logical states.
- debounce_
stateful_ 9 - Create a new stateful debouncer that can detect stable state changes after 9 consecutive logical states.
- debounce_
stateful_ 10 - Create a new stateful debouncer that can detect stable state changes after 10 consecutive logical states.
- debounce_
stateful_ 11 - Create a new stateful debouncer that can detect stable state changes after 11 consecutive logical states.
- debounce_
stateful_ 12 - Create a new stateful debouncer that can detect stable state changes after 12 consecutive logical states.
- debounce_
stateful_ 13 - Create a new stateful debouncer that can detect stable state changes after 13 consecutive logical states.
- debounce_
stateful_ 14 - Create a new stateful debouncer that can detect stable state changes after 14 consecutive logical states.
- debounce_
stateful_ 15 - Create a new stateful debouncer that can detect stable state changes after 15 consecutive logical states.
- debounce_
stateful_ 16 - Create a new stateful debouncer that can detect stable state changes after 16 consecutive logical states.