0

According to numerous online sources, the Raspberry Pi Pico can perform 500,000 A to D reads a second, i.e., 2 microseconds per read. I am programming in C++ using the Arduino IDE and cannot get better than 7.7 microseconds. Given a clock speed of 125 MHz, this implies the loop adds an overhead of 713 clock cycles per execution which seems unlikely.

In the attached code, the additional step to store the value in the array, only adds about 0.1% to the execution time.

Example line of the output:

time for 1000 ADC reads without store to array: 7732 microseconds.
time for 1000 ADC reads with store to array: 7688 microseconds.

In MicroPython, each read takes twice as long.

How can I speed this up?

// using Arduino IDE 1.8.19 to program Raspberry Pi Pico
#define ADC 27
#define DATALENGTH 1000

void setup() {
  Serial.begin(9600); 
}

void loop() {
  int data[DATALENGTH];
  unsigned long start = micros();
  unsigned long adcTime = 0;
  for (int i=0;i<DATALENGTH;i++)
  {
    analogRead(ADC);
  }
  adcTime = micros() - start;
  Serial.println("time for " + String(DATALENGTH) + " ADC reads without store to array: " + String(adcTime)+ " microseconds.");     

  start = micros();
  for (int i=0;i<DATALENGTH;i++)
  {
    data[i] = analogRead(ADC);
  }
  adcTime = micros() - start;
  Serial.println("time for " + String(DATALENGTH) + " ADC reads with store to array: " + String(adcTime)+ " microseconds.");   
  delay(5000);
}
Jonas
  • 121,568
  • 97
  • 310
  • 388
John Buckwell
  • 111
  • 2
  • 9

1 Answers1

2

The issue is caused by the Arduino IDE analogRead() method. It abstracts away some of the complexity of setting up the ADC but at the expense of a noticeable overhead. Rebuilding with Visual Studio and the GCC 9.2.1 arm-none-eabi compiler and calling lower level interfaces, yields approximately 2.5 microseconds per cycle for this loop. Writing the value read to an array does not measurably change the timing.

  #define DATALENGTH 1000
  absolute_time_t  start;   
  absolute_time_t  stop;    
  adc_gpio_init(26);
  adc_init();
  adc_select_input(0);
  int c = 10;
  while (c > 0){
    start = get_absolute_time();    
    for (int i=0;i<DATALENGTH;i++)
    {
      adc_read();
    }
    stop = get_absolute_time(); 
    int64_t tDiff =     absolute_time_diff_us (start, stop);
    printf("time for %d ADC reads without store to array: %d microseconds. \n",DATALENGTH,tDiff); 
    c--;
  }

It is possible to achieve exactly 2 microseconds per ADC read but that requires setting up the adc_fifo queue and using DMA transfer.

John Buckwell
  • 111
  • 2
  • 9