1

I'm still at a beginner level in C++. I need to debounce a button (PCINT10) using an interrupt and a timer. I'm using an atmega328p microcontroller and a HW-262 shield. Currently using timer0 to increment time by 1ms.

This is part of my code so far:

ISR(TIMER0_COMPA_vect) {
    now++; //increment by 1ms
}
//interrupt setup
    PCICR = 0b00000010; 
    PCIFR = 0b00000010;
    PCMSK1 = 0b00000100;// interrupt on PCINT10

//global variables
uint8_t A2 = 0b00000100;
uint32_t A2_time = 0;
uint32_t buttons;
uint32_t oldb = 0;
uint32_t newb;

//ISR
ISR(PCINT1_vect) {
    newb = PINC;
    int changed = oldb ^ newb; // changed is 1 for buttons that have changed
    if (changed & A2) {
        if ((now - A2_time) > 10) { // 10 ms debounce
            // new S1_A1 press
            A2_time = now;
            if ((oldb & ~newb) & A2) {
                buttons |= A2;
            }
        }
    }
}

//calling button to change states (not part of the ISR)
if (((PINC & A2) == 0)) { //if A2 pressed
                    current_state = Pause;
                }

The ISR has had no effect on the button. Still detecting multiple button presses.

Elle
  • 11
  • 2
  • Is this: `if (((PINC & A2) == 0))` how you test the button state in the code? Since you are attempting to have the debounced state in `buttons`, should that not be: `if (((buttons & A2) == 0))`? – Frodyne Mar 31 '23 at 11:16
  • Beyond that, I agree with the answer by @Lundin. You may also gain from reading this: https://www.compuphase.com/electronics/debouncing.htm It is about debouncing several inputs in parallel, but the general considerations about what bounce is and how and why we want to get rid of it should apply to your case. – Frodyne Mar 31 '23 at 11:19
  • You never update `oldb`. – Clifford Apr 05 '23 at 06:49
  • Your title refers to "_a button_", but the code appears to be handling more than one. – Clifford Apr 05 '23 at 06:50
  • All but `buttons` should be local static in the ISR, while `buttons` should be `volatile`. The code has multiple semantic issue beyond the wisdom of the denounce method that @Lundin has already covered. – Clifford Apr 05 '23 at 06:54

1 Answers1

3

You shouldn't place the switch on an interrrupt-triggered pin, because it will trigger for each bounce (and on other forms of EMI noise as well).

Instead you need to do the debouncing from inside the timer ISR. And for most switches it should trigger at most once every 5ms or so. (You can measure the bounce exactly by plugging in a voltage to the switch and measure with an oscilloscope.)

So drop the PINC interrupt and move the code from there to the timer ISR. Comparing the current read with the previous and waiting until both are the same is the simplest form of de-bouncing and usually sufficient in most cases.

Also note that all variables shared between an ISR and the main program should be declared volatile or you might run into problems with an optimizing compiler generating incorrect code.

Lundin
  • 195,001
  • 40
  • 254
  • 396