Button Debouncing with ESP32

What is Button Bouncing?

  • When a button is pressed or released, it does not change its state instantaneously.
  • Due to mechanical and physical issues, the button may rapidly fluctuate between HIGH and LOW states before stabilizing.
  • This phenomenon is known as "button bouncing".

What is Button Bouncing?

Illustrating Button Bouncing

  • A MicroPython script with an ISR demonstrates button bouncing on an ESP32 by incrementing a counter on pin 32 for each falling edge.
from machine import Pin
import time

# Initialize global counter
counter = 0

# Define the interrupt service routine
def isr(pin):
    global counter
    counter += 1
    print('Button pressed count:', counter)

# Setup the button input and attach the ISR
button = Pin(32, Pin.IN, Pin.PULL_UP)
button.irq(trigger=Pin.IRQ_FALLING, handler=isr)

# Run an infinite loop to keep the program running
while True:
    time.sleep(1)  # sleep to reduce CPU usage

Illustrating Button Bouncing

  • With this script, when the button is pressed, you'll observe the counter incrementing multiple times due to bouncing.

Why is Debouncing Important?

  • Without debouncing, a single button press could be interpreted as multiple presses, causing unexpected behavior.
  • Debouncing ensures that a single press is only registered once.

Debouncing Techniques

  • Software debouncing
  • Hardware debouncing

Software Debouncing with MicroPython

  • A simple way to implement software debouncing is to use a delay.
  • Check the button state, wait for a short period, then check the state again.
  • If the state is the same, the button press is considered valid.

Software Debouncing Example

from machine import Pin
import time

button = Pin(32, Pin.IN)

def debounce(pin):
    # initial state
    state = pin.value()
    # wait for 20 milliseconds
    time.sleep(0.02)
    # check state again
    return state if pin.value() == state else None

while True:
    button_state = debounce(button)
    if button_state is not None:
        print('Button state:', button_state)

Software Debouncing Example

from machine import Pin, Timer  # Import necessary classes from the machine module
import time  # Import the time module

# Initialize global variables
button = Pin(32, Pin.IN, Pin.PULL_UP)  # Initialize pin 32 as a pull-up input
counter = 0  # Counter to keep track of button presses
irq_isenable = True  # Flag to indicate whether IRQ is enabled

def isr(pin):  # ISR function to handle button presses
    global counter, irq_isenable  # Access global variables
    if irq_isenable:  # Check if IRQ is enabled
        print(f'Button pressed, IRQ disabled, starting timer')
        counter += 1  # Increment the counter
        print('Button pressed count:', counter)
        timer.init(mode=Timer.ONE_SHOT, period=200, callback=enable_irq)  # Start a one-shot timer
        print(f'Timer start {timer}')
        irq_isenable = False  # Disable IRQ

def enable_irq(timer):  # Function to re-enable IRQ
    global irq_isenable  # Access global variable
    irq_isenable = True  # Re-enable IRQ
    print('Timer expired, IRQ re-enabled')

# Attach ISR
button.irq(trigger=Pin.IRQ_FALLING, handler=isr)  # Attach ISR to handle falling edge triggers

# Set up the one-shot timer
timer = Timer(0)  # Initialize a Timer object

print("Program Start")  # Print program start message
# Run an infinite loop to keep the program running
while True:
    time.sleep(1)  # Sleep to reduce CPU usage

Hardware Debouncing Example

Recap

  • Button bouncing is a common issue that can cause unexpected behavior.
  • Software debouncing is a simple and effective method to handle button bouncing.
  • The MicroPython code provided demonstrates a basic debouncing technique using a delay.