Problem with my readVoltage() function

Hi there,

The main problem with the following test code (readVoltage()) that I have is that it only diplays the factional part of voltage reading. For example the voltage reading should be xx.yy. But it only displays yy part and not the xx part. It actually display xx part but always zero which can not be. Where is the problem. Thanks

char buffer2[]="The reading is \n";	// 
char buffer3[]=" volts \r";	// 


void main(void)
{

	InitUART();
	char selection;
	
	DDRB = 0xFF;
	PORTB = 0xFF;
	int ADC_int;
	float ADC_float;
	int hundreds;
	int tens;
	
	//hundreds = (ADC_int/100);
	//tens = (ADC_int-(hundreds*100));*/
	
	InitADC();
	
	//ADC_float = ADCH;
	//hundreds = (ADC_int/100);
	
	
	
	
	
	
	while(1)
	{
	
		//ADC_float = ADCH;
		//DC_float = ReadADC();
		//ADC_int = (ADC_float/51)*100;
		//hundreds = (ADC_int/100);
		//tens = (ADC_int-(hundreds*100));
		
		
		selection =	receive();
		
		if (selection == 'P')
		{
			readVoltage();
		}


	}
	
}



void readVoltage(void)
{
	char integerPartOfVoltage[]={'0','0','0','\0'};
	char fractionalPartOfVoltage[]={'0','0','0','\0'};
	int integerPart = 0;
	int fractionalPart = 0;
	int ADCresult = 0;
	ADCresult = ReadADC();
	integerPart = ADCresult/50;
	fractionalPart = ADCresult%50;
	
	itoa(integerPart, fractionalPart, 10);
	itoa(fractionalPart, fractionalPartOfVoltage, 10);
	displayMessage2();
	transmit(integerPartOfVoltage[0]);
	transmit('.');
	transmit(fractionalPartOfVoltage[0]);
	displayMessage3();
}



void displayMessage2(void)
{
	int i=0;
	while(buffer2[i] != 0 )
	{
		transmit(buffer2[i++]);
	}
}

void displayMessage3(void)
{
	int i=0;
	while(buffer3[i] != 0 )
	{
		transmit(buffer3[i++]);
	}
}




void InitADC(void)
{

	ADCSRA |= (1 << ADPS2) | (1 << ADPS1) |(1 << ADPS0); // Set ADC prescalar to 128 - 125KHz sample rate @ 16MHz 
	ADMUX |= (1 << REFS0);	 // Set ADC reference to AVCC
	ADMUX |= (1 << ADLAR); //Left adjust ADC result to allow easy 8 bit reading
	
	// No MuX values needed to be changed to use ADC0
	
	ADCSRA |= (1 << ADATE);    //Set ADC to Free-Running mode
	ADCSRA |= (1 << ADEN);  // Enable ADC
	//ADCSRA |= (1 << ADSC);  // Start A2D conversions
	
	
}



int ReadADC(void)
{

	ADCSRA |= (1 << ADSC);  // Start A2D conversions
	while(!(ADCSRA & (1<<ADIF)));	// wait for conversion to complete
	ADCSRA |= (1 << ADIF);  // necessary ?
	
	return(ADCH);
}

Shouldn’t you be reading ADCL and ADCH? Details are in the data sheet for the AVR you are using.

Leon

Nah, you can see his ADC init function is doing left-adjust, he only needs to read ADCH and he’ll get an 8 bit number.

I’d venture that this is the problem line:

itoa(integerPart, fractionalPart, 10);

Based on the rest of the code, it should actually be:

itoa(integerPart, integerPartOfVoltage, 10);

…since that’s what you’re transmitting.

Hi there,

The problem with the function is solved, at least partially. There was a mistake in using the function itoa(). Now I get the reading the I expect. However there are two problems.

Problem 1:

I took several repeated readings at different positions of pots. For the most part the readings are consistent but there are some variations. What causes those variations and how to prevent them? See below for the reading result which appear of Brays++ terminal on PC

