Crate debouncr

Source
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:

DebouncerRepetitionsBytes
Debouncer2..81
DebouncerStateful2..82
Debouncer9..162
DebouncerStateful9..164

Structs§

Debouncer
A debouncer.
DebouncerStateful
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.