DSPRelated.com
Forums

low frequency IIR BPF - help !!

Started by timelypest December 29, 2011
Hi All,

I have never worked on DSP before so please forgive my lack of education!

I have a signal sampled every 1mS by a 14bit ADC. From this signal I wish
to extract a signal between 0.4Hz and 2.5Hz (while discarding some
components less than 0.4Hz), so I designed a 2nd order butterworth BPF
using Matlab, and it works fine. Next I implemented the filter on Visual
studio using C#, and it works fine too. 

Then I copied the code to my target PIC32 microcontroller and all I get is
junk. I tried using FLOAT and DOUBLE to minimize wordlength (?) issues, but
still there's no difference. 

To test wordlength issues, I went back to Visual studio and tried using
"float" instead of double, and the filter produces junk. I am not able to
visualize the reason of this? Could any of you give me any pointers as to
what's happening and any suggestions on how to fix the filter?

The filter coefficients are (working):
            double[] B = new double[5] { 4.3122003325465159E-5, 0.0,
-8.6244006650930318E-5, 0.0, 4.3122003325465159E-5 };

            double[] A = new double[5] {  1.0,  -3.9812618362095562, 
5.9440373174333914,  -3.9442883933007971,  0.98151291362106841 };

NOT working:
      float[] B= new float[5] { 4.3122003325465159E-5F, 0.0F,
-8.6244006650930318E-5F, 0.0F, 4.3122003325465159E-5F };

      float[] A= new float[5] { 1.0F, -3.9812618362095562F,
5.9440373174333914F, -3.9442883933007971F, 0.98151291362106841F };

Thanks!


On Thu, 29 Dec 2011 21:22:55 -0600, timelypest wrote:

> Hi All, > > I have never worked on DSP before so please forgive my lack of > education! > > I have a signal sampled every 1mS by a 14bit ADC. From this signal I > wish to extract a signal between 0.4Hz and 2.5Hz (while discarding some > components less than 0.4Hz), so I designed a 2nd order butterworth BPF > using Matlab, and it works fine. Next I implemented the filter on Visual > studio using C#, and it works fine too. > > Then I copied the code to my target PIC32 microcontroller and all I get > is junk. I tried using FLOAT and DOUBLE to minimize wordlength (?) > issues, but still there's no difference. > > To test wordlength issues, I went back to Visual studio and tried using > "float" instead of double, and the filter produces junk. I am not able > to visualize the reason of this? Could any of you give me any pointers > as to what's happening and any suggestions on how to fix the filter? > > The filter coefficients are (working): > double[] B = new double[5] { 4.3122003325465159E-5, 0.0, > -8.6244006650930318E-5, 0.0, 4.3122003325465159E-5 }; > > double[] A = new double[5] { 1.0, -3.9812618362095562, > 5.9440373174333914, -3.9442883933007971, 0.98151291362106841 }; > > NOT working: > float[] B= new float[5] { 4.3122003325465159E-5F, 0.0F, > -8.6244006650930318E-5F, 0.0F, 4.3122003325465159E-5F }; > > float[] A= new float[5] { 1.0F, -3.9812618362095562F, > 5.9440373174333914F, -3.9442883933007971F, 0.98151291362106841F }; > > Thanks!
First, don't trust your compiler. It's sad that I say that -- but it's true. Double check that your PIC32 compiler actually gives you a 64-bit variable when you specify "double". It should, but floating point math is the area where compilers most often get things wrong, either by deliberately not living up to the specification, or by supplying buggy library code. Second, it appears that you are not doing what you said you did. Rather, it appears that you have designed a 4th-order filter, presumably one that is a cascade of a low-pass filter and a high-pass filter. This is the right thing to do as a design, but it is the wrong way to implement things. Split up your filter into a high-pass and a low-pass, and cascade them. This will significantly ease the requirements on precision. Your filter should be at least giving recognizable results with one of the direct- form structures and single-precision floating point (at least it will if I'm doing my math right) -- but you should _always_ split things up into cascades of 1st- and 2nd-order filters. The "all in one" is, at best, marginal with single-precision floating point -- the cascade should work really well. As I mention above, your filter, assuming that you really are implementing a 4-th order direct form filter, should be pumping out at least recognizable output even with single-precision floating point arithmetic. I'm not sure why it isn't -- which makes me wonder what you're really doing, and what constitutes "junk" as filter output in your mind. -- My liberal friends think I'm a conservative kook. My conservative friends think I'm a liberal kook. Why am I not happy that they have found common ground? Tim Wescott, Communications, Control, Circuits & Software http://www.wescottdesign.com