Master Arduino Interrupts

Master Arduino Interrupts

In this chapter, you’ll learn about using Arduino Interrupts to manage time-sensitive tasks. Functions such as attachInterrupt(), detachInterrupt(), interrupts(), and noInterrupts() will be covered in detail, providing you with the knowledge needed to trigger specific actions based on external or internal events.

Syntax Table: Arduino Interrupts

Topic Syntax Simple Example
attachInterrupt() attachInterrupt(digitalPinToInterrupt(pin), ISR, mode); attachInterrupt(digitalPinToInterrupt(2), toggleLED, RISING);
detachInterrupt() detachInterrupt(digitalPinToInterrupt(pin)); detachInterrupt(digitalPinToInterrupt(2));
digitalPinToInterrupt() digitalPinToInterrupt(pin); digitalPinToInterrupt(2);
interrupts() interrupts(); interrupts();
noInterrupts() noInterrupts(); noInterrupts();

 

attachInterrupt() – Attach an External Interrupt in Arduino

 attachInterrupt() is an Arduino function that allows you to assign an interrupt service routine (ISR) to an external event. Interrupts are used to detect events, such as a button press or sensor input, and trigger a specific function immediately, even if the Arduino is busy with other tasks. By using interrupts, you can make your Arduino respond instantly to real-time events without continuously checking the state of pins in the main loop.

Use purpose
The attachInterrupt() function is typically used for:

  • Responding to external events: Detecting real-time events like button presses, sensor changes, or communication signals.
  • Handling time-sensitive tasks: Ensuring immediate reaction to critical inputs, such as handling motor encoders or counting pulses.
  • Efficient processing: Reducing the need to constantly monitor pins, as the interrupt can trigger a function only when needed.

Arduino Syntax use
attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);

Arduino Syntax Explanation

  • digitalPinToInterrupt(pin): Converts the digital pin number to the interrupt number. Most Arduinos use pin 2 and pin 3 for external interrupts.
  • ISR: The Interrupt Service Routine is the name of the function to be called when the interrupt occurs. This function must return void and cannot take any parameters.
  • mode: Defines when the interrupt should trigger. The options are:
    • LOW: Triggers the ISR whenever the pin is low.
    • CHANGE: Triggers the ISR whenever the pin changes from HIGH to LOW or from LOW to HIGH.
    • RISING: Triggers the ISR when the pin goes from LOW to HIGH.
    • FALLING: Triggers the ISR when the pin goes from HIGH to LOW.

Arduino code Example

int ledPin = 13; // Pin connected to an LED
volatile bool state = LOW; // Variable to track LED state
void setup() {
  pinMode(ledPin, OUTPUT); // Set pin 13 as output
  attachInterrupt(digitalPinToInterrupt(2), toggleLED, RISING); 
}
void loop() {
  digitalWrite(ledPin, state); // Set LED based on the interrupt-triggered state
}
void toggleLED() {
  state = !state; // Toggle the LED state whenever interrupt occurs
}

Code Explanation

  • pinMode(ledPin, OUTPUT);: Sets pin 13 as an output to control the LED.
  • attachInterrupt(digitalPinToInterrupt(2), toggleLED, RISING);: Attaches an interrupt to pin 2, which triggers the toggleLED() function when a RISING edge (LOW to HIGH) is detected.
  • toggleLED(): This function is triggered by the interrupt and toggles the state of the LED (turns it on or off).
  • volatile bool state: A volatile variable is used to ensure that the value of state can change inside the interrupt function and reflect accurately in the main program.

Notes

  • Interrupts should be used for time-sensitive tasks where quick reaction is essential, such as detecting fast pulses or changes in input signals.
  • The ISR (Interrupt Service Routine) should be short and fast. Avoid using functions like delay(), Serial.print(), or other lengthy operations inside the ISR.
  • Only certain pins on Arduino support interrupts, and these vary by board. For instance, the Arduino Uno and Nano support interrupts on pins 2 and 3.
  • detachInterrupt() can be used to disable an interrupt by calling it with the interrupt number.

detachInterrupt() – Detach an External Interrupt in Arduino

 detachInterrupt() is an Arduino function used to disable or detach an external interrupt from a pin that was previously set up using the attachInterrupt() function. Once an interrupt is detached, the associated Interrupt Service Routine (ISR) will no longer be triggered, allowing you to stop the Arduino from responding to that external event. This function is useful for cases where you want to temporarily or permanently stop responding to an interrupt.

