Last active
November 13, 2016 04:31
-
-
Save nadavmatalon/fdf4ea35345546378ef58c699c6adb26 to your computer and use it in GitHub Desktop.
Arduino: Debounced Switch (ISRs only, no polling)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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