Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
9 years, 7 months 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 :
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 :
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. But as for HPF:
Is it still errors existed inside my code of HPF or other factors effect the result?
2 Answers
9 years, 7 months 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.
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 13 Apr 2015I 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 13 Apr 20159 years, 7 months 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...