Use purpose
The detachInterrupt() function is used for:

  • Disabling an interrupt: Stops the Arduino from reacting to external events on a specific pin.
  • Controlling when interrupts are active: Used when you need to enable or disable interrupts dynamically in the program.
  • Managing interrupt-sensitive tasks: Ideal for temporarily disabling interrupts during critical sections of the code.

Arduino Syntax use
detachInterrupt(interruptNumber);

Arduino Syntax Explanation

  • interruptNumber: The interrupt number corresponding to the pin where the interrupt was attached. This is usually determined by the digitalPinToInterrupt(pin) function.

Arduino code Example

int ledPin = 13; // Pin connected to an LED
volatile bool state = LOW; // Variable to track LED state
void setup() {
  pinMode(ledPin, OUTPUT); // Set pin 13 as output
  attachInterrupt(digitalPinToInterrupt(2), toggleLED, RISING); 
  delay(5000); // Wait for 5 seconds
  detachInterrupt(digitalPinToInterrupt(2)); // Detach the interrupt after 5 seconds
}
void loop() {
  digitalWrite(ledPin, state); // Set LED based on the interrupt-triggered state
}
void toggleLED() {
  state = !state; // Toggle the LED state when the interrupt occurs
}

Code Explanation

  • pinMode(ledPin, OUTPUT);: Configures pin 13 as an output to control the LED.
  • attachInterrupt(digitalPinToInterrupt(2), toggleLED, RISING);: Attaches an interrupt to pin 2, which triggers the toggleLED() function when a RISING edge (LOW to HIGH) is detected.
  • detachInterrupt(digitalPinToInterrupt(2));: After a 5-second delay, this function disables the interrupt on pin 2, stopping the Arduino from responding to further events on this pin.
  • toggleLED(): This function toggles the state of the LED whenever the interrupt is triggered.

Notes

  • detachInterrupt() is used to disable an interrupt. This can be useful in situations where you only want the Arduino to respond to an event for a limited time.
  • attachInterrupt() and detachInterrupt() work together to manage when the Arduino responds to external signals on specific pins.
  • Not all pins support external interrupts, so check which pins are capable of interrupt handling on your specific Arduino board. On most boards like the Arduino Uno, pins 2 and 3 support interrupts.
  • To re-enable the interrupt after it has been detached, use attachInterrupt() again.

digitalPinToInterrupt() – Get Interrupt Number for a Pin in Arduino

digitalPinToInterrupt() is a function in Arduino that converts a digital pin number to the corresponding interrupt number. This function is crucial when working with attachInterrupt() and detachInterrupt(), as it allows you to associate a specific pin with an external interrupt. Not all Arduino pins can be used for interrupts, and this function helps you find the correct interrupt number for a supported pin.

Use purpose
The digitalPinToInterrupt() function is used for:

  • Attaching interrupts: It allows you to correctly specify the pin when using attachInterrupt() to enable an interrupt.
  • Detaching interrupts: It provides the correct interrupt number to use with detachInterrupt() when you want to disable an interrupt.
  • Managing interrupts programmatically: Ensures that the right pin is used for interrupt handling.

Arduino Syntax use
digitalPinToInterrupt(pin);

Arduino Syntax Explanation

  • pin: The digital pin number you want to convert to its corresponding interrupt number. This pin must support external interrupts.

Arduino code Example

int ledPin = 13; // Pin connected to an LED
volatile bool state = LOW; // Variable to track LED state
void setup() {
  pinMode(ledPin, OUTPUT); // Set pin 13 as output
  attachInterrupt(digitalPinToInterrupt(2), toggleLED, RISING); 
}
void loop() {
  digitalWrite(ledPin, state); // Control the LED based on the interrupt
}
void toggleLED() {
  state = !state; // Toggle the LED state when interrupt is triggered
}

Code Explanation

  • pinMode(ledPin, OUTPUT);: Configures pin 13 as an output to control the LED.
  • attachInterrupt(digitalPinToInterrupt(2), toggleLED, RISING);: Uses digitalPinToInterrupt(2) to get the correct interrupt number for pin 2. This sets up an interrupt that triggers the toggleLED() function when a RISING edge (LOW to HIGH) is detected on pin 2.
  • toggleLED(): This function toggles the state of the LED each time the interrupt is triggered.

