I have a routine that polls the status of a button connected on the microcontroller ATMega328P (on chip arduino nano but code is written in C++), the routine code is this:
#include <avr/io.h>
#include <avr/interrupt.h>
bool GPIO::GetPressed()
{
if (bit_is_clear(*this->GetPortOrPin(), this->wichPin))
{
this->confidenceReleased = 0;
++this->confidencePressed;
if (!this->pressed && confidencePressed > thresholdPressed)
{
this->pressed = true;
confidencePressed = 0;
return true;
}
}
else
{
this->confidencePressed = 0;
++this->confidenceReleased;
if (this->pressed && confidenceReleased > thresholdReleased)
{
this->pressed = false;
confidenceReleased = 0;
}
}
return false;
}
This method returns true
if the button is pressed (it's a little bit sophisticated because there is some debouncing stuff going on), and returns false
otherwise.
*this->GetPortOrPin()
returns the PINX register of interest.
When I use this method inside main
it works perfectly.
If I try to poll the button using this same method on an interrupt service routine (triggered by the button itself), this method returns always false
.
By interrupt service routine I mean:
ISR (PCINTX_vect) //X can be 1 2 or 3
{
//i press the button and code makes till this point
if (somebutton.GetPressed() )
{
//never gets inside
}
}
I tried to disable the interrupts once inside the ISR so maybe if the bouncing effect triggers a lot of interrupts on pin change I get rid of this problem but that didn't work.
The problem with the code of buttonpressed method is that if you call it in the main recursively the counters will be increased in each call in the polling "fashion": if you call it on a interrupt routine the function will be executed only once and the output will always evaluate to false because the counters cannot reach threshold.