Go Down

Topic: FIR Filter Code _ not getting reasonable results (Read 733 times) previous topic - next topic

amrtariq

Aug 16, 2013, 06:36 pm Last Edit: Aug 16, 2013, 09:06 pm by amrtariq Reason: 1
I use this code to High pass filter accelerometer data but the problem is the reading at "m/2 "although the sensor is stabilized  always around -46 ... if there is any one that understands FIR filter please check this code and tell me where is the problem ..also if any one can provide a working FIR code that would be very helpful ...
Thanks in Advance :)

Code: [Select]
//******************************************************************
// "m" : is the order of filter NOTE : it must be even.            #
//                                                                 #
//                  "IMPORTANT" : Please set m in te main file.    #
//                                                                 #
//more info:                                                       #
// http://www.labbookpages.co.uk/audio/firWindowing.html           #
//******************************************************************

//// store fn:
//
// this function stores previous values for the filter.
// "acc" : is acceleromrter reading on required axis.
// start of store fn.

void store(float acc )
{
 if(order < m+1)

 {
   previous[order] = acc;
   Serial.print("previous ");Serial.print(order); Serial.print(":"); Serial.print(previous[order]);
   Serial.println();
   order++;

 }
 else
 {
   order = 0;
   filtered = 0;
 }
}
// end of store fn.
//////////////////////
//// weights fn:
//
// this function gets the weight for every stored data.
// "fr" : is called normalized transition freq, for more details check the attached link above.
//start weights fn.

void weights( float fr )
{
 for (int z = 0; z<m+1 ; z++)
 {
   if(z == m/2)
   {
     b[z] = 1 -(2*fr) ;
         Serial.print("b[z] : ");  Serial.print(b[z]);
             Serial.print("fr : ");  Serial.print(fr);


   }
   else
   {
     b[z] = -(sin(2*(22/7)*fr*(z - (m/2)))/((22/7)*(z - (m/2))));
                   Serial.print("fr : ");  Serial.print(fr);

   }
   Serial.println(b[z]);
 }  
}
//end weights fn.
//////////////////////
//// final FIR fn:
//
// this function gets the filtered data of FIR high pass filter.
// "cut_off" : is the cut off frequency in "Hz" required.
// "dt" : sampling time in ms.
//start FIR fn.

void FIR(float acc ,  float cut_off, float dt)
{
 
 if (d >0)
{
 float fr = ((cut_off*dt)/(1000));
               Serial.print("fr : ");  Serial.print(fr);

 store(acc);
//  if (y ==0)
//  {
 weights(fr);
//  y++;
//  }
 for (int k =0 ; k< m+1; k++)
 {
   filtere[k] = b[k]*previous[m-k];
   Serial.print("Filtered  "); Serial.print(k); Serial.print(" : "); Serial.print(filtere[k]);
   Serial.println();

   Serial.print("weight : ");  Serial.print(b[k]);
   Serial.println();
 }
}

   d++;
 
}
//end FIR fn.

el_supremo

First thing to do is post your code properly. Read this: How to post code properly

Pete

amrtariq

I use this code to High pass filter accelerometer data but i keep getting results tends to 200--> if there is any one that understands FIR filter please check this code and tell me where is the problem ..also if any one can provide a working FIR code that would be very helpful ...

Thanks in Advance :)

Code: [Select]
//******************************************************************
// "m" : is the order of filter NOTE : it must be even.           
//                                                                 
//                  "IMPORTANT" : Please set m in te main file.   
//                                                                 
//more info:                                                       
// http://www.labbookpages.co.uk/audio/firWindowing.html           
//******************************************************************

//// store fn:
//
// this function stores previous values for the filter.
// "acc" : is acceleromrter reading on required axis.
// start of store fn.

void store(float acc )
{
  if(order < m+1)

  {
    previous[order] = acc;
    Serial.print("previous ");Serial.print(order); Serial.print(":"); Serial.print(previous[order]);
    Serial.println();
    order++;

  }
  else
  {
    order = 0;
    filtered = 0;
  }
}
// end of store fn.
//////////////////////
//// weights fn:
//
// this function gets the weight for every stored data.
// "fr" : is called normalized transition freq, for more details check the attached link above.
//start weights fn.

void weights( float fr ,float pre[])
{
  for (int z = 0; z<m+1 ; z++)
  {
    if(z == m/2)
    {
      b[z] = 1 -(2*fr) ;
    }
    else
    {
      b[z] = -(sin(2*(22/7)*fr*(z - (m/2)))/((22/7)*(z - (m/2))));
    }
    Serial.println(b[z]);
  } 
}
//end weights fn.
//////////////////////
//// final FIR fn:
//
// this function gets the filtered data of FIR high pass filter.
// "cut_off" : is the cut off frequency in "Hz" required.
// "dt" : sampling time in ms.
//start FIR fn.

void FIR(float acc ,  float cut_off, float dt)
{
   
  if (d >0)
{
  float fr = (cut_off/(1000/dt));
  store(acc);
  if (y ==0)
  {
  weights(fr, previous);
  y++;
  }
  for (int k =0 ; k< m+1; k++)
  {
    filtered += b[k]*previous[m-k];
    Serial.print("Filtered : ");  Serial.print(filtered);
    Serial.println();
  }
}

    d++;
 
}
//end FIR fn.

el_supremo

You need to post all of your code.

Code: [Select]
      b[z] = -(sin(2*(22/7)*fr*(z - (m/2)))/((22/7)*(z - (m/2))));

This isn't going to work very well because it uses the value 3 for PI. The term (22/7) is an integer division which throws away the fractional part, resulting in 3. Even if you change it to use floating point (22./7.) it is still not a good approximation to PI and will throw off the results.

Pete

amrtariq

#4
Aug 16, 2013, 08:16 pm Last Edit: Aug 16, 2013, 09:05 pm by amrtariq Reason: 1
first: thanks pete I'm attaching here the full code :)
the problem is the output is so huge when it comes to m/2 although other readings around zero. so I have doubt I'm using the wrong equations as I'm new to FIR Concept .
finally : how can I fix the PI problem ?
Here also attached a snapshot of the results.

el_supremo

The PI problem can be fixed by replacing each occurrence of 22/7 by 3.141592654

I don't know enough about FIR filters to help you with the specifics of your application.
But, why are you using a high-pass filter and how do you know that what you are getting is wrong?
The data shown in Capture.JPG looks like the filtered output is a sawtooth waveform.

Pete

amrtariq

I don't know actually if it is wrong as I said I'm new to filters. But, I'm using High_pass filter to cancel accelerometer drift so that i can integerate data twice getting both velocity and Displacement of Quad Chopter. looking at the data if the data is inegrated the result will give displacement while sensor is stable as it is thats why I think it is wrong.

el_supremo

As I say, I have only played with FIR filters but there are a couple of things that seem to be wrong.

You have specified a cutoff frequency of 7kHz which means that your sampling rate must be considerably more than double that. For an FIR to work, the samples must all be collected at a fixed sampling rate. I can't find anything in your code which does this.

In my (limited) experience, when an FIR is run, it is done continuously on every input sample. This requires some form of circular buffer. That is, when you input a new sample, the FIR is run on that sample and the previous M samples which then produces a new output value. On the next sample, you throw out the oldest sample and then run the FIR again. Your code generates a block of samples at some varying rate, does an FIR on them and then throws those away and starts on a new block.

Pete

Go Up