Notes

  • digitalPinToInterrupt() ensures that you are using the correct interrupt number for a pin when working with interrupts. This is important because attachInterrupt() and detachInterrupt() require the interrupt number, not the pin number.
  • Not all Arduino pins support interrupts. For example, on the Arduino Uno, only pin 2 and pin 3 can be used for external interrupts. Other boards may support more pins, so check your board’s documentation.
  • When using attachInterrupt() or detachInterrupt(), always use digitalPinToInterrupt() to avoid confusion between pin numbers and interrupt numbers.

interrupts() – Enable Interrupts in Arduino

interrupts() is an Arduino function used to enable global interrupts. Interrupts are disabled by default when the microcontroller is reset, or when the noInterrupts() function is called. The interrupts() function re-enables them, allowing the microcontroller to respond to external and internal interrupt events. Interrupts are essential for handling time-sensitive tasks like monitoring sensors or communication protocols without continuously polling in the main program.

Use purpose
The interrupts() function is used for:

  • Re-enabling global interrupts: After calling noInterrupts(), use interrupts() to allow the microcontroller to respond to interrupt events again.
  • Managing critical sections: Temporarily disabling and enabling interrupts ensures that certain parts of the code are executed without interruption, while still allowing the use of interrupts when necessary.
  • Optimizing performance: Ensures that the system can handle external events without constantly polling pins or signals.

Arduino Syntax use
interrupts();

Arduino Syntax Explanation

  • interrupts(): This function re-enables all globally disabled interrupts, allowing them to function again.

Arduino code Example

int ledPin = 13; // Pin connected to an LED
volatile bool state = LOW; // Variable to track LED state
void setup() {
  pinMode(ledPin, OUTPUT);  // Set pin 13 as output
  attachInterrupt(digitalPinToInterrupt(2), toggleLED, RISING); 
}
void loop() {
  noInterrupts();             // Disable interrupts temporarily
  digitalWrite(ledPin, state); // Control the LED
  interrupts();               // Re-enable interrupts
}
void toggleLED() {
  state = !state; // Toggle the LED state whenever interrupt is triggered
}

Code Explanation

  • pinMode(ledPin, OUTPUT);: Configures pin 13 as an output to control the LED.
  • attachInterrupt(digitalPinToInterrupt(2), toggleLED, RISING);: Attaches an interrupt to pin 2, using digitalPinToInterrupt() to get the correct interrupt number. The interrupt triggers on a RISING edge (LOW to HIGH).
  • noInterrupts();: Temporarily disables all interrupts, preventing any external or internal events from interrupting the code in the loop.
  • digitalWrite(ledPin, state);: Sets the LED state based on the current value of state.
  • interrupts();: Re-enables all interrupts, allowing the system to respond to new events.
  • toggleLED(): This function toggles the state of the LED when the interrupt is triggered.

Notes

  • interrupts() re-enables global interrupts after they have been disabled using noInterrupts().
  • Use noInterrupts() and interrupts() with caution, as disabling interrupts for too long can cause the Arduino to miss critical events, such as timing-sensitive signals from sensors or communication devices.
  • Avoid placing time-consuming code inside the critical sections where interrupts are disabled. Keep these sections as short as possible to minimize the impact on the system’s ability to handle interrupts.
  • Interrupts are automatically enabled at the start of the Arduino program unless explicitly disabled with noInterrupts().

noInterrupts() – Disable Interrupts in Arduino

noInterrupts() is an Arduino function used to disable global interrupts, preventing the microcontroller from responding to any interrupt events. When interrupts are disabled, the processor will not handle any external or internal interrupts until they are re-enabled using the interrupts() function. This function is typically used when you need to ensure that a specific portion of code runs without being interrupted, such as when managing critical data or hardware operations.

Use purpose
The noInterrupts() function is used for:

  • Disabling all interrupts: Prevents the Arduino from responding to interrupts while performing critical tasks.
  • Managing critical sections: Ensures that time-sensitive or atomic code is executed without being interrupted, which can be important for ensuring data consistency.
  • Temporary suspension of interrupt handling: Useful in situations where you need precise control over when interrupts are allowed to occur.

Arduino Syntax use
noInterrupts();

