Blog Datasheets Home About me Clients My work Services Contact

G2Labs Grzegorz Grzęda

Implementing Digital Input Debouncing on AVR Atmega-328

March 28, 2024

Implementing Digital Input Debouncing on AVR Atmega-328

Debouncing is a common problem when working with digital inputs in microcontroller-based systems, especially mechanical switches and buttons. When a switch is pressed or released, it may generate multiple, rapid changes in logic state due to physical bouncing of the contacts. In this blog post, we will discuss the concept of debouncing and provide practical examples of implementing it on the AVR Atmega-328 microcontroller.

Understanding the Problem

Before we dive into implementation details, let’s understand the problem at hand. When a switch state transitions from low to high (or high to low), it may rapidly alternate between these two states multiple times in a very short period. This is known as switch bouncing, caused by mechanical vibrations and imperfections.

These rapid transitions can lead to erratic behavior and false triggering in your code. Ideally, we would like the switch’s state to change only once during a single press or release event.

To overcome this issue, we need to implement a debouncing algorithm/software that will stabilize the input signal and provide a clean, debounced state.

Debouncing Techniques

There are multiple techniques to implement digital input debouncing. In this blog post, we will explore two popular methods:

  1. Software Debouncing: This technique utilizes software delays and time-based checks to determine the final debounced state of the input.

  2. Hardware Debouncing: This technique relies on additional hardware components, such as capacitors, resistors, or specialized debounce ICs, to filter out switch bounce.

Software Debouncing Code Example

Let’s dive into a concrete example of implementing software debouncing using the AVR Atmega-328 microcontroller and the Arduino framework. The following code example demonstrates a simple debouncing algorithm using a timer-based approach:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <avr/io.h>
#include <util/delay.h>

#define DEBOUNCE_DELAY_MS 20

volatile uint8_t prevInputState = 0;
volatile uint8_t debouncedInputState = 0;

int main(void) {
    // Configure input pin as an input
    DDRD &= ~(1 << PD2);

    // Enable internal pull-up resistor for the input pin
    PORTD |= (1 << PD2);

    // Enable Timer/Counter1 interrupt
    TIMSK1 |= (1 << TOIE1);

    // Configure Timer/Counter1 with a prescaler of 1024
    TCCR1B |= (1 << CS12) | (1 << CS10);

    // Enable global interrupts
    sei();

    while (1) {
        // Do other tasks
    }

    return 0;
}

// Timer/Counter1 overflow interrupt handler
ISR(TIMER1_OVF_vect) {
    _delay_ms(DEBOUNCE_DELAY_MS);

    uint8_t currentInputState = PIND & (1 << PD2);

    if (prevInputState == currentInputState) {
        debouncedInputState = currentInputState;
    }

    prevInputState = currentInputState;
}

In this example, we use Timer/Counter1 as a timing mechanism. We configure it with a prescaler of 1024, which makes it overflow approximately every 16.384 milliseconds. Inside the ISR(TIMER1_OVF_vect), we introduce a delay of DEBOUNCE_DELAY_MS (20ms in this case) to ensure the bouncing settles down.

We then read the current input state, compare it with the previous debounced state, and update debouncedInputState only if the two match.

Please note that this code assumes the button is connected to PD2 (pin 4) and uses the internal pull-up resistor. Modify the code accordingly if your setup differs.

Hardware Debouncing

Software debouncing is a flexible and commonly used approach. However, in certain scenarios, using hardware-based debouncing techniques might be more efficient or necessary. These methods involve adding external components to filter out the switch bounce, such as capacitors, resistors, or dedicated debounce ICs.

Hardware debouncing can offer a faster response time, reduce power consumption, and eliminate the need for additional processing. However, it requires additional components and careful circuit design.

Conclusion

Debouncing digital input signals is a common challenge in microcontroller-based systems. By using either software or hardware debouncing techniques, we can ensure stable and reliable input readings. In this blog post, we explored a software debouncing example using the AVR Atmega-328 microcontroller but also touched on the concept of hardware debouncing.

Remember to consider the specific requirements of your project, such as response time, power consumption, and available resources, when choosing the appropriate debouncing method.

Feel free to explore other advanced debouncing algorithms or libraries available in various microcontroller frameworks to further enhance your implementation.

Happy debouncing!


➡️ Advanced topics in Rust


⬅️ Flask configuration and environment


Go back to Posts.