¿La conversión de ADC a un voltaje depende del valor real del pin de +5 V?

13

Preguntas:

  1. ¿La conversión del recuento de ADC a voltaje depende del voltaje real del pin de +5 V?
  2. En caso afirmativo, ¿cuál es el método aceptado para obtener ese voltaje de la placa?

Fondo / Detalle:

Tengo un circuito en el que tengo un Arduino Nano (clon) que se ejecuta desde un conector USB (desde un concentrador). El trabajo del Arduino es medir el voltaje en una batería que conducirá un segundo circuito encendido / apagado por el Nano. Como referencia es un probador de batería.

Circuito de prueba

Hay una pantalla Nokia 5110 que muestra el voltaje del boceto muy simple a continuación.

void setup() {
  Serial.begin(9600);
  display.begin();
  // Init done

  // You can change the contrast around to adapt the display
  // for the best viewing!
  display.setContrast(50);

  // Text display tests
  display.setTextSize(1);
  display.setTextColor(BLACK);
}


void loop() {
  display.clearDisplay();   // Clears the screen and buffer
  display.setCursor(0,0);
  display.print("Vin=");
  int rawVIN = analogRead(VIN);
  float floatVin = (rawVIN*4.75)/1023.0;
  display.println(floatVin);
  Serial.println(rawVIN);
  display.display();
  delay(1000);
}
  • Medí el voltaje de la batería usando un DVM y es de 4.13 V, sin embargo, el Nano reporta 4.35 V.
  • Tengo un terreno común entre la batería y Arduino.
  • Debido a que la conexión para probar el voltaje puede flotar, tengo una resistencia pulldown para detener las fluctuaciones salvajes (> 10 kΩ)

Después de investigar un poco, descubrí que el +5 V en realidad estaba produciendo 4.75 V y cambié mi boceto de

float v = (rawVIN*5.0)/1024.0;

a

float v = (rawVIN*4.75)/1024.0;

y la lectura de voltaje en el Arduino ahora era correcta. Hice esto no porque entiendo lo que hice, lo hice porque tenía el presentimiento de que podría cambiar el valor al correcto.

Caribú
fuente
3
Como un lado, no deberías dividir entre 1024, no 1023. Este es un error que se repite una y otra vez, presumiblemente derivado del error que se encuentra en los ejemplos de Arduino. ¿Fuente? La hoja de datos para el AVR.
Tom Carpenter
@TomCarpenter Creo que esto es el resultado de mi torpeza con el cálculo y la lectura de algo después de mucho tiempo de golpearme la cabeza contra el escritorio: comencé con 1024 pero, como ves, terminé con 1023, corregiré mi pregunta .
Caribú

Respuestas:

16

El ADC dentro del Arduino no mide voltaje, sino más bien una relación de voltaje . Es decir, la relación entre el voltaje en la entrada analógica y el voltaje en el pin Vref.

En la configuración predeterminada, el pin Vref está vinculado internamente a la línea +5 V. Puede seleccionar usar en su lugar una referencia interna como Vref :

analogReference(INTERNAL);

Esta referencia es de aproximadamente 1.1 V, y es bastante inmune a las fluctuaciones en los +5 V. El problema es que no puede medir voltajes más altos que la referencia.

Para su probador de batería, si desea algún tipo de medición "absoluta", puede usar la referencia interna y un divisor de voltaje para asegurarse de que el voltaje medido sea inferior a 1.1 V.

Editar : Otra opción que no requiere un divisor de voltaje es usar Vcc como referencia para medir tanto la entrada analógica como la referencia interna de 1.1 V "bandgap". Medir 1.1 V contra Vcc es una forma indirecta de medir Vcc. Esto no es compatible con la biblioteca principal de Arduino, pero puede hacerlo programando directamente los registros de control del ADC:

// Return the supply voltage in volts.
float read_vcc()
{
    const float V_BAND_GAP = 1.1;     // typical
    ADMUX  = _BV(REFS0)    // ref = Vcc
           | 14;           // channel 14 is the bandgap reference
    ADCSRA |= _BV(ADSC);   // start conversion
    loop_until_bit_is_clear(ADCSRA, ADSC);  // wait until complete
    return V_BAND_GAP * 1024 / ADC;
}

Tenga en cuenta que la primera lectura después del arranque puede ser falsa.

