[sdiy] understanding direct AVR ADC...multiple channels

Olivier Gillet ol.gillet at gmail.com
Tue Mar 6 11:25:25 CET 2012


You can also read the application notes from ATmel:
http://www.atmel.com/Images/doc8444.pdf

Yes, the Arduino analogRead() is blocking. You can do conversion in
the background, by starting a conversion on the ADC, doing other
stuff, and then checking back the ADC status bit. The downside is that
depending on what you do during the conversion, you might get more
noise. For example it is not recommended to toggle pins while a
conversion takes place (from the above AN).

I'll second Ove on using the "Left-aligned" mode if you want only 8
bits. This way, you only have to read ADCH.

Regarding triggering, this allows you to start a conversion on an
external event (a voltage crossing a threshold as set by the
comparator, an external interrupt, a timer event). Usually, you use
this in conjunction with the ADIF bit (interrupt enable flag) so that
the conversion is automatically started in the background and you get
an interrupt at the end of it. Don't bother with it for the moment.

"Where to put the code?" You won't go very far by putting things in
the main Arduino "loop()". You won't get good timing because the time
between samples will be uneven. My recommendation would be to setup a
timer and do the conversion from there. At the very beginning of the
timer interrupt, copy the ADC register to a variable, and immediately
start a new conversion. Then in the rest of your ISR you can do
something useful with the read value, or just push it in a FIFO and do
your audio processing in the main loop by polling the FIFO for blocks
of samples. This interrupt will also be the right place to write to
your DAC ; so it'll look like this:

Read ADC register into variable adc_value
Write variable dac_value to DAC register (it's probably just a whole
8-bit port in your case)
Start a new ADC conversion
Compute dac_value from adc_value

OR

Read ADC register into variable adc_value
Write variable dac_value to DAC register (it's probably just a whole
8-bit port in your case)
Start a new ADC conversion
push adc_value to a FIFO
pull dac_value to a FIFO

and in your loop()

If 32 samples are readable from the input FIFO and 32 samples are
writable to the output FIFO
  Process a block of 32 samples (to benefit from all the goodies of
block processing)

This works for 1 input / 1 output.

If you have N inputs, you have to cycle through them ; so the rate of
the timer interrupt will be N times your target sample rate ; and
you'll have to do the DAC write every N-th interrupt only. This is
where timing will get trickier, as you'll want to avoid conditionals
in the code that precedes starting up a conversion (so conversions
starts are always equally spaced).

Olivier



More information about the Synth-diy mailing list