Hello everybody,

For a project i’m trying to capture the vibrations sensed by an analogue accelerometer. To capture the vibrations correctly, I know I need a rather high sampling speed.

Herein lies the problem. I’m using a MKR1000 board to capture the data, but when I try to verify the sampling speed I average about 1200 samples per second which is slow for an SAMD21 board, if I’m correct? Since the Arduino Uno has a standard (theoretical) sampling speed of ±9600 Hz. This sampling speed of 1200 S/s is really constant as well. I did not change any prescalers, clock speeds or have serial prints in the code. If I change to a MKR NB1500 board, I get the same results. Since both boards output the correct ADC values, just at ‘low’ sampling speeds, I am rather puzzled about what the problem could be?

In attachment you can find the code used to output the sampling speeds. If I forgot about some valuable information, just let me know.

Example.txt (411 Bytes)

Hi count_jones,

The MKR board's ADC is capable of sampling up to 350k samples/s, however Arduino have set the sample rate for analogRead() to a very conservative 1200 samples/s.

The ADC is clocked at 48MHz from generic clock 0 (GCLK0). This clock is divided down by the ADC prescaler set to 512:

ADC Clock Rate = 48MHz / 512 = 93750Hz

Arduino sets the ADC to single ended, single read mode, gain divide by 2 with 10-bit resolution. According to the SAMD21 datasheet, a conversion takes 7.5 ADC clock cycles to complete:

Conversion ADC clock cycles = 1 + (10-bits / 2) + 1.5 delay gain = 7.5 clock cycles

However, in addition Arduino set the ADC sample control register to 0x3f (63 decimal), this adds a further 64 half clock cycles to the conversion time:

ADC Conversion Time = (7.5 / 93750) + ((63 + 1) * (1 / (2 * 93750))) = 421.333us = 2373 samples/s

The Arduino analogRead() function performs two sequential reads each time it's called, therefore this gives a final sample rate of:

2373 / 2 = 1187 samples/s

Which is what you're observing on the MKR 1000 and 1500 boards.

It's possible to change the ADC sample rate, but this requires register manipulation.

Thanks for the reply and the good explanation!

What is the reason that this is done? And why isn't it done on the regular 8 bit boards? Or do they?

Hi count_jones,

I don't know why Arduino decided to set the sample control register to the maximum value of 0x3f. Increasing the sample time gives the ADC's sample and hold capacitor more time to charge, allowing for a larger source resistance at the analog input.

Here's an example that reads the ADC on A0, using single shot mode, 12-bit resolution and up to 11000 samples/s with register manipulation:

``````// Set-up the ADC to read analog input on A0 with 12-bit resolution
void setup() {
SerialUSB.begin(115200);                         // Set-up the native serial port at 115200 bit/s
while(!SerialUSB);                               // Wait for the console to open
ADC->SAMPCTRL.reg = 0x00;                        // Set max Sampling Time Length to half divided ADC clock pulse (5.33us)
}

void loop() {
ADC->SWTRIG.bit.START = 1;                       // Initiate a software trigger to start an ADC conversion
while(ADC->STATUS.bit.SYNCBUSY);                 // Wait for write synchronization
while(!ADC->INTFLAG.bit.RESRDY);                 // Wait for the conversion to complete
`ADC->SAMPCTRL.reg = 0x00;`