Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

ADC result in Three Decimal point

Status
Not open for further replies.

micropad

Member
This is related to pic 16f887a MCU

As we all aware the ADC result is loaded to ADRESL AND ADRESH

in 10 bit mode I need to display voltage variation on seven segment display from 0 to 5V

So I need to display in three decimal point too. ex ( 2.254) Like wise

I know how configure ADC part

It would be much appreciated if any one can help in assembly

Thanks in advance
 
Last edited:
Use fixed point math... 10 bit ADC result = 0 to 1023 convert to 0 to 5 volts USING the three decimal places... ADC result * 5000 / 1023...

Example 2.5volts will relate to 512 digitally.. So 512 * 5000 / 1023 = 2502.... Insert the "." like so 2.502Volts...

You'll need four consecutive numbers for the math routine.. there many examples here..

You don't need to divide by 1023 as you can just shift the result right twice and ditch the LSByte.
 
The BIG problem with this is that the calculated readings aren't 'smooth' - for example, if you scale it (multiply) by a factor of two, then the last digit changes in intervals of two - I find this particularly annoying :D

That was why my analogue tutorial scales to give a range of 0-10.23V - so it gives a nice 'smooth' progression - which the LSD changing by ones.

My original tutorial code included multiply and division routines, to scale the readings as you wanted - but I removed them before publishing the tutorials.
 
The other way is sample 5 times, then and add together... This gives a a reading 5115 ( Not quite 5 volts )...

Makes for easy 'maths' - but doesn't solve the 'smooth' problem, the last digit can only be 0 or 5.

Easiest way, if you can't live with decimal multiples of 1.023, is to scale it and discard the last digit - so in the case you mentioned in this quote, a range of 0 to 5.11V

But as 0-5.00 is 0.2% resolution, that should be plenty - and most likely more accurate than the rest of the system anyway?.

The same result though is achieved even easier by scaling the ADC to read 10.23V (as in my tutorials) and using that to read a 5V range (same 0.00 two decimal place result).
 
Makes for easy 'maths' - but doesn't solve the 'smooth' problem, the last digit can only be 0 or 5.

