Interaction Design WikiElectrical Engineering

Interrupt Service Routine (en)

Interrupt Service Routine (DE version)

An Interrupt Service Routine (ISR) is an interruption of the main routine of program, to execute a time-critical task. In the case of the Arduino, this means that the loop() can be interrupted for a something more important. This interruption is usually triggered by a digital input. The use of an ISR is helpful when measuring speed or for reading out rotary encoders - i.e. whenever inputs have to be processed very quickly.

We use the function attachInterrupt(INTERRUPT, ISR, MODE) in setup() to "listen" to a PIN for an event. The Arduino UNO has two interrupt pins (D2 = INTERRUPT 0, D3 = INTERRUPT 1). The ISR parameter designates the function that is to be called when the interrupt is triggered. As a rule, we only do simple routines in this function. For example, it is not recommended to use the serial interface because sending data takes too long. We also use so-called volatile variables within the ISR. These variables are marked as volatile because they can change at any time. Finally, the mode specifies when the ISR is to be executed. There are three modes: RISING, FALLING or CHANGE. RISING means that the interrupt is set from LOW to HIGH. FALLING means that the interrupt is set from HIGH to LOW and CHANGE is executed on both events.

Rotary Encoder

Below is an example reading a rotary encoder with the Arduino. We use the EC12 from ALPS (data sheet).


Interrupt Example Expand source
#define ENCODER_A 2
#define ENCODER_B 4
volatile int encoderValue = 0;
volatile int oldEncoderReading = 0;
int oldEncoderValue = 0;
void setup()
{
  Serial.begin(9600);
  pinMode(ENCODER_A, INPUT_PULLUP);
  pinMode(ENCODER_B, INPUT_PULLUP);
  attachInterrupt(0, readEncoder, CHANGE);
}
void loop()
{
  if (encoderValue != oldEncoderValue)
  {
    Serial.print("ENCODER: ");
    Serial.println (encoderValue, DEC);
    oldEncoderValue = encoderValue;
  }
}

void readEncoder()
{
  int currReading = digitalRead(ENCODER_A);
  if (oldEncoderReading == LOW && currReading == HIGH)
  {
    if (digitalRead(ENCODER_B) == LOW)
    {
      encoderValue++;
    }
    else
    {
      encoderValue--;
    }
  }
  oldEncoderReading = currReading;
  delayMicroseconds(500);
}


Further Information:

attachInterrupt() - Arduino.cc

Interrupts - from Nick Gammon