Say Goodbye to Key Bounce | Stable Button Inputs with Arduino ESP32 Timing


Key Bounce is a common challenge in electronic projects, especially when using mechanical keys. Due to unstable contact between the key’s mechanical components, a series of high and low voltage signal fluctuations may occur. If proper debouncing is not applied, these fluctuations could be mistakenly interpreted as multiple key presses, leading to erratic device behavior. Whether for DIY projects or complex IoT devices, solving the key bounce problem is crucial for stable input and reliable operation.

Key Bounce

Introduction

This article will introduce how to effectively solve the key bounce problem using Arduino and ESP32. We will utilize the ESP32’s interrupt functionality and efficient timing techniques to achieve stable key inputs, avoiding blocking the main loop. Next, you will learn what key bounce is, why debouncing is necessary, and how to implement an accurate and reliable solution through step-by-step code examples.

What is Key Bounce?

Key bounce is a phenomenon caused by unstable mechanical contact, which produces signal fluctuations when a key is pressed or released. These fluctuations result in a series of high and low voltage changes (see below). These variations could be misinterpreted by the microcontroller (MCU) as multiple key presses.

Ideal Signal:   ──────┘─────────┘───────────────
Actual Signal:  ──────┐││││─┘──────┐││││─┘──────

How to Solve Key Bounce?

Key bounce refers to the phenomenon where mechanical contacts cause small fluctuations when a key is pressed or released, resulting in multiple erroneous triggers. This can lead the microcontroller to mistakenly register multiple key events, affecting system stability. To solve this issue, we need to implement debouncing.

Three Methods to Solve Key Bounce:

  1. Hardware Debouncing: Using RC circuits (resistors and capacitors) or specialized debouncing chips to filter out noise from the key signal. While effective, this method requires additional hardware components, increasing costs.
  2. Software Delay Method: After detecting a key press, using the delay() function to pause the program for a set period, ensuring the signal is stable. This method is simple but blocks program execution and prevents handling other events, reducing system responsiveness.
  3. Timing Method: Using a timer to check if the key signal is stable. Only after the signal has been stable for a certain period will it be confirmed as a valid key event.

This article will focus on how to use the ESP32’s timing method to handle key bounce. This method is efficient, precise, and won’t block the main loop, making it ideal for applications that require handling multiple tasks.

Development Environment

Before starting your programming, make sure to complete the following preparations:

  • Arduino IDE: Install the Arduino IDE and set up the ESP32 development environment. The IDE supports multiple operating systems, including Windows, macOS, and Linux.
  • ESP32 Development Board: An ESP32 board is required.

Handling Key Bounce & Arduino ESP32 Timing

Non-blocking timing method for handling key bounce using Arduino ESP32:

const int buttonPin = 2;
volatile unsigned long lastPressTime = 0;
const unsigned long debounceDelay = 50;  // Debounce delay time (in milliseconds)
volatile bool buttonPressed = false;     // Flag to indicate button press

void IRAM_ATTR handleButtonPress() {
  unsigned long currentTime = millis();
  if (currentTime - lastPressTime > debounceDelay) {
    lastPressTime = currentTime;
    buttonPressed = true;  // Set the flag when button is pressed
  }
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);  // Set the button pin as input with pull-up resistor
  attachInterrupt(digitalPinToInterrupt(buttonPin), handleButtonPress, FALLING);  // Set up interrupt on button press (falling edge)
  Serial.begin(115200);  // Initialize serial communication
}

void loop() {
  // Main loop can handle other tasks
  if (buttonPressed) {
    Serial.println("Button pressed!");  // Print to serial if button was pressed
    buttonPressed = false;  // Reset the flag after processing
  }
}

Code Explanation

  • Button Pin Setup: The button is connected to pin 2, with the internal pull-up resistor enabled (INPUT_PULLUP). This ensures that the pin is high when the button is not pressed.
  • Interrupt Setup: Using attachInterrupt(), we set up an interrupt to monitor the button’s state change. When the button is pressed, a falling edge (change from high to low) triggers the handleButtonPress function.
  • Debounce Logic: In the handleButtonPress function, we use the millis() function to obtain the current time (in milliseconds) and compare it with the time of the last button press. If the interval between two presses is greater than the set debounce delay time (debounceDelay), the current press is considered valid, and the related actions are executed.
  • Serial Output: After the debounce logic is applied and the button is pressed, the message "Button pressed!" is displayed on the serial monitor, indicating that the button has been successfully triggered.

This method effectively handles button events, avoids blocking the main loop, and uses millis() for debouncing, efficiently preventing key bounce problems.

Output

When you run this code, the Serial Monitor will display the following output when you press and release the button:

Button pressed!

This allows you to observe real-time button status changes. If you need more detailed information or variables, you can add additional details to the Serial.println() function to display the current state or time.

Tip: If you need to observe the output, ensure that you open the Serial Monitor in Arduino IDE (the magnifying glass icon in the top right) and set the baud rate to 115200 to match the Serial.begin(115200) setting in the code.

Conclusion

We have discussed how to use the ESP32 to handle key bounce issues through timing and interrupts for efficient, precise debouncing. By using the timing method, we can avoid the blocking issues associated with the traditional delay method and handle key events accurately without interrupting the main loop. This approach not only solves key bounce problems but also ensures system stability and performance.

Specifically, the solution using interrupts and timing has the following advantages:

  • Efficiency: Interrupts allow immediate processing when the button is pressed, avoiding unnecessary delays.
  • Precision: The millis() function ensures that only valid key events are triggered after the signal stabilizes.
  • Non-blocking: This method does not block the main loop, allowing it to handle other tasks simultaneously.

In summary, the timing method is an ideal solution to key bounce problems, especially in embedded applications that require real-time responses and efficient processing. Using this approach, we can achieve stable key inputs, enhancing the reliability and performance of the system.