Lowpass filter not making any difference

62 visualizaciones (últimos 30 días)
Nick Li
Nick Li el 5 de Abr. de 2023
Editada: Cris LaPierre el 9 de Oct. de 2024
I'm new to filtering, trying to use a low-pass filter to filter a sine wave with another high frequency sine wave on top of it. Using highpass(valArray, .03) I can effectively isolate the higher frrequency. But lowpass(valArray, .03) just appears to return the original signal (or something close to it).
It's possible my setup is incomplete. I'm simply using the lowpass() and highpass() commands. But seems odd that the highpass filter works fine while the lowpass filter fails.
lowpass(valArray, .03);
highpass(valArray, .03)
  4 comentarios
Cris LaPierre
Cris LaPierre el 6 de Abr. de 2023
So your data is something like this.
millis = linspace(1,33850,17000);
valArray = 3600 * sin(mod(millis,3600)/3600 * 6.28) + 200 * sin(mod(millis,100)/100 * 6.28);
figure
lowpass(valArray, .03);
figure
highpass(valArray, .03);
Nick Li
Nick Li el 6 de Abr. de 2023
Yes, exactly. It looks like you're getting the same results as me? Is there something I'm missing as to be able to isolate the lower frequency wave?

Iniciar sesión para comentar.

Respuesta aceptada

Cris LaPierre
Cris LaPierre el 6 de Abr. de 2023
Editada: Cris LaPierre el 6 de Abr. de 2023
The reason your lowpass filter is not working is because your filter settings are not aggressive enough to both pass your low frequency signal and block your high frequency signal (they are very close together for a filter to separate them). It took a little investigation to be able to explain why.
Normalized frequency can make it a bit harder to undestand the cutoff frequencies, so I started by figuring out your approximate sample frequency (~500 Hz).
You can then convert normalized frequency back to Hz by multiplying it by fs/2. You are using a wpass of 0.03.
fs = 500;
wpass = 0.03;
fpass = wpass*fs/2
fpass = 7.5000
As you can see, your corner frequency (fpass) is around 7.5 Hz. Next we need to determine the frequencies of your two sine waves. Inspecting the signals confirmed that they are approximately 1/3.6 Hz and 1/0.1 Hz.
LF = 1/3.6 % low frequency wave, Hz
LF = 0.2778
HF = 1/.1 % high frequency wave, Hz
HF = 10
Let's look at what is happening in the lowpass scenario. For that, I think this figure is helpful.
The first thing to notice is that the frequency does not just shut off after your corner frequency is reached. Instead, there is a transition period until you reach the specified StopbandAttenuation (60 dB by default). The steepness of this transition is set by the Steepness parameter (85% by default).
Since you are using all the default settings for lowpass, , and W is 15% of :
fstop = fpass + 0.15*(fs/2 - fpass)
fstop = 43.8750
As you can see, your high frequency signal is well within this window. To exclude it, you can lower fpass, but that alone won't do it, as you can only reduce by around 7 Hz. You need to adjust Steepness so that is below 10 Hz. Playing around with this equation, you can see that, if you keep fpass the same, your Steepness will need to be 99% or higher, and even then, it's not perfect.
fstop = fpass + 0.01*(fs/2 - fpass)
fstop = 9.9250
millis = linspace(1,33850,17000);
valArray = 3600 * sin(mod(millis,3600)/3600 * 6.28) + 200 * sin(mod(millis,100)/100 * 6.28);
figure
lowpass(valArray, wpass,"Steepness",0.99);
Fortunately, though, this approach does mean you do not have to modify your highpass function code, as wpass stayed the same.
You can go through the same exercise with high pass filters by using the corresponding info found here.
  7 comentarios
Cris LaPierre
Cris LaPierre el 3 de Oct. de 2024
Editada: Cris LaPierre el 9 de Oct. de 2024
Trial and error. I knew the approximate number of samples (17000), and from the arduino code could assume millis was milliseconds. Since the user shared the expression for the waveform, I just had to find a value for milliseconds that duplicated the waveform.
So, for example, if the plot contained 10 seconds of data, this is what it would look like:
start = 1; % milliseconds
stop = 10000; % millisecons
millis = linspace(start,stop,17000);
valArray = 3600 * sin(mod(millis,3600)/3600 * 6.28) + 200 * sin(mod(millis,100)/100 * 6.28);
plot(valArray)
xlim([0,17000])
This does not contain the same number of cycles, so I need to increase the stop time. This contains about 2.75 cycles. The original signal contains about 9.35 cycles, so I need to increase by a factor of 9.35/2.75
stop = stop*9.35/2.75
stop = 34000
millis = linspace(start,stop,17000);
valArray = 3600 * sin(mod(millis,3600)/3600 * 6.28) + 200 * sin(mod(millis,100)/100 * 6.28);
plot(valArray)
xlim([0,17000])
That's a little too much, but hopeefully you see the process. Once I have the correct stop time, I can figure out the sample frequency by inverting the time step.
dt = (millis(2)-millis(1))/1000 % convert to seconds
dt = 0.0020
fs = 1/dt
fs = 499.9853
Hope that helps.
Jing
Jing el 8 de Oct. de 2024
Thanks so much for this detailed explanation! It really helps me to understand this process. Thanks for your time and your patience!

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Statistics and Linear Algebra en Help Center y File Exchange.

Productos


Versión

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by