ADC gives unexpected binary numbers in proteus

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

I am writing a code to use the the ADC peripheral of the Atmega32.

I use the 'ADC_init' function to give the ADC choices for Vref, number of single ended channel, and division factor(prescaler). This function writes the proper values in the ADC registers as the given choices imply. It left justifies the result in ADC registers by default , sets the ADEN and ADSC bits in ADCSRA register.

 

Here in this picture, I make Vref = internal 2.56V, choose single ended channel 3, and choose division factor of 128.

  

 

As you can see in the I/O section in AS7, the ADCSRA, ADMUX registers have the proper values after calling 'ADC_init' and before calling 'ADC_readChannel'.

 

This is the code of the 'ADC_readChannel 'function

void ADC_readChannel(void)
 {
	while((ADC_ADCSRA & (1 << ADSC)) == 1);

	uint8 lowByte = (ADC_ADCL & 0b11000000);
	uint8 highByte = ADC_ADCH;

	GPIO_writePortVal(PORTB_ID, lowByte);
	GPIO_writePortVal(PORTC_ID, highByte);

	SET_BIT(ADC_ADCSRA, ADIF);
	SET_BIT(ADC_ADCSRA, ADSC);
 }

GPIO_writePortVal, and SET_BIT work perfectly.

I take the ADCL contents and write them into PortB, and take the ADCH contents and write them into PortC.

 

For Vref = 2.56V, Step size = 2.56V/1024 = 2.5 mV.

 

Comparing with the binary data I calculate,when I simulate this code in Proteus, the ADC gives some correct and some incorrect binary data, as shown in the following pictures.

 

 

This binary data is correct. For 0.23V the output should be 92 decimal or 0b0001011100.

 

 

 

This is incorrect. For 0.31V the output should be 124 or 0b0001111100.

 

 

 

 

This is incorrect. For 2.02V the output should be 808 or 0b1100101000.

 

And it gives the same binary output for analog voltages from 0.51V to 2.56V, which is in the picture above.

 

Thus, the ADC produces incorrect binary output. If anyone knows where the problem is it would be appreciated.

Thank you. 

This topic has a solution.
Last Edited: Mon. Aug 26, 2019 - 09:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Forget the leds, just provide the counts.  what count do you get & what count do you expect?

 

If you think you might get 15  (01111) and get 16  (10000) that will be very typical (within a count or two), however the led bit patterns are completely different. 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Thu. Aug 22, 2019 - 03:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What do you have in ADMUX? The way you read ADCL/ADCH suggests you are using ADLAR but what's the point in that if you plan to read all 10 bits? Why not forget ADLAR and then just read the whole of ADCL and take the other two (high) bits from the bottom 2 bits of ADCH ?

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

avrcandies wrote:

Forget the leds, just provide the counts.  what count do you get & what count do you expect?

 

If you think you might get 15  (01111) and get 16  (10000) that will be very typical (within a count or two), however the led bit patterns are completely different. 

 

How can I get the counts from the ADC registers without using LEDs to provide display ?

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

It's a simulator - add a simulated terminal and print the results to the simulated UART that is attached to the simulated terminal

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

clawson wrote:

What do you have in ADMUX? The way you read ADCL/ADCH suggests you are using ADLAR but what's the point in that if you plan to read all 10 bits? Why not forget ADLAR and then just read the whole of ADCL and take the other two (high) bits from the bottom 2 bits of ADCH ?

 

The same problem exists when I leave theh ADLAR bit cleared.

This is the new code

 

void ADC_readChannel(void)
 {
	while((ADC_ADCSRA & (1 << ADSC)) == 1);

	uint8 lowByte = ADC_ADCL;
	uint8 highByte = (ADC_ADCH & 0b000011);

	GPIO_writePortVal(PORTB_ID, lowByte);
	GPIO_writePortVal(PORTC_ID, highByte);

	SET_BIT(ADC_ADCSRA, ADIF);
	SET_BIT(ADC_ADCSRA, ADSC);
 }

 

Last Edited: Thu. Aug 22, 2019 - 04:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

It's a simulator - add a simulated terminal and print the results to the simulated UART that is attached to the simulated terminal

 

I know the serial port, but don't know how to use it at the moment.

 

Last Edited: Thu. Aug 22, 2019 - 04:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AhmedH wrote:
How can I get the counts from the ADC registers without using LEDs to provide display ?

clawson wrote:
It's a simulator

So you should be able to stop the program with a break point and examine any register or memory location!!!

That is what simulators are good at!

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

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

ki0bk wrote:
That is what simulators are good at!

 

Not all of them....

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

AhmedH wrote:

Thus, the ADC produces incorrect binary output.

 

I am afraid that, unless there is a minor mistake in the hex file, we may say instead that Proteus produces incorrect ADC binary output sad

 

Kerim

 

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

KerimF wrote:
we may say instead that Proteus produces incorrect ADC binary output 
That's because Proteus can't do binary; only base 6.

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

Why are you bothering to do this simulation anyhow--why aren't you busy building your circuit?  You will encounter reality there.

 

You can convert your "leds" to a number...then you can say, I expected 66, but got 63...not bad at all.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It was all about connecting a capacitor to the AREF pin, and connecting a capacitor and an inductor to the AVCC pin. These extra connections gives the ADC the required accuracy to produce the correct numbers.

Now the ADC produce the correct numbers.

 

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

Now I have a question related to the ADC :

If at some moment the ADH, and ADCL registers have a result of a conversion, and a new conversion starts while the data in the ADCH, ADCH registers haven't been picked yet 

Will the new result overwrite the old one ?

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

Yes the old results will be wiped out by any new results..there is nowhere else to put them!

 

It's highly doubtful the simulator will care about adding an LC to AVcc---you are probably fooling yourself.

In a real board, with noise, it  can make a small difference.

 

 

Oh, you had it connected to nothing???!?? ...that's a different story

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Thu. Aug 22, 2019 - 11:58 PM