Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Please explain how to get correct voltage from A2d return value

Status
Not open for further replies.

ayesh

Newbie level 1
Joined
May 27, 2012
Messages
1
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,303
This will give an output for P .P is a voltage. But when we set any voltage(0-5v) as input, output not shows the correct value.

please give a solution...........

Code:
/* Sample code to set up the A2D module */
void init_a2d(void){
	ADCON0=0x50;	// select Fosc/2
	ADCON1=0x80;	// select left justify result. A/D port configuration 0
	ADON=1;		// turn on the A2D conversion module
}

/* Return an 8 bit result */
unsigned char read_a2d(){

	GO=1;	// initiate conversion on the selected channel
while(GO)continue;

	return((ADRESH<<8)+(ADRESL));

}

void main(void){
	unsigned int x,p;
	

sci_Init(9600,0);
	init_a2d();	// initialise the A2D module
	GIE=0;		// we don't want interrupts
TRISA=0xff;
	TRISB=0x00;	// the lower four bits of POTRB will be used in output mode
	TRISC=0x80;
PORTC=0xff;
		
	
		while(1){
		x=read_a2d();		// sample the analog value on RA0
[COLOR="#FF0000"]   p = (x*5000)/1023;[/COLOR]

char array[10];
int i = p;
sprintf(array, "%d", i);


for(int j=0;j<5;j++)
sci_PutByte(array[j]);

while(1){
}
		
	}
}
 
Last edited by a moderator:

p = (x*5000)/1023; ?

I think this is causing an overflow of the unsigned int x.

It is divide by 1024 by the way, 0 -1023 is 1024 values.
 

p = (x*5000)/1023; ?

I think this is causing an overflow of the unsigned int x.

It is divide by 1024 by the way, 0 -1023 is 1024 values.

I think divide by 1023 is fine, since 1023 is the maximum value. So result varies from 0-1023 as you mentioned. So, maximum possible value is 1023. So, p = (1023*5000)/1023 = 5000. If you had divide by 1024, answer would be 4995, which would be wrong, as 1023 should represent 5000 and 1024 ADC result is not possible.

_________________________________________________________________________________________

p is declared as int. So, max possible value is 65535. So, as btbass mentioned, p overflows. Declare p as long int.

Hope this helps.
Tahmid.
 

I disagree!
This is called the off by one error when an array starts at 0.
0 is a valid value. 0 - 1023 is 1024 different values.
2 to the power of 10 = 1024.
10 bits is 1024 different values.
 

Hello,

if you select left justify
ADRESH is on the left of Byte
so like multiply by 16

you better have to choose Right justify !



.......
ADCON1=0x80; // select left justify result. A/D port configuration 0
........
return((ADRESH<<8)+(ADRESL));

}
 

Are you sure?

I think the situation becomes more clear with an example. Let's use this part of the code as an example:
Code:
x=read_a2d(); // sample the analog value on RA0
p = (x*5000)/1023;

x is a value between 0 to 1023 as it returns the ADC result.
Let's say the ADC reference is 5V and the input is 5V. So, the ADC returns the value of 1023 (maximum possible value).

Let's first use divide by 1023:
So, p = (1023*5000)/1023 = 5000

If we use divide by 1024:
p=(1023*5000)/1024 = 4995

The algorithm is that the value of p is the input voltage in mV. So, by dividing by 1023, p stores 5000 which is the correct input voltage - 5.000 V. But, dividing by 1024, p stores 4995. So, we think that the input voltage is 4.995V, when in reality it is 5.000 V.

Hope this helps.
Tahmid.
 

You are assuming the A/D can actually measure 5 Volts?
It cant.

Resolution = 5 / 1024 = 0.0048828125
1023 * 0.0048828125 = 4.9951171875

This is the maximum value that the 10-bit A/D can measure without overflow.
 
  • Like
Reactions: Tahmid

    Tahmid

    Points: 2
    Helpful Answer Positive Rating
You are assuming the A/D can actually measure 5 Volts?
It cant.

Resolution = 5 / 1024 = 0.0048828125
1023 * 0.0048828125 = 4.9951171875

