Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Arduino Zero ADC Sample Time Too Long #327
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):
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.