Edgar Bonet
fuente
Gracias por la pronta respuesta :) esto tiene mucho sentido ahora y explica por qué mediante el ajuste de mi código (fudge) obtengo la respuesta correcta. Esto combinado con una respuesta enriquecida me da todo lo que necesito para continuar.
Caribú
9

Un Arduino Nano alimentado por USB tendrá una referencia de voltaje ADC que no se puede confiar, debido a la tolerancia de +/- 5% del voltaje USB entrante. Además de eso, el Nano tiene un diodo Schottky MBR0520 (D1) que caerá entre 0.1 y 0.5 V dependiendo de sus propias tolerancias de fabricación, su temperatura y el consumo de corriente de su placa.

¿Qué puedes hacer al respecto?

El MCU a bordo del Arduino Nano es un ATmega328P. El ADC de Nano puede escalar sus lecturas de voltaje analógico de acuerdo con varias referencias disponibles (y puede elegir la que más le convenga). Puede hacerlo a través de la analogReference (type)función y elegir entre las siguientes referencias type:

  • PREDETERMINADO: la referencia analógica predeterminada de 5 voltios (en placas Arduino de 5 V) o 3,3 voltios (en placas Arduino de 3,3 V)
  • INTERNO: Una referencia integrada, igual a 1.1 voltios en el ATmega168 o ATmega328 y 2.56 voltios en el ATmega8 (no disponible en el Arduino Mega) [...]
  • EXTERNO: el voltaje aplicado al pin AREF (solo de 0 a 5 V) se utiliza como referencia.

Fuente: analogReference

Este es el esquema ADC de lo que hay dentro del ATmega328 para que pueda ver lo que está sucediendo allí:

ATmega328P bloque ADC

Fuente: hoja de datos ATmega328

Entonces, la solución directa es construir un divisor de voltaje débil para obtener el voltaje que desea medir por debajo de la referencia interna de 1.1 V, y luego configurarlo en analogReferenceconsecuencia.

El divisor de voltaje debe ser débil (valores R altos) para que no extraiga demasiada corriente de la batería, pero no demasiado débil como para ser cargado por la impedancia de entrada del ADC.

Prima

Sin embargo, si necesita una referencia de voltaje más alta que la referencia interna de banda prohibida de 1.1 V del ATmega328, todavía no tiene suerte. Una opción sería utilizar la salida del regulador LDO de 3.3 V del FT232RL incorporado, que está disponible en el pin 14 del encabezado, pero tampoco creo que sea confiable. La hoja de datos FT232RL lo especifica a 3.0 - 3.6 V (nominal 3.3 V)

Entonces, una solución universal sería construir una referencia de voltaje externo basada en un TL431 barato . Eso podría darle una referencia confiable de hasta 4.0 - 4.25 V con una precisión de +/- 1%.

El circuito de referencia de voltaje externo sería algo tan fácil como esto (¡y el TL431 está disponible en el paquete TO-92 amigable para la placa de pruebas!):

Regulador de voltaje de derivación basado en TL431

Enric Blanco
fuente
Gracias por esta respuesta integral y todas las alternativas que podría adoptar: probablemente iré simple y haré un divisor de voltaje para escalar mi entrada entre 0 y 1.1. La sugerencia sobre los valores de resistencia fue valiosa para mí, gracias
Caribú
3

Tengo una página sobre el convertidor ADC en el Atmega328P . Algo más abajo en la página describo referencias de voltaje. Puede usar el chip TL431 para proporcionar una variedad de voltajes de referencia, por ejemplo 4V:

Referencia de voltaje de 4V

Al cambiar las resistencias puede obtener otros voltajes (parece que quiere alrededor de 4.2V).

El voltaje de salida no está influenciado por el voltaje de entrada (5V en este caso).

La página vinculada describe cómo puede elegir valores de resistencia.

Nick Gammon
fuente
2

¿La conversión del recuento de ADC a voltaje depende del voltaje real del pin + 5v?

sí y no: el módulo adc se preocupa por Vref, que se puede suministrar a través de Vdd, interna o externamente.

En caso afirmativo, ¿cuál es el método aceptado para obtener ese voltaje de la placa?

configurando el módulo adc. la hoja de datos del dispositivo debe tener registros / bits que deben configurarse para eso.

dannyf
fuente