This is the maximum value that the 10-bit A/D can measure without overflow.

Now I'm the one who disagrees :smile:
4.9951171875 is the switching points from 0b1111111110 to 0b1111111111.
This is not an overflow value.

Lets assume that we have a 2bit ADC with a ref voltage of 4v

The resolution is 4v/4= 1v
the max result of the ADC is 3 so 3 * 1v = 3v

This 3v value is the same as the 4.9951171875v in your example , anything above that will give a result of 0b11 (in my example) or 0b1111111111 (in your example)

This is what the conversion result will be based on the input

Code:
0<------->1v<------->2v<------->3v<------->4v
    0b00       0b01       0b10       0b11

The 00 result can be any input between 0v and 1v
The 01 result can be any input between 1v and 2v
The 10 result can be any input between 2v and 3v
The 11 result can be any input between 3v and 4v

It is a matter of choice if you want to divide the ADC result (for example the max of 0b11) by 4 and get 3v or divide by 3 and get 4v.
Consider it like a round function, you decide if the result will be rounded to the closest higher or lower voltage.

Alex
 

No!
The last 4mV go from 1023 to 1024

4.9951171875 is the switching point from 0b1111111111 to 0b10000000000 (0x3ff to 0x400)

Overflow to 1024.
 

hello,


The main probleme is not there (1023 or 1024)!

Code:
unsigned char read_a2d(){

	GO=1;	// initiate conversion on the selected channel
while(GO)continue;

	return((ADRESH<<8)+(ADRESL));

}

this function return a byte , but must return a 16 bits value !

and for calculation , use of long integer for x and p , to get a correct result of multiply by 5000.
 

re-hello

I saw another probleme, tested in reality mode , but with a 18F46K22
I am using C18, and a function ReadADC() allready exist...
so i did some test with read_A2d() with somme corrections like using unsigned integer for the result
and long int for calculation.. i added floatting point result.
it doesn't work correctly !!!!
So i add intermediate printout and i discovered that we cannnot use Directly ADRESH register with shifft register value!
k2=ADRESH << 8; // is BAD !! maybe because it is a register and not a C variable .
or maybe we have to use a special cast type for use it ?

so see the code ..
k2=ADRESH;
k2= k2<<8 ; .. result is OK

Result on VBRAY terminal

Code:
 Port Com 38400bds & Init HARD.

C18: 18F46K22_ADC.c
ADRESH ADRSL readADC   Long    Float
256    40    M2=296    1446    1.44
256    40    M2=296    1446    1.44
256    40    M2=296    1446    1.44
256    26    M2=282    1378    1.37
0    	206    M2=206    1006    1.0
0    	180    M2=180    879     0.87
0    	109    M2=109    532     0.53
0    	60     M2=60     293     0.29
0    	0    	 M2=0      0       0.0
0    	0      M2=0      0       0.0
0    	22     M2=22     107     0.10
0    	65     M2=65     317     0.31
0    	88     M2=88     430     0.42
0    	137    M2=137    669     0.66
0    	180    M2=180    879     0.87
0    	233    M2=233    1138    1.13
256    96    M2=352    1720    1.71
256    203   M2=459    2243    2.24
512    39    M2=551    2693    2.69
512    115   M2=627    3064    3.6
512    196   M2=708    3460    3.45
768    38    M2=806    3939    3.93
768    75    M2=843    4120    4.11
768    149   M2=917    4481    4.47
768    235   M2=1003   4902    4.89
768    255   M2=1023   5000    4.99
768    255   M2=1023   5000    4.99
 

Attachments

  • 18F46K22_test_c.txt
    14.8 KB · Views: 46

paulfjujo
I think you have explained the problems in the code.

alexan_e
0 - 7 = 8 different values.
Resolution 1 / 8 = 0.125
Maximum resolution of A/D = 7 * 0.125 = 0.875 above this, unknown.
Output at 1 volt input = 8, overflow.

Resolution 8, maximum output 8 - 1.
 

