Wrong results from THD calculation in MATLAB - matlab

I have measured signals (grid voltages and currents at 50Hz) of which I want to calculate the THD in MATLAB. However, using thd(signalVector, samplingFrequency, numberOfHarmonics) gives completely wrong results.
See the attached screenshot: The measured signal is on the left, the middle plot shows the FFT, on the right there is a closeup view of the FFT. As you can see, the THD is calculated to be too high at 86%:
Looking at the thd() itself, it obviously mismatches the FFT:
I used both fft() and thd() like in the MATLAB examples.
For FFT I use:
NFFT = 2^nextpow2(L);
Y = fft(signal_vector,NFFT)/(samples_vector);
f = sampling_frequency/2*linspace(0,1,NFFT/2+1);
y_fft = 2*abs(Y(1:NFFT/2+1));
plot(f,y_fft)
For THD up to the 40. harmonic I simply use:
thd(signal_vector,sampling_frequency,40)
where sampling frequency is 40kHz.
I guess I am doing something essentially wrong. Where is the flaw?
Do you need additional information? Any help is appreciated (I hope this is the right place for my question)
EDIT: Using a THD function from the Matlab File Exchange I get a THD of 1.78%, but I do not know if this is correct, but seems realistic.

Related

how to calculate SNR in matlab from given two signals?

I am working on calculating the SNR of given signals.
length = linspace(-2*pi,2*pi);
signal_1 = sin(length);
plot(signal_1);
noise_1 = 0.5*rand(size(signal_1));
plot(noise_1);
snr_22 = snr(signal_1,noise_1);
But it shows only the noise figure (attached below) whenever I run this, nothing else. But it should also show signal figures and SNR in decibels. Can anyone help me out? I am using Matlab R2015b.
As the documentation on snr() shows:
snr(___) with no output arguments plots the spectrum of the signal in the current figure window and labels its main features. It uses different colors to draw the fundamental component, the DC value and the harmonics, and the noise. The SNR appears above the plot. This functionality works for all syntaxes listed above except snr(x,y).
emphasis mine.
In other words, call figure; snr(signal_1,noise_1, __);, i.e. with at least one other input argument and no output argument, at the end of your code to have the spectrum appear. Otherwise, take a look at the contents of snr_22 and plot it by hand.

Trying to plot the fft of a sinc function

I am trying to plot the fft of a set of data I have. These data form a nearly perfect sinc function. Here is the data of which I am trying to plot the fft:
.
I know the fft of a sinc function should look like kind of a step function. However, the results I get are nowhere near that. Finding the fft in itself is super easy, but I think my mistake is when I try to compute the frequency axis. I have found several methods online, but so far I have not been able to make it work. Here is my code:
sampleRate = (max(xdata) - min(xdata))/length(xdata);
sampleN = length(xdata);
y = fft(ydata, sampleN);
Y = y.*conj(y)/sampleN;
freq = (0:1:length(Y)-1)*sampleRate/sampleNumber;
plot(freq, Y)
I have found pretty much all of that online and I understand pretty much none of it (which might be why it's not working...)
Zoom on what I get using that code:
It now seems to be working! This is what I get when I subtract the mean:
What you see here is the zero frequency being much, much larger than everything else. Plot with plot(freq,Y,'o-') to prove that the shape you see is just the linear interpolation between two samples.
The zero frequency is the sum of all samples. Because the mean of your signal is quite a bit larger than the amplitude, the zero frequency dwarfs everything else. And because you are plotting the power (absolute square of the DFT), this difference is enhanced even more.
There are two simple solutions:
Plot using logarithmic y-axis:
plot(freq, Y)
set(gca,'yscale','log')
Subtract the mean from your signal, remove the zero frequency, or scale the y-axis (these are all more or less equivalent):
y = fft(ydata-mean(ydata), sampleN);
or
y(1) = 0;
or
plot(freq, Y)
set(gca,'ylim',[0,max(Y(2:end))]);

FFT on accelerometer data spike at 0

I have some accelerometer data in MATLAB and I was told to try FFT and try to use FFT features on classification. However, I am confused about the plot after FFT. It seems that there is a large spike only in the beginning of the plot and I am not sure what to make of it. I tried using some code from other posts such as this one: Accelerometer with FFT - strange output, and also some examples on the Mathworks website, but it did not help.
data = acc_data_x(1:300);
fs = 1/(1/12);
m = length(data);
nfft = 2^nextpow2(m);
y = fft(data,nfft)/m;
f = fs/2 * linspace(0,1,nfft/2+1);
power = abs(y);
plot(f,power(1:nfft/2+1))
t = (0 : m-1)/fs;
figure
plot(t,data);
I attached the plot of the accelerometer data in x and the result of the FFT. Is there some other step I am missing? I apologize for any ignorance since this is my first time trying FFT and working with this type of data.
Accelerometer Data in X plot:
After FFT:
Edit: I have tried Gareth's suggestion and used detrend function in MATLAB
After Detrend and FFT:
Also here is the full data with FFT (in the first example I only used up to 300 data points).
I'm now confused if this tells me any information?
You should first detrend your data. FFT inputs that have an uncorrected DC bias (ie, sits positive or negative) have a strong 0 Hz component.
Try data = detrend(data) after your first line. It'll skew some of the other things you do, but might help with showing the issue in the FFT. You can more carefully manage your data so that you can both clean it for FFT and also plot the original raw data once you feel happy with the issue being mostly fixed.
The amplitude of the first "zero-frequency" component in FFT is exactly the mean value of your data. If you fft(x-mean(x)), the first component will be zero. Other components nearby can be related with slow trend.

How to produce a log scale FFT with MatLab

It's my first time performing an FFT within MatLab by experimenting with some example code from the MathWorks website. I was wondering if it was possible to take the code I have and transform the x axis to a log-scale representation rather than linear. I understand most of the code, but it is the x axis line of code that I'm still not 100% sure exactly what it is doing apart from the +1 at the end of the line, which is that fact that MatLab's indexing structure doesn't start on 0.
My code so far is:
[y,fs] = wavread('Wav/800Hz_2sec.wav');
NFFT = 4096;
Y = fft(y,NFFT)/length(y);
f = fs/2*linspace(0,1,NFFT/2+1);
plot(f,2*abs(Y(1:NFFT/2+1))
frequency usually comes out in linear scale from Discrete Fourier Transform. if you want, you can make a new frequency vector in log scale and interpolate the results you already have
fnew=fs/2.*logspace(log10(fs/length(y)),0,npts);
Ynew= interp1(f,Y(1:NFFT/2+1),fnew);
where npts is the length of your new frequency vector. for just plotting
loglog(f,2*abs(Y(1:NFFT/2+1));
honestly IMO, the interpolation thing doesn't work very well because FFT of real signals produces strong peaks and troughs in spectra, so unless you smooth your spectrum first, the interpolated spectrum won't look as nice

Plotting the log amplitude and frequency

I'm trying to display a spectrum of a sound sample with the correct frequency-axis, in Hertz, and a
log-amplitude y-axis. I thought I had the frequency display right, but the graphs that it produces look rather weird and I've found absolutely nothing regarding displaying the log amplitude on an axis.
The code that I'm using (heavily borrowed from mathsworks fft example) is:
y=x(100:200);
Fs = 10000; % Sampling frequency
numsamples = 20000; % Number of samples in the signal
NFFT = 2^nextpow2(numsamples); % Next power of 2 from length of y
Y = fft(y,NFFT)/numsamples;
f = Fs/2*linspace(0,1,NFFT/2+1);
plot(f,2*abs(Y(1:NFFT/2+1)))
And here's one of the graphs that it produced:
I don't know if that's right or not, but it doesn't look anything like the examples I've seen....
I'm aware this is probably a really stupid question and I'm missing something obvious, or maybe I've actually got it right and don't understand enough to realise it, but this stuff is really doing my head in and I'm not finding the documentation particularly illuminating.
I think the x-axis is correct.
To obtain a logarithmic y-axis replace the plot bysemilogy:
semilogy(f,2*abs(Y(1:NFFT/2+1)))
or equivalently use plot as it stands followed by
set(gca,'YScale','log')