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.
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
volatileor you might run into problems with an optimizing compiler generating incorrect code.