I agree... The op wants THREE decimal places... I personally would over sample and average 24 times the divide by 6 ( this gives a decent 12 bit result... But as there are only 1024 possible bits 4.999 will always be icky...

His choice....
 
I personally would over sample and average 24 times the divide by 6 ( this gives a decent 12 bit result...

Can't quite follow that math. If you want to get 12 bit result from 10 bit ADC, you need to add 16 samples and then shift twice to the right. This works well only if you have enough noise or "dithering" in the signal, and that the signal information itself is quite steady during the 16 samples taken.

I think taking 24 samples and dividing by 6 gives an average of six 11 bit results multiplied by two. The result looks like 12 bit, but is not actually more accurate than 11 bits.
 
Last edited:
Use fixed point math... 10 bit ADC result = 0 to 1023 convert to 0 to 5 volts USING the three decimal places... ADC result * 5000 / 1023...

Example 2.5volts will relate to 512 digitally.. So 512 * 5000 / 1023 = 2502.... Insert the "." like so 2.502Volts...

You'll need four consecutive numbers for the math routine.. there many examples here..

You don't need to divide by 1023 as you can just shift the result right twice and ditch the LSByte.

Dear Rogers

Thank you so much for reply
It could be much appreciated if you can provide a sample code from assembly
Thanks again and again
 
Can't quite follow that math. If you want to get 12 bit result from 10 bit ADC, you need to add 16 samples and then shift twice to the right. This works well only if you have enough noise or "dithering" in the signal, and that the signal information itself is quite steady during the 16 samples taken.

I think taking 24 samples and dividing by 6 gives an average of six 11 bit results multiplied by two. The result looks like 12 bit, but is not actually more accurate than 11 bits.

Dear mister,
Thanks for the reply

Could you please give me a sample code from assembly
Thanks in advance
 
Can't quite follow that math. If you want to get 12 bit result from 10 bit ADC,

24 * 1024 ( 10 bits) = 24552..... /6 = 4096 (12 bits).... Which bit don't you get!!!
 
The same result though is achieved even easier by scaling the ADC to read 10.23V (as in my tutorials) and using that to read a 5V range (same 0.00 two decimal place result).

Dear Nigel,
Thanks for the reply

I did not see such a tutorials in you tutorials
Could you please give me a link of that
Thanks in advance
 
24 * 1024 ( 10 bits) = 24552..... /6 = 4096 (12 bits).... Which bit don't you get!!!

If you multiply a 10 bit ADC result by two, you don't increase the (ADC conversion) resolution. If you take 24 consecutive samples and divide by 6, you'll practically get an average of six 11 bit samples multiplied by two (or 4 averaged 10 bit results added together, which increases the resolution by 1 bit).

Take a look at this: https://www.electro-tech-online.com/custompdfs/2013/01/doc8003-1.pdf

If you really want an average of six 12 bit samples (using 10 bit ADC), you'll need to take 96 samples, add them, and then divide by 24.
 
Last edited:
Mr T you seen to be forgetting noise... On my systems the above procedure works extremely well.... If I did 96 samples I would need a long, but as I use a word it works very well


I have used this system on HUGE cranes and I get less than 0.01° accuracy. If you take a 1k pot over the 1023 bits available and measure 90° arc there will be 255 resolutions or 0.35° of a degree.. If I was only getting 11 bit resolution I would be seeing 0.17° resolution. I am definitely getting a reasonable 12 bit resolution.

Theory is brilliant, until you try building one....
 
Use fixed point math... 10 bit ADC result = 0 to 1023 convert to 0 to 5 volts USING the three decimal places... ADC result * 5000 / 1023...

Example 2.5volts will relate to 512 digitally.. So 512 * 5000 / 1023 = 2502.... Insert the "." like so 2.502Volts...

Dear Roger
Can you please teach me how may i multiply 512 * 5000

Please advice
 
<=1023 * 5000 has a max result of over 5 million, it needs a 32bit math module. :)

You can do it without 32bit multiplication, by successive addition. This will be much smaller code in assembler but of course takes longer, however the few mS needed to do it the slow way may be ok?

Code:
long accum;
int ADC;

// assuming the new ADC reading is in the var ADC,
// this is effectively; ADC*5000
accum = 0;
while(ADC)
{
 accum += 5000;  
 ADC--;
}
// now the division, is effectively accum/1024;
accum >>= 10;

You can do it with 16bit math by finding two numbers with a ratio very close to 5000/1024, like 39/8 which is within about 0.16% of the perfect result (less than 2 ADC counts error worst case);

Code:
int accum;
int ADC;

// assuming the new ADC reading is in the var ADC,
// this is effectively; ADC*39
accum = 0;
while(ADC)
{
 accum += 39;  
 ADC--;
}
// now the division, is effectively accum/8;
accum >>= 3;

I know that is in C style code but would be do-able in assembler quite easily.
 
If you multiply a 10 bit ADC result by two, you don't increase the (ADC conversion) resolution. If you take 24 consecutive samples and divide by 6, you'll practically get an average of six 11 bit samples multiplied by two (or 4 averaged 10 bit results added together, which increases the resolution by 1 bit).

Take a look at this: https://www.electro-tech-online.com/custompdfs/2013/01/doc8003-1.pdf

If you really want an average of six 12 bit samples (using 10 bit ADC), you'll need to take 96 samples, add them, and then divide by 24.
I'm not sure why you say oversample by 96, then divide by 24 is correct whereas os x24 / 6 is not. For 2 extra bits, the oversample rate need only be 16 as 4^2 = 16. 24 is larger than 16, so satisfies this requirement. Your referenced paper quotes an oversample factor of 4 per bit, not 9.8 as you have implied by your values.


I read that paper a long time ago and IIRC the author seems to differentiate between right shifting and dividing as if they are different. They do the same thing; there is nothing magical about shifting.

The main point of the oversampling theory in that paper is that oversampling a signal with dither by at least 4 will give you 1 bit of extra precision. To get this to an integer that contains all the bits, the summation is then divided by the square root of the oversampling rate.

[LATEX]ADC^*_{N+M} \approx \lfloor {\frac{1}{2^M} \sum_{i=1}^{4^M} {ADC_N^i}} \rfloor[/LATEX]

The paper should state that this is biased downwards, i.e. the resulting value will be up to a bit too low - rounding should be used to maintain no worse than 1/2 LSB rounding error. i.e.

[LATEX]ADC^*_{N+M} \approx \lfloor {\frac{1}{2^M} (2^{(M-1)} + \sum_{i=1}^{4^M} {ADC_N^i}}) \rfloor[/LATEX]
 
I'm not sure why you say oversample by 96, then divide by 24 is correct whereas os x24 / 6 is not. For 2 extra bits, the oversample rate need only be 16 as 4^2 = 16. 24 is larger than 16, so satisfies this requirement. Your referenced paper quotes an oversample factor of 4 per bit, not 9.8 as you have implied by your values.

I said: "average of six 12 bit samples (using 10 bit ADC) you'll need to take 96 samples, add them, and then divide by 24".

Getting 12 bit result from a 10 bit ADC takes 16 samples. and taking average of six 12 bit samples out of 10 bit ADC takes 16*6 samples divided by 6*4.
 
Last edited:
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top