Arduino Syntax Explanation

  • noInterrupts(): Disables all global interrupts, preventing any interrupt service routines (ISR) from being executed.

Arduino code Example

int ledPin = 13; // Pin connected to an LED
volatile bool state = LOW; // Variable to track LED state
void setup() {
  pinMode(ledPin, OUTPUT);  // Set pin 13 as output
  attachInterrupt(digitalPinToInterrupt(2), toggleLED, RISING); 
}
void loop() {
  noInterrupts();              // Disable all interrupts
  digitalWrite(ledPin, state); // Control the LED without being interrupted
  interrupts();                // Re-enable interrupts
}
void toggleLED() {
  state = !state; // Toggle the LED state when the interrupt is triggered
}

Code Explanation

  • pinMode(ledPin, OUTPUT);: Configures pin 13 as an output to control the LED.
  • attachInterrupt(digitalPinToInterrupt(2), toggleLED, RISING);: Attaches an interrupt to pin 2, which triggers the toggleLED() function when a RISING edge (LOW to HIGH) is detected.
  • noInterrupts();: Temporarily disables all interrupts, ensuring that no external or internal interrupts occur while the digitalWrite() operation is running.
  • digitalWrite(ledPin, state);: Writes the current state to the LED without the risk of being interrupted.
  • interrupts();: Re-enables global interrupts, allowing the Arduino to respond to new events.
  • toggleLED(): This function toggles the state of the LED whenever the interrupt is triggered.

Notes

  • noInterrupts() is useful when dealing with critical sections of the code where interrupts could cause inconsistencies, such as when modifying shared variables or controlling hardware.
  • Once noInterrupts() is called, interrupts remain disabled until interrupts() is called to re-enable them. Always ensure that interrupts() is used after noInterrupts() to avoid missing important interrupt events.
  • While interrupts are disabled, the Arduino will not be able to respond to any external or internal interrupt signals, so use this function carefully and only for short periods.
  • Keeping noInterrupts() active for too long can result in missed time-sensitive tasks, such as missing sensor readings or communication signals.

Common Problems and Solutions

  1. Missed Interrupts
    • Problem: Arduino fails to respond to external events.
    • Solution: Ensure the correct pin is used with attachInterrupt() and check that the pin supports interrupts.
  2. Program Crashes During ISR
    • Problem: Using functions like delay() or Serial.print() inside the Interrupt Service Routine (ISR) causes program instability.
    • Solution: Keep the ISR short and avoid using blocking functions such as delay() and Serial.print() inside the ISR.
  3. ISR Not Triggering
    • Problem: The Interrupt Service Routine is not being triggered when expected.
    • Solution: Ensure that the pin is properly configured for the desired event (RISING, FALLING, CHANGE, or LOW).

Chapter Summary

  • attachInterrupt() is used to attach an interrupt to a pin that triggers an ISR when a specific event occurs (e.g., RISING or FALLING edge).
  • detachInterrupt() disables the interrupt on a specific pin.
  • interrupts() and noInterrupts() are used to enable and disable global interrupts, respectively, giving control over when interrupts are handled.
  • Interrupts allow the Arduino to immediately react to time-sensitive events, such as button presses or sensor readings, without constantly polling the pins in the main loop.

FAQ

  1. What is an interrupt in Arduino?
    An interrupt allows Arduino to respond to external or internal events immediately by pausing the current process and executing a specific function (ISR).
  2. How do I attach an interrupt in Arduino?
    Use attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);, where you specify the pin, the ISR function, and the trigger mode (e.g., RISING, FALLING, CHANGE).
  3. What are the limitations of using interrupts?
    Interrupts should not contain blocking functions like delay() or Serial.print(). They should be kept as short as possible to avoid disrupting other parts of your program.

Simple MCQ Questions and Answers

  1. Which function is used to attach an interrupt in Arduino?
    a) detachInterrupt()
    b) attachInterrupt()
    c) digitalPinToInterrupt()
    Answer: b) attachInterrupt()
  2. What is the purpose of noInterrupts() in Arduino?
    a) Disable interrupts
    b) Enable interrupts
    c) Attach an interrupt
    Answer: a) Disable interrupts

Which of the following modes triggers an interrupt when the pin goes from LOW to HIGH?
a) FALLING
b) RISING
c) CHANGE
Answer: b) RISING