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 Apr 26 '16 at 4:40
  • Alternatively, you could check the ADC voltage every now and then, to see if it's above 3.16V – Paul Apr 26 '16 at 9:49
  • @Paul: I tried that, but it is too slow for my needs. – 3871968 Apr 26 '16 at 15:04
  • @jBot-42 it can be usefull to state timing requirements in your questions, or the things you've tried yourself (: – Paul Apr 26 '16 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 Mar 25 '18 at 11:46

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 Oct 18 '17 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 Oct 19 '17 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, privacy policy and cookie policy

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