Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple Debounce Routine

Tags:

embedded

Do you have a simple debounce routine handy to deal with a single switch input?

This is a simple bare metal system without any OS.

I would like to avoid a looping construct with a specific count, as the processor speed might fluctuate.

like image 837
Benoit Avatar asked Sep 30 '08 20:09

Benoit


3 Answers

Simplest solutions are often the best, and I've found that simply only reading the switch state every N millseconds (between 10 and 50, depending on switches) has always worked for me.

I've stripped out broken and complex debounce routines and replaced them with a simple slow poll, and the results have always been good enough that way.

To implement it, you'll need a simple periodic timer interrupt on your system (assuming no RTOS support), but if you're used to programming it at the bare metal, that shouldn't be difficult to arrange.

Note that this simple approach adds a delay to detection of the change in state. If a switch takes T ms to reach a new steady state, and it's polled every X ms, then the worst case delay for detecting the press is T+X ms. Your polling interval X must be larger than the worst-case bounce time T.

like image 73
Roddy Avatar answered Sep 26 '22 14:09

Roddy


I think you could learn a lot about this here: http://www.ganssle.com/debouncing.pdf

Your best bet is always to do this in hardware if possible, but there are some thoughts on software in there as well.

Simple example code from TFA:

#define CHECK_MSEC 5 // Read hardware every 5 msec
#define PRESS_MSEC 10 // Stable time before registering pressed
#define RELEASE_MSEC 100 // Stable time before registering released
// This function reads the key state from the hardware.
extern bool_t RawKeyPressed();
// This holds the debounced state of the key.
bool_t DebouncedKeyPress = false;
// Service routine called every CHECK_MSEC to
// debounce both edges
void DebounceSwitch1(bool_t *Key_changed, bool_t *Key_pressed)
{
    static uint8_t Count = RELEASE_MSEC / CHECK_MSEC;
    bool_t RawState;
    *Key_changed = false;
    *Key_pressed = DebouncedKeyPress;
    RawState = RawKeyPressed();
    if (RawState == DebouncedKeyPress) {
        // Set the timer which allows a change from current state.
        if (DebouncedKeyPress) Count = RELEASE_MSEC / CHECK_MSEC;
        else Count = PRESS_MSEC / CHECK_MSEC;
    } else {
        // Key has changed - wait for new state to become stable.
        if (--Count == 0) {
            // Timer expired - accept the change.
            DebouncedKeyPress = RawState;
            *Key_changed=true;
            *Key_pressed=DebouncedKeyPress;
            // And reset the timer.
            if (DebouncedKeyPress) Count = RELEASE_MSEC / CHECK_MSEC;
            else Count = PRESS_MSEC / CHECK_MSEC;
        }
    }

}

like image 27
GEOCHET Avatar answered Sep 24 '22 14:09

GEOCHET


There's no single simple solution that works for all types of buttons. No matter what someone here tells you to use, you'll have to try it with your hardware, and see how well it works. And look at the signals on a scope, to make sure you really know what's going on. Rich B's link to the pdf looks like a good place to start.

like image 32
KeyserSoze Avatar answered Sep 23 '22 14:09

KeyserSoze