How to FFT my xlsx files from time domain to frequency domain?

2 views (last 30 days)
Hi, i'm new to Matlab. I have 4 column of different voltages signal in time domain. i need to transform it into frequency domain. How do i use FFT in Matlab?
Also, can i filter the signal with Matlab as well? If the answer is yes, then how?
The link was inserted below, please help.

Accepted Answer

Star Strider
Star Strider on 17 May 2022
Try this —
T1 = readtable('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1000730/delay%2040ms%20speed%20100%20length%2020%20(1).xlsx', 'VariableNamingRule','preserve');
T1.Var1.Format = 'dd-MMM-yyyy HH:mm:ss.SSS'
T1 = 340×5 table
Var1 Var2 Var3 Var4 Var5 ________________________ ____ ____ ____ ____ 10-May-2022 11:27:28.626 0.01 0.01 0.02 0.02 10-May-2022 11:27:28.626 0.01 0.01 0.01 0.02 10-May-2022 11:27:28.678 0.02 0.02 0.02 0.01 10-May-2022 11:27:28.717 0 0.02 0.02 0.01 10-May-2022 11:27:28.766 0.02 0.02 0.01 0.02 10-May-2022 11:27:28.817 0.01 0.02 0.02 0.01 10-May-2022 11:27:28.856 0.02 0.02 0.02 0.01 10-May-2022 11:27:28.904 0.02 0.02 0.02 0.02 10-May-2022 11:27:28.904 0.01 0.01 0.02 0.02 10-May-2022 11:27:28.966 0.01 0.02 0.02 0.01 10-May-2022 11:27:29.014 0.03 0.02 0.01 0.01 10-May-2022 11:27:29.060 0.02 0.02 0.01 0.02 10-May-2022 11:27:29.107 0 0.02 0.02 0.01 10-May-2022 11:27:29.150 0.02 0.02 0.01 0.02 10-May-2022 11:27:29.196 0.02 0.02 0.01 0.02 10-May-2022 11:27:29.242 0.03 0.02 0.01 0.02
TT1 = table2timetable(T1);
TT1 = retime(TT1,'regular','mean', 'TimeStep',seconds(0.1))
TT1 = 146×4 timetable
Var1 Var2 Var3 Var4 Var5 ________________________ ________ ________ ________ ________ 10-May-2022 11:27:28.600 0.013333 0.013333 0.016667 0.016667 10-May-2022 11:27:28.700 0.01 0.02 0.015 0.015 10-May-2022 11:27:28.800 0.015 0.02 0.02 0.01 10-May-2022 11:27:28.900 0.013333 0.016667 0.02 0.016667 10-May-2022 11:27:29.000 0.025 0.02 0.01 0.015 10-May-2022 11:27:29.100 0.013333 0.02 0.013333 0.016667 10-May-2022 11:27:29.200 0.02 0.02 0.01 0.016667 10-May-2022 11:27:29.300 0.02 0.015 0.02 0.015 10-May-2022 11:27:29.400 0.015 0.02 0.015 0.01 10-May-2022 11:27:29.500 0.01 0.013333 0.023333 0.01 10-May-2022 11:27:29.600 0.015 0.005 0.01 0.02 10-May-2022 11:27:29.700 0.015 0.015 0.02 0.02 10-May-2022 11:27:29.800 0.02 0.015 0.02 0.02 10-May-2022 11:27:29.900 0.013333 0.023333 0.016667 0.016667 10-May-2022 11:27:30.000 0.025 0.01 0.015 0.02 10-May-2022 11:27:30.100 0.01 0.015 0.02 0.01
TT1.Tv = TT1.Var1 - TT1.Var1(1);
TT1.Tv = seconds(TT1.Tv)
TT1 = 146×5 timetable
Var1 Var2 Var3 Var4 Var5 Tv ________________________ ________ ________ ________ ________ ___ 10-May-2022 11:27:28.600 0.013333 0.013333 0.016667 0.016667 0 10-May-2022 11:27:28.700 0.01 0.02 0.015 0.015 0.1 10-May-2022 11:27:28.800 0.015 0.02 0.02 0.01 0.2 10-May-2022 11:27:28.900 0.013333 0.016667 0.02 0.016667 0.3 10-May-2022 11:27:29.000 0.025 0.02 0.01 0.015 0.4 10-May-2022 11:27:29.100 0.013333 0.02 0.013333 0.016667 0.5 10-May-2022 11:27:29.200 0.02 0.02 0.01 0.016667 0.6 10-May-2022 11:27:29.300 0.02 0.015 0.02 0.015 0.7 10-May-2022 11:27:29.400 0.015 0.02 0.015 0.01 0.8 10-May-2022 11:27:29.500 0.01 0.013333 0.023333 0.01 0.9 10-May-2022 11:27:29.600 0.015 0.005 0.01 0.02 1 10-May-2022 11:27:29.700 0.015 0.015 0.02 0.02 1.1 10-May-2022 11:27:29.800 0.02 0.015 0.02 0.02 1.2 10-May-2022 11:27:29.900 0.013333 0.023333 0.016667 0.016667 1.3 10-May-2022 11:27:30.000 0.025 0.01 0.015 0.02 1.4 10-May-2022 11:27:30.100 0.01 0.015 0.02 0.01 1.5
figure
plot(TT1.Tv, TT1{:,1:4})
grid
xlabel('Time (s)')
ylabel('Amplitude')
Fs = 1/mean(diff(TT1.Tv));
Fn = Fs/2;
L = size(TT1,1);
NFFT = 2^nextpow2(L);
FT_TT1 = fft(TT1{:,1:4} - mean(TT1{:,1:4}),NFFT)/L;
Fv = linspace(0, 1, NFFT/2+1)*Fn;
Iv = 1:numel(Fv);
figure
for k = 1:4
subplot(2,2,k)
plot(Fv, abs(FT_TT1(Iv,k))*2)
grid
xlabel('Frequency (Hz)')
ylabel('Amplitude')
title(sprintf('Var%d',k))
end
.
  2 Comments
