Algunas cosas sobre los ATtiny: Se puede leer el voltaje de la alimentación de los ATtiny (y otros avr) sin usar un pin

Ésta es una de esas cosas que a algunos nos parece brujería. Resulta que jugando con los interruptores puede utilizarse como voltaje de referencia para el ADC el voltaje de la alimentación, usarla para leer el valor del voltaje de referencia interno de 1.1v y calcular el voltaje de la alimentación (¡Brujería!, ¡brujería os digo!).

Para realizar una lectura del ADC, el microcontrolador, toma la lectura del ADC la multiplica el voltaje de referencia y lo divide entre el número de bits del ADC:

adc1

Como el nuevo voltaje de referencia va a ser el de la alimentación:

adc2

Despejamos la alimentación. Como el valor que estamos midiendo es el voltaje de referencia interior que sabemos que es 1.1v:

adc3

De este modo podemos calcular el voltaje de la fuente de alimentación.

long readVcc() {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  ADMUX = _BV(MUX3) | _BV(MUX2);

  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring

  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
  uint8_t high = ADCH; // unlocks both

  long result = (high<<8) | low;

  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}

La lectura no es muy precisa porque usa el valor nominal del voltaje de referencia interno, que en realidad puede ser entre 1.0v y 1.2v, y varía con la temperatura. Esto introduce un error de un 10% en la lectura que se podría mitigar determinado cuál es el voltaje de referencia interno para cada voltaje de alimentación y calibrar la medida.

Otra cosa, si vas a utilizar el ADC para realizar alguna lectura, hay que tener en cuenta que el voltaje de referencia es ahora el de la alimentación y tenerlo en cuenta al relalizar los cálculos.