Go Down

Topic: Analog Input conversion time (Read 5354 times) previous topic - next topic


The current Arduino Library (coming with IDE 1.0.1) only has one function to read analoge inputs. Since the conversion is started with the call of AnalogRead and the function waits until the conversion is complete, it is one of the most time-consuming function calls. Reading all 12 inputs one after each other lasts therefore ca. 1ms which is a long time if the sketch needs high sample rates or performs other time critical functions that have to wait for the conversion.
It is possible by register manipulation to increase the clock speed of the A/D conversion, but at the cost of 1bit accuracy with respect to standard frequency - and the register manipulation is processor dependent.
I suggest to have an additional function that allows to start a conversion but comes back immediately (e.g. naming it "AnalogStart"). The AnalogRead should then check whether an AnalogStart has already been called (means conversion is already in progress) and wait for the result; otherwise internally call AnalogRead first if one does not care so much about speed and staying compatible with existing Sketches.
This would allow to start the conversion of numerous analog inputs before the result of the conversion is needed, and then later to quickly read all of the analog inputs.
Especially for the new Arduino Due, it would be very unsatisfying to have a 32Bit ARM CPU with 87 MHz but still have to wait such long times for analog conversions.


It took you longer to write that post than it would to implement what you suggest.
Per Arduino ad Astra


Oct 24, 2012, 02:41 pm Last Edit: Oct 25, 2012, 09:51 am by Nantonos Reason: 1

This would allow to start the conversion of numerous analog inputs before the result of the conversion is needed, and then later to quickly read all of the analog inputs.

Just checking - you are aware that

a) although there are multiple analog input pins, they are all multiplexed to one ADC?
b) the sample and hold capacitor in the ADC takes some time to charge, and takes longer if the inputs are switched?


Thanks for the hints - I knew that there is only one ADC, but did not have this in mind when I wrote my topic. Nevertheless, my suggestion makes sense, it just means one could start a conversion for a certain pin, doing some other processing, read the result, starting conversion of the next pin, and so on. The point is, not to waste processing time while waiting for the sample and hold capacitor to charge and performing the conversion.
@Groove: I would be very happy if I could implement this in 10 Minutes.


I'd be disappointed if it took that long.
You have the source of analogRead.
Per Arduino ad Astra


check this threads

- http://arduino.cc/forum/index.php?topic=109259.0
- http://arduino.cc/forum/index.php/topic,56396.0.html
- http://arduino.cc/forum/index.php/topic,74895.0.html

completely irq driven
- http://arduino.cc/forum/index.php/topic,125766.msg946608.html#msg946608
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)


Code: [Select]

void startAnalogRead(uint8_t pin)
uint8_t low, high;

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#elif defined(__AVR_ATmega32U4__)
if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__)
if (pin >= 24) pin -= 24; // allow for channel or pin numbers
if (pin >= 14) pin -= 14; // allow for channel or pin numbers

#if defined(__AVR_ATmega32U4__)
pin = analogPinToChannel(pin);
ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#elif defined(ADCSRB) && defined(MUX5)
// the MUX5 bit of ADCSRB selects whether we're reading from channels
// 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
// set the analog reference (high two bits of ADMUX) and select the
// channel (low 4 bits).  this also sets ADLAR (left-adjust result)
// to 0 (the default).
#if defined(ADMUX)
ADMUX = (analog_reference << 6) | (pin & 0x07);

// without a delay, we seem to read from the wrong channel

#if defined(ADCSRA) && defined(ADCL)
// start the conversion

bool analogReadIsReady() {
return !bit_is_set(ADCSRA, ADSC);

int finishAnalogread() {
#if defined(ADCSRA) && defined(ADCL)
// we have to read ADCL first; doing so locks both ADCL
// and ADCH until ADCH is read.  reading ADCL second would
// cause the results of each conversion to be discarded,
// as ADCL and ADCH would be locked when it completed.
low  = ADCL;
high = ADCH;
// we dont have an ADC, return 0
low  = 0;
high = 0;

// combine the two bytes
return (high << 8) | low;

30 seconds, but haven't tested it

Go Up