MKR FOX 12000 sample rate of analogRead() slow vs. MEGA2560

Hello,

I was determining the sample frequency of the analogRead() for the MKR FOX 12000, when I came across the following

Problem:

  • From the theory, I am expecting a sampling frequency of about 28.8kHz but I experimentally determined a sample frequency of ~1.2kHz. The analogResolution() i set to 10bit, in order to be comparable to the MEGA2560.

Observations:

  • Running the same code on the MEGA2569 I obtain a sample frequency of 8.9kHz.
  • Using the adaino AnalogIn.readInput() I obtian a sample frequency of 2.5kHz for the MKR FOX 12000
  • Serial communicaiton should not be the issue. As different connection cables are used, I made the MKR FOX send the frequency to SigFox to assure that it is not a cable problem.

Code

void setup()
{
  Serial.begin(5000000);
  pinMode(A0, INPUT);
}

void loop()
{
  long t0, t;
  t0 = micros();
  for(int i=0; i<1000; i++) {
 analogRead(A0);
  }

  t =(micros()-t0);  // calculate elapsed time

  
  //Serial.println(analogRead(A0));
  Serial.print("Time per sample: ");
  Serial.println((float)t/1000);
  Serial.print("Frequency: ");
  Serial.println((float)1000*1000000/t);
  Serial.println();
  delay(200);
  
}

Question:

  1. Is there something wrong between in the code? Does the compilation on the MKR FOX 12000 cause the slow down?
  2. Am I getting my theory wrong or is there something wrong with my MKR FOX 12000?
  3. Anyone else faced similar problems?

Theory:

The sampling rate of the Arduino analogRead() depends strongly on the chosen resolution and the ADC clock (different from processor clock). Which in the case of the Arduino Mkr Fox 1200 ist 32.768 kHz (RTC), 48 MHz. Thus, its ATmega microcontroller can execute up to 48 million instructions per second. An Arduino needs to do a lot in order to execute even simple operations, consequently it sounds much but it really isn’t that much. For many projects, the clock cycles are shared between things like calculations, I2C communication, reading and writing to pins and registers, and many more operations. The ADC clock us given by 48MHz divided by a prescale factor. Its default setting is 128. Thus, resulting in and ADC clock speed of: 48MHz/128=375 kHz. A conversion takes 13 ADC clocks, resulting in a sample frequency of about 375/13=28.8 kHz.

May be this can help

ADC is known to be sluggish

It is because the default setting for the MKR Fox 1200 for the prescalar is set to 512 where I expected 128 like on the Arduino Uno.

The library library allows to change the Pre scalar without going into the libraries!
As one had to be careful about the noise when setting the Pre-scalar down using the function analogPrescaler(ADC_PRESCALER_DIV64);. I made a little program to compare the noise within the data for different prescalars and further return the sampling frequency of each.

#include "ATSAMD21_ADC.h"

void setup()
{
  Serial.begin(115200);
  analogPrescaler(ADC_PRESCALER_DIV64);
  pinMode(A0, INPUT);
}
int counter=0;

void loop()
{
  counter++;
  long t0, t;

  t0 = micros();
  for(int i=0; i<1000; i++) {
    analogRead(A0);
  }
  t = micros()-t0;  // calculate elapsed time

  Serial.print("Time per sample: ");
  Serial.println((float)t/1000);
  Serial.print("Frequency: ");
  Serial.println((float)1000*1000000/t);
  Serial.println();
  delay(300000);
  LowPower.deepSleep(1000);
  
if(counter==128)
{
    analogPrescaler(ADC_PRESCALER_DIV32);

}

if(counter==256)
{
    analogPrescaler(ADC_PRESCALER_DIV16);

}  

if(counter==512)
{
    analogPrescaler(ADC_PRESCALER_DIV8);

}  
}

Further it’s important to verify that the chosen analog resolution does not introduce more noise to the readings.