I have an application with Arduino, where some of the analog pins need AVCC as their reference voltage, while another one needs the internal 1.1V as the reference voltage to obtain a measurement with better precision than comparing against 5V.
I just found out that switching from AVCC to 1.1V internal requires a 5ms delay. The following code works:
void setup() {
ADMUX = 0b01000011; // configure ADC
ADCSRA = 0b10010111;
ADCSRB = 0;
DIDR0 = 8; // disable A3 digital
Serial.begin(9600);
}
void loop() {
ADMUX = 0b11000011; // select channel 3 and 1.1V ref
delay(5);
ADCSRA |= 64; // start conversion
while ((ADCSRA & 16) == 0); // wait for conversion to complete
ADCSRA = 0b10010101; // clear the conversion complete signal for another time
int bat = ADCL;
bat |= (ADCH << 8);
Serial.print("a3=");Serial.print(bat);
// read touch A6
ADMUX = 0b01000110; // select channel 6 and AVCC ref
ADCSRA |= 64; // start conversion
while ((ADCSRA & 16) == 0); // wait for conversion to complete
ADCSRA = 0b10010111; // clear the conversion complete signal for another time
int touch = ADCL;
touch |= (ADCH << 8);
Serial.print(", a6=");Serial.println(touch);
}
However, if I change 5ms to less, then the result of measurement against 1.1V is wrong. It is less. The less the program waits, the lower value. This indicates that when the 1.1V regulator is not selected, it is switched off and it needs 5ms to power up. I did not find anything of this sort in the datasheet, but I could have overlooked it.
Interestingly, in the analogRead() function of Arduino, there is a mysterious commented-out delay(1):
// without a delay, we seem to read from the wrong channel
// delay(1);
uncommenting it does not help as 1ms is not enough for this end. Therefore the code that uses analogReference() and analogRead() does not work at all, since analogReference() only changes a global variable and the actual switching is done only in analogRead(). Even subsequent analogRead() does not help (as it only takes about 20 usec), one has to wait those 5ms for the 1.1V guy to warm up.
So I was wondering - is there a way to keep it heated to avoid wasting so much time in the main loop? OK, I know I could use state variables like heating1v1 = true and measure the time, but maybe there was another way...?
And of course, it can be a feature of this particular mega328, which is probably some clone... so your original atmel microchip can be in a better shape. I tried two different boards with the same outcome.