Arduino Forum

Products => Arduino Due => Topic started by: Totv on Jan 23, 2013, 03:12 pm

Title: How to make analogRead() faster?
Post by: Totv on Jan 23, 2013, 03:12 pm
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?
Title: Re: How to make analogRead() faster?
Post by: robtillaart on Jan 23, 2013, 08:07 pm
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.

Title: Re: How to make analogRead() faster?
Post by: ralphnev on Jan 23, 2013, 08:37 pm
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);

Title: Re: How to make analogRead() faster?
Post by: Totv on Jan 24, 2013, 08:30 am
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.
Title: Re: How to make analogRead() faster?
Post by: ralphnev on Jan 24, 2013, 09:02 am
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

Title: Magical quick solution.
Post by: Totv on Jan 24, 2013, 10:31 am
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.
Title: Re: How to make analogRead() faster?
Post by: ralphnev on Jan 24, 2013, 10:44 am
good find // i'll make a note of that