i need to implement a Butterworth filter in C. Is it easier get a library with this functionality or write the code?

Louis Branco picture Louis Branco · Mar 20, 2009 · Viewed 35.3k times · Source

My project is in C, CodeBlocks is my IDE and i´m running on windows Vista. I need to apply a Butterworth Filter to my data. I could do this automatically with Matlab as it had this (and other) Filter as a built in function. Computers and programming aren´t exactly my area and i have never "imported" a new library, and dont know how to do this. Is it complicated? and what would it be best I do? write the code for the Butterworth Filter as a function? or "import" a library to do this for me? (personally, if isnt that complicated, i´de prefer to get a library because it would probably have other types of filters i could also test)

Answer

Mike Renshaw picture Mike Renshaw · Mar 20, 2009

We had to apply a Butterworth Filter to some data on a project that I worked on recently. (Pressure measurements that drift over time because the measuring instrument heats up.) It's actually even simpler than including a library. You really just need to include a single function and add it to whatever C file you need to use it in.

This is the site that we used to generate our filter:

http://www-users.cs.york.ac.uk/~fisher/mkfilter/

If you specify the parameters, it will generate the function for you. Here is an example of the function we used in our application, based on the code generated by the above website. (We typedef DOUBLE because it's being developed on a PC, but targeted for an embedded platform -- we need to make sure that the size doesn't change.)

I love reading this site, glad to finally have something to contribute!

/* Butterworth filter constants */

#define NZEROS 4
#define NPOLES 4
static DOUBLE xv[NZEROS+1], yv[NPOLES+1];

/* Sampling rate 3000 for testing existing */
/* raw data.  Change to 300 for final product */
#define SAMPLING_RATE 3000

/*******************************************************************************
 * Function:      ButterworthFilter
 *
 * Description:   This function uses the Butterworth filter and returns a new
 *                value for an individual floating point value.
 *
 * Access:        PRIVATE
 *
 * Parameters:    DOUBLE input - value to be converted
 *
 * Globals:       None
 *
 * Returns:       DOUBLE - new value that has been converted
 ******************************************************************************/
static DOUBLE ButterworthFilter (DOUBLE input)
{ 
    /* http://www-users.cs.york.ac.uk/~fisher/cgi-bin/mkfscript */
    /* Butterworth Bandpass filter */
    /* 2nd order */
    /* sample rate - choice of 300 or 3000 Hz */
    /* corner1 freq. = 0.5 or 1 Hz */
    /* corner2 freq. = 20 Hz */
    /* removes high and low frequency noise */

    DOUBLE dCoefficient1 = 0.0;
    DOUBLE dCoefficient2 = 0.0;
    DOUBLE dCoefficient3 = 0.0;
    DOUBLE dCoefficient4 = 0.0;
    DOUBLE dCoefficient5 = 0.0;
    DOUBLE dGain = 0.0;

    /* coefficients will vary depending on sampling rate */
    /* and cornering frequencies                         */
    switch(SAMPLING_RATE)
    {
        case 300:
            /* 1 to 20 Hz */
            dCoefficient1 = 2.0;
            dCoefficient2 = -0.5698403540;
            dCoefficient3 = 2.5753677309;
            dCoefficient4 = -4.4374523505;
            dCoefficient5 = 3.4318654424;
            dGain = 3.198027802e+01;
            break; 

        case 3000:
        default:
            /* 0.5 to 20 Hz */ 
            dCoefficient1 = 2.0;
            dCoefficient2 = -0.9438788347;
            dCoefficient3 = 3.8299315572;
            dCoefficient4 = -5.8282241502;
            dCoefficient5 = 3.9421714258;
            dGain = 2.406930558e+03;
            break;  
    } 

    xv[0] = xv[1]; 
    xv[1] = xv[2]; 
    xv[2] = xv[3]; 
    xv[3] = xv[4]; 
    xv[4] = (DOUBLE)(input / dGain);
    yv[0] = yv[1]; 
    yv[1] = yv[2]; 
    yv[2] = yv[3]; 
    yv[3] = yv[4]; 
    yv[4] = (DOUBLE)((xv[0] + xv[4]) - (dCoefficient1 * xv[2]) + (dCoefficient2 * yv[0]) +
                    (dCoefficient3 * yv[1]) + (dCoefficient4 * yv[2]) +
                    (dCoefficient5 * yv[3]));

    return (yv[4]);
}