0
votes

I am trying to read values from ADC0 on the ATMEGA328p. The values expected are between 0-5v. This is due to ADC0 being connected to a potentiometer connected to the 5v output of a Xplained mini. I am getting either 0v or 5v usually. With no variation when the potentiometer is changed. I have looked at multiple ADC examples and tutorials online but cant find the error in my code.

void adc_initialise (){
    //set vref to AVcc, channel selection is initially ADC0 as wanted
    ADMUX |= (1<<6);
    //set ADC enable, Set adc clock prescalar 64
    ADCSRA |= (1<<7)|(1<<2)|(1<<1);
}

uint16_t adc_read (){
    ADCSRA |= (1<<6); // start conversion
    while( ADCSRA & (1<<ADSC) ); //wait until conversion is complete
    return ADCW;
}

float adc_calculation(uint16_t adcValue){
    float stepSize = (5.0/1024.0);
    float voltageIn = adcValue*stepSize;
    return voltageIn;   
}

then in my main i have

while(1){   
    adc_initialise();
    uint16_t adcValue = adc_read();
    float voltageIn = adc_calculation(adcValue);
    adcConverterToUART(voltageIn);//I know that this part of the code is working as I have hardcoded many test values and all have transmitted correctly.
}

And as mentioned above I know the error is not in my UART code but somewhere in the above ADC code. Cheers in advance for any help.

1
Store the integer value somewhere, and inspect the memory, and/or place a breakpoint there. Also, of course verify with a multimeter that you really do have a varying voltage at the point the ADC is connected. Electronics is hard. :) - unwind

1 Answers

0
votes

I could mention a few things. You could try it if it help.

  1. You should do your adc_initialise() before the while(1). You initialize it again and again.
  2. while( ADCSRA & (1<<ADSC) ); here you should add maybe NOPs that the compiler don't optimize it out of the code.

The rest looks good in my eyes.

Do you get any value of the conversion ?

mfg

EDIT1:

I looked in one of my old files. There we made it like this to get the value from the ADC.

  // Get count value
  adValue  = ADCL;
  adValue |= (UI_16_t)(ADCH << 8);

ADCL is the low byte of the value and ADCH the high byte. We shifted the high byte in the front of the low byte to get the value.