Problem 2:

I wanted to make sure that the values that I read using mcu is correct. So I compared each reading with the actual readings that I took using multimeters. As you can see below, the reading by mcu is not that accurate speacially the fractional part of it. How to get a matching reading? I tried to read the other part of the array like array[1], array[2] but I could not increase the number of digits either for integer part or factional part. How to do that? I mean how to display this for example 5.23 ? Thanks

multimeter(V)	MCU (V)

3.95 		3.4
2.954		2.4
1.204		1.5
2.819		2.3
0.990		0.4
0.698		0.3
4.04		4.1
4.38		4.1
4.85		4.4
5.04		5.2
5.05		5.3
related to problem 1 above:
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 

The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.9 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 

The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 
The reading is 1.4 volts 

The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 
The reading is 3.1 volts 

The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 

The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 
The reading is 4.1 volts 

The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts 
The reading is 4.3 volts
 
The reading is 4.3 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 5.0 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 5.0 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 


The reading is 5.3 volts 
The reading is 5.3 volts 
The reading is 5.0 volts 
The reading is 5.4 volts 
The reading is 5.4 volts 
The reading is 5.3 volts 
The reading is 5.1 volts 
The reading is 5.3 volts 
The reading is 5.0 volts 
The reading is 5.3 volts 
The reading is 5.4 volts 
The reading is 5.4 volts 
The reading is 5.2 volts 
The reading is 5.3 volts 
The reading is 5.4 volts 

The reading is 4.4 volts 
The reading is 5.3 volts 
The reading is 5.4 volts 
The reading is 5.3 volts 
The reading is 5.3 volts 
The reading is 5.3 volts 
The reading is 5.2 volts 
The reading is 5.3 volts 
The reading is 5.2 volts 
The reading is 5.3 volts 
The reading is 5.1 volts 
The reading is 5.3 volts 
The reading is 5.1 volts 
The reading is 5.3 volts 
The reading is 5.2 volts 
The reading is 5.4 volts 

The reading is 5.3 volts 
The reading is 5.2 volts 
The reading is 5.3 volts 
The reading is 5.3 volts 
The reading is 5.2 volts 
The reading is 5.3 volts 
The reading is 5.2 volts 
The reading is 5.4 volts 
The reading is 5.3 volts 
The reading is 5.4 volts 
The reading is 5.2 volts 
The reading is 5.3 volts 
The reading is 5.2 volts 
The reading is 5.3 volts 
The reading is 5.2 volts 
The reading is 5.2 volts 


The reading is 5.4 volts 
The reading is 5.5 volts 
The reading is 5.3 volts 
The reading is 5.3 volts 
The reading is 5.3 volts 
The reading is 5.2 volts 
The reading is 5.3 volts 
The reading is 5.0 volts 
The reading is 5.3 volts 
The reading is 5.4 volts 
The reading is 5.3 volts 
The reading is 5.2 volts 
The reading is 5.2 volts 
The reading is 5.2 volts 
The reading is 5.3 volts 

The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 
The reading is 4.4 volts 


The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 
The reading is 4.2 volts 

The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 4.0 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 4.0 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 
The reading is 3.4 volts 

The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 
The reading is 2.4 volts 


The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 
The reading is 0.3 volts 

The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.9 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts 
The reading is 0.1 volts
  1. Good analog grounding, low noise power supplies, a good voltage reference. Pots also can be especially noisy.

  2. Your decimal conversion system is very suspect. An input of 255 (pegged analog input) will return 5.5. Is your Vref/Vadc maxing out at 5.5? Further more, 240 % 50 = 40, and 240 / 50 = 4, leading to you printing 4.4. The correct result assuming max voltage at 5.0 and 0.0196 volts per ADC count is 4.704V.

You could bandaid it by making the modulus with a leading 0 and always two digits. It would then be a vague approximation of the true math.

