Reading multiple adc channels

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

Hi All

 

I having some issues reading the voltage from two ADC channels. It seems like both channels are outputting the same value, where it should be different. This is my code.


void InitADC(void)
{
	//ADMUX=(1<<REFS0);                         // For Aref=2.5V;
	ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); //Rrescalar div factor =128
}

uint16_t ReadADC(uint8_t ch)
{
	ADMUX =0;
	ADMUX |=(1<<ch);
	//Start Single conversion
	ADCSRA|=(1<<ADSC);
	//Wait for conversion to complete
	while(!(ADCSRA & (1<<ADIF)));
	ADCSRA|=(1<<ADIF);
	uint16_t number = ((ADCH<< 8)|ADCL);			
	return(number);
}

I am then calling the following in my code

chA = ReadADC(1);
chB = ReadADC(2);

At fist i though i would need to clear ADMUX, which i am doing but it make no difference.

 

Please advice what i am doing wrong?

Thanks

Regards

DJ

Last Edited: Sun. Mar 29, 2020 - 07:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry i am using the ATMEGA48PA, but it seems like i have posted this on wrong page. How can i change it?

Thanks

Regards

DJ

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

How do you expect to get your desired reference voltage, when you clear ADMUX?

 

Are all Vcc and Gnd pais connected, including AVcc?

What voltage is on AVcc pin, RIGHT AT THE PIN?

What voltage is on AREF pin, RIGHT AT THE PIN?

What voltage is on PC1, RIGHT AT THE PIN?

What voltage is on PC2, RIGHT AT THE PIN?

What counts are you getting?

What counts do you expect?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
uint16_t ReadADC(uint8_t ch)
{

	ADMUX = ch | (1 << REFS0);
	//Start Single conversion
	ADCSRA|=(1<<ADSC);
	//Wait for conversion to complete
	while((ADCSRA & (1<<ADSC)));

    return ADC;
}

I dare say the root cause was your ADMUX |= (1<<ch);

It is not one bit per channel - it is an enumeration to select the input.

 

I have no idea why you would bother with the ADIF flag  except if your were using interrupts. Use the ADSC flag for what is was meant for.

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

Note that in #4 Kartman changed:

	uint16_t number = ((ADCH<< 8)|ADCL);			
	return(number);

to be:

    return ADC;

this is also quite important. There is a dictated reading order for ADCL/ADCH and your original code may not achieve it (it's up to the compiler). But as Kartman's change also chose there's no need to deal with ADCL/ADCH separately anyway - the compiler provides "ADC" to red the whole thing (in the correct order) in one go.