Arduino Interrupts I am amazed by how much I learned in preparing for this talk. I would encourage each of you to consider making a presentation, however.

Slides:



Advertisements
Similar presentations
Interrupts, Low Power Modes and Timer A (Chapters 6 & 8)
Advertisements

Lab7: Introduction to Arduino
A look at interrupts What are interrupts and why are they needed.
68HC11 Polling and Interrupts
Interrupts What is an interrupt? What does an interrupt do to the “flow of control” Interrupts used to overlap computation & I/O – Examples would be console.
COMP3221: Microprocessors and Embedded Systems Lecture 15: Interrupts I Lecturer: Hui Wu Session 1, 2005.
A look at interrupts What are interrupts and why are they needed in an embedded system? Equally as important – how are these ideas handled on the Blackfin.
A look at interrupts What are interrupts and why are they needed.
AVR Programming CS-212 Dick Steflik. ATmega328P I/O for our labs To get data into and out of our Arduino its a little trickier than using printf and.
Timers and Interrupts Shivendu Bhushan Summer Camp ‘13.
Arduino Interrupts Paul MacDougal September 8, 2014.
The 8051 Microcontroller and Embedded Systems
INTERRUPTS PROGRAMMING
Timers and Interrupts Shivendu Bhushan Sonu Agarwal.
UNIT 8 Keypad Interface Contact Closure Counter Exceptions (Interrupts and Reset)
MCU: Interrupts and Timers Ganesh Pitchiah. What’s an MCU ?
Khaled A. Al-Utaibi  The Push Button  Interfacing Push Buttons to Arduino  Programming Digital Inputs  Working with “Bouncy”
Introduction to Sensor Technology Week Five Adam Taylor
Sparkfun Electronics ATtiny85 Arduino Quick Reference Sheet
Timers and Interrupts Anurag Dwivedi. Let Us Revise.
1 Interrupts, Resets Today: First Hour: Interrupts –Section 5.2 of Huang’s Textbook –In-class Activity #1 Second Hour: More Interrupts Section 5.2 of Huang’s.
Interrupt On a very basic level, an interrupt is a signal that interrupts the current processor activity. It may be triggered by an external event (change.
CSCI1600: Embedded and Real Time Software Lecture 16: Advanced Programming with I/O Steven Reiss, Fall 2015.
TIMERS AND INTERRUPTS AVI SINGH KEVIN JOSE PIYUSH AWASTHI.
Microcontrollers, Microcomputers, and Microprocessors
EE/CS-352: Embedded Microcontroller Systems Part V The 8051 Assembly Language Interrupts.
WCL 조윤정 Arduino Bootloader 코드 분석. BAUD_RATE 설정 /* set the UART baud rate defaults */ #ifndef BAUD_RATE #if F_CPU >= L #define BAUD_RATE.
CS-280 Dr. Mark L. Hornick 1 Sequential Execution Normally, CPU sequentially executes instructions in a program Subroutine calls are synchronous to the.
Embedded Programming and Robotics Lesson 11 Arduino Interrupts 1.
Microcontroller basics Embedded systems for mortals.
Networked Embedded Systems Pengyu Zhang & Sachin Katti EE107 Spring 2016 Lecture 4 Timers and Interrupts.
Programming in Arduino Materials:Arduino Board Casperelectronics Pre Pres. Notes Photos from workshop?
Atmega328p Introduction for Digital and PWM Output Brion L Fuller II Robotics Club.
INSTITUTE: INSTITUTE:PARUL INSTITUTE OF TECHNOLOGY BRANCH : BRANCH :B.E. E.C.5 TH SEM. SUBJECT:MICROCONTROLLER & INTERFACING TOPIC:AVR INTTRUPT TOPIC:AVR.
DEPARTMENT OF ELECTRONICS ENGINEERING V-SEMESTER MICROPROCESSOR & MICROCONTROLLER 1 CHAPTER NO microcontroller & programming.
Chapter 10 Interrupts. Basic Concepts in Interrupts  An interrupt is a communication process set up in a microprocessor or microcontroller in which:
Timers and Scheduled Interrupts
A walk through interrupts on the PPC 823
Outline Introduction to Arduino UNO Programming environment setup GPIO
Lab 7 Basic 1: Game of Memory
Architectures of Digital Information Systems Part 1: Interrupts and DMA dr.ir. A.C. Verschueren Eindhoven University of Technology Section of Digital.
80C51 Block Diagram ECE Overview.
Embedded Systems Programming Examples and Comparison
Microcontroller basics
68HC11 Interrupts & Resets.
Microprocessor Systems Design I
Microcontroller basics
Timer and Interrupts.
UNIT – Microcontroller.
Computer Architecture
BITS EDU. CAMPUS , VARNAMA
Callback TYWu.
Interrupts, Counter and Timers
AVR Addressing Modes Subject: Microcontoller & Interfacing
BVM Engineering College Electrical Engineering Department : Microprocessor and Microcontroller Interfacing Interrupts of 8051 Prepared by:
The Arduino Microcontroller: Atmel AVR Atmega 328
Timer/Counter Modified from Dr. Lam Phung’s Slides.
* * * * * * * 8051 Interrupts Programming.
CSCI1600: Embedded and Real Time Software
Interrupts, Tasks and Timers
1 Code
CSCI1600: Embedded and Real Time Software
CSCI1600: Embedded and Real Time Software
Embedded System Development Lecture 7 2/21/2007
Wireless Embedded Systems
Digital INPUTS/OUTPUTS and interrupts
CSCI1600: Embedded and Real Time Software
COMP3221: Microprocessors and Embedded Systems
Surjo Dutta and David Friedman
Interrupts.
Presentation transcript:

Arduino Interrupts I am amazed by how much I learned in preparing for this talk. I would encourage each of you to consider making a presentation, however short and simple. You will learn so much while collecting information, formulating your thoughts, and putting it on “paper”. So, tonight’s presentation is on interrupts on the Arduino Uno. Much of what I cover will apply to other versions of Arduino and other microcontrollers. 1

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.

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) External interrupts, pin change interrupts, timer interrupts, I/O interrupts, … 3

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 … We will be looking at examples of these. 4

