Butterworth filters

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
nyragu
Posts: 3
Joined: Tue Jan 02, 2018 2:22 am

Butterworth filters

Post by nyragu » Tue Jan 02, 2018 2:25 am

Has anyone implemented Butterworth filters in Micropython? Given how commonly they are needed, I wonder if there are any open source implementations out there.

User avatar
pythoncoder
Posts: 4380
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Butterworth filters

Post by pythoncoder » Tue Jan 02, 2018 12:10 pm

I wrote some general FIR filter code in Assembler for the Pyboard. It is here. It includes a webref for a utility which generates the coefficients from the required response.
Peter Hinch

nyragu
Posts: 3
Joined: Tue Jan 02, 2018 2:22 am

Re: Butterworth filters

Post by nyragu » Tue Jan 02, 2018 6:47 pm

Thanks Peter! This is wonderful stuff!
The filters from TFilter are ripple filters and not Butterworth. I'm a newbie to DSP, but I figure a multi-tap FIR may make more sense than a Butterworth especially given your optimized code.

I'm getting ~1200 taps for a band pass filter. It will likely mean lots of compute time on an M4. Any tips to reduce the number of taps would be greatly welcome.

regards & thanks
-Ragu

User avatar
pythoncoder
Posts: 4380
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Butterworth filters

Post by pythoncoder » Wed Jan 03, 2018 7:55 am

I suggest experimenting with the TFilter app. The number of taps is dependent on the constraints you place on the response curve. 1200 is excessive unless you have very stringent requirements and there will be consequences in terms of compute time, RAM usage and signal time delay.

Bear in mind that an ideal "brick wall" filter requires an infinite number of taps and implies an infinite time delay. That's why such a filter cannot physically be realised in the digital or analog domains. So you have to accept some compromise on passband flatness, stopband rejection and rolloff rates.
Peter Hinch

User avatar
Kip
Posts: 31
Joined: Sat Dec 26, 2015 7:23 am

Re: Butterworth filters

Post by Kip » Thu Jan 25, 2018 4:05 am

Hi Peter,

I'm new to digital filters and I was wondering if you could give me some guidance.

I want a 10KHz bandpass filter and my ADC is sampling at 64KHz. I'm doing this with the read_timed() function capturing the data in a bytearray.

Here's my problem, most of the digital filters for python implement SiPy which is not an option for micropython. I want to be able to filter the data from the bytearray and store the filtered data into a list. Is there a way I could use your FIR filter for this? If so, how would I go about doing so?

User avatar
pythoncoder
Posts: 4380
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Butterworth filters

Post by pythoncoder » Thu Jan 25, 2018 6:13 am

My FIR library is written in Assembler and is designed for real time filtering of a continuous stream of data. So the first question is whether you need to perform the filtering in real time. If so, you only have 15μs in which to process a sample which is right on the limit of what my code can achieve.

If you don't require real time processing - and your description implies that you don't - then there is no problem. By all means use the library, although you can equally code the FIR algorithm in MicroPython. It's simple and any textbook will explain it.

I'd be better able to help with the library if you explained where your problem lies. I suggest you work through the docs and try the example program to get a feel for how it works. In essence you use the weblink to design the filter: this produces a set of coefficients which you can cut and paste into your code to initialise an array. You set up a second integer array (say array2) as per the docs. Then, for each sample you call fir.fir(array2, array_coeffs, sample) which will return the filtered value which you can put into another list or replace the sample in the original list.
Peter Hinch

nyragu
Posts: 3
Joined: Tue Jan 02, 2018 2:22 am

Re: Butterworth filters

Post by nyragu » Thu Jan 25, 2018 10:51 pm

Thanks Peter. While TFilter/FIR filter works well as a low pass filter, when used as a high pass or band pass filter, one loses too much. If the problem didn't appear in the high pass I'd just couple the low pass and high pass filters. But given the losses it does not look too good.

I'm looking to design a bandpass from 50-15000 Hz for standard 44.2KHz samples. Any ideas/advice on how to use your code with TFilter for this would be highly welcome!

regards
-Ragu

pythoncoder wrote:
Wed Jan 03, 2018 7:55 am
I suggest experimenting with the TFilter app. The number of taps is dependent on the constraints you place on the response curve. 1200 is excessive unless you have very stringent requirements and there will be consequences in terms of compute time, RAM usage and signal time delay.

Bear in mind that an ideal "brick wall" filter requires an infinite number of taps and implies an infinite time delay. That's why such a filter cannot physically be realised in the digital or analog domains. So you have to accept some compromise on passband flatness, stopband rejection and rolloff rates.

User avatar
pythoncoder
Posts: 4380
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Butterworth filters

Post by pythoncoder » Fri Jan 26, 2018 6:53 am

@nyragu I don't know your level of experience so apologies in advance if I'm stating the obvious. If you're sampling analog data at 44.2KHz sampling theory (the Nyquist limit) dictates that the maximum frequency which can be captured is 22.1KHz. If there are any frequencies above that on the analog input (such as digital noise) they will be aliased down into the passband. So you must have an analog low pass anti-aliasing filter prior to the ADC. In your case this would have a passband to 15KHz and would have a high degree of rejection above 22.1KHz.

There are techniques of anti-aliasing which combine digital and analog filtering: these involve sampling at a higher rate and using digital decimation filters. The aim is to simplify the analog filter. If this is unfamiliar territory and of interest there are numerous textbooks and tutorials around.

To reject frequencies below 50Hz an FIR low pass filter will be fine.
Peter Hinch

Post Reply