CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

How can I improve ADC accuracy?
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
gpsmikey



Joined: 16 Nov 2010
Posts: 588
Location: Kirkland, WA

View user's profile Send private message

PostPosted: Sat Mar 12, 2011 12:13 pm     Reply with quote

If you are interested, a couple of books I have found quite helpful and keep on my shelf are "The Circuit Designers Companion" (Tim Williams) and "The Art of Electronics" (Horowitz and Hill). Not cheap, but both excellent books and very handy as everyday reference.
http://www.amazon.com/Circuit-Designers-Companion-Second-Engineers/dp/0750663707
http://www.amazon.com/Art-Electronics-Paul-Horowitz/dp/0521370957
The "Art of Electronics" is a bit dated, but still an excellent reference. See if your local technical library has copies of them you could snoop through.

mikey
_________________
mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3
hawking1122



Joined: 10 Mar 2011
Posts: 11

View user's profile Send private message

PostPosted: Sun Mar 13, 2011 8:54 am     Reply with quote

Thank you guys for invaluable help, I'll do the hardware job and feedback anything I explore.
hawking1122



Joined: 10 Mar 2011
Posts: 11

View user's profile Send private message

PostPosted: Mon Mar 14, 2011 2:20 am     Reply with quote

I've added some bypass caps and the result is now much more stable. Thank you all!
However, something I want to see clearer:
1. My Vref is generated using LM317L, the schematic is below:

The 3 caps are chosen based on datasheet. As you can see, the resistor and pot are quite small, so the current flowing through them is not small, so I do not have to worry about instability of LM317L even though current flowing into Vref pin of microcontroller is small?

2.
temtronic wrote:

If you have the time, sample 64 times then get the average using int16. If you need more speed, sample 8,16, or 32 times. Try not to rely on just 1 reading..

Is there any reason we should choose to everage exactly 64, 32, 16 or 8 samples? They are all powers of 2. Is there anything special here?
hawking1122



Joined: 10 Mar 2011
Posts: 11

View user's profile Send private message

PostPosted: Mon Mar 14, 2011 2:29 am     Reply with quote

3. The amount of time for 1 sample is 22usec, but the maximum number of samples I can get from my Pic18f2550 is just 16 samples/1second (my computer software need to display analog value every second, I'm averaging 16 samples to get more accurate value). I've tried averaging 64 samples but it take about 4 second to receive all 64 10bit values.
The phenomenom above does not appear (I can average up to 300 samples each time) if I used value=read_adc() instead of
read_adc(ADC_START_ONLY);
sleep();
value=read_adc(ADC_READ_ONLY);
Does it mean sleep() takes too much time to complete?
hawking1122



Joined: 10 Mar 2011
Posts: 11

View user's profile Send private message

PostPosted: Mon Mar 14, 2011 3:25 am     Reply with quote

I've double checked my code and see there are some delay functions which slow down the rate of transmiting/receiving usb data, but after I've deleted them all, the maximum rate of sampling is 40 samples/second. It seems not as short as 22usec mentioned in datasheet?
Ttelmah



Joined: 11 Mar 2010
Posts: 19545

View user's profile Send private message

PostPosted: Mon Mar 14, 2011 4:16 am     Reply with quote

On the 'why use 8,16,32 for averaging'. This is down to division. Dividing an integer by eight for example, is just a 3bit rotation. Takes a handful of machine cycles. Dividing by 10 instead, takes perhaps 50* as much work.....
A good averaging algorithm, is:
Code:

int16 smooth{int16 ival) {
    static int32 isum;
    static int1 firstflag=TRUE;
    int16 iresult;
    if (firstflag) {
       isum=(int32) ival*64;
       firstflag=FALSE;
       iresult=ival;
    }
    else {
       isum+=ival; //update the sum
       iresult=isum/64; //Change this to adjust the damping
   
       isum-=iresult;
    }
    return iresult;
}


The key point here is that you get a new value each time, and the maths is fast. The 'sum' builds by the difference between the new sample, and the rolling 'sum', less the sum/64.
With /64, it'll take a long time to actually 'reach' the value at the start, so the code on the first call 'preloads' the sum with 64* the first reading, to speed this up.

Now, on your timings, though the ADC takes nominally 22uSec to do the conversion, when you sleep, you stop the processor clock, and then start it again. The chip samples the clock, and only goes 'live', once the clock is seen to be stable. If you have PUT selected in the fuses, it then waits another 70 cycles of the clock, before starting (so for fast wake up, this option needs to be off)/ How long the clock takes to start depends on your clock hardware. However you should be talking only perhaps 100uSec maximum, even with PUT enabled. Something like 10000 samples/second....
There is something else slowing it down.

Best Wishes
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Mon Mar 14, 2011 6:50 am     Reply with quote

With simple averaging, the more samples the better, but the answer only improves by the square root of the number of samples, and that is assuming the noise is gaussian.

If the data is generally good, with occasional bad readings, I often use what I call "Olympic Scoring." I take a number of samples, often 10, and keep track of the maximum, the minimum, and the sum. Then I subtract out the max and the min from the sum and average the rest. 10 samples minus the two extremes leaves you 8. Dividing by 8 is a simple bit shift. You don't even have to store all 10 samples, just 3 numbers, min, max, and sum. And a sum of 10 samples at 12 bits each still fits in an INT16. So the math and RAM consumption is minimal and you eliminate one outlier either high, low, or both. It works a lot like a median filter but with a little smoothing and a lot less CPU resources.

Search the forum for "olympic" to get more info on the method.
_________________
The search for better is endless. Instead simply find very good and get the job done.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group