# IIR filter with circular buffer - Arduino [closed]

I am trying to implement a butterworth lowpass filter with a circular buffer. The code below does not filter as intended and I am not really able to understand what is wrong. Any suggestion?

#define PERIOD_MICROSECS 1000

int analog_pin = 0;
int32_t analog_input0 = 0;
double analog_input0_lp_filtered = 0;

// The coefficients are calculated offline. I set the sample frequency to 1000 Hz, the cutoff to 50 Hz.
// The filter has order = 4.
double c[] = {0.000416599204407, 0.001666396817626, 0.002499595226440, 0.001666396817626, 0.000416599204407};
double d[] = {1.000000000000, -3.180638548875, 3.861194348994, -2.112155355111, 0.438265142262};

int m = 10;
double x[10];
double y[10];

int n = 0;

double lp_butterworth(double input_sample, double *x, double *y, int m, int n)
{
x[n] = input_sample;
y[n] = d[0] * x[n] + d[1] * x[(n-1+m)%m] + d[2] * x[(n-2+m)%m] + d[3] * x[(n-3+m)%m] + d[4] * x[(n-4+m)%m]
- c[1] * y[(n-1+m)%m] - c[2] * y[(n-2+m)%m] - c[3] * y[(n-3+m)%m] - c[4] * y[(n-4+m)%m];

return y[n];
}

// ************************* //

void setup() {

Serial.begin(115200);
}

void loop() {

if (micros() - lastRead >= PERIOD_MICROSECS) {

analog_input0_lp_filtered = lp_butterworth(analog_input0, x, y, m, n);
n = (n + 1) % m;

//Check the original and filtered signals with the serial plotter
Serial.print(analog_input0);
Serial.print(" ");
Serial.println(analog_input0_lp_filtered);
}
}


Below you can see the result of the code in the serial plotter using as analog input an accelerometer at steady state. You can notice a huge offset and not really a filtering effect.

• Can you describe in what way it doesn't work like it should? Also, I'm always very skeptical when people say "I used a digital Butterworth", because that is often just because that's the first thing they found in their textbook, but almost never what they actually need. So, could you explain why you're using a Butterworth IIR here? What's the purpose/greater applicational scope of all this? – Marcus Müller May 22 '19 at 12:20
• Simply the result is not really a signal result of filtering. There must be something wrong in the code. I am getting the coefficients from exstrom.com/journal/sigproc . I have update the post with a screenshot of the serial plotter. I am willing to filter various analog sensors (including accelerometers and infrared sensors) and I want to be able to control the cutoff frequency. The butterworth is known to be have maximally flat response, which is what I want. – L_T May 22 '19 at 12:56
• you'll need to be more precise than "Not a result of filtering". Please test with a sensible test signal (for example $1,0,0,\ldots, 0$), and see how the result differs from your expectation! – Marcus Müller May 22 '19 at 13:09
• There is no error in my testing methodology: the signal I am using is more than reasonable, and I know what I should expect from a butterworth filtering. Do you have any suggestion about the actual code? Simply the result is that there is no filtering. – L_T May 22 '19 at 13:12

• @L_T without trying to be mean (honestly!), that's something that you would have started to suspect when you tested with a $1,0,\ldots$ signal, because that isolates problems pretty well :) anyway, I'm happy that the issue was resolved! – Marcus Müller May 22 '19 at 16:22