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