¿Cómo puedo obtener una relación lineal entre un divisor de voltaje y un ADC?

4

Estoy haciendo un medidor de nivel pequeño usando un microcontrolador ATtiny. Utiliza un potenciómetro lineal de 5K como un divisor de voltaje acoplado a un pin ADC. Hasta ahora está funcionando, excepto que los valores digitales no parecen estar bien correlacionados con el voltaje medido.

El esquema:

simular este circuito : esquema creado usando CircuitLab

El código relevante:

#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>

int adc_value;

void ADC_init()
{
    // Enable ADC
    ADCSRA |= (1 << ADEN);

    // Set ADC reference to AVCC
    ADMUX  |= (1 << REFS0);

    // Prescaler /8, 125kHz ADC sample rate @ 1MHz
    ADCSRA |= (0 << ADPS2) | ( 1 << ADPS1) | (1 << ADPS0);

    // Auto trigger enable
    ADCSRA |= (1 << ADATE);

    // Use input channel ADC2 (PB4)
    ADMUX |= (1 << MUX1) | (0 << MUX0);

    // Left shift ADC result
    ADMUX  |= (1 << ADLAR);

    // Start converting
    ADCSRA |= (1 << ADSC);
}

int main(void)
{
    DDRB = 0x07;
    PORTB = 0x00;

    ADC_init();

    while(1)
    {
        adc_value = ADCH;

        if (adc_value < 64)
            // output A
        else if (adc_value < 128)
            // output B
        else if (adc_value < 192)
            // output C
        else
            // output D
    }
}

Medí el voltaje en PB4 y noté los puntos en los que cambió la salida:

  • Mínimo: 196 mV
  • 64: ~ 235 mV
  • 128: ~ 500 mV
  • 192: ~ 770 mV
  • Máximo: 2.849 V

Esperaba que aproximadamente 1.5 V estuvieran donde se obtiene un valor digital de 128, no 500 mV.

Si entiendo correctamente, el ATtiny13A tiene un ADC de 10 bits, cuyos valores se almacenan en dos registros, ADCH y ADCL. Con ADLAR (el ajuste a la izquierda) habilitado, el valor se cambia al registro ADCH y efectivamente se descartan dos bits.

La hoja de datos indica:

  

Si el resultado se deja ajustado y no se requiere una precisión de más de 8 bits, es suficiente para leer ADCH.

Estoy confundido acerca de por qué estoy obteniendo una conversión no lineal en el ADC. ¿Puedes explicar lo que puedo estar pasando por alto?

    
pregunta JYelton

2 respuestas

11

Dice que a 128, mide alrededor de 500 mV. Esto significa que a escala completa (256) se mide aproximadamente 1V.

Según la hoja de datos (14.12) con:

// Set ADC reference to AVCC
ADMUX  |= (1 << REFS0);

En realidad haces lo siguiente:

  

Este bit selecciona la referencia de voltaje para el ADC, como se muestra en la Tabla 14-2. Si este bit se cambia durante una conversión, el cambio no entrará en vigencia hasta que se complete esta conversión (se establece ADIF en ADCSRA).

Tabla 14-2.

Voltage Reference Selections for ADC
REFS0   Voltage Reference Selection
0       VCC used as analog reference.
1       Internal Voltage Reference.

El párrafo 14.3 dice:

  

El ADC convierte una tensión de entrada analógica a un valor digital de 10 bits a través de una aproximación sucesiva. El valor mínimo representa GND y el valor máximo representa el voltaje en VCC o un voltaje de referencia interno de 1.1V .

En conclusión, está configurando el voltaje de referencia del ADC a 1.1 V y con ese conocimiento, sus conclusiones son bastante precisas.

    
respondido por el jippie
4

El comentario no coincide con el código.

// Set ADC reference to AVCC
ADMUX  |= (1 << REFS0);

Pero la hoja de datos dice:

    
respondido por el markrages

Lea otras preguntas en las etiquetas