theatrus:

  1. Good analog grounding, low noise power supplies, a good voltage reference. Pots also can be especially noisy.

So that means I am not the problem. I can live with that for now

  1. Your decimal conversion system is very suspect. An input of 255 (pegged analog input) will return 5.5. Is your Vref/Vadc maxing out at 5.5? Further more, 240 % 50 = 40, and 240 / 50 = 4, leading to you printing 4.4. The correct result assuming max voltage at 5.0 and 0.0196 volts per ADC count is 4.704V.

I use STK 500 and my power supply to pot is a desk top PC power supply. It provide a very stable 5 V, actually 5.04 V as measured by multimeter.

You could bandaid it by making the modulus with a leading 0 and always two digits. It would then be a vague approximation of the true math.

I would implement that just for learning but my aim is accuracy and precision. Thanks

.

Hi there,

As was suggested, I tried to take several readings and then averged them. Wow!! the results as you see below vary wildly. I am not sure what is wrong or what am I doing wrong. Is the averaging method correct?

int ReadADC(void)
{

	int i;
	int tempADC = 0;
	int tempADCH = 0;
	
	
	
		ADCSRA |= (1 << ADSC);  // Start A2D conversions
		while(!(ADCSRA & (1<<ADIF)));	// wait for conversion to complete
	
	
	
	for (i=0;i<8; i++)
	{
	
		ADCSRA |= (1 << ADSC);  // Start A2D conversions
		while(!(ADCSRA & (1<<ADIF)));	// wait for conversion to complete
		//ADCSRA |= (1 << ADIF);  // necessary ?
		tempADC +=(ADCH << 8);	// read ADCH register
		
		// accumulate result, 8 readings for  averaging
		tempADCH += tempADC;
		//ADCr = ADCr + ADC_temp;
	}
	
	tempADCH = tempADCH >> 3;	// average the 8 readings
	
		
	return(tempADCH);
}



The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 
The reading is 0.0 volts 

The reading is -.- volts 
The reading is -.- volts 
The reading is -.- volts 
The reading is -.- volts 
The reading is -.- volts 

The reading is 9.3 volts 
The reading is 1.4 volts 
The reading is 2.4 volts 
The reading is -.- volts 
The reading is 7.2 volts 

The reading is 2.3 volts 
The reading is 2.2 volts 
The reading is 2.8 volts 
The reading is 2.2 volts 
The reading is 3.1 volts 

The reading is 6.4 volts 
The reading is 6.0 volts 
The reading is 7.1 volts 
The reading is 6.6 volts 
The reading is 5.3 volts 


The reading is -.- volts 
The reading is -.- volts 
The reading is -.- volts 
The reading is -.- volts 
The reading is -.- volts 

The reading is 1.1 volts 
The reading is -.- volts 
The reading is -.- volts 
The reading is -.- volts 
The reading is 5.3 volts 

The reading is 7.2 volts 
The reading is -.- volts 
The reading is 7.2 volts 
The reading is -.- volts 
The reading is 7.2 volts 

The reading is -.- volts 
The reading is -.- volts 
The reading is -.- volts 
The reading is 7.8 volts 
The reading is -.- volts 
The reading is 7.3 volts 
The reading is 7.1 volts 
The reading is 7.1 volts 
The reading is -.0 volts 
The reading is 7.1 volts

.

Why are you shifting ADCH by 8 bits? Also, why tempADC and tempADCH? Your accumulator is double-adding this way.

Try this to average 8 readings…

   tempADC = 0;
   for (i=0;i<8; i++) 
   { 
       ADCSRA |= (1 << ADSC);  // Start A2D conversions 
       while(!(ADCSRA & (1<<ADIF)));   // wait for conversion to complete 
       tempADC += ADCH;   // read ADCH register 
   }
   tempADC = tempADC >> 3;   // average the 8 readings