Basic functions: detachInterrupt(pin) - Turns off the given interrupt. attachInterrupt(pin, ISR, mode) - Turns on the given interrupt by calling ISR function

attachInterrupt(pin, ISR, mode) ; ISR: is the function to be called without brackets Modes: LOW to trigger the interrupt whenever the pin is low, CHANGE to trigger the interrupt whenever the pin changes value RISING to trigger when the pin goes from low to high, FALLING for when the pin goes from high to low.

Interrupt vector is the address of memory location where the interrupt info is located. Pin2 and 3 corresponds to INT0 and INT1. So it is the memory reference where the Arduino processor has to see if the interrupt occured

ISRs should be short and sweet ISRs should be short and sweet. You don't want to derail the main loop for too long! There are no input variables or returned values. All changes have to be made on global variables. 

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(); //initialize digital pin 2 as an input with //the internal pull-up resistor enabled Say we want a program where a pushbutton is used as input. Using good Human/Machine Interface design, we want to acknowledge the input ASAP. We decide to do that by turning off an LED (we could turn on an LED, but that takes a tiny bit more code and I am being frugal). So, let’s start with a simple program that reads a switch and toggles an LED Pin 13 is the onboard LED Pin 2 has a NO momentary switch connected to ground. Note that the internal pullup is enabled. This is how I typically organize my programs. Loop just makes calls to handleFoo routines. We have handleSW that reads pin 2 and writes the result to pin 13 9

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(); Here, we add an additional handler function. We have handleOtherStuff that takes a long time (1/4th of a second in this case) This version feels sluggish and will miss inputs occasionally. One potential solution is to split up handleOtherStuff and call handleSW more times handleSW() handleThis() handleThat() … But that is ugly and still has issues. The shorter the pulse, the more often we have to poll. 10

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(); We remove the call to handleSW from loop() and add it as an ISR for external interrupt 0 using attachInterrupt() On an Arduino Uno, pin 2 is INT0. Other chips differ in the numbering. Pin 3 is INT1. The mode argument to attachInterrupt() can be RISING, FALLING, CHANGE, HIGH, or LOW. So, your code will be looping (and delaying). When the switch pulls pin2 low, the microcontroller hardware generates an interrupt, which interrupts your code, saves the state of the machine, calls handleSW, restores the state of the machine, and resumes your code. The result is much more responsive! It is as if we have two threads, one handling the switch and one handling the other stuff. 11

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(), Serial etc… This one is good: void myISR () { count++; } You can call millis() to record the current time. But, since the millisecond counter is updated by an interrupt, the current time will not increment while you are in an ISR, so you cannot use it do measure elapsed time. Pending interrupts are handled in priority order. Lowest one first. 12

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?

