I need to do use a pin change interrupt with a current project as all the other pins are used up and i am only left with A0 free. I will use this pin to put the Arduino to sleep and wake it up. What is the best way to use software to debounce the button press as there can be multiple interrupts when the button is pressed.
As the others have explained, you do not use interrupts to handle button presses as such. You enable the interrupt only just before your "sleep" call, the interrupt routine itself does nothing and as soon as you exit from sleep, you immediately disable the interrupt so that there are no further interrupts. To handle the button any other time, you just poll it in your main loop and use the standard software debounce routines.
Here is an example of button debouncing:
// Blink without "delay()" - multi!
const int led1Pin = 13; // LED pin number
const int led2Pin = 10;
const int led3Pin = 11;
int led1State = LOW; // initialise the LED
int led2State = LOW;
int led3State = LOW;
unsigned long count1 = 0; // will store last time LED was updated
unsigned long count2 = 0;
unsigned long count3 = 0;
// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check
boolean timeout(unsigned long *marker, unsigned long interval) {
if (millis() - *marker >= interval) {
*marker += interval; // move on ready for next interval
return true;
}
else return false;
}
// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
switch (*butnstate) { // Odd states if was pressed, >= 2 if debounce in progress
case 0: // Button up so far,
if (button == HIGH) return false; // Nothing happening!
else {
*butnstate = 2; // record that is now pressed
*marker = millis(); // note when was pressed
return false; // and move on
}
case 1: // Button down so far,
if (button == LOW) return false; // Nothing happening!
else {
*butnstate = 3; // record that is now released
*marker = millis(); // note when was released
return false; // and move on
}
case 2: // Button was up, now down.
if (button == HIGH) {
*butnstate = 0; // no, not debounced; revert the state
return false; // False alarm!
}
else {
if (millis() - *marker >= interval) {
*butnstate = 1; // jackpot! update the state
return true; // because we have the desired event!
}
else
return false; // not done yet; just move on
}
case 3: // Button was down, now up.
if (button == LOW) {
*butnstate = 1; // no, not debounced; revert the state
return false; // False alarm!
}
else {
if (millis() - *marker >= interval) {
*butnstate = 0; // Debounced; update the state
return false; // but it is not the event we want
}
else
return false; // not done yet; just move on
}
default: // Error; recover anyway
{
*butnstate = 0;
return false; // Definitely false!
}
}
}
void setup() {
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
pinMode(led3Pin, OUTPUT);
}
void loop() {
// Act if the latter time (ms) has now passed on this particular counter,
if (timeout(&count1, 500UL )) {
if (led1State == LOW) {
led1State = HIGH;
}
else {
led1State = LOW;
}
digitalWrite(led1Pin, led1State);
}
if (timeout(&count2, 300UL )) {
if (led2State == LOW) {
led2State = HIGH;
}
else {
led2State = LOW;
}
digitalWrite(led2Pin, led2State);
}
if (timeout(&count3, 77UL )) {
if (led3State == LOW) {
led3State = HIGH;
}
else {
led3State = LOW;
}
digitalWrite(led3Pin, led3State);
}
}
And FYI to original poster ... if all your input PINS are used up, look at using Shift Register IC's to expand your input (and output) options. You can even chain them together to create dozens of new input or output virtual "pins".