9 years, 1 month ago.

What's wrong of my code

-This is the history Hi guys! I am trying to create a FIR highpass digital filter by using LPC1768. The Specification of this filter is : /media/uploads/Oneoftherulingparty/360----20150413123408.jpg then I write the code and try to implement it. I select 100hz and 3khz as input signal. here is the code: /media/uploads/Oneoftherulingparty/firhpf.cpp I dont know what is wrong of my code, because I successfully simulated in MATLAB. The results of real-time implementation is : /media/uploads/Oneoftherulingparty/tek0003.jpg Could you pls help me to check my code?

-This is the question now--

Before I state my next problem, pls let me express my gratitude to Andy and Raph, they help me to find out my problem inside the code. After that, i modify it and test.

here is the code: LPF: /media/uploads/Oneoftherulingparty/firlpf.cpp

HPF: /media/uploads/Oneoftherulingparty/firhpf2.cpp

The result of LPF is perfect. /media/uploads/Oneoftherulingparty/tek0005.jpg But as for HPF: /media/uploads/Oneoftherulingparty/tek0006.jpg

Is it still errors existed inside my code of HPF or other factors effect the result?

2 Answers

9 years, 1 month ago.

As it is your code could be simplified to:

double FIRHPF(double FIRHPF_in) {
  return FIRHPF_in*0.011799780247487023;
}

x is set to all 0's, you then shift all those zeros to a new location in the array, set x[0] to your new input and do a multiply and accumulate between x and a constant array. Since all but x[0] are 0 the end result is the input multiplied by a[0].

As Raph said, you need to only initialize x to 0's the first time the code is run, not every single time.

Accepted Answer

Thank you but i dont know how to modify my code after i consider your idea for a while, could you pls tell me?

posted by Joe Davis 13 Apr 2015

Thank you and i updated my question, may i ask for your help again?

posted by Joe Davis 13 Apr 2015

The code you linked to for the HPF still has the same bug in.

posted by Andy A 13 Apr 2015

Sorry, that is because I linked wrong code before now

posted by Joe Davis 13 Apr 2015

And now I upload the right one.

posted by Joe Davis 13 Apr 2015

I think you simply have a speed issue. Your high pass output looks like a standard RC curve that you'll get any time you change an output pin with the output value changing about every 200us.

Looking at your code each sample you do 75 multiplies and additions on doubles.

A quick google found that for a cortex M3 a floating point multiplication or addition will both take about 30 clock cycles, normally doubles require 4 times as many cycles as floats but for now let's just assume it's twice as long, it's certainly not going to be faster than that.

So at a minimum that's (75 + 75) * 2 * 30 = 9000 clock cycles.

The LPC1768 clocks at 96MHz, let's call it 100MHz to make the numbers simpler. At 100MHz a cycle is 0.01us so 9000 cycles will take 90us.

Your output is updating at about 200us, which would be consistent with a double taking about 4 times as long as a float rather than twice as long.

These are all very rough estimates but I think it's fairly safe to say that your CPU is busy going flat out and the high pass result you are seeing is the result of that.

You should also check that your filter frequency is correct, if the filter is running at 5kHz not the 100kHz you are assuming your cut off frequencies are going to be wrong.

How to fix this?

Start by moving everything to floats, that should give you a factor of 4 speed up, you only have a 12 bit input so using a float isn't going to cost you any significant accuracy. Make sure you also define a[] and y as being floats or you lose the benefit. Or alternatively use the adc read_u16() function and do everything using integers, that will be even faster but make the maths a little messier.

Also rather than shifting the contents of the x array each time, something that will take up a few hundred cycles just copying memory values, it can be faster (but again messier) to leave the values where they are and increase a pointer telling you where in the array to start from.

Once you're done with the optimizations benchmark how fast the CPU can actually run your filter loop, set the ticker to run a tiny bit slower than that and adjust the coefficents to match the new sample rate.

posted by Andy A 13 Apr 2015
9 years, 1 month ago.

static double x[75];
  double y = 0;
  
  for(int n=0;n<=74;n++)
  x[n]=0;
  
  for(int i=74;i>0;i--) 
  x[i] = x[i-1];          

Array X is staic that seems ok, but every time the Fir function is called, you fill the x array with 0.. so from, when you move values by one sample, there are only 0's... No ? I don't know how to do calculus with FIR, but this fact seems to be quite odd...

Thank you for you answer, but when you see the next line , you will know the logic is right ,I think. This will cause delay but i think it won t effect the results. I create IIR using same way and i get the perfect results.

posted by Joe Davis 13 Apr 2015

Thank you and i updated my question, may i ask for your help again?

posted by Joe Davis 13 Apr 2015