This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Debounce in callbacks

Hello!

I currently have an external button and LED connected to the Icarus IoT dev board. For the time being, I just want to turn on the LED in the callback function when I press the button. However, the button (and the board) is highly sensitive and registers several interrupts with one push. I can even turn on the LED by touching the pin with my finger!

So I was wondering if there is any easy way to add some kind of debounce code in the callback itself? I have seen some examples here and there, but none of them that is a really proper method nor being used inside the callback itself. 

Looking forward to seeing your suggestions!

Parents
  • Hi Baowz,

    For debouncing a button, you can simply keep the uptime value at the moment of the button callback (eg k_uptime_get_32()) in a variable, let's call it last_button_press_time, and in your callback do something like the following:

    #define BUTTON_DEBOUNCE_TIME 50
    uint32_t last_button_press_time;
    
    void button_pressed_callback(...) {
        uint32_t newPressTime = k_uptime_get_32();
    
        // debounce
        if (k_uptime_get_32() - last_button_press_time < BUTTON_DEBOUNCE_TIME) {
            return;
        }
    
        is_button_press_pending = true;
        // use (and re-set) the `is_button_press_pending` flag in your main loop
        // or submit work to queue at this point
    
        last_button_press_time = newPressTime;
    }
    

    Also, it sounds like you may not have the internal pull-up resistor active on your input, making your pin floating and triggering "too easily". Make sure to turn it on when you initialize your GPIO.

    Let me know in case of any questions!

    BR,

    Mike

Reply
  • Hi Baowz,

    For debouncing a button, you can simply keep the uptime value at the moment of the button callback (eg k_uptime_get_32()) in a variable, let's call it last_button_press_time, and in your callback do something like the following:

    #define BUTTON_DEBOUNCE_TIME 50
    uint32_t last_button_press_time;
    
    void button_pressed_callback(...) {
        uint32_t newPressTime = k_uptime_get_32();
    
        // debounce
        if (k_uptime_get_32() - last_button_press_time < BUTTON_DEBOUNCE_TIME) {
            return;
        }
    
        is_button_press_pending = true;
        // use (and re-set) the `is_button_press_pending` flag in your main loop
        // or submit work to queue at this point
    
        last_button_press_time = newPressTime;
    }
    

    Also, it sounds like you may not have the internal pull-up resistor active on your input, making your pin floating and triggering "too easily". Make sure to turn it on when you initialize your GPIO.

    Let me know in case of any questions!

    BR,

    Mike

Children
  • This seems to be a really good solution, thank you! However, I'm a little bit confused by the code. You say that you want to store it in a variable called "last_button_press_time". But it ends up being stored in "newPressTime" and "last_button_press_time" is never declared. I feel like I'm missing something from your explanation, I'm sorry about that. But can you elaborate a little bit more for me?

  • Hi Baowz,

    You should declare the `last_button_press_time` variable outside the function, I edited my answer above to show you how the `last_button_press_time` and `BUTTON_DEBOUNCE_TIME` can be declared.

    The `newPressTime` is just used so that the "entry" time is used as a last_button_press_time, you can even skip it, and put the uptime directly in the `last_button_press_time` if you prefer.

    BR,

    Mike

  • Hello again, Mike!

    The code works perfectly, thank you so much for the help!

    Just a quick question when it comes to enabling the resistor in the GPIO. Should I do it the same way as I did with the button? I used the sample that is shown from your website found here. And the way I tried to initialize the resistor is as follows:

    ...   
        resistors {
            TV_resistor: resistor0 {
                gpios = <&gpio0 0 GPIO_PULL_UP>;
                label = "Video resistor";
            };
        };
    	aliases {
    	   ...
    	   resistor0 = &TV_resistor;
        };
    ...

  • Hello Baowz,

    A device tree declaration will not initialize a pull-up resistor, you have to do it in the gpio_pin_configure(). If you want to use a similar way with what we do in the "leds & button" sample, then you should declare an extra button in your overlay (you can copy paste the button declaration from the icarus board files and change the gpio to pin 0 where you seem to have your external button connected) and just initialize the gpio the same way it is done for the on-board button in the sample, i.e. using the device tree flags in gpio_pin_configure().

    BR,

    Mike

Related