i need to implement a Butterworth filter in C. Is it easier get a library with this functionality or write the code?
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]);
}
It is almost certainly simpler and safer to use a well tested external library (assuming you can find one....tried Google yet?) than to code a non-trivial filter yourself.
But, since you haven't said anything about you application, the format of you data, etc, there is little more that we can tell you.
I don't know anything about how your IDE (CodeBlocks) works, but importing usual takes one of three forms depending on how the library is made available to you (details to follow):
- You obtain source code for one or more functions (hopefully with good documentation): Read the docs, copy the code into the appropriate directory, add the files to the project, attempt to compile, fix missing preprocessor symbols, etc...
- You obtain a plain binary library and headers for you platform (possibly from you OS package management system): Read the docs, tell the IDE where to find the headers and the library, attempt to link, fix problems...
- You obtain a framework that provides the functionality: This is a bit more trouble, but it also starts with read the docs, then probably proceeds a lot like the library case, but with more code to be written...
In any case you will at some point be doing
#include "library.h"
in some of your source files to make the external functionality visible to your code.
Probably you want to find a candidate library first, to see what form it is provided in, then read more about your IDE to see where you go from there.
Another SO question that might be relevant to your needs: Analog circuit simulation library?.
It's been a long time since I used matlab, but if that is your base programming experience, you should be aware that there are a lot of facility that matlab provided to you that are not in plain vanilla c. You almost certainly want to use some framework or another to give you some of that support back.
If you're using Matlab, is it taboo to link to Matlab from your C code? This is a starting point. You can actually ask the Matlab engine to do anything you can do from within the Matlab interface by calling it from C.
A Butterworth filter is recursive, so it should be implemented as an IIR filter. Once you have stable filter coefficients from your Matlab testing you can simply feed them to a generic IIR algorithm (pretty simple). You can approximate the filter response with a large FIR filter and convolution, which can be moved into frequency domain to solve phase problems, but it's not truly Butterworth if you do that.
I'd recommend building an algorithm from scratch as a learning exercise, but if you need it ASAP there's probably any number of libraries out there to help you. This came up in search.