Arduino Interrupts Paul MacDougal September 8, 2014.
-
Upload
bennett-miles -
Category
Documents
-
view
215 -
download
0
Transcript of Arduino Interrupts Paul MacDougal September 8, 2014.
![Page 1: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/1.jpg)
ArduinoInterrupts
Paul MacDougal
September 8, 2014
![Page 2: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/2.jpg)
What are they?
• Interrupts are a way for a microcontroller to temporarily stop what it is doing to handle another task.
• The currently executing program is paused, an ISR (interrupt service routine) is executed, and then your program continues, none the wiser.
![Page 3: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/3.jpg)
Kinds of interrupts• There are 26 different interrupts on an Arduino Uno
– 1 Reset– 2 External Interrupt Request 0 (pin D2)– 3 External Interrupt Request 1 (pin D3)– 4 Pin Change Interrupt Request 0 (pins D8 to D13)– 5 Pin Change Interrupt Request 1 (pins A0 to A5)– 6 Pin Change Interrupt Request 2 (pins D0 to D7)– 7 Watchdog Time-out Interrupt– 8 Timer/Counter2 Compare Match A– …– 18 SPI Serial Transfer Complete– 19 USART Rx Complete – …– 25 2-wire Serial Interface (I2C)– …
![Page 4: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/4.jpg)
When would you use one?
• Interrupts can detect brief pulses on input pins. Polling may miss the pulse while you are doing other calculations.
• Interrupts are useful for waking a sleeping processor.
• Interrupts can be generated at a fixed interval for repetitive processing.
• And more …
![Page 5: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/5.jpg)
Example 1 (no interrupts)const byte LED = 13, SW = 2;
void setup() { pinMode(LED, OUTPUT); pinMode(SW, INPUT_PULLUP);}
void handleSW() { digitalWrite(LED, digitalRead(SW));}
void loop() { handleSW();}
![Page 6: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/6.jpg)
Example 2 (no interrupts)const byte LED = 13, SW = 2;
void handleSW() { digitalWrite(LED, digitalRead(SW));}
void handleOtherStuff() { delay(250);}
void setup() { pinMode(LED, OUTPUT); pinMode(SW, INPUT_PULLUP);}
void loop() { handleSW(); handleOtherStuff();}
![Page 7: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/7.jpg)
Example 3 (interrupt)const byte LED = 13, SW = 2;
void handleSW() { // ISR digitalWrite(LED, digitalRead(SW));}
void handleOtherStuff() { delay(250);}
void setup() { pinMode(LED, OUTPUT); pinMode(SW, INPUT_PULLUP); attachInterrupt(INT0, handleSW, CHANGE);}
void loop() { // handleSW(); commented out handleOtherStuff();}
![Page 8: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/8.jpg)
ISR
• Interrupt Service Routines should be kept short. Interrupts are disabled when the ISR is called, so other interrupts are postponed.
• Do not call millis() or delay() or Serial or … • This one is good:void myISR () { count++;}
![Page 9: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/9.jpg)
What we have learned
• The hardware can call a routine for us based on activity on pin 2 (INT0)
• Our loop() code does not need to know what is happening
• But, we often want to know what is going on. How do we share that information?
![Page 10: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/10.jpg)
Example 4const byte LED = 13, SW = 2;
volatile unsigned char count = 0;void handleSW () { digitalWrite(LED, digitalRead(SW)); count+
+;}
unsigned char lastCount = -1;void handleOtherStuff() { if (count != lastCount) { Serial.print("Count "); Serial.println(count); lastCount = count; }}
void loop () { handleOtherStuff();}
void setup () { //Start up the serial port Serial.begin(9600); Serial.println(F(“Example4")); pinMode (LED, OUTPUT); pinMode (SW, INPUT_PULLUP); attachInterrupt(INT0, handleSW, CHANGE);}
![Page 11: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/11.jpg)
![Page 12: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/12.jpg)
A little more on sharing data• An interrupt can happen at any time.
• If you share a multi-byte value (e.g. short int) between an ISR and your code, you have to take additional precautions.
volatile short count;if (count == 256) …
1fa: 80 91 10 01 lds r24, 0x0110 ; count lower1fe: 90 91 11 01 lds r25, 0x0111 ; count upper202: 80 50 subi r24, 0x00204: 91 40 sbci r25, 0x01206: 69 f5 brne .+90
![Page 13: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/13.jpg)
Sharing continued// Disable interrupts and copynoInterrupts();short int myCount = count;interrupts();if (myCount == 256) …
1fa: f8 94 cli1fc: 80 91 10 01 lds r24, 0x0110200: 90 91 11 01 lds r25, 0x0111204: 78 94 sei206: 80 50 subi r24, 0x00208: 91 40 sbci r25, 0x0120a: 69 f5 brne .+90
![Page 14: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/14.jpg)
What we have learned
• Switches bounce and we may be interrupted more often than expected
• We must take precautions when sharing data between an ISR and the main code
![Page 15: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/15.jpg)
Pin Change Interrupt
• Pin 2 is INT0
• Pin 3 is INT1
• But, what about pins 0,1,4,5,6,…
• Pin Change Interrupts can monitor all pins
![Page 16: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/16.jpg)
Example 5#include <PinChangeInt.h>const byte LED = 13, SW = 5;
volatile unsigned char count = 0;void handleSW () { digitalWrite(LED, digitalRead(SW)); count++;}
unsigned char lastCount = -1;void handleOtherStuff() { if (count != lastCount) { Serial.print("Count "); Serial.println(count); lastCount = count; }}
void loop () { handleOtherStuff();}
void setup () { //Start up the serial port Serial.begin(9600); Serial.println(F(“Example4")); pinMode (LED, OUTPUT); pinMode (SW, INPUT_PULLUP); PCintPort::attachInterrupt(SW,
handleSW, CHANGE);}
![Page 17: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/17.jpg)
What we have learned
• We can monitor any pin and have it generate an interrupt
• Different pins can have different ISRs
![Page 18: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/18.jpg)
Example 6#include <avr/sleep.h>#include <PinChangeInt.h>
void wake() { // ISR sleep_disable(); // first thing after waking from sleep: PCintPort::detachInterrupt(SW); // stop LOW interrupt}
void sleepNow(){ set_sleep_mode(SLEEP_MODE_PWR_DOWN); noInterrupts(); // stop interrupts sleep_enable(); // enables sleep bit in MCUCR PCintPort::attachInterrupt(SW, wake, LOW); interrupts(); // allow interrupts sleep_cpu(); // here the device is put to sleep}
![Page 19: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/19.jpg)
Timer Interrupts
• There are three timers on an Uno. Two are 8 bit and one is 16 bit. They can generate an interrupt when they overflow or when they match a set value.
• The frequency at which the timers increment is programmable
• Arduino uses the timers for PWM and for timing (delay(), millis(), micros())
![Page 20: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/20.jpg)
Timers
• Timer0 – 8 bit – controls PWM on pins 5 and 6. Also controls millis()
• Timer1 – 16 bit – controls PWM on pins 9 and 10.
• Timer2 – 8 bit – controls PWM on pins 11 and 3.
![Page 21: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/21.jpg)
Example 7#include <TimerOne.h>const byte LED = 13;
void handleOtherStuff() { delay(250);}
unsigned int led = LOW;void timerISR(){ digitalWrite(LED, led); led ^= (HIGH^LOW);}
void setup () { pinMode (LED, OUTPUT); Timer1.initialize(); // breaks analogWrite() for digital pins 9 and 10 Timer1.attachInterrupt(timerISR, 500000); // attaches timerISR() as a timer overflow interrupt --
blinks at 1 Hz}
void loop () { handleOtherStuff();}
http://playground.arduino.cc/Code/Timer1http://code.google.com/p/arduino-timerone
![Page 22: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/22.jpg)
What have we learned
• The fundamental Arduino code uses each of the timers.
• We can sacrifice some functionality and use them for our own purposes.
• The timers are very complex (pages 94-165 in the datasheet). They can be used for lots of cool things.
![Page 23: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/23.jpg)
Watchdog Timer
• The watchdog timer is a separate timer.
• A selectable timeout is programmable (15ms, 30ms, 60ms, 120ms, 250ms, 500ms, 1s, 2s, 4s, 8s) Times are approx.
• If the SW does not reset the WDT (kick the dog) within the timeout period, an interrupt or a reset (or both) occur.
![Page 24: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/24.jpg)
Example 8#include <avr/wdt.h>const byte LED = 13;uint8_t led = LOW;ISR (WDT_vect) { wdt_setup(WDTO_500MS); digitalWrite(LED, led); led ^= (HIGH^LOW);}void setup () { // configure the pins pinMode (LED, OUTPUT);
noInterrupts(); wdt_setup(WDTO_500MS); interrupts();}void loop () { delay(250);}
void wdt_setup(uint8_t duration){ // interrupts should be disabled wdt_reset(); // kick the dog WDTCSR = (1<<WDCE) |(1<<WDE) |(1<<WDIF); WDTCSR = (0<< WDE)|(1<<WDIE) |(duration&0x7) |((duration&0x8)<<2);}
![Page 25: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/25.jpg)
Resources
• Interrupts
• http://www.gammon.com.au/forum/?id=11488
• Timers
• http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106
![Page 26: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/26.jpg)
Q/A
• Questions?
![Page 27: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/27.jpg)
Notes
• All examples were compiled using arduino 1.0.5 and run on an Arduino Uno R3
![Page 28: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/28.jpg)
#if defined(__AVR_ATtiny45__) #error "__AVR_ATtiny45"#elif defined(__AVR_ATtiny84__) #error "__AVR_ATtiny84"#elif defined(__AVR_ATtiny85__) #error "__AVR_ATtiny85"#elif defined (__AVR_ATtiny2313__) #error "__AVR_ATtiny2313"#elif defined (__AVR_ATtiny2313A__) #error "__AVR_ATtiny2313A"#elif defined (__AVR_ATmega48__) #error "__AVR_ATmega48"#elif defined (__AVR_ATmega48A__) #error "__AVR_ATmega48A"#elif defined (__AVR_ATmega48P__) #error "__AVR_ATmega48P"#elif defined (__AVR_ATmega8__) #error "__AVR_ATmega8"#elif defined (__AVR_ATmega8U2__) #error "__AVR_ATmega8U2"#elif defined (__AVR_ATmega88__) #error "__AVR_ATmega88"#elif defined (__AVR_ATmega88A__) #error "__AVR_ATmega88A"#elif defined (__AVR_ATmega88P__) #error "__AVR_ATmega88P"#elif defined (__AVR_ATmega88PA__) #error "__AVR_ATmega88PA"#elif defined (__AVR_ATmega16__) #error "__AVR_ATmega16"#elif defined (__AVR_ATmega168__) #error "__AVR_ATmega168"#elif defined (__AVR_ATmega168A__) #error "__AVR_ATmega168A"#elif defined (__AVR_ATmega168P__) #error "__AVR_ATmega168P"#elif defined (__AVR_ATmega32__) #error "__AVR_ATmega32"#elif defined (__AVR_ATmega328__) #error "__AVR_ATmega328"#elif defined (__AVR_ATmega328P__) #error "__AVR_ATmega328P"#elif defined (__AVR_ATmega32U2__) #error "__AVR_ATmega32U2"#elif defined (__AVR_ATmega32U4__) #error "__AVR_ATmega32U4"#elif defined (__AVR_ATmega32U6__) #error "__AVR_ATmega32U6"#elif defined (__AVR_ATmega128__) #error "__AVR_ATmega128"#elif defined (__AVR_ATmega1280__) #error "__AVR_ATmega1280"#elif defined (__AVR_ATmega2560__) #error "__AVR_ATmega2560"#else #error "Unknown processor"#endif
![Page 29: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/29.jpg)
Arduino main()• #include <Arduino.h>
• int main(void)• {• init();
• #if defined(USBCON)• USBDevice.attach();• #endif
• setup();
• for (;;) {• loop();• if (serialEventRun) serialEventRun();• }
• return 0;• }
![Page 30: Arduino Interrupts Paul MacDougal September 8, 2014.](https://reader035.fdocuments.in/reader035/viewer/2022062421/56649d6f5503460f94a5031c/html5/thumbnails/30.jpg)
ISR(INT0_vect) { 2e8: 1f 92 push r1 2ea: 0f 92 push r0 2ec: 0f b6 in r0, 0x3f ; 63 2ee: 0f 92 push r0 2f0: 11 24 eor r1, r1 2f2: 2f 93 push r18 2f4: 3f 93 push r19 2f6: 4f 93 push r20 2f8: 5f 93 push r21 2fa: 6f 93 push r22 2fc: 7f 93 push r23 2fe: 8f 93 push r24 300: 9f 93 push r25 302: af 93 push r26 304: bf 93 push r27 306: ef 93 push r30 308: ff 93 push r31 30a: 80 91 13 01 lds r24, 0x0113 30e: 90 91 14 01 lds r25, 0x0114 312: 89 2b or r24, r25 314: 29 f0 breq .+10 ; 0x320 <__vector_1+0x38> 316: e0 91 13 01 lds r30, 0x0113 31a: f0 91 14 01 lds r31, 0x0114 31e: 09 95 icall 320: ff 91 pop r31 322: ef 91 pop r30 324: bf 91 pop r27 326: af 91 pop r26 328: 9f 91 pop r25 32a: 8f 91 pop r24 32c: 7f 91 pop r23 32e: 6f 91 pop r22 330: 5f 91 pop r21 332: 4f 91 pop r20 334: 3f 91 pop r19 336: 2f 91 pop r18 338: 0f 90 pop r0 33a: 0f be out 0x3f, r0 ; 63 33c: 0f 90 pop r0 33e: 1f 90 pop r1 340: 18 95 reti