why 50hz can't be removed compeletely?

1 view (last 30 days)
Dear, I am try to remove the 50 hz. It works very well if I plot the result using amplitude. However when when I plot the result using 10*log10(amp), the 50hz will be still there with large amplitude.
%% build filter
N = 20; % Order
F3dB1 = 49; % First
F3dB2 = 51; % Second
Fs = 1000; % Sampling Frequency
d = designfilt('bandstopiir','FilterOrder',2, ...
'HalfPowerFrequency1',49,'HalfPowerFrequency2',51, ...
'DesignMethod','butter','SampleRate',Fs);
%% test data
fs = 1000;
t = 0:1/fs:5-1/fs;
x = cos(2*pi*50*t)+cos(2*pi*100*t);
%plot(t,x)
%plotChannelSpectral(x);
[psd,f] = pwelch(x,500,200,500,1000);
plot(f,10*log10(psd));
plot(f,(psd));
fdata=filtfilt(d,double(x));
[psd2,f2] = pwelch(fdata,500,200,500,1000);
figure;
plot(f2,psd2); % 50hz almost gone in this plot
plot(f,10*log10(psd2)); % however I still can see large 50hz in this plot, even I re-run the filtfilt 20 times, I still can see relative large amplitude around 50hz, though there is a groove at 50hz.
Does it means that I should be satisfied as long as I can't see the 50hz in amplitude? And there is no way to totally eliminate the large value under 10*log10(amplitude)?
Thanks in advance.

Accepted Answer

Mathieu NOE
Mathieu NOE on 24 Nov 2020
hello again
I like simple solutions - see demo code below adapted to your case
I hope 200 dB attenuation can be considered as "complete washed out" !!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FFT parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
NFFT = 1024*4; %
NOVERLAP = round(0.75*NFFT);
w = hanning(NFFT); % Hanning window / Use the HANN function to get a Hanning window which has the first and last zero-weighted samples.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% load signal
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% test data
Fs = 1000;
t = 0:1/Fs:10-1/Fs;
signal = cos(2*pi*50*t)+cos(2*pi*100*t);
%% notch filter section %%%%%%
% H(s) = (s^2 + 1) / (s^2 + s/Q + 1)
fc = 50; % notch freq
wc = 2*pi*fc;
Q = 2; % adjust Q factor for wider (low Q) / narrower (high Q) notch
% at f = fc the filter has gain = 0
w0 = 2*pi*fc/Fs;
alpha = sin(w0)/(2*Q);
b0 = 1;
b1 = -2*cos(w0);
b2 = 1;
a0 = 1 + alpha;
a1 = -2*cos(w0);
a2 = 1 - alpha;
% analog notch (for info)
num1=[1/wc^2 0 1];
den1=[1/wc^2 1/(wc*Q) 1];
% digital notch (for info)
num1z=[b0 b1 b2];
den1z=[a0 a1 a2];
freq = linspace(fc-1,fc+1,200);
[g1,p1] = bode(num1,den1,2*pi*freq);
g1db = 20*log10(g1);
[gd1,pd1] = dbode(num1z,den1z,1/Fs,2*pi*freq);
gd1db = 20*log10(gd1);
figure(1);
plot(freq,g1db,'b',freq,gd1db,'+r');
title(' Notch: H(s) = (s^2 + 1) / (s^2 + s/Q + 1)');
legend('analog','digital');
xlabel('Fréquence (Hz)');
ylabel(' dB')
% now let's filter the signal
signal_filtered = filtfilt(num1z,den1z,signal);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display : averaged FFT spectrum before / after notch filter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[sensor_spectrum, freq] = pwelch(signal,w,NOVERLAP,NFFT,Fs);
sensor_spectrum_dB = 20*log10(sensor_spectrum);% convert to dB scale (ref = 1)
[sensor_spectrum_filtered, freq] = pwelch(signal_filtered,w,NOVERLAP,NFFT,Fs);
sensor_spectrum_filtered_dB = 20*log10(sensor_spectrum_filtered);% convert to dB scale (ref = 1)
figure(2),semilogx(freq,sensor_spectrum_dB,'b',freq,sensor_spectrum_filtered_dB,'r');grid
title(['Averaged FFT Spectrum / Fs = ' num2str(Fs) ' Hz / Delta f = ' num2str(freq(2)-freq(1)) ' Hz ']);
legend('before notch filter','after notch filter');
xlabel('Frequency (Hz)');ylabel(' dB')

More Answers (1)

Mathieu NOE
Mathieu NOE on 23 Nov 2020
hello
2 gifts for you in the same day (you lucky ! )
  • a code for spectral analysis and time / frequency analysis
  • a the end , some code for a better notch filter digital implementation ; your notch is not effective enough
