I am trying to find some information on how to use the analog comparator on an Atmega328 to detect when an analog pin has reached a certain voltage (3.16 volts).

I cannot find any example code that says how to do this, although I have read that the analog comparator can compare the voltage on an analog pin with the voltage output by a PWM pin. I do not understand how this would work as the PWM pins do not output an analog voltage, but a pulse width modulated square wave. Is it possible to use the comparator to compare with a certain voltage this way?

I have tried polling with analogRead(), but it is too slow for my application.

  • 1
    I have read that the analog comparator can compare the voltage on an analog pin with the voltage output by a PWM pin - do you really need to vary the reference voltage, or is 3.16V what you want? The analog output pins do not output analog voltages (they are not DAC), they are PWM output.
    – Nick Gammon
    Commented Apr 26, 2016 at 4:40
  • Alternatively, you could check the ADC voltage every now and then, to see if it's above 3.16V
    – aaa
    Commented Apr 26, 2016 at 9:49
  • @Paul: I tried that, but it is too slow for my needs.
    – 3871968
    Commented Apr 26, 2016 at 15:04
  • @jBot-42 it can be usefull to state timing requirements in your questions, or the things you've tried yourself (:
    – aaa
    Commented Apr 26, 2016 at 15:06
  • This works fine to enable comparator mode, but I can't seem to restore normal ADC operation after using comparator mode. Joe
    – Joe
    Commented Mar 25, 2018 at 11:46

2 Answers 2


I have a page about the analog comparator that has code:

volatile boolean triggered;

  triggered = true;

void setup ()
  Serial.begin (115200);
  Serial.println ("Started.");
  ADCSRB = 0;           // (Disable) ACME: Analog Comparator Multiplexer Enable
  ACSR =  bit (ACI)     // (Clear) Analog Comparator Interrupt Flag
        | bit (ACIE)    // Analog Comparator Interrupt Enable
        | bit (ACIS1);  // ACIS1, ACIS0: Analog Comparator Interrupt Mode Select (trigger on falling edge)
   }  // end of setup

void loop ()
  if (triggered)
    Serial.println ("Triggered!"); 
    triggered = false;

  }  // end of loop

This is for a fixed reference voltage, for example:

Reference voltage

  • 1
    I might be missing something, but in this diagram won't the voltage on AIN1 always be lower than that on AIN0 ?
    – kellogs
    Commented Oct 18, 2017 at 22:02
  • 1
    Er, yes, my example resistances were not well chosen. Probably AIN1 should have a voltage divider more in the middle range (eg. 4.7k and 4.7k making AIN1 = 2.5V which the LDR would be above in one situation, and below in another.
    – Nick Gammon
    Commented Oct 19, 2017 at 3:46

You need a low-pass filter between the PWM output and the comparator input. This will allow you to produce an analog voltage from the PWM output, which can the be used as a reference voltage for the comparator.

Typically, a simple RC LPF is sufficient. Choose a large time constant relative to your PWM frequency (the Arduino defaults to 490Hz) so that you don't have ripple in your reference voltage.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.