Andrew CJ
Andrew CJ on 24 May 2022
Hey, thanks for the code. It seems like the way i expect. But sorry, can you explain what is each code's row for, please?
Star Strider
Star Strider on 24 May 2022
As always, my pleasure!
A general description is that the code reads the file into a table, then because the sampling interval is not constant (I determined that earlier however did not post that code since it was not relevant here) then converted it to a timetable and use the retime function to interpolate it to the nearest 100 milliseconds. The rest oif the code calculates the Fourier transform magnitude and plots the results.

Sign in to comment.

More Answers (1)

Mathieu NOE
Mathieu NOE on 17 May 2022
hello
see my demo below
now your signals look like a bunch of spikes so I wonder what you expect from the fft analysis ?
clc
clearvars
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% load signal
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
filename = ('delay 40ms speed 100 length 20 (1).xlsx');
data = xlsread(filename); % 5 channels : Time + 4 column of different voltages signal in time domain
time = data(:,1);
dt = mean(diff(time));
signal = data(:,2:5); % select here one or several channels
Fs = 1/dt; % sampling rate
[samples,channels] = size(signal);
% time vector
t = (0:samples-1)*dt;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FFT parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
NFFT = 100; %
OVERLAP = 0.75;
% 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;
%% decimate (if needed)
% NB : decim = 1 will do nothing (output = input)
decim = 1;
if decim>1
for ck = 1:channels
newsignal(:,ck) = decimate(signal(:,ck),decim);
Fs = Fs/decim;
end
signal = newsignal;
end
samples = length(signal);
time = (0:samples-1)*1/Fs;
%%%%%% legend structure %%%%%%%%
for ck = 1:channels
leg_str{ck} = ['Channel ' num2str(ck) ];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display 1 : time domain plot
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure(1),plot(time,signal);grid on
title(['Time plot / Fs = ' num2str(Fs) ' Hz ']);
xlabel('Time (s)');ylabel('Amplitude');
legend(leg_str);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display 2 : averaged FFT spectrum
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[freq, sensor_spectrum] = myfft_peak(signal,Fs,NFFT,OVERLAP);
% 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(2),plot(freq,sensor_spectrum_dB);grid on
df = freq(2)-freq(1); % frequency resolution
title(['Averaged FFT Spectrum / Fs = ' num2str(round(Fs)) ' Hz / Delta f = ' num2str(df,3) ' Hz ']);
xlabel('Frequency (Hz)');ylabel(my_ylabel);
legend(leg_str);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display 3 : time / frequency analysis : spectrogram demo
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for ck = 1:channels
[sg,fsg,tsg] = specgram(signal(:,ck),NFFT,Fs,hanning(NFFT),floor(NFFT*OVERLAP));
% 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+ck);
imagesc(tsg,fsg,sg_dBpeak);colormap('jet');
axis('xy');colorbar('vert');grid on
df = fsg(2)-fsg(1); % freq resolution
title([my_title ' / Fs = ' num2str(Fs) ' Hz / Delta f = ' num2str(df,3) ' Hz / Channel : ' num2str(ck)]);
xlabel('Time (s)');ylabel('Frequency (Hz)');
end
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
function [freq_vector,fft_spectrum] = myfft_peak(signal, Fs, nfft, Overlap)
% FFT peak spectrum of signal (example sinus amplitude 1 = 0 dB after fft).
% Linear averaging
% signal - input signal,
% Fs - Sampling frequency (Hz).
% nfft - FFT window size
% Overlap - buffer percentage of overlap % (between 0 and 0.95)
[samples,channels] = size(signal);
% fill signal with zeros if its length is lower than nfft
if samples<nfft
s_tmp = zeros(nfft,channels);
s_tmp((1:samples),:) = signal;
signal = s_tmp;
samples = nfft;
end
% window : hanning
window = hanning(nfft);
window = window(:);
% compute fft with overlap
offset = fix((1-Overlap)*nfft);
spectnum = 1+ fix((samples-nfft)/offset); % Number of windows
% % for info is equivalent to :
% noverlap = Overlap*nfft;
% spectnum = fix((samples-noverlap)/(nfft-noverlap)); % Number of windows
% main loop
fft_spectrum = 0;
for i=1:spectnum
start = (i-1)*offset;
sw = signal((1+start):(start+nfft),:).*(window*ones(1,channels));
fft_spectrum = fft_spectrum + (abs(fft(sw))*4/nfft); % X=fft(x.*hanning(N))*4/N; % hanning only
end
fft_spectrum = fft_spectrum/spectnum; % to do linear averaging scaling
% one sidded fft spectrum % Select first half
if rem(nfft,2) % nfft odd
select = (1:(nfft+1)/2)';
else
select = (1:nfft/2+1)';
end
fft_spectrum = fft_spectrum(select,:);
freq_vector = (select - 1)*Fs/nfft;
end
  3 Comments
