Go Down

Topic: How to make analogRead() faster? (Read 2615 times) previous topic - next topic

Totv

I have measured the run-time of function analogRead () [for analogReadResolution (12)]. On average, it is 40 uS. However, I would like to digitize at least at 200 Ksample / s on one channel. It is known that sam3x8e processor can do it much faster.
Is it possible to get a faster work of function analogRead () for Arduino Due?

robtillaart

don't know the DUE yet in detail, but with the UNO I did the following trick once:

I split the analogRead() in three functions:
- one to start conversion: void analogReadStart(int pin);
- one to check if it is ready: bool analogReadReady(int pin);
- one to read the data when conversion was ready int analogRead(int pin);

This allowed me to do the following:

Code: [Select]
void setup()
{
  ...
  analogReadStart(A0);
}

void loop()
{
  if (analogReadReady(A0))
  {
    value = analogRead(A0);
    analogReadStart(A0);  // restart the next conversion immediately

    process(value);
  }
  // do other things here

}

It is an "analogRead() without (polling) delay" construct. It allowed me to process more samples per second than wit the standard analogRead().

Don't know if similar trick is possible with DUE

Another possibility might be a continuous mode conversion that triggers an ISR() when a new reading is ready. For an UNO this exists, agian don't know for the DUE.

Rob Tillaart

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

ralphnev

#2
Jan 23, 2013, 08:37 pm Last Edit: Jan 23, 2013, 08:59 pm by ralphnev Reason: 1
don't use analogRead ;)

Really .. you have to get into the guts / shorten the track time / read time / setling time

keep it  on / don't use a sleep mode
use a constant trigger ..I'm using the PWM,
read the data via the PDC

below was modeled after  the Atmel Studio adc/PWM example
Code: [Select]

 adc_init (ADC, VARIANT_MCK, adc_clk,  ADC_STARTUP_FAST);

 adc_configure_timing (ADC, 0, //uc_tracking,        
(const enum adc_settling_time_t) ADC_MR_SETTLING_AST3, //settling,
(const uint8_t) 1); //uc_transfer
  adc_enable_channel ((Adc *) ADC,
     (const enum adc_channel_num_t) 0);
 adc_disable_anch (ADC);

adc_configure_power_save (ADC, ADC_MR_SLEEP_NORMAL, ADC_MR_FWUP_OFF);
adc_configure_trigger (ADC, ADC_TRIG_PWM_EVENT_LINE_0, ADC_MR_FREERUN_OFF);


Totv

Thanks, robtillaart. I'm using the Arduino 1.5.1r2. Alack, there are no such functions as analogReadStart() and analogReadReady().
I agree with ralphnev, that Atmel Studio should be used to optimize code on a low level. It remains only to find out how to combine the Arduino and Atmel Studio. :)
Is it possible to add into Arduino language the functions from Atmel Studio? Give me links to documents on this issue, please.

ralphnev

I'm using Arduino 1.5.1r2 as well ,  the low level libs from Atmel are all there ,
though i do have to go grep'ing ever time i need a function ...

i did make myself a cheat sheet of locations when working on the PWM - they will be the same for adc :

.../arduino-1.5.1r2/hardware/arduino/sam/variants/arduino_due_x/variant.cpp
.../arduino-1.5.1r2/hardware/arduino/sam/variants/arduino_due_x/variant.h
.../arduino-1.5.1r2/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/component/component_pwm.h
.../arduino-1.5.1r2/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/instance/instance_pwm.h
.../arduino-1.5.1r2/hardware/arduino/sam/system/libsam/source/pwmc.c
.../arduino-1.5.1r2/hardware/arduino/sam/system/libsam/include/pwmc.h
.../arduino-1.5.1r2/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/sam3x8c.h


Totv

Careful examination of the file c:\arduino-1.5.1r2\hardware\arduino\sam\cores\arduino\wiring_analog.c showed that the function analogRead() always finished with disabling of the analog channel. This is completely unnecessary, if the analog inputs are used only for streaming read from the ADC.
It was enough to comment out the line 164 where the disabling operation of the analog channel executes:

163:       // Disable the corresponding channel
164:       // adc_disable_channel (ADC, ulChannel);

Only one this comment dramatically increased the speed of the ADC. Now the function analogRead () holds less than 2 uS. Reading 12 channels in FOR loop now takes exactly 24 uS. This is with analogReadResolution(12). I think that for many applications this is sufficient.
However, for such a relatively powerful processor, as SAM3X8E, the low-level code inserting into Arduino will always be necessary. We need more new libraries to use all features of this processor.
Thanks all for advises.

ralphnev

good find // i'll make a note of that


 

Go Up