ArduinoCore-samd icon indicating copy to clipboard operation
ArduinoCore-samd copied to clipboard

Arduino Zero ADC Sample Time Too Long

Open ghost opened this issue 6 years ago • 2 comments

The conversion time for the Arduino Zero is currently around 426us, at 12-bit resolution.

This value can be calculated from the SAMD21 datasheet:

1) ADC Sample Time Calculation

Take the processor clock at (approximately) 48MHz and divide by the ADC prescaler set at 512:

ADC Clock Frequency = 48MHz / 512 = 93750Hz

Therefore the ADC clock period is 10.66us (1 / 93750).

The default ADC sample time is half the ADC clock period, so normally the sample time is:

Default ADC sample time = 10.66us / 2 = 5.33us

However, in the “wiring.c” file the ADC's SAMPLEN bitfield in the SAMPCTRL register that extends the sample time, has been set to 63, (0x3F hex). This determines the number of half ADC cycles taken to complete the sample given by the formula:

Adjusted ADC sample time = (63 + 1) * (10.66us / 2) = 341.12us

2) ADC Conversion Time Calculation

For the ADC configured for a 0.5 gain, in single ended mode, as on the Arduino Zero, the delay gain is 1.5. (Table 33-1 in the SAMD21 datasheet).

Using the formula in the datasheet, at 12-bits resolution and a delay gain of 1.5, the propagation delay or in other words the number full ADC clock cycles to complete a conversion for the ADC is:

Propagation Delay (ADC Conversion Time) = (1 + 12 / 2 + 1.5) / 93750 = 90.66us

As the propagation delay includes the sample time (half ADC clock period) at 5.33us, the total ADC conversion time is:

ADC Conversion Time = 341.12us + 90.66us – 5.33us = 426us

3) The SAMPCTRL register and ADC prescaler

The issue is that the SAMPCTRL register's SAMPLEN bitfield has been set at a maximum value of 63, this allows the maximum input source resistance, but at the expense of a hugely increased sample time.

In the electrical characteristics of the SAMD21 datasheet, the criteria for setting the sample time at 12-bit resolution is given by the formula:

T(sample) >= (R(source) + R(sample)) * C(sample) * 9.02

where R and C sample are characteristics of the ADC input (taken from the SAMD21 datasheet): R(sample) = 3.5kOhms C(sample) = 3.5pF R(source) = source resistance T(sample) = sample time (usually half ADC clock period)

Using this equation, even if the SAMPCTRL register were to be set to 0, giving an ADC sample time of 5.33us, this would allow a maximum source resistance of:

R(source) = 5.33us / (3.5pF * 9.02) – 3.5kOhms = 165331 Ohms

The resultant ADC conversion time of 90.66us, is more than a four fold decrease on the current value.

Furthermore, decreasing the ADC clock prescaler to say 128, instead of 512:

ADC Sample Time = (1 / ( 2 * 48MHz / 128)) = 1.33us

ADC Conversion Time = 8.5 * 2.66us = 22.67us

In practice the however the conversion time takes around just less than 30us, as the analogRead() function enables and disables the ADC each time it's called. (Using register manipulation it does take around 23us).

The maximum source resistance would be:

R(source) = 1.33us / (3.5pF * 9.02) – 3.5kOhms = 38628 Ohms

In my opinion, the ADC conversion time could be vastly reduced to around 30us without any noticeable effect for the vast majority of Arduino Zero users, unless of course they're using some voltage divider with large resistor values.

ghost avatar Jun 20 '18 10:06 ghost

Your calculation is perfect. I didnt understand why the lock up at very very slow sample rate. =(

Muplex avatar Sep 03 '19 20:09 Muplex

I have found out with the SAM21 being in deep sleep, it needs more than 100ms after wakeup for the ADC to give usable measurements. Not 100% related to this but should be taken into consideration when making the sampling time even shorter.

mamama1 avatar Jun 25 '22 15:06 mamama1