LockedSimple low pass filter

Page: 12 > Showing page 1 of 2
Author
Guest
Super Member
  • Total Posts : 80499
  • Reward points : 0
  • Joined: 2003/01/01 00:00:00
  • Location: 0
  • Status: online
2005/08/20 14:41:51 (permalink)
0

Simple low pass filter

How can I create simple low pass filter in software (using pic18 in C)?? Are there any older topics about this? I couldn't find any...
#1

24 Replies Related Threads

    ric
    Super Member
    • Total Posts : 22098
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    RE: Simple low pass filter 2005/08/20 15:35:01 (permalink)
    0
    You really need to supply some more information.
    Are you talking about reading an analog signal with an ADC, doing some low pass filtering on that signal, then outputting it somehow?

    Even if you do this, you still must have an external low pass filter which cuts off at around half of your sampling rate. If you don't, you will suffer from aliasing problems.

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #2
    Guest
    Super Member
    • Total Posts : 80499
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: Simple low pass filter 2005/08/21 03:37:18 (permalink)
    0
    Maybe I should include it in my topic. I read a signal from AD channel. I only want to use the values in software, not push it forward via output pins.

    I also low-pass filter the signal by a simple RC link. I want to "smooth" the values in the PIC.
    #3
    p.erasmus
    Super Member
    • Total Posts : 1799
    • Reward points : 0
    • Joined: 2004/11/25 03:18:34
    • Location: Saratov Russia
    • Status: offline
    RE: Simple low pass filter 2005/08/21 05:17:17 (permalink)
    0
    Hi
    MCC has a couple of documents on implementing sofware filters and code on the PIC 18 look under application notes.
    #4
    jspaarg
    Super Member
    • Total Posts : 2926
    • Reward points : 0
    • Joined: 2005/05/25 16:47:08
    • Location: PA, now MN via NJ,AZ,OR,CA
    • Status: offline
    RE: Simple low pass filter 2005/08/21 06:18:57 (permalink)
    0
    There are many ways to accomplish smoothing.

    What time period of the filter are you looking for.

    Smoothness vs response time is your general trade off.

    Are you coding in C or assembler.

    How tight are your timing requirements for your calculation?
    #5
    Guest
    Super Member
    • Total Posts : 80499
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: Simple low pass filter 2005/08/21 07:53:15 (permalink)
    0
    Currently I use pic18f2455 and code in c. The timing requirements are not that critical so Im open for all suggestions. Frequency response app. at 50Hz.
    #6
    jspaarg
    Super Member
    • Total Posts : 2926
    • Reward points : 0
    • Joined: 2005/05/25 16:47:08
    • Location: PA, now MN via NJ,AZ,OR,CA
    • Status: offline
    RE: Simple low pass filter 2005/08/21 16:47:06 (permalink)
    0
    My knowledge of correct terminology is often limited, but the concept that you want is

    output = (x * last_output + present_reading) / (x+1)

    Then the next time through the algorithm output becomes last_output.

    To speed up the calculation

    1: keep x an integer (no real numbers like 4.7)
    2: make x a value of 2 ** n -1 (a value like 3, ,7, 15, 31, etc), then your divide is just a bit shift.

    There are a number of other tricks to make the algorithm execute quickly, but I wouldn't do them in C.
    #7
    Kruse
    Super Member
    • Total Posts : 1224
    • Reward points : 0
    • Joined: 2005/04/15 09:04:09
    • Location: Denmark
    • Status: offline
    RE: Simple low pass filter 2005/08/22 00:27:55 (permalink)
    0
    My knowledge of correct terminology is often limited


    Me too. But atleast you could provide an usefull answer [8|]

    Generally I allways get the 'new' A/D value and add it to a variable (holding AD result) divide it by 2, easy and quickly but not allway enough.

    A PIC listens to your commands -not your intentions.
    #8
    Guest
    Super Member
    • Total Posts : 80499
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: Simple low pass filter 2005/08/22 04:43:35 (permalink)
    0
    jspaarg, whats the function of 'x'? I dont get it....[8|]

    Say I use x=7 my samples are {128,130,140,128}. These values result:

    16
    128
    131
    138
    < Message edited by fatpo -- Aug. 22, 2005 4:48:25 AM >
    #9
    ric
    Super Member
    • Total Posts : 22098
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    RE: Simple low pass filter 2005/08/22 05:12:05 (permalink)
    0
    The value of x determines the ratio between the current average, and the new reading.

    You seem to have misunderstood the calculation. For x=7, and asusming the "current reading" starts at zero, then:

    128 => (0*7 + 128)/8 = 16
    130 => (16*7 + 130)/8 = 30 (30.25)
    140 => (30*7 + 140)/8 = 44 (43.75)
    128 => (44*7 + 128)/8 = 54 (54.6)

    So there isn't enough data there for the average to settle.

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #10
    jspaarg
    Super Member
    • Total Posts : 2926
    • Reward points : 0
    • Joined: 2005/05/25 16:47:08
    • Location: PA, now MN via NJ,AZ,OR,CA
    • Status: offline
    RE: Simple low pass filter 2005/08/22 05:29:22 (permalink)
    0
    x is a constant (I should have used k) and represents the number of samples in your filter.

    Using the values in your example, your output would be

    last reading output
    0 128 16
    16 130 30
    30 140 44
    44 128 55

    It will take a while for the filter output to approximate your reading, but I hope you get the idea.

    The one issue that you either have to use floating point math or maintain the remainder from each filter operation to use in the following operation (if you are using integer math).

    Forget what I said earlier about not using floating point.
    If you are using C and are not in a tight timing requirement, use floating point. It is much easier than dealing with integer math in this particular algorithm.

    Hope this helps.
    #11
    maxwell
    Super Member
    • Total Posts : 1510
    • Reward points : 0
    • Joined: 2003/11/07 12:35:27
    • Status: offline
    RE: Simple low pass filter 2005/08/22 06:04:38 (permalink)
    0
    The subject of digital filter design is too extensive to be covered completely by any of the specific posts on this board. The most you will find are rules of thumb that were used in particular projects which may or may not parallel what you are doing. It would be more productive if you defined not only the parameters of the filter (cutoff frequency, shape, etc.) but also just how serious you are about the performance.

    In general, digital filters are implemented in two broad ways. In the first, the output is the weighted sum of the last N inputs. Each input (the past N-1 and the current one) is multiplied by a different "coefficient" and the products are added together to get the current output. These are the "Finite Impulse Response" or FIR filters. The coeficients determine the filter response (shape and cutoff frequency). This is where the math and theory come in.

    The IIR (Infinite Impulse Response) filters constitute the second type. The output of these is the weighted sum of the last N inputs and the last M outputs. This type can produce more complicated stop and pass characteristics with fewer stages (coefficients), at the expense of potentially unstable behavior (oscillation and overshoot, e.g.). As with the FIR, calculation of the coefficients is math intensive.

    If you don't care about precision (the performance mentioned above), use a simple averaging algorithm. To use jargon: make an FIR filter with all coefficients equal to 1/N. This is the classic "boxcar integrator". The response is sin(f)/f , which has a bumpy shape and works best if you just want DC. If you need a fancier design, make a simple exponentially shaped filter using
    (formula edited)
    output = (1 -a) * input + a * previous_output, 0 < a < 1
    Of course, you can accomplish the same thing by putting an analog RC filter before the A/D (unless the noise being filtered is caused by the digitization process itself). The digital form is more useful if you only have the digitized data to work with. The digital method pulls ahead when the filter becomes more complicated than a simple exponential.
    < Message edited by maxwell -- Aug. 22, 2005 6:33:41 AM >

    John N. Power
    #12
    Guest
    Super Member
    • Total Posts : 80499
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: Simple low pass filter 2005/08/22 07:15:31 (permalink)
    0
    There is an AN on IIR filters at microchip.com that might give you some starting point. if your project already includes an FPGA, look at the site below. It offers a program that generates VHDL code for you for various types of filters.

    bharat gill
    #13
    RP Henry
    Starting Member
    • Total Posts : 65
    • Reward points : 0
    • Joined: 2005/01/13 15:30:37
    • Status: offline
    RE: Simple low pass filter 2005/08/22 07:25:08 (permalink)
    0
    A quick-and-dirty exponential filter (based on a hardware filter I once worked with):

    (This method depends on the ratio being a power of 2). For this example, we will take the running average A, the current sample a, and the filtering ratio to be 1/8.

    temp = A>>3; //A/8
    A -= temp; //A is now reduced to 7/8 of the original A
    A += a>>3; //add 1/8 a to get the new average
    #14
    Guest
    Super Member
    • Total Posts : 80499
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: Simple low pass filter 2005/08/22 07:41:19 (permalink)
    0
    I have used the approach laid out by RP Henry many times for temperature (DC), and motion control (motor current) when either I need only to average readings OR i don't have processing bandwidth for a proper filter. In assembly this is real fast.
    You wouldn't like it for waveform signal processing, though.
    #15
    jspaarg
    Super Member
    • Total Posts : 2926
    • Reward points : 0
    • Joined: 2005/05/25 16:47:08
    • Location: PA, now MN via NJ,AZ,OR,CA
    • Status: offline
    RE: Simple low pass filter 2005/08/22 08:26:38 (permalink)
    0
    The problem that I have had with using straight integer math like this is that you can never reach a steady state input because of loss of precision.

    The longer your filter period, the further away you are from steady state.

    Even rounding won't get you there.

    e.g. If you use a period of eight and change from 0 to an ADC reading of 483, you would reach a filtered reading of 480 after 36 iterations, and would never exceed 480. This is because you are losing the remainder of your integer operation.

    I have found that you need to keep the LOB (low order byte) of the operation (even if you don't output it) and use it when the next output is calculated.
    For a sample weight of 255, the difference is even more dramatic.

    The math is still integer and still very fast, but the extra byte has to be handled.

    Of course someone probably knows another trick that I don't.
    #16
    DougShaw
    Starting Member
    • Total Posts : 49
    • Reward points : 0
    • Joined: 2005/01/05 14:33:40
    • Status: offline
    RE: Simple low pass filter 2005/08/22 10:29:32 (permalink)
    0
    Well this is a little long but difference equations translate int C very well:

    Let $ = integral (had to use some character)
    Let Xn = X at sample time n
    Let Xn-1 = X at sample time n-1

    A first order filter in the laplace domain is
    Y/X = 1/(tau*s + 1 )

    where:
    x=input
    y=output
    s=laplace operator
    tau = time constant in sec/rad
    w = 1/tau = break frequency in rad/sec (Note 2*pi rad = 1cycle)

    You can arrange the equation above like this
    Y(tau*s+1) = X .... Multiply denominators
    tau*Y*s + Y = X ..... Expand equation
    tau*Y + Y/s = X/s .... Divide by the laplace operator s

    Now our knowledge of lapace operators is
    Z/s = $Z .... The integral of Z

    Substituting into the equation we get
    tau*Y + $Y = $X ... Tranfering from lapace domain to time domain

    If this is true continuously, we can say for small delta time steps (n) it is also true
    tau*Yn + $Yn = $Xn ... discretized version (A)

    There are many types of integration routines but for small delta time steps let's use rectangular integration
    $Zn = $Zn-1 + dt*Zn

    substituting into (A) we get
    tau*Yn + $Yn-1 +dt*Yn = $Xn-1 + dt*Xn ... Integral Substitution (B)

    Now if Equation A is true for n, it must also be true for n-1
    tau*Yn-1 + $Yn-1 = $Xn-1 ... discretized to n-1 (C)

    Now the fun part, the difference equation (B - C).
    tau*Yn + dt*Yn - tau*Yn-1 = dt*Xn

    Or we could rearrange terms
    Yn = (dt/(tau+dt))*Xn + (tau/(tau+dt))*Yn-1

    OK more fun with math, add and subtract (dt/(tau+dt))*Yn-1
    Yn = (dt/(tau+dt))*Xn + (tau/(tau+dt))*Yn-1 + (dt/(tau+dt))*Yn-1 - (dt/(tau+dt))*Yn-1

    Combining terms we get
    Yn = (dt/(tau+dt))*Xn + (tau+dt)/(tau+dt))*Yn-1 - (dt/(tau+dt))*Yn-1

    Combining terms again and moving terms around we get
    Yn = Yn-1 + (dt/(tau+dt))*(Xn - Yn-1)

    Oh what fun we are going to have now
    Let K = dt/(tau+dt)
    Then we get
    Yn = Yn-1 + K*(Xn - Yn-1)

    So in C we could use the follwing
    Y = Y + K*(X - Y);

    Or better yet
    Y+=K*(X-Y);

    The math may require scaling (I'd suggest long variables) but this filter has been used many times, is very fast and accurate if scaled correctly

    Hope this helps.

    To a man that only has a hammer in his toolbox, every problem looks like a nail
    #17
    jspaarg
    Super Member
    • Total Posts : 2926
    • Reward points : 0
    • Joined: 2005/05/25 16:47:08
    • Location: PA, now MN via NJ,AZ,OR,CA
    • Status: offline
    RE: Simple low pass filter 2005/08/22 10:49:31 (permalink)
    0
    I used to think I understood math, now I think that I didn't, I think :-o

    Are you saying that

    new output = last output + k * (new reading - last output)?

    What kind of value do you have for k?
    It seems like it would have to be a real number something around unity.
    #18
    DougShaw
    Starting Member
    • Total Posts : 49
    • Reward points : 0
    • Joined: 2005/01/05 14:33:40
    • Status: offline
    RE: Simple low pass filter 2005/08/22 21:13:12 (permalink)
    0
    I wrote a very long response that was killed because it logged out of the forum.

    So here is the short answer: YES

    Here is an example of scaled math, the input and ouput are 16 bit integers, using scaled math

    #define SF10 (10)
    #define SCALE10 (2^SF10)
    #define DT (0.01)
    #define TAU (0.9)
    #define K (DT/(TAU+DT))
    #define K_SCALE10 = (K*SCALE10)l // Note this is 102, truncation of 0.4 doesn't affect filter really
    #define FILTER_IC (0.0*SCALE10)l // Note this is 0 as a long

    int lag1order( int x )
    {
    long x_scaled;
    static long y_scaled;

    x_scaled = x*SCALE10;
    y_scaled += ((K_SCALED*(x_scaled-y_scaled))/SCALE10)
    // Note: if A is scaling this is (KA*(XA-YA))/A = KAX-KAY
    // Same order of scaling as y_scaled for the +=
    return(y_scaled/SCALE10);
    }

    For the purist, I didn't check for overflow, perform casting, etc.
    but for demo purposes this should suffice.

    I didn't try to compile this, so don't hold me to syntax errors.
    If someone is interested, I could put together a word document on filters.
    They seem simple but getting them to operate correctly takes patience.

    Also if anyone is interested, I usually simulate all filters in MATLAB.
    I would post the MATLAB code if there is a desire.
    < Message edited by DougShaw -- Aug. 22, 2005 9:17:53 PM >

    To a man that only has a hammer in his toolbox, every problem looks like a nail
    #19
    DougShaw
    Starting Member
    • Total Posts : 49
    • Reward points : 0
    • Joined: 2005/01/05 14:33:40
    • Status: offline
    RE: Simple low pass filter 2005/08/22 21:32:32 (permalink)
    0
    Well after all that work I forgot to mention why I put in all that math.

    The example was for a 1st order lag
    Y/X = 1/(tau*s+1)

    But you can easily create lead lags
    Y/X = (tau1*s+1)/(tau2*s+1)

    Or even second order filters
    Y/X = 1/(s^2 + (2z/w)*s + 1)

    But don't forget the Anit-aliasing hardware filter -- VERY, VERY important

    To a man that only has a hammer in his toolbox, every problem looks like a nail
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2017 APG vNext Commercial Version 4.5