volatile` is a C keyword applied to variables volatile` is a C keyword applied to variables. It means that the value of that variable is not entirely within a program's control. It reflects that the value could change, and the program can't predict.

Example 4 const 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 () { Serial.begin(9600); Serial.println(“Example4"); pinMode (LED, OUTPUT); pinMode (SW, INPUT_PULLUP); attachInterrupt(INT0, handleSW, CHANGE); } Volatile is used to mark variables that may change outside the normal program flow (like in an ISR). The compiler reads the variable from memory each time it uses it rather than saving it in a register. Anything that we share between ISR and loop() should be marked volatile. Each time the switch pin changes, handleSW is called and count is incremented. Before we run the demo, what do you expect to see if the switch is pressed and released three times? Switches bounce. We are getting multiple interrupts from what we think of as one event. 15

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 Library is needed for pin change interrupt ATTinys have INT0, but not INT1. For my rain gauge, I wanted to awaken on either a rain bucket tip or a switch press. I had to use pin change interrupts. 17

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(“Example4"); pinMode (LED, OUTPUT); pinMode (SW, INPUT_PULLUP); PCintPort::attachInterrupt(SW, handleSW, CHANGE); } Using the PinChangeInt library, you can do a simple replacement of what we had before. It is not going to be quite as quick, as the ISR has to handle which pin caused the interrupt. If we look back at slide 3, we can see three pin change interrupts, handling 6, 6, and 8 pins. Note that we really have no idea which pin caused the interrupt or what the pins’ values were when the interrupt was generated 18

What we have learned We can monitor any pin and have it generate an interrupt Different pins can have different ISRs 19

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()) ICP1 is pin 8 21

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.

Example 7 http://playground.arduino.cc/Code/Timer1 #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/Timer1 http://code.google.com/p/arduino-timerone There are several timer libraries available. Some are SW implementations that just look at millis() and do not use interrupts. TimerOne is available on code.google.com You could change 500000 to 13 and get a 38kHz blink rate. I wonder why that might be interesting… There is some confusion on the net about using pins 9 and 10 when you take over timer 1. You can use them as inputs. You can use them as outputs with digitalWrite. You cannot use them as outputs with analogWrite (i.e. PWM). 23

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. For example, you can make a square wave generator with no software required (other than configuring the timer). 24

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. The classic use is to have the system reset if the watchdog timer expires. The SW kicks the dog within loop(). If something happens to the SW and it stops kicking the dog, the system will reset. The normal Arduino bootloader does not kick the dog and it does not disable watchdog timer reset. On reset, the system comes up with the shortest timeout duration. If WDT reset is enabled, the bootloader will not complete and you will suffer and endless loop of resets until you cycle power. The watchdog timer interrupt can be used to awaken a sleeping system. 25

Example 8 Blink the LED at 1Hz using the watchdog interrupt #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(); 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); } Blink the LED at 1Hz using the watchdog interrupt The datasheet says not to set WDIE from within the ISR, but we are going to ignore that The two writes to WDTCSR have to happen within 4 cycles of each other. I had issues with the compiler on my laptop doing all of the shifting and masking between the writes. 26

Resources Interrupts http://www.gammon.com.au/forum/?id=114 88 Timers http://www.avrfreaks.net/index.php?name= PNphpBB2&file=viewtopic&t=50106

Q/A Questions?

Notes All examples were compiled using arduino 1.0.5 and run on an Arduino Uno R3

#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

Arduino main() #include <Arduino.h> int main(void) { init(); #if defined(USBCON) USBDevice.attach(); #endif setup(); for (;;) { loop(); if (serialEventRun) serialEventRun(); } return 0;

Push a bunch of stuff (registers) onto the stack Call the user code 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 This is the code for the ISR handler. The call to your routine is at 0x31e. Push a bunch of stuff (registers) onto the stack Call the user code Pop a bunch of stuff off of the stack 32