[][src]Crate debouncr

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.

This example is not tested
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.