by

Introduction to Arduino Interrupts and the ATmega328 Analog Comparator

Interrupts are exactly what they sound like. They are events that cause a microcontroller’s CPU to stop executing a main program in order to execute a snippet of code on the side. As an example, here I discuss how the analog comparator on the ATmega328 (Arduino Uno) can be configured to generate an interrupt. Let me first show you the code then I will tell you what it does.

void setup()
{
pinMode(7,INPUT);
Serial.begin(9600);
ACSR = B01011010; // comparator interrupt enabled and tripped on falling edge.
}

void loop()
{
}

ISR(ANALOG_COMP_vect)
{
Serial.println("Interrupt Executed!")
}

Now for the explanation. The 8-bit ACSR register (Analog Comparator Control and Status Register) has the following bit structure.

ACSR – [ACD, ACBG, ACO, ACI, ACIE, ACIC, ACIS1, ACIS0]

I won’t explain what all of these bits do, only the ones I am setting in the code. First, seting the ACBG (Analog Comparator Bandgap Select) bit to one tells the ATmega328 to apply its own internal bandgap voltage (about 1.1V) to the positive input of the comparator. The negative input is analog pin 7 on the Arduino. I set the ACI (Analog Comparator Interrupt Flag) bit to one (this clears the interrupt flag) because I am changing other settings and I don’t want these changes to accidently trigger an interrupt. The ACIE (Analog Comparator Interrupt Enable) bit is set so when the analog comparator output changes as specified by the ACISx bits, an interrupt is executed. Setting the ACISx bits to 10 triggers the interrupt on a falling edge occurring at the comparator output. Setting these bits differently will trigger the interrupt on any change of the comparator output (00), or on a rising edge (11).

An aside about how the analog comparator works: The analog comparator output is high if the voltage applied to the positive input is greater then the voltage applied to the negative input. The output is low if the voltage applied to the positive input is less then that applied to the negative input. So, my setup will result in the comparator output going low when the voltage applied to Arduino pin 7 rises above 1.1 V (the bandgap reference voltage applied to the positive input). The falling edge occurring when this happens triggers the interrupt. This allows me to detect analog inputs above 1.1 V on pin 7 and do something when the input is detected. Now back to the explanation of the code above.

When the interrupt is executed, the code contained in the ISR(ANALOG_COMP_vect) function is executed before the CPU returns to the main program. ISR stands for interrupt service request. Here, whenever the interrupt occurs, I am simply printing a message to the serial monitor.

6 Comments


  1. // Reply

    So you could use an external square wave oscillator to trigger the interrupts I’m assuming? As long as you set the comparator up correctly and then your oscillator goes above 1.1 volts?


    1. // Reply

      Yes, that would work. Just curious, what type of use do you have in mind?


  2. // Reply

    A good use for it is period measurement. the microseconds() difference between two isr calls, is the wave period, with about the 8-16 us latency time of the interrupt call.


    1. // Reply

      Carlos,

      If one assumes that all interrupt function calls have the same latency then I don’t think you would have to take this latency into account when figuring out the period. Both the start and stop time would have this latency built into it. What do you think?


  3. // Reply

    I see this is an older posting, so I hope it is still active. Your sample is for pin 7 . What exactly tells the chip which pin the interrupt should respond to? Can it be assigned to another pin, and then back when multiple inputs are used? If so, how?
    Great information. I appreciate it.


Leave a Reply

Your email address will not be published. Required fields are marked *