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

ADC filtering

This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    CCS Forum Index -> Best Of
View previous topic :: View next topic  
Author Message

Joined: 11 Mar 2010
Posts: 19277

View user's profile Send private message

ADC filtering
PostPosted: Wed Apr 22, 2020 2:02 am     Reply with quote

There are lots of different ways of filtering the signal from ADC's.
The 'best' depends massively on what the actual error is coming 'from'.
However I've tried to put links here to the types that people have found
useful in the past.

First the simplest. Sum and average:

int16 average(void)
    //return an average of 8 readings
    int32 sum;
    int count;
    //assuming ADC is already setup, and we are reading channel 1
    for (count=0;count<8;count++)
       delay_us(10); //most PIC ADC's require about 10uSec to acquire
       sum+=reac_adc(); //add the reading to the sum
    sum/=8; //gives the average
    return sum;

Comments here:
The most efficient integer divisions on the PIC are the 'binary' divisions.
So /2, /4, /8, /16 etc.. So if you average 4, 8, 16 etc., samples, the
maths is quicker.
This is a simple and effective average, but takes 8 loops before a
reading is returned. An average can also be done using an array of
values, so the result can update with just one new sample. An example
of this is lower down this thread in a post with a median filter as well.

Second, the 'rolling average':

int16 rolling(void)
    static int32 sum;
    int16 val;
    static int1 first=TRUE; //used to say this is the first loop
    if (first)
        sum=val*8; //load the sum first time
    return val;

Here the 'sum' is loaded initially with 8* the ADC reading. Then at
the exit of the loop, this is divided by 8, and this becomes the result.
The sum then has this result subtracted.
The sum is maintained for each successive call.

Each time the sum maintained is 7* the last result, and then the new
value is added to this and the new average generated.

The effect is that the new result takes 1/8th from the new reading,
but is affected by much older results than the simple average. However
with less and less effect the older the reading. This can be a very
effective way of averaging, and gives you a new result with just one
sample each time it is called.

Then the 'olympic' average. This is a 'simple' average, but throwing
away the highest and lowest values first. Makes it a very good way of
rejecting individual 'outliers'.
Asmboy posted a implementation here:

Then a more sophisticated filter the 'median' filter. This always returns
a value that is actually 'in' the values being read. It tries to return what
you can think of as the 'central' value. Implementation by PCM_programmer

This also has a basic averaging filter, but using a rolling array of values
allowing a new result with just a single new reading.

In all cases the actual amount of smoothing can be increased or decreased
by changing the number involved, but the more damping, the greater the
'lag' that will be experienced in the output.

Obviously all these filtering techniques can be applied to signals other
than the ADC as well, but the ADC is the one that most people will be
dealing with.
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    CCS Forum Index -> Best Of All times are GMT - 6 Hours
Page 1 of 1

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