0% found this document useful (0 votes)
869 views

ADC Arduino Due

The default Arduino Due ADC settings initialize the ADC to run at its maximum possible speed of 20MHz. It configures the timing to use a settling time of 17 clock periods and disables interrupts and channels. Useful documentation includes the datasheet and Arduino source code files. The analogRead() function is slow because it waits for ADC startup time by default, but this can be improved by reducing the startup time in the ADC mode register to speed up the conversion time.

Uploaded by

Vicencio Monge
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
869 views

ADC Arduino Due

The default Arduino Due ADC settings initialize the ADC to run at its maximum possible speed of 20MHz. It configures the timing to use a settling time of 17 clock periods and disables interrupts and channels. Useful documentation includes the datasheet and Arduino source code files. The analogRead() function is slow because it waits for ADC startup time by default, but this can be improved by reducing the startup time in the ADC mode register to speed up the conversion time.

Uploaded by

Vicencio Monge
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 6

Analog-to-Digital Converter (ADC) SAM3x

The default Arduino Due ADC settings are:

// Initialize Analog Controller


pmc_enable_periph_clk(ID_ADC);
adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST);
adc_configure_timing(ADC, 0, ADC_SETTLING_TIME_3, 1);
adc_configure_trigger(ADC, ADC_TRIG_SW, 0); // Disable hardware trigger.
adc_disable_interrupt(ADC, 0xFFFFFFFF); // Disable all ADC interrupts.
adc_disable_all_channel(ADC);

Useful links:

Datasheet - ADC description starts on page 1317.

adc_init (ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST);

// initialize, set maximum possible speed

ADC_STARTUP_FAST 12

ADC_STARTUP_NORM 40

ADC_FREQ_MIN = 1000000 (1Mhz)

ADC_FREQ_MAX = 20000000 (20MHz)


adc_configure_timing(ADC, TRACKING_TIME, ADC_SETTLING_TIME_3, TRANSFER_PERIOD);

TRACKING_TIME = 1
ADC_SETTLING_TIME_0 = ADC_MR_SETTLING_AST3,
ADC_SETTLING_TIME_1 = ADC_MR_SETTLING_AST5,
ADC_SETTLING_TIME_2 = ADC_MR_SETTLING_AST9,
ADC_SETTLING_TIME_3 = ADC_MR_SETTLING_AST17 (17 periods ADCClock)
TRANSFER_PERIOD = 1

Each sample is formed from: Transfer Time + Tracking Time + Settling Time

Transfer Time = (TRANSFER * 2 + 3) / ADCClock


Tracking Time = (TRACKTIM + 1) / ADCClock
Settling Time = settling value / ADCClock

Sampling rate = ((TRACKING_TIME * 2 + 3) + (TRANSFER_PERIOD + 1) + ADC_SETTLING_TIME_3) /


ADC_FREQ_MIN = (1 + 1 + 17)/1000000 = 52.6Khz

https://github.com/arduino/Arduino/blob/ide-
1.5.x/hardware/arduino/sam/system/libsam/source/adc.c#L84
Due ADC Speed (http://www.djerickson.com/arduino/due_adc.html)
The function analogRead() in a tight loop takes 39uS per loop. Considering that the ADC can
convert in 1uS and the processor can execute dozens of instruction in 1 uS. what's the beef? I dug
into the analogRead() function to find out why. The first observation is that analogRead() does not
initialize the ADC, it just sets the channel, starts a conversion and waits for the result. Initialization
is done elsewhere. So basic code structure isn't the problem. Then I dug into the register settings.
The register ADC_MR (Mode Register) contains a number of settings that affect ADC timing:
TRACKTIM, SETTLING, STARTUP, and PRESCALE in addition to SLEEP. The following code allow you
to display the 32 bit contents of the MR register via the serial port.

unsigned long reg;


reg = REG_ADC_MR;
Serial.print("REG_ADC_MR = ");
Serial.println(reg, HEX);

When run, you get:

REG_ADC_MR = 103C0100

The master clock, MCLK is 84MHz. The ADC prescaler is set to 0x01 which is divide by 4 so the ADC
clock is 84MHz / 4 = 21MHz. That is as fast as it can go, so that's not the problem. The ADC clock
period is 1 / 21MHz = 37.6nS. The 0xC sets STARTUP is 768. 768 / 21MHz = 36.6uS. Bingo! So I set
STARTUP to a smaller number, 2, (value = 16 / 21M = .76uS) with this line of code:
REG_ADC_MR = (REG_ADC_MR & 0xFFF0FFFF) | 0x00020000;

And the ADC loop now takes 4uS. Cool. To make it even faster, I also set the Settling number down
from 3 to 1. The data sheet recommends settling and tracking numbers. It also says that if you
want the ADC to convert faster than 500KHz, set the IBCTL field in ADC_ACR to 01. I checked, and
it was already is set to 01.

You might also like