Go Down

Topic: Faster Analog Read? (Read 61 times) previous topic - next topic

chrios

I need to read an analog signal at about 50khz (for maybe 50-500 samples, not sure yet).  The reference seems to indicate the analogRead() takes about 100us, which is good enough for 10khz.  Is this limitation set by the Arduino libraries, or the ATMEGA chip?

Any help much appreciated,
Chris

P.S. does anyone know how fast the digital read is?

Oracle

The analog read speed is a limitation of the ATMEGA chip.  There are standalone ADC chips which are a lot faster, but I have no experience with them.

A digital read takes 1 instruction cycle.  I think the ATMEGA chip has a 1 to 1 mapping from clock speed to instruction cycle, so a digital read would take 1/16th of a microsecond.

jmknapp

#2
Apr 21, 2008, 12:52 am Last Edit: Apr 21, 2008, 02:30 am by jmknapp Reason: 1
According to the specs:

Quote

By default, the successive approximation circuitry requires an input clock frequency [ADC clock] between 50 kHz and 200 kHz to get maximum resolution. If a lower resolution than 10 bits is needed, the input clock frequency to the ADC can be higher than 200 kHz to get a higher sample rate.


The ADC clock is 16 MHz divided by a prescale factor. The prescale is set to 128 (16MHz/128 = 125 KHz) in wiring.c. Since a conversion takes 13 ADC clocks, the sample rate is about 125KHz/13 or 9600 Hz.

So anyway, setting the prescale to, say, 16, would give a sample rate of 77 KHz. Not sure what kind of resolution you would get though!

EDIT:

Found this reference:

http://www.atmel.com/dyn/resources/prod_documents/DOC2559.PDF

Here's a relevant quote:

Quote

The ADC accuracy also depends on the ADC clock. The recommended maximum ADC clock frequency is limited by the internal DAC in the conversion circuitry. For optimum performance, the ADC clock should not exceed 200 kHz. However, frequencies up to 1 MHz do not reduce the ADC resolution significantly.

Operating the ADC with frequencies greater than 1 MHz is not characterized.


So looks like using a prescale of 16 as above would give an ADC clock of 1 MHz and a sample rate of ~77KHz without much loss of resolution. BTW, this is the code to set the prescale to 16:

Code: [Select]

// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// set prescale to 16
sbi(ADCSRA,ADPS2) ;
cbi(ADCSRA,ADPS1) ;
cbi(ADCSRA,ADPS0) ;


chrios

#3
Apr 21, 2008, 06:57 am Last Edit: Apr 21, 2008, 06:57 am by chrios Reason: 1
Wow.  Thank you jmknapp and oracle.

So if I just include your defines in the top of my code and the function calls in my setup, I should be good to go?  As in, analogReads will just return a lot faster (at a bit lower precision)?

How exactly is your code setting it to a prescale of 16.  I don't see any numbers in there..

Chris

mem

#4
Apr 21, 2008, 10:18 am Last Edit: Apr 21, 2008, 10:23 am by mem Reason: 1
Bear in mind that the Arduino digital and anlog read/write abstractions that make this platform so easy to use, do reduce the execution time over what could be achieved if one used low level code to directly access these functions. The arduino functions will be slower than the timings quoted above.

For example, the Arduino digitalRead function first does a lookup to convert the Arduino pin number to an actual port and pin. It then disables any PWM function that could be running on this pin. And finally, it executes another dozen instructions or so to actually read the port. I would think it would take well over twenty times longer for each digitalRead compared to directly accessing a specific low level port pin.

AnalogRead also does the Arduino pin mapping lookup and it sets the analog reference bits each time analogRead is called, although this probably represents a small fraction of the total ADC conversion time.

If your application does need digital read times under a microsecond, you can read more about direct port manipulation here: http://www.arduino.cc/en/Reference/PortManipulation

Go Up