I have a microphone and I need as precise values as possible. I have been told by my teacher, that it is somehow possible to make a ADC timer interrupt, which would interrupt always when the value is ready, so that the reading itself would not slow the program down.
I know, how to use timer interrupts to read the analog value every other ms or something and I even have a code that lets the ADC read automaticly and takes the value, but I need to make it take the value always when it's ready, so that I would have every value the ADC read. I tried to look into the datasheet, but it's too complicated for me.
How can I achieve such thing? I am using arduino uno.

this is the code I have that sets up the ADC interrupt:

  ADCSRA = 0;  
  ADCSRB = 0;  
  ADMUX = 0;  
  ADMUX |= (1 << REFS0) + (1 << REFS1);  
  ADMUX |= (1 << ADLAR);  

  ADCSRA |= (1 << ADATE); //enabble auto trigger  
  ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete  
  ADCSRA |= (1 << ADEN); //enable ADC  
  ADCSRA |= (1 << ADSC);  
  ADCSRA |= 0b010;  

ISR(ADC_vect) {//when new ADC value ready
  af = af + ADCH;

I found this on the internet, but it didn't work as I expected.

  • 1
    ISR(ADC_vect){...} You also probably want to use a timer to start the conversions at an constant interval.
    – Gerben
    Jun 5, 2016 at 16:05
  • @Gerben: You can also have the ADC trigger itself at a constant rate if you set it to the so called “free running mode”. Jun 5, 2016 at 17:09
  • @EdgarBonet that rate would be as fast as it can. Aky-her might want to use a lower speed.
    – Gerben
    Jun 5, 2016 at 18:20
  • 1
    @Gerben: Right, but “as fast as it can” is 9615 S/s, which is not excessive for audio processing, and is easier to achieve since you have only one device to configure instead of two. Jun 5, 2016 at 20:00
  • 2
    By “as precise values as possible”, do you mean accurate voltage readings, or accurately-timed, or what? Jun 5, 2016 at 23:51

2 Answers 2


I have been told by my teacher that it is somehow possible to make a ADC timer interrupt.

You might have asked him or he could explain it ;)

Generally, if you want to do anything with an Arduino, which isn't implemented by the Arduino libraries, you're going to have to roll your own code (or copy it from the internet).

The answer from Nick will most certainly be enough to help you with the problem. However, it'd be way more cooler to find out how you can solve these problems yourself.

Getting started

I couldn't find a duplicate of this question, though it's a rather common question. You should've checked some of the tutorials on the web, it'll get you started a lot faster.

But don't forget the datasheet and manuals of the ATMega328(P). In case you can't really find something that fits your needs, or if you want to check some background information.

Setting registers (ADC)

This piece of code (from Nick Gammon), sets up the ADC.

  ADCSRA =  bit (ADEN);                      // turn ADC on
  ADCSRA |= bit (ADPS0) |  bit (ADPS1) | bit (ADPS2);  // Prescaler of 128
  ADMUX  =  bit (REFS0) | (adcPin & 0x07);    // AVcc and select input port

Fair enough, but if you wanted to change anything of it, you'll think: "How did he ever come up with this."

These are the registers of the microcontroller. By setting bits in the right pattern, you can enable/disable functions or change settings of the microcontroller.

You should download the ATMega328(P) datasheet. You can very easily navigate through it (if you've got a PDF reader that supports "bookmarks").

Check for "24. Analog to Digital converter" you should read through it, and go to "24.9 (Analog to Digital converter) - Register description.".

Here you can see, which bits of (in example) the ADCSRA register you have to set to enable the adc (ADEN), start the conversion (ADSC). And enable interrupts for it (ADIE).

enter image description here


Since you also want behavior that has to do with interrupts. You should also check out the interrupts bookmark (#12). 12.1 will show you an table with all interrupt vectors.

It's quite a shame that they don't have a nice C example code, they do have an reference manual though, but you'll implement an interrupt handler like this (from Nick Gammon).

// ADC complete ISR
ISR (ADC_vect)
  adcReading = ADC;
  adcDone = true;  
  }  // end of ADC_vect

If you now want to interrupt on SPI you can check the datasheet or reference manual for the vector name. (SPI_STC_vect)


it is somehow possible to make a ADC timer interrupt

The ADC and the timers are two different things. If you mean a timer interrupt, I'm not sure why you would want that. If you mean an ADC interrupt, yes you can do do that.

Here is some example code from my page about the ADC which shows using the interrupt (on a Uno):

const byte adcPin = 0;
volatile int adcReading;
volatile boolean adcDone;
boolean adcStarted;

void setup ()
  Serial.begin (115200);
  ADCSRA =  bit (ADEN);                      // turn ADC on
  ADCSRA |= bit (ADPS0) |  bit (ADPS1) | bit (ADPS2);  // Prescaler of 128
  ADMUX  =  bit (REFS0) | (adcPin & 0x07);    // AVcc and select input port

}  // end of setup

// ADC complete ISR
ISR (ADC_vect)
  adcReading = ADC;
  adcDone = true;  
  }  // end of ADC_vect

void loop ()
  // if last reading finished, process it
  if (adcDone)
    adcStarted = false;

    // do something with the reading, for example, print it
    Serial.println (adcReading);
    delay (500);

    adcDone = false;

  // if we aren't taking a reading, start a new one
  if (!adcStarted)
    adcStarted = true;
    // start the conversion
    ADCSRA |= bit (ADSC) | bit (ADIE);

  // do other stuff here

}  // end of loop

I should point out that if you do an analogRead it blocks until the read is done, so the very next line to be executed after analogRead will be when the data is ready.

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.