Andrew CJ
Andrew CJ on 24 May 2022
hi, thanks for the code, but when i tried it, it showed error on the myfft_peak.
Mathieu NOE
Mathieu NOE on 24 May 2022
hello again
maybe you are running an older matlab release
in this case , the functions that appears at the end of my code (read again) must be saved in a separate m file (and the file name must be identical to the function name)
this applies to both supplied functions - here again :
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
% and
function [freq_vector,fft_spectrum] = myfft_peak(signal, Fs, nfft, Overlap)
% FFT peak spectrum of signal (example sinus amplitude 1 = 0 dB after fft).
% Linear averaging
% signal - input signal,
% Fs - Sampling frequency (Hz).
% nfft - FFT window size
% Overlap - buffer percentage of overlap % (between 0 and 0.95)
[samples,channels] = size(signal);
% fill signal with zeros if its length is lower than nfft
if samples<nfft
s_tmp = zeros(nfft,channels);
s_tmp((1:samples),:) = signal;
signal = s_tmp;
samples = nfft;
end
% window : hanning
window = hanning(nfft);
window = window(:);
% compute fft with overlap
offset = fix((1-Overlap)*nfft);
spectnum = 1+ fix((samples-nfft)/offset); % Number of windows
% % for info is equivalent to :
% noverlap = Overlap*nfft;
% spectnum = fix((samples-noverlap)/(nfft-noverlap)); % Number of windows
% main loop
fft_spectrum = 0;
for i=1:spectnum
start = (i-1)*offset;
sw = signal((1+start):(start+nfft),:).*(window*ones(1,channels));
fft_spectrum = fft_spectrum + (abs(fft(sw))*4/nfft); % X=fft(x.*hanning(N))*4/N; % hanning only
end
fft_spectrum = fft_spectrum/spectnum; % to do linear averaging scaling
% one sidded fft spectrum % Select first half
if rem(nfft,2) % nfft odd
select = (1:(nfft+1)/2)';
else
select = (1:nfft/2+1)';
end
fft_spectrum = fft_spectrum(select,:);
freq_vector = (select - 1)*Fs/nfft;
end

Sign in to comment.

Products


Release

R2021a

Community Treasure Hunt

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

Start Hunting!