hope it helps
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FFT parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
NFFT = 1024; %
NOVERLAP = round(0.75*NFFT);
w = hanning(NFFT); % Hanning window / Use the HANN function to get a Hanning window which has the first and last zero-weighted samples.
% spectrogram dB scale
spectrogram_dB_scale = 80; % dB range scale (means , the lowest displayed level is XX dB below the max level)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% options
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% if you are dealing with acoustics, you may wish to have A weighted
% spectrums
% option_w = 0 : linear spectrum (no weighting dB (L) )
% option_w = 1 : A weighted spectrum (dB (A) )
option_w = 0;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% load signal
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%[data,Fs]=wavread('Approach_Gear_Drop_Aft Ctr.wav '); %(older matlab)
% or
[data,Fs]=audioread('myWAVaudiofile.wav'); %(newer matlab)
channel = 1;
signal = data(:,channel);
samples = length(signal);
dt = 1/Fs;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display 1 : averaged FFT spectrum
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[sensor_spectrum, freq] = pwelch(signal,w,NOVERLAP,NFFT,Fs);
% convert to dB scale (ref = 1)
sensor_spectrum_dB = 20*log10(sensor_spectrum);
% apply A weigthing if needed
if option_w == 1
pondA_dB = pondA_function(freq);
sensor_spectrum_dB = sensor_spectrum_dB+pondA_dB;
my_ylabel = ('Amplitude (dB (A))');
else
my_ylabel = ('Amplitude (dB (L))');
end
figure(1),semilogx(freq,sensor_spectrum_dB);grid
title(['Averaged FFT Spectrum / Fs = ' num2str(Fs) ' Hz / Delta f = ' num2str(freq(2)-freq(1)) ' Hz ']);
xlabel('Frequency (Hz)');ylabel(my_ylabel);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display 2 : time / frequency analysis : spectrogram demo
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[sg,fsg,tsg] = specgram(signal,NFFT,Fs,w,NOVERLAP);
% FFT normalisation and conversion amplitude from linear to dB (peak)
sg_dBpeak = 20*log10(abs(sg))+20*log10(2/length(fsg)); % NB : X=fft(x.*hanning(N))*4/N; % hanning only
% apply A weigthing if needed
if option_w == 1
pondA_dB = pondA_function(fsg);
sg_dBpeak = sg_dBpeak+(pondA_dB*ones(1,size(sg_dBpeak,2)));
my_title = ('Spectrogram (dB (A))');
else
my_title = ('Spectrogram (dB (L))');
end
% saturation of the dB range :
% saturation_dB = 60; % dB range scale (means , the lowest displayed level is XX dB below the max level)
min_disp_dB = round(max(max(sg_dBpeak))) - spectrogram_dB_scale;
sg_dBpeak(sg_dBpeak<min_disp_dB) = min_disp_dB;
% plots spectrogram
figure(2);
imagesc(tsg,fsg,sg_dBpeak);colormap('jet');
axis('xy');colorbar('vert');grid
title([my_title ' / Fs = ' num2str(Fs) ' Hz / Delta f = ' num2str(fsg(2)-fsg(1)) ' Hz ']);
xlabel('Time (s)');ylabel('Frequency (Hz)');
function pondA_dB = pondA_function(f)
% dB (A) weighting curve
n = ((12200^2*f.^4)./((f.^2+20.6^2).*(f.^2+12200^2).*sqrt(f.^2+107.7^2).*sqrt(f.^2+737.9^2)));
r = ((12200^2*1000.^4)./((1000.^2+20.6^2).*(1000.^2+12200^2).*sqrt(1000.^2+107.7^2).*sqrt(1000.^2+737.9^2))) * ones(size(f));
pondA = n./r;
pondA_dB = 20*log10(pondA(:));
end
% %%%%%%%%%%% other infos %%%%%%%%%%%%%%%%%%%%%%%%
%
%
% %% notch filter section %%%%%%
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% % notch : H(s) = (s^2 + 1) / (s^2 + s/Q + 1)
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% fc = 50; % notch freq
%
% Q = 100; % the higher the Q factor, the deeper the notch
%
% %%%%%%
% w0 = 2*pi*fc;
%
% alpha = sin(w0)/(2*Q);
%
%
% b0 = 1;
% b1 = -2*cos(w0);
% b2 = 1;
% a0 = 1 + alpha;
% a1 = -2*cos(w0);
% a2 = 1 - alpha;
% %
% num1z=[b0 b1 b2];
% den1z=[a0 a1 a2];
%
% % now let's filter the signal
% signal_filtered = filter(num1z,den1z,signal);
  1 Comment
Xiaolong wu
Xiaolong wu on 23 Nov 2020
I think so as well, my filter just not powerful enough. I am not sure how to design a powerful notch filter with designfilt.

Sign in to comment.

Tags

Community Treasure Hunt

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

Start Hunting!