Arduino which is based on ATmega328p microcontroller has built-in analog comparator which can be used for different application. In order to use the Arduino Analog Comparator we must understand how it
works, what it can do and what registers are needed to be configured in
order to use it. In this arduino tutorial it is shown with example program code how one can configure and use arduino analog comparator to compare two external signal magnitude and turn on/off a LED according to the comparator result.
Arduino Analog Comparator Block Diagram
Below is block diagram of Analog Comparator of Arduino taken from ATmega328p Datasheet.
The AIN0(PD6) and AIN1(PD7) pins are the two inputs for the comparator. The AIN0 is positive input and the AIN1 is the negative input. We can fed external signals into these two inputs and compare their magnitude. If the input to the AIN0 is higher than AIN1 then the output of the comparator ACO(in ACSR register) is high otherwise low. Using the output we can take further action. We can also have different sources for the two inputs AIN0 and AIN1. For the positive input AIN0 we can configure the microcontroller to use internal reference bandgap voltage. For the negative input AIN1 we can configure to use any of the 8 analog inputs(A0 to A7). Furthermore we can use the output of the comparator to trigger the input capture feature of Timer/Counter1.
Important Registers for Analog Comparator
There are 5 registers which are important in relation to using Analog Comparator. These are:
1. ACSR – Analog Comparator Control and Status Register
2. DIDR1 – Digital Input Disable Register 1
3.ADCSRB – ADC Control and Status RegisterB
4. ADCSRA – ADC Control and Status Register A
5. ADMUX – ADC Multiplexer Selection Register
Not all of these registers needs to configured. It depends upon one's application. We can divide which registers are required depending upon the sources of inputs for the AIN0 and AIN1.
a. Normal operation
In this type of operation of analog comparator, the signals are fed from external source into the AIN1 and AIN0 pins. In this type of operation, only the ACSR and DIDR1 are used.
b. Different source for AIN0 and AIN1
We can apply different sources to the AIN0 and AIN1 inputs of the comparator. For positive AIN0 input, we can use bandgap reference voltage input to the AIN0. For negative AIN1 we can apply one of the 8 analog inputs. For this cases, we may need to configure all of the 5 registers or just 3 depending upon application.
i) If bandgap reference voltage is to be used then ACSR is required. ACSR is also required to monitor the analog comparator output flag and enable/disable power and enable/disable analog comparator interrupt.
ii) If external analog input source(A0 to A7) is to be used for negative input AIN1 then ADCSRA, ADCSRB and ADMUX registers are required.
iii) In all cases if we want to save digital input buffer power then the DIDR1 is required.
1. ACSR – Analog Comparator Control and Status Register
The register which is important in configuring the Analog
Comparactor of Arduino is the the ACSR register. This register controls
various aspects of the Analog comparator as well as has flag bits which
can be monitored.
ACSR register:
ACD: This Analog Comparator Disable(ACD) bit is used to turn on/off power to the analog comparator. When this bit is set the analog comparator is disabled which saves power.
ACBG: The ACBG(Analog Comparator Bandgap Select) bit is used to set a fixed bandgap reference voltage instead of the positive input to the Analog Comparator. If it is cleared then an input into the AIN0 +ve pin is used.
ACO: The ACO(Analog Comparator Output) is the output of the Analog Comparator which can be high or low depending upon whether the AIN0 is higher than AIN1 and vice versa.
ACI: The ACI(Analog Comparator Interrupt Flag) indicates the state of the analog comparator interrupt. This bit is set whenever interrupt occurs when interrupt is set. There are different modes of interrupt.
ACIE: The ACIE(Analog Comparator Interrupt Enable) is used to enable the analog comparactor interrupt. In order to use the analog comparator interrupt the I bit in the status register must also be enabled.
ACIC: The ACIC(Analog Comparator Input Capture Enable)
bit is used to enable(set)/disable(clear) the input capture function of
the Timer/Counter 1 that is triggered by the analog comparator output.
ACIS1, ACIS0: These two bits ACIS1 and ACIS0(Analog Comparator Interrupt Mode Select0/1) are used to configure type of comparator interrupt. The different modes of analog comparator using these bits is shown in table below.
2. DIDR1 – Digital Input Disable Register 1
The DIDR1 registers contains the two bits AIN0D and AIN1D which can be set to disable the digital input buffer for those pins. By disabling the digital input buffer for these pins we can save power by reducing the power consumption.
DIDR1 register:
3. ADCSRB – ADC Control and Status Register B
The
ADCSRB contains the ACME bit which controls whether to use or not to
use the analog multiplexed input. If this bit is set and the ADEN in
ADCSRA is cleared(that is ADC is switched off) then the AIN1 negative
input is from one of the 8 analog input. Which of the 8 analog input is
used depends upon the MUX2..0 in the ADMUX register.
ADCSRB Register:
The following table shows how the input AIN1 is selected.
3.ADCSRA – ADC Control and Status Register A
The ADCSRA register contains the ADEN bit which is used to enable or disable the ADC(Analog to Digital Converter). When using analog input(A0..A7) the ADC should be disabled by writing 0 to the ADEN bit.
ADCSRA register:
5. ADMUX – ADC Multiplexer Selection Register
When AIN1 input from analog source is used, which of the analog input from A0 to A7 is to be used is selected using the MUX3:1 bits in the ADMUX register.
ADMUX register:
The following table shows which analog source A0 to A7 is used depending upon the MUX bits used.
Example Program Codes for using Arduino Analog Comparator
Here we provide some examples to illustrate how we can use the Arduino Analog Comparator with C/C++ programming.
Example 1: Using direct external signals on the Analog comparator inputs.
In this example we will simple input signals into the AIN0 and AIN1 inputs and turn on/off a LED according to whether the AIN1 input voltage is higher or lower with respect to AIN0 input voltage. When the AIN1 input voltage is lower than the input voltage at AIN0 then the LED will turn ON and vice versa.
The following is the schematic diagram for wiring Arduino with two 10KOhm POT to the two inputs AIN0 and AIN1.
The program code is as below.
void setup () {
DDRD |= (1<<PD4);
DIDR1 |= (1<<AIN0D) | (1<<AIN1D); // Disable Digital Inputs at AIN0 and AIN1
ADCSRB &= ~(1<<ACME); //Clear ACME bits in ADCSRB to use external input at AIN1 -ve input
ACSR =
(0 << ACD) | // Analog Comparator: Enabled
(0 << ACBG) | // Clear ACBG to use external input to AIN0 +ve input
(0 << ACO) | // Analog Comparator Output: OFF
(1 << ACI) | // Analog Comparator Interrupt Flag: Clear Pending Interrupt by setting the bit
(0 << ACIE) | // Analog Comparator Interrupt: Disabled
(0 << ACIC) | // Analog Comparator Input Capture: Disabled
(0 << ACIS1) | (0 << ACIS0); // Analog Comparator Interrupt Mode: Comparator Interrupt on Output Toggle
}
void loop() {
if (ACSR & (1<<ACO))
PORTD |= (1<<PD4);
else
PORTD &= ~(1<<PD4);
}
In the setup() function we setup the PD4 pin as output for the LED. Then we disable the digital buffer for the AIN0 and AIN1 pins. We have to clear the ACME bit in the ADCSRB register in order to use the external input source to the AIN0 pin. Then for setup we have to configure the ACSR register. We enable the Analog comparator by clearing the ACD bit, the ACBG bit is cleared in order to configure the comparator to use the external input at the AIN0 pin. The analog comparator output is configured off by clearing the ACO bit. The ACI bit is set to clear any pending interrupt. The analog comparator interrupt is disabled by clearing the ACIE bit. The Analog Comparator Input Capture is disabled by clearing the ACIC bit. Finally the ACIS0 and ACIS1 bits are cleared to configure the interrupt mode as toggle output mode(this has no effect since the interrupt is already disabled).
In the main() function we periodically check the ACO bit in the ACSR register. If it is high then it means the AIN1 input is lower than the AIN0 input in which case we turn on the LED. Otherwise we turn off the LED.
Video Demonstration:
In the next example we show how to use one of the analog input(A1) as the negative input for the analog comparator of Arduino. For this see Using Analog Input as Analog Comparator Input of Arduino.