Buttons can send many quick signals when pressed or released. Debouncing helps to clean these signals so the program reads just one press or release.
Button debouncing in software in Embedded C
void debounce_button() {
static int button_state = 0;
static int last_button_state = 0;
static unsigned long last_debounce_time = 0;
unsigned long debounce_delay = 50; // milliseconds
int reading = read_button_pin();
if (reading != last_button_state) {
last_debounce_time = current_millis();
}
if ((current_millis() - last_debounce_time) > debounce_delay) {
if (reading != button_state) {
button_state = reading;
if (button_state == PRESSED) {
// Button pressed action
}
}
}
last_button_state = reading;
}This example uses a timer to check if the button state is stable for a set time.
Use static variables to remember states between function calls.
int debounce(int raw_button_state) { static int stable_state = 0; static int last_state = 0; static unsigned long last_time = 0; unsigned long delay = 50; if (raw_button_state != last_state) { last_time = current_millis(); } if ((current_millis() - last_time) > delay) { if (stable_state != raw_button_state) { stable_state = raw_button_state; } } last_state = raw_button_state; return stable_state; }
if (debounce(read_button_pin()) == PRESSED) {
// Handle button press
}This program simulates noisy button presses and uses software debouncing to detect a clean press.
#include <stdio.h> #include <time.h> #define PRESSED 1 #define RELEASED 0 // Simulated button readings with noise int button_readings[] = {0, 1, 0, 1, 1, 1, 1, 1, 0, 0}; int index = 0; unsigned long current_millis() { return (unsigned long)(clock() * 1000 / CLOCKS_PER_SEC); } int read_button_pin() { if (index < sizeof(button_readings)/sizeof(button_readings[0])) { return button_readings[index++]; } return RELEASED; } int debounce() { static int button_state = RELEASED; static int last_button_state = RELEASED; static unsigned long last_debounce_time = 0; unsigned long debounce_delay = 50; // ms int reading = read_button_pin(); if (reading != last_button_state) { last_debounce_time = current_millis(); } if ((current_millis() - last_debounce_time) > debounce_delay) { if (reading != button_state) { button_state = reading; if (button_state == PRESSED) { return PRESSED; } } } last_button_state = reading; return RELEASED; } int main() { printf("Starting button debounce test...\n"); while (index < sizeof(button_readings)/sizeof(button_readings[0])) { if (debounce() == PRESSED) { printf("Button pressed detected!\n"); } } printf("Test finished.\n"); return 0; }
Debounce delay time (like 50 ms) can be adjusted depending on the button and hardware.
Using static variables inside the debounce function helps keep track of previous states.
Software debouncing is simple but may use CPU time; hardware debouncing is another option.
Button presses can be noisy and cause multiple signals.
Software debouncing waits for a stable signal before confirming a press.
This helps programs respond correctly to user button presses.
Practice
button debouncing in software?Solution
Step 1: Understand button signal noise
Mechanical buttons often create multiple quick on/off signals when pressed, called noise or bouncing.Step 2: Purpose of debouncing
Debouncing waits for the signal to stabilize before confirming a press, ignoring these unwanted rapid signals.Final Answer:
To ignore rapid, unwanted signals caused by mechanical button noise -> Option AQuick Check:
Debouncing = Ignore noise [OK]
- Thinking debouncing speeds up detection
- Confusing debouncing with hardware voltage changes
- Assuming debouncing disables buttons
Solution
Step 1: Understand debounce delay
A typical debounce delay is around 20-50 milliseconds to wait for signal stabilization.Step 2: Analyze code options
if(button_pressed()) { delay_ms(50); if(button_pressed()) { /* valid press */ } } uses 50 ms delay, which is correct. if(button_pressed()) { delay_ms(0); if(button_pressed()) { /* valid press */ } } uses 0 ms (no delay), C uses negative delay (invalid), D uses 5000 ms (too long).Final Answer:
if(button_pressed()) { delay_ms(50); if(button_pressed()) { /* valid press */ } } -> Option BQuick Check:
Debounce delay ~50ms = if(button_pressed()) { delay_ms(50); if(button_pressed()) { /* valid press */ } } [OK]
- Using zero or negative delay
- Using too long delay causing slow response
- Not checking button state after delay
int debounce_button() {
if (read_button_pin() == 0) {
delay_ms(40);
if (read_button_pin() == 0) {
return 1;
}
}
return 0;
}
What will debounce_button() return if the button is pressed and held steadily?Solution
Step 1: Check initial button state
The function checks if the button pin reads 0 (pressed).Step 2: Wait and re-check
After 40 ms delay, it checks again. If still 0, it returns 1 indicating a valid press.Final Answer:
1 -> Option CQuick Check:
Stable press returns 1 [OK]
- Assuming immediate return without delay
- Confusing 0 and 1 as pressed/released
- Thinking function loops infinitely
if (read_button_pin() == 0) {
delay_ms(10);
if (read_button_pin() == 0) {
button_pressed_flag = 1;
}
}Solution
Step 1: Analyze debounce delay duration
10 ms delay is often too short to filter mechanical bouncing which can last up to 50 ms.Step 2: Effect of short delay
Short delay allows noise to pass, causing multiple press detections.Final Answer:
Delay of 10 ms is too short to filter bouncing -> Option AQuick Check:
Too short delay causes multiple presses [OK]
- Assuming logic inversion causes multiple presses
- Thinking delay after flag needed
- Confusing delay units (ms vs us)
Solution
Step 1: Understand debounce counting logic
To count presses without bounces, confirm stable press with delay, then count once.Step 2: Avoid multiple counts during one press
Waiting until release before next count prevents multiple increments from one press.Final Answer:
Check button state, wait 50ms, check again; if still pressed, increment count and wait until release -> Option DQuick Check:
Stable press + wait release = correct count [OK]
- Counting immediately without debounce
- Using too short delay causing multiple counts
- Counting on release only misses presses
Ready to prove it?
Pass the test and this pattern moves unknown
