Search code examples
cadc

potentiometer adc practice in atmega128


I'm a beginner in this field. My goal is to change the output of 8 LEDs (which are connected to PORTA) according to the potentiometer. I have connected the middle line of the potentiometer to PF0, which is ADC0. I also connected the other two lines to the 5V and ground.

I know there's no problem with the chip or connection because the LEDs are working just fine.

But no matter how I change the code below (what I mean by changing is by slightly changing the ADMUX and ADCSRA registers) no output is shown!

I am using atmega128 with 16MHZ clock. Below is the code that I'm trying to solve.

#include <asf.h>
#include <avr/io.h>
#define F_CPU 16000000L

int init_board(void)
{
  DDRA=0xff;
  PORTA=0x01;
}

int ADC_init(void)
{
  //ADCSRA
  ADCSRA = 0b10000111;
  //ADMUX
  ADMUX = 0b01100000; // middle line connected to ADC0
}

int main (void)
{   
  init_board();
  ADC_init();

  ADCSRA |= (ADSC >> 1);
  while(1)
  {
    if(ADSC == 0)
    {
      uint8_t disp_value = ADCL;
      PORTA = disp_value; 
      delay_ms(200);
      ADCSRA |= (ADSC >> 1);
    }
  }
}

I have no idea why the code doesn't work.

I suppose it's because it didn't set my register correctly, but I've followed all the instructions on the atmega128 datasheet.


Solution

  • First issue is your bit shifting, it should be ADCSRA |= (1 << ADSC).

    Next issue is results reading. You set fifth bit of ADMUX to 1, so ADLAR=1 and in that mode result is left adjusted so you should read ADCH.

    Moreover when you switch to 10-bit resolution, i.e. you start working with multi-byte results, be aware that reading only ADCL is not enough, see datasheet 23.3 for explanation: "Once ADCL is read, ADC access to data registers is blocked. This means that if ADCL has been read, and a conversion completes before ADCH is read, neither register is updated and the result from the conversion is lost. When ADCH is read, ADC access to the ADCH and ADCL Registers is re-enabled."

    Lastly, using hardcoded delays for reading is not good practice especially when you change code later to read ADC as fast as possible. In such case after conversion start you should check if ADIF flag is set or react with interrup when ADEN is set. Refer to datasheet for details.