Arduino Mini Pro 3.3V does not use 1.1V internal reference for ADC

3k views Asked by At

Using the Arduino Mini Pro 3.3V I just stumbled over a problem when switching between the "INTERNAL" and "DEFAULT" voltage reference for the ADC. I want to measure the output of a voltage divider [GND - 110kOhm - A2 - 500kOhm - VCC] for calculating VCC. VCC has been measured as 3.3V. It is provided by a voltage regulator.

In the loop I firstly measure the voltage divider output with the internal reference and afterwards with the default voltage reference. I saw code examples where people recommend to wait some milliseconds before reading the next value and the (analogReference() documentation) recommends to ignore the first readings after calling analogReference(). I follow these guidlines.

I'll provide a minimum example sketch:

// the setup function runs once when you press reset or power the board
void setup()
{
  pinMode(A2, INPUT);    // ADC pin
  Serial.begin(9600);
  Serial.println("----------------");
}

void burn8Readings(int pin)
{
  for (int i = 0; i < 8; i++)
  {
    analogRead(pin);
  }
}

// the loop function runs over and over again forever
void loop()
{
  uint16_t nResult1, nResult2;

  analogReference(INTERNAL);    // set the ADC reference to 1.1V
  delay(10);                    // idle some time
  burn8Readings(A2);            // make 8 readings but don't use them to ensure good reading after ADC reference change

  nResult1 = analogRead(A2);    // read actual value

  analogReference(DEFAULT);     // set the ADC reference back to internal for other measurements
  delay(10);                    // idle again
  burn8Readings(A2);            // make 8 readings but don't use them to ensure good reading after ADC reference change

  nResult2 = analogRead(A2);    // do other measurements

// print result to serial interface..
  Serial.print("1: ");  
  Serial.print(nResult1);
  Serial.print(" - 2: ");
  Serial.println(nResult2);

  delay(2000);
}

The first pair of ADC results seems correct (553 / 184), but in the following iterations the first value is faulty without changing the actual voltage on the ADC pin. (240 / 183) The ADC result of the DEFAULT reference is always fine.

For a 2.56V reference the value of 240 would be feasible. I know that some ATmegas use a 2.56V reference voltage, but the ATmega328 should have 1.1V only. Strangely the (ATmega328/P datasheet) mentions a 2.56V reference in an ADC example in chapter 28.7, so I'm confused.

Is there a possibility there is a 2.56V ADC reference in a certain ATmega328p version?

1

There are 1 answers

0
random On BEST ANSWER

It turns out the similarity to the 2.56V was a coincidence and probably an error in the datasheet (or in my understanding). The problem was that after the analogReference(INTERNAL) call the ADC value has to be read immediately! Not after some milliseconds as I did it. (Source)

Still it is important to also wait some milliseconds after doing the dummy readout. For me one readout and delay(5) was just enough, but I guess that depends on the charge left in the capacitor of the ADC: So I'd recommend higher delays.

The correct sequence is:

  analogReference(INTERNAL);    // set the ADC reference to 1.1V
  burn8Readings(A2);            // make 8 readings but don't use them
  delay(10);                    // idle some time
  nResult1 = analogRead(A2);    // read actual value

and

  analogReference(DEFAULT);     // set the ADC reference back to internal
  burn8Readings(A2);            // make 8 readings but don't use them
  delay(10);                    // idle again
  nResult2 = analogRead(A2);    // read actual value

Changing the reference back to DEFAULT seems to be less prone...but at least one readout still was necessary for precise results.

I hope no one has to spend time on this one anymore...