comportamiento extraño ADC (ATmega)

4

Estoy construyendo un osciloscopio de hobby en ATmega16. Estoy probando el ADC generando una onda cuadrada a 2 kHz con pequeña amplitud y aplicándolo al pin del ADC a través de una entrada capacitiva con un divisor de voltaje para cambiar el nivel cero.

AsíescomosevelaseñaldespuésdesermuestreadaporADC:

Se ve bien, pero después de comenzar a cambiar el nivel cero ajustando el potenciómetro, obtengo estos picos extraños:

Despuésdecambiardenivelunpocomásalto,sevebienotravez:

Y luego el patrón se repite:

En general, obtengo 3 rangos donde aparecen los picos.

Alguna información

  • AVR se está ejecutando a 16MHz
  • ADC usa voltaje de referencia interno de 2.56
  • ADC está en modo de funcionamiento libre a 125 kHz (prescaler = 128)
  • Transfiero datos a través de CP210 a una tableta de Android que se usa para trazar en tiempo real. El circuito también se alimenta desde la tableta. Obtengo los mismos resultados cuando el circuito está conectado a la PC.
  • La velocidad en baudios de USART es 500000b / s (UBRR = 1)
  • AVcc y AREF no están conectados. También intenté conectar AVcc a Vcc y agregar un límite de .1uF entre Gnd y AVcc, pero esto no tuvo ningún efecto.

Un poco más de información

  • este ruido no proviene del generador (probado con un osciloscopio analógico)
  • este ruido no proviene del potenciómetro
  • LFUSE = 0xFF, HFUSE = 0x89.

rutina de inicialización de ADC

ADMUX = (1 << REFS0); // AVCC with external capacitor at AREF pin
ADCSRA = (1 << ADEN)
        | (1 << ADIE)
        | (1 << ADATE) 
        | (1 << ADPS0)
        | (1 << ADPS1)
        | (1 << ADPS2); // Division factor = 128
MCUCR |= 1 << SM0;
MCUCR |= 1 << SE; // Sleep-mode enabled
ADCSRA |= (1 << ADSC);

rutina de transferencia de datos ADC

volatile uint8_t adcLow;
volatile uint8_t adcHigh;

int main(void) {
    ....
    while (1) {
        if (ADCSRA != 0x00) {
            USARTSendByte(adcLow);
            USARTSendByte(adcHigh);
        }
    }
}

ISR(ADC_vect) {
    adcLow = ADCL;
    adcHigh = ADCH;
}
    
pregunta Ashton H.

1 respuesta

4

Los picos están claramente recortados a valores muy particulares (probablemente una potencia de dos) o estás usando enteros con signo que son demasiado pequeños para contener todo el valor.

No proporcionaste el código fuente completo, así que supongo que aquí. Es probable que intentes ajustar el valor medido en un entero demasiado pequeño. Haz un volcado de las vástagos que obtienes y encuentra los picos en ellos. Luego mire la representación binaria de estos números y vea si puede encontrar algo en común.

Con una estimación rápida, la distancia entre dos picos es de aproximadamente 1.28 V, un poco demasiado casualmente cercana al tamaño de un entero de 8 bits con signo.

Recomiendo usar definiciones de tipo como int8_t [-128: 127], uint8_t [0: 255], int16_t [-32768: 32767], uint16_t [0: 65535], int32_t [-2147483648: 2147483647] y uint32_t [0: 4294967295], que muestra claramente qué tan grande es la variable.

    
respondido por el jippie

Lea otras preguntas en las etiquetas