STM32 and digital filters: Finite Impulse Response Filter (FIR)

In the previous guide (here), we took a look at the IIR filter and how to implement it on STM32 and filter the output from HMC5883L.

In this guide, we shall cover the Finite Impulse Response Filter.

We shall cover the following:

  • Overview of FIR filter
  • Software implementation
  • Code
  • Demo

1. Overview of FIR:

In signal processing, a finite impulse response (FIRfilter is a filter whose impulse response (or response to any finite length input) is of finite duration, because it settles to zero in finite time. This is in contrast to infinite impulse response (IIR) filters, which may have internal feedback and may continue to respond indefinitely (usually decaying).

The impulse response (that is, the output in response to a Kronecker delta input) of an Nth-order discrete-time FIR filter lasts exactly N+1 samples (from first nonzero element through last nonzero element) before it then settles to zero.

FIR filters can be discrete-time or continuous-time, and digital or analog.

Bellow is a block diagram of a 8 Tap FIR filter, Z−1 is a delay of 1 sample and b[N] are the coefficients for each Tap:

For in depth overview of FIR, please check this video (here).

2. Software implementation:

We start off by creating new header file named FIRFilter.h.

The contents of header is as following:

#ifndef FIR_FILTER_H
#define FIR_FILTER_H

#include <stdint.h>

#define FIR_FILTER_LENGTH 10

typedef struct {
	float 	buf[FIR_FILTER_LENGTH];
	uint8_t bufIndex;

	float out;
} FIRFilter;

void FIRFilter_Init(FIRFilter *fir);
float FIRFilter_Update(FIRFilter *fir, float inp);

#endif

And also, we create source file with name FIR.c.

The code for the source file as following:

#include "FIRFilter.h"

static float FIR_IMPULSE_RESPONSE[FIR_FILTER_LENGTH] = {0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f};


void FIRFilter_Init(FIRFilter *fir) {

	/* Clear filter buffer */
	for (uint8_t n = 0; n < FIR_FILTER_LENGTH; n++) {

		fir->buf[n] = 0.0f;

	}

	/* Reset buffer index */
	fir->bufIndex = 0;

	/* Clear filter output */
	fir->out = 0.0f;

}

float FIRFilter_Update(FIRFilter *fir, float inp) {

	/* Store latest sample in buffer */
	fir->buf[fir->bufIndex] = inp;

	/* Increment buffer index and wrap around if necessary */
	fir->bufIndex++;

	if (fir->bufIndex == FIR_FILTER_LENGTH) {

		fir->bufIndex = 0;

	}

	/* Compute new output sample (via convolution) */
	fir->out = 0.0f;

	uint8_t sumIndex = fir->bufIndex;

	for (uint8_t n = 0; n < FIR_FILTER_LENGTH; n++) {

		/* Decrement index and wrap if necessary */
		if (sumIndex > 0) {

			sumIndex--;

		} else {

			sumIndex = FIR_FILTER_LENGTH - 1;

		}

		/* Multiply impulse response with shifted input sample and add to output */
		fir->out += FIR_IMPULSE_RESPONSE[n] * fir->buf[sumIndex];

	}

	/* Return filtered output */
	return fir->out;

}

In the main file, we start by including the filter library

#include "FIRFilter.h"

Then we declare the filter structure as following:

FIRFilter FIR_Filter;

Also, we declare float to store the filtered output

float gx_fir;

Then we initialize the filter as following:

FIRFilter_Init(&FIR_Filter);

Then we can call the filter output as following:

gx_fil=FIRFilter_Update(&FIR_Filter,gx);

3. Code:

You may download the code from here:

4. Demo:

Since the filter is not tuned, the results are incorrect however, once it is tuned, the filter shall work without any issue

Happy coding 🙂

Add Comment

Your email address will not be published. Required fields are marked *