ADC strange output

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am using a Mega88 running on its internal 8M clock to measure 2 voltages, using 10bit resolution, and output them on a LCD. Sounds simple enough.
ADC(1) and ADC(2) are used.
I get strange results. the output on the display seems to be unstable and varies over a wide range. if I comment out the first conversion, ADC(1), I get the correct result for ADC(2). Likewise if I then comment out the second conversion ADC(2), I get the correct result for ADC(2).
Here is my code to set up the ADC

	ADMUX=(1<<REFS0);    // For Aref=AVcc;
	ADCSRA=(1<<ADEN)|
		(1<<ADPS2)|
		(1<<ADPS0)|
		(1<<ADPS1); 	//prescalar div factor =128
	DIDR0 = 0xff;		// Disable the digital Function for PORTC

This is how I am reading the ADC

uint16_t ReadADC(uint8_t ch)
{
   //Select ADC Channel ch must be 0-7
   ch=ch&0b00000111;
   ADMUX|=ch;

   //Start Single conversion
   ADCSRA|=(1<<ADSC);

   //Wait for conversion to complete
   while(!(ADCSRA & (1<<ADIF)));

   //Clear ADIF by writing one to it
   ADCSRA|=(1<<ADIF);

   return(ADC);
}

and finally this the portion of my main code

int16_t  temp;

temp = ReadADC(1)*40;
utoa( temp , dig, 10);
lcd_gotoxy(2,0);
lcd_puts(dig);	

temp = ReadADC(2)*5;
utoa( temp , dig, 10);
lcd_gotoxy(2,1);
lcd_puts(dig);		

I understand the output on the display will be unformatted.

I think maybe I am running out of stack but am not sure. Any pointer as where I should look to fix this would be greatly appreciated.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   ADMUX|=ch;

This may keep the old channel bits plus the new channel bits. ie reading the wrong channel. Should read ADMUX, clear the lower 3 bits and then OR the new channel to be read.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

so something like

ADMUX = (ADMUX & 0xe0) | (ch & 0x07)  //Maintain state of REFS1, REFS0 and ADLAR and then change the channel selection 

would be better?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Should do. Tried it out yet :)

May be a little faster if you OR the values of REFS1, REFS0 and ADLAR along with ch rather than reading ADMUX, anding it and then OR it, but then it it not as flexible for general purpose ADC reading.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I will have a go. Thanks.
It is Footy season again so watch out for mis-kicked balls.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
watch out for mis-kicked balls.
...that can be rather painfull.... :lol:

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My inability to write good code continues to assound me.
ADMUX selection now works like a treat.
I used

ADMUX = (ADMUX & 0xe0) | (ch & 0x07)

Many thanks