I'm talkink about 8 values too but I dissgree with you definition of the max resolution and the overflow you describe.
I have already provided you two links that showcase what I say, so is the wikipedia graph wrong?
Can you point to a reference showing your definition?
 

The resolution of a 10-bit A/D is Vref / 1024.
In the case of a 5 volt ref that is 0.0048828125.
The output will be 1023 for an input of 4.9951171875

The wiki graph gives an output of 7 for an input of .875?
It folows that it would give an output of 8 for a 1 volt input.
Resolution 8, maximum output value 7.

Wiki is clearly wrong when it states that the resolution of an 8-bit convertor is Vref / 255. It may only be capable of giving 255 as it's maximum value, but there are the values above and below the switching points.
0 is a value, 0 - 255 is 256 values.

The resolution is Vref / 256.

I guess we are just going to have to agree to disagree on this one.
 
Last edited:

Let me put the graph here

597px-ADC_voltage_resolution.svg.png


What I'm saying and also the graph shows (for a 3 bit ADC) is that you have 8 possible results 0-7, and the resolution in the graph example with Vref=1v is 1v/8=0.125v

What we disagree on is what every of these eight result values represents.
I say that it represents a range as shown in the graph, in this case

000 = voltage between 0v and 0.125v
001 = voltage between 0.125v and 0.250v
010 = voltage between 0.250v and 0.375v
011 = voltage between 0.375v and 0.5v
100 = voltage between 0.5v and 0.625v
101 = voltage between 0.625v and 0.750v
110 = voltage between 0.750v and 0.875v
111 = voltage between 0.875v and 1v

You disagree on that and you say that 111 represents 0.875v and the slightest voltage above that overflows the ADC and gives a binary result of 1000.
Do you have any reference that shows such a case?

Wiki is clearly wrong when it states that the resolution of an 8-bit convertor is Vref / 255

Where did you see that?
It says
The voltage resolution of an ADC is equal to its overall voltage measurement range divided by the number of discrete values:
f766f8c0bb46fe4d20fbdba3ad3e2748.png

2 in the power of M for 8 bit is 2^8=256

Also it says
Normally, the number of voltage intervals is given by
c84efdbc111df57fe61438fd782898da.png

In the case of 8bit this gives 255.

So you have 256 possible results and 255 voltage intervals (point where you change digital state), does that seem wrong?
It is like what I described in post #9 for two bit ADC

Code:
0<------->1v<------->2v<------->3v<------->4v
    0b00       0b01       0b10       0b11

You have four possible binary results (0,1,2,3) and three voltage intervals (1v,2v,3v)

Alex
 

you disagree on that and you say that 111 represents 0.875v and the slightest voltage above that overflows the ADC and giver a binary result of 1000.

No, 0.125 above that gives 1000.

Where did you see that?

Wiki says:
ADC resolution is 8 bits: 256 - 1 = 255 quantization levels (codes)
ADC voltage resolution, Q = (10 V - 0 V) / 255 = 10 V / 255 ~0.039 V ~39 mV.

Which I believe is wrong.

I am not disputing anything else you say,

just that Vref / 1024 is correct and Vref / 1023 is wrong.
 

I think the example sentence of wiki that you refer to is just a misspell but all the equations given are correct as shown in my previous post.

You disagree on that and you say that 111 represents 0.875v and the slightest voltage above that overflows the ADC and gives a binary result of 1000.
No, 0.125 above that gives 1000.

But 0.875v+0.125v=1v which is Vref, this is a different thing from what you said before.

In post #7
Resolution = 5 / 1024 = 0.0048828125
1023 * 0.0048828125 = 4.9951171875

post #10
The last 4mV go from 1023 to 1024
4.9951171875 is the switching point from 0b1111111111 to 0b10000000000 (0x3ff to 0x400)

You said 4.9951171875 , not 5v
4.9951171875 in your example is the equivalent of 0.875v in my example and 5v in your example is 1v in my example.

That is what I disagree on all along , what I say is that 4.9951171875 is the switching point from 0b1111111110 to 0b1111111111 (1022 to 1023).
The same as with 0.875v which is the switching point from 6 to 7 in my example.
So we agree on that?

Alex
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top