Static Accuracy Tests of the Arduino Internal ADC.

ardnut,
I would have expected 1023 also but the datasheet and Atmel app notes say 1024.

ADC = VIN ? 1024/VREF

Data sheets for most SAR ADCs use 2^n where n is the number of bits. I often use 2^n-1 since that is full scale.

MarkT,

Here is a demonstration of how the ADC MUX and S/H are affected by external resistance.

I connected analog pin 0 to ground and analog pin 1 to 5V through a resistor. I used resistor values from 10K to 470K.

I used ADC prescalers values from 16 to 128 which results in an ADC clock from 1MHz to 125kHz in this sketch.

const uint8_t ADC_PS_16  = (1 << ADPS2);
const uint8_t ADC_PS_32  = (1 << ADPS2) | (1 << ADPS0);
const uint8_t ADC_PS_64  = (1 << ADPS2) | (1 << ADPS1);
const uint8_t ADC_PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
const uint8_t ADC_PS_BITS = ADC_PS_128;

void setup() {
  Serial.begin(9600);
  ADCSRA &= ~ADC_PS_BITS;
  ADCSRA |= ADC_PS_128;    
}
void loop() {
  uint16_t v0 = analogRead(0);
  uint16_t v1 = analogRead(1);
  Serial.print(v0);
  Serial.write(',');
  Serial.println(v1);
  delay(500);
}

Here are the results for the value of v1. It should be 1023.

10K 22K 33K 47K 68K 100K 220K 330K 470K
PS16 970 920 880 840 805 770 727 710 704
PS32 1023 1015 997 970 932 883 797 760 745
PS64 1023 1022 1019 1010 990 950 858 808 785
PS128 1023 1023 1023 1023 1022 1016 964 913 874

Note that even with zero external resistance, PS16 has an error. This is because the ADC input has more than 10K of internal resistance.

I then ran the test after adding a line to throw away the first reading after changing the channel to analog pin 1. This is recommended by Atmel for more accuracy in an app note.

Here is the sketch.

const uint8_t ADC_PS_16  = (1 << ADPS2);
const uint8_t ADC_PS_32  = (1 << ADPS2) | (1 << ADPS0);
const uint8_t ADC_PS_64  = (1 << ADPS2) | (1 << ADPS1);
const uint8_t ADC_PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
const uint8_t ADC_PS_BITS = ADC_PS_128;

void setup() {
  Serial.begin(9600);
  ADCSRA &= ~ADC_PS_BITS;
  ADCSRA |= ADC_PS_128;    
}
void loop() {
  uint16_t v0 = analogRead(0);
  analogRead(1);
  uint16_t v1 = analogRead(1);
  Serial.print(v0);
  Serial.write(',');
  Serial.println(v1);
  delay(500);
}

Here are the results.

10K 22K 33K 47K 68K 100K 220K 330K 470K
PS16 1023 1023 1022 1019 1012 999 947 901 870
PS32 1023 1023 1023 1023 1022 1017 992 966 941
PS64 1023 1023 1023 1023 1023 1022 1010 997 983
PS128 1023 1023 1023 1023 1023 1023 1022 1016 1011

If you have a very high impedance sensor you can add a one ms delay after the first analogRead(1) with PS128. Then even a 1Meg resistor will result in 1022 or 1023.

  analogRead(1);
  delay(1);
  uint16_t v1 = analogRead(1);