MATLAB: How can i obtain different frequencies from a waveform using FFT

fft on csv

I have a csv file which i used to plot data. I'm trying to use FFT in matlab to obtain the different frequencies this signal is made up of. My fft doesn't look correct. How can i fix this? First i try to use Savitzky Golay filter to smoothen the signal then take fft. below is my code and CSV has been attached.
clear all; close all; clc;
data = csvread('TEK00001.csv'); x=data(:,1); y=data(:,2);
Fs=100; polymonial_order=0; framelength=201; % plot(x,y) % hold on %%%%%%%%%%%%%%%%%% Savitzky Golay filter %%%%%%%%%%%%%%%%%%%%% new_data=sgolayfilt(data, polymonial_order,framelength); x_col1=new_data(:,1); y_col2=new_data(:,2);
new_data(:,2)=new_data(:,2)-min(new_data(:,2));
subplot(4,1,1) plot(x,y,'r') title('Original CSV waveform') grid on grid minor xlabel('Time [s]'); ylabel('Amplitude [mV] ');
subplot(4,1,2) plot(x_col1,y_col2,'b') title('Filtered waveform using Savitzky Golay Filter') grid on grid minor xlabel('Time [s]'); ylabel('Amplitude [mV]'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% nfft=length(data); nfft2=2^nextpow2(nfft); ff=fft(new_data,nfft2); %plot(abs(ff)); %plots the magnitude of signal xfft=Fs*(0:nfft2/2-1)/nfft2;
subplot(4,1,3) fff=ff(1:nfft2/2); plot(xfft,abs(fff))%plots the one symetrical side of fft signal title('FFT Magnitude') grid minor xlabel('Frequency [Hz]'); ylabel('Amplitude [mV]');

Best Answer

It doesn’t look correct to me either.
I would not use the Savitzky-Golay filter here, at least not with you original data. (I’m not certain what you want to do with it, anyway.)
If you want to get the frequency content of your signal, I would do something like this:
data = csvread('TEK00001.csv');
x=data(:,1);
y=data(:,2);
L = numel(x); % Signal Length (Samples)
Fs = mean(diff(x)); % Sampling Frequency (Hz)
Fn = Fs/2; % Nyquist Frequency (Hz)
nfft2=2^nextpow2(L); % Desired Fourier Transform Length
ymc = y-mean(y); % Subtract Mean (Eliminates d-c- Offset)
FTy = fft(ymc, nfft2)/L; % Fourier Transform (Scaled By Length Of Data Vector)
Fv = linspace(0, 1, fix(L/2)+1)*Fn; % Frequency Vector (One-Sided Fourier Transform)
Iv = 1:numel(Fv); % Index Vector
[pks,locidx] = findpeaks(abs(FTy(Iv))*2, 'MinPeakDistance',20, 'MinPeakHeight',2E-3); % Peak Amplitudes & Indices
figure(2)
plot(Fv, abs(FTy(Iv))*2)
grid
xlim([0 1.5E-6])
title('FFT Magnitude')
grid minor
xlabel('Frequency [Hz]');
ylabel('Amplitude [mV]');
text(Fv(locidx), pks, sprintfc('%11.2E Hz\n%11.2E mV', [Fv(locidx)' pks]))
There are three peaks, at 1.1E-7 Hz, 3.2E-7 Hz, and 5.3E-7 Hz. (I see nothing of significance in the higher frequencies.) I used the findpeaks (link) function to isolate the most significant peak amplitudes and their frequencies, and text (link) function to label them. (The sprintfc function is undocumented. It produces a cell array of strings, very efficient for this sort of application. It otherwise works the same as sprintf.)
If you want to filter your signal, there are several options, the easiest being to use the bandpass (link) and related functions, introduced in R2018a. An appropriate high-frequency cutoff would be 1E-6 Hz.