Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Arduino: Debounced Switch (ISRs only, no polling)
/*
HOOK-UP: NORMALLY OFF
---------------------
Connect one pin of the push-button or toggle switch to pin D5.
Connect a 10K pull-down resistor between the above pin and GND.
Connect the other pin of the push-button or toggle switch to 5V.
HOOK-UP: NORMALLY ON
--------------------
Connect one pin of the push-button or toggle switch to pin D5.
Connect a 10K pull-up resistor between the above pin and GND
(or use the Arduino's weaker ~20-50K internal pull-up resistor
by setting pin D5 to INPUT_PULLUP mode).
Connect the other pin of the push-button or toggle switch to GND.
LED INDICATOR
-------------
This code example uses the built-in LED on the Arduino's
digital pin D13 as an indicator for the push-button or
toggle switch state changes.
*/
#include <avr/wdt.h> // collection of watchdog timer handling functions
void setup() {
bitClear(DDRD, DDD5); // pinMode(5, INPUT);
// bitClear(DDRD, DDD5); bitSet(PORTD, PORTD2); // pinMode(5, INPUT_PULLUP); (for internal pull-up resistor setup)
bitSet(DDRB, DDB5); // pinMode(13, OUTPUT);
noInterrupts(); // disable global interrupts (cli);
bitWrite(PORTB, PORTB5, bitRead(PIND, PIND5)); // digitalWrite(13, digitalRead(5));
// bitWrite(PORTB, PORTB5, !bitRead(PIND, PIND5)); // digitalWrite(13, !digitalRead(5)); (for pull-up resistor setup with normally off mode)
bitSet(PCMSK2, PCINT21); // specify interupt on pin D5
bitSet(PCIFR, PCIF2); // clear any outstanding interrupts for D8 - D13
bitSet(PCICR, PCIE2); // enable pin change interrupts for D8 - D13
bitClear(MCUSR, WDRF); // clear watchdog timer interrupt flag to allow clearing of WDE (2nd operation below)
WDTCSR = (1 << WDCE) | (1 << WDE); // enter watchdog timer configuration mode
WDTCSR = (1 << WDIE) | (1 << WDP1); // set watchdog timer overflow interrupt (without system reset) to 64mS
interrupts(); // enable global interrupts (sei);
}
void loop() {}
ISR(PCINT2_vect) { // pin change interrupt service routine for pin D5
wdt_reset(); // start measuring fixed time interval (64mS) after which watchdog timer ISR is automatically triggered
GPIOR1 = bitRead(PIND, PIND5); // digitalRead(5) and store value in the second General Purpose I/O register
// GPIOR1 = !bitRead(PIND, PIND5); // !digitalRead(5) and store (inversed) value in the second General Purpose I/O register (for pull-up resistor setup with normally off mode)
}
ISR(WDT_vect) { // watchdog timer interrupt service routine for switch debouncing
if (GPIOR1 == bitRead(PIND, PIND5)) { // verify new state presists by compering value of the second General Purpose I/O register with current state of pin D5
// if (GPIOR1 != bitRead(PIND, PIND5)) { // verify new state presists by compering (inversed) value of the second General Purpose I/O register with current state of pin D5 (for pull-up resistor setup with normally off mode)
bitWrite(PORTB, PORTB5, GPIOR1); // digitalWrite(13, GPIOR1);
bitSet(PCIFR, PCIF2); // clear any outstanding interrupts for D8 - D13
}
}
/*
Reference: http://gammon.com.au/interrupts
ISR (PCINT0_vect) {
// handles pin change interrupts for D8 - D13
}
ISR (PCINT1_vect) {
// handles pin change interrupts for A0 - A5
}
ISR (PCINT2_vect) {
// handles pin change interrupts for D0 - D7
}
void setup () {
// pin change interrupt (example for D9)
PCMSK0 |= bit (PCINT1); // want pin 9
PCIFR |= bit (PCIF0); // clear any outstanding interrupts
PCICR |= bit (PCIE0); // enable pin change interrupts for D8 - D13
}
ARDUINO PIN INTERRUPT VECTOR MAPPING
--------------------------------------
D0 PCINT16 (PCMSK2 / PCIF2 / PCIE2)
D1 PCINT17 (PCMSK2 / PCIF2 / PCIE2)
D2 PCINT18 (PCMSK2 / PCIF2 / PCIE2)
D3 PCINT19 (PCMSK2 / PCIF2 / PCIE2)
D4 PCINT20 (PCMSK2 / PCIF2 / PCIE2)
D5 PCINT21 (PCMSK2 / PCIF2 / PCIE2)
D6 PCINT22 (PCMSK2 / PCIF2 / PCIE2)
D7 PCINT23 (PCMSK2 / PCIF2 / PCIE2)
D8 PCINT0 (PCMSK0 / PCIF0 / PCIE0)
D9 PCINT1 (PCMSK0 / PCIF0 / PCIE0)
D10 PCINT2 (PCMSK0 / PCIF0 / PCIE0)
D11 PCINT3 (PCMSK0 / PCIF0 / PCIE0)
D12 PCINT4 (PCMSK0 / PCIF0 / PCIE0)
D13 PCINT5 (PCMSK0 / PCIF0 / PCIE0)
A0 PCINT8 (PCMSK1 / PCIF1 / PCIE1)
A1 PCINT9 (PCMSK1 / PCIF1 / PCIE1)
A2 PCINT10 (PCMSK1 / PCIF1 / PCIE1)
A3 PCINT11 (PCMSK1 / PCIF1 / PCIE1)
A4 PCINT12 (PCMSK1 / PCIF1 / PCIE1)
A5 PCINT13 (PCMSK1 / PCIF1 / PCIE1)
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.