Arduino Comparator Tutorial with Example

In this short guide, we will discuss Arduino’s analog comparator. This will include a brief introduction to the analog comparator including its registers. Then, we will demonstrate these concepts with the help of an Arduino sketch that toggles an LED.

Arduino Comparator

Arduino Comparator Introduction

The ATmega328P chip is used to operate the Arduino UNO board. This chip features an analog comparator module that is used to compare the input voltages at the positive pin AIN0 and the negative pin AIN0. The output of the comparator, ACO, is set when the voltage reading at the positive pin is higher than the voltage reading at the negative pin. This output can then be used to trigger an interrupt including the Timer/Counter1 input capture function or a separate interrupt (triggered at output rise, fall, toggle).

The block diagram below shows the analog comparator found in ATmega328P:

Block Diagram of Arduino Analog Comparator

Note: Pins AIN0 and AIN1 are connected externally with Arduino UNO digital pins 6 and 7.

Analog Comparator Registers

The analog comparator is managed by the ACSR register as shown below. All the bits except bit 5 (read only) are readable and writable in case of ACSR which is the analog comparator and status register.

The ACSR register is primarily responsible for controlling the analog comparator.

Bit ACD may be used to turn off the comparator, while bit ACBG can be used to link the bandgap reference to the comparator (A +). The bits ACIE and ACIC control whether the interrupt or input capture is enabled.

Bit76543210
0x30 (0x50)ACDACBGACOACIACIEACICACIS1ACIS0ACSR
Read/WriteR/WR/WRR/WR/WR/WR/WR/W
Initial Value00NA00000
ACSR-Analog Comparator Control and Status Register

If the bit ACME in register ADCSRB is set to 1, the comparator is shifted to AIN1 (A-). When ACME is set in ADCSRB and ADEN in ACSRA, the results are the same. Depending on the assignment of the MUX bits, if ACME is set and ADEN is reset, an ADC channel is moved to the comparator.

Bit76543210
(0x7B)ACMEADTS2ADTS1ADTS0ADCSRB
Read/WriteRR/WRRRR/WR/WR/W
Initial Value00000000
ADCSRB-ADC Control and Status Register B

Set the bits ACIS1 and ACIS0 as shown in the table below for comparator interrupt configuration.

ACIS1ACIS0Mode
00Comparator Interrupt at level change on ACO
01Reserved
10Comparator Interrupt at falling edge on ACO
11Comparator Interrupt at rising edge on ACO
ACIS1/ACIS0 Settings for Interrupt Configuration

Arduino Comparator Example Sketch

Open your Arduino IDE and go to File > New to open a new file. Copy the code given below in that file.

This sketch shows how the analog comparator triggers an interrupt according to the output ACO which in return toggles the onboard LED of Arduino.

// Definition of interrupt names
#include <avr/io.h>
// ISR interrupt service routine
#include <avr/interrupt.h>
const int pLED = 13; // LED at Pin13
const int pAIN1 = 7; // AIN1 at Pin7
volatile boolean iflag = true;
int idx;

// Install the interrupt routine for ACOMP
ISR(ANALOG_COMP_vect)
{
if ( ACSR & (1<<ACO) ) // ACO is set?
{
iflag = false;
digitalWrite(pLED, HIGH);
}
else
{
iflag = true;
digitalWrite(pLED, LOW);
}
}
void setup()
{
Serial.begin(9600);
pinMode(pLED, OUTPUT);
digitalWrite(pLED, LOW);
pinMode(pAIN1, INPUT);
cli();
ADCSRA &= ~(1<<ADEN); // ADC disabled
ADCSRB |= ~(1<<ACME); // AMUX enabled
ACSR = (1<<ACBG) | (1<<ACIE); // ACOMP Interrupt enabled
DIDR1 = (1<<AIN1D) | (1<< AIN0D);
sei();
Serial.print("ADCSRA: "); Serial.println(ADCSRA, HEX);
Serial.print("ADCSRB: "); Serial.println(ADCSRB, HEX);
Serial.print("ACSR: "); Serial.println(ACSR, HEX);
Serial.print("DIDR1: "); Serial.println(DIDR1, HEX);
Serial.println("Setup finished.");
}
void loop()
{
if (iflag) 
Serial.println(idx); // iflag controls serial output
idx++;
delay(500);
}

How the Code Works?

Firstly, include the definition of the interrupt names and the ISR interrupt service routine.

#include <avr/io.h>
#include <avr/interrupt.h>

Create two variables. ‘pLED’ to hold the Arduino pin connected with the onboard LED and ‘idx’ will be incremented inside the main program.

const int pLED = 13;
int idx;

‘pAIN1’ variable holds the Arduino digital pin 7 connected with AIN1.

const int pAIN1 = 7;

Create a volatile boolean variable called ‘iflag’ that will be set while toggling the LED. Initially, it is set to ‘true.’

volatile boolean iflag = true;

This is the interrupt service routine for the analog comparator.

ISR(ANALOG_COMP_vect)
{
if ( ACSR & (1<<ACO) ) // ACO is set?
{
iflag = false;
digitalWrite(pLED, HIGH);
}
else
{
iflag = true;
digitalWrite(pLED, LOW);
}
}

Inside the setup() function, open the serial communication at the set baud rate. Configure the led pin as an output pin and set its value to LOW. Moreover, we will configure the AIN1 pin as an input pin. Then, we disable the ADC and enable the AMUX. The analog comparator interrupt is enabled. The ADCSRA, ADCSRB, ACSR, DIDR1 values are printed in the serial monitor.

void setup()
{
Serial.begin(9600);
pinMode(pLED, OUTPUT);
digitalWrite(pLED, LOW);
pinMode(pAIN1, INPUT);
cli();
ADCSRA &= ~(1<<ADEN); // ADC disabled
ADCSRB |= ~(1<<ACME); // AMUX enabled
ACSR = (1<<ACBG) | (1<<ACIE); // ACOMP Interrupt enabled
DIDR1 = (1<<AIN1D) | (1<< AIN0D);
sei();
Serial.print("ADCSRA: "); Serial.println(ADCSRA, HEX);
Serial.print("ADCSRB: "); Serial.println(ADCSRB, HEX);
Serial.print("ACSR: "); Serial.println(ACSR, HEX);
Serial.print("DIDR1: "); Serial.println(DIDR1, HEX);
Serial.println("Setup finished.");
}

Inside the loop() function, we increment the variable ‘idx.’

void loop()
{
if (iflag) 
Serial.println(idx); // iflag controls serial output
idx++;
delay(500);
}

Demonstration

To see the demonstration of the above code, upload the code to Arduino. But, before uploading code, make sure to select the Arduino board from Tools > Board and also select the correct COM port to which the Arduino board is connected from Tools > Port.

select Arduino uno

Once the code is uploaded to Arduino, open your serial monitor and set its baud rate.

Arduino Analog Comparator Serial Monitor demo

You may also like to read:

Leave a Comment