Issue with plotting sin wave on Matlab - matlab

I have to plot the signal m(t) = ASin(2pi1000t) and I am using the following Matlab code to do it.
Fm=1000;%1 kHz
Fs = 2*Fm;
t = 0:1/Fs:10; % ( that is, time will run from 0 to 10 with a sample at every 1/2000th second )
Am=1;%amplitude
m=Am*sin(2*pi*Fm*t);
figure(1)
plot(t,m)
title('Message signal')
xlabel('Time in Seconds')
ylabel('m(t)')
However, I am getting the plot as
But on the other hand, if I use the following code,
Fm=1000;%1 kHz
t=linspace(0,10,2000);
Am=1;%amplitude
m=Am*sin(2*pi*Fm*t);
figure(1)
plot(t,m)
title('Message signal')
xlabel('Time in S')
I am getting a proper sin wave. What's actually happening here? What is wrong with the first code?

The problem with the first code snippet is that the sampling period is exactly half the period of the sinusoid. Due to the specific sampling instants that you use, you always sample the signal at its nulls. That's why you get values close to 0 (they are not exactly 0 because of the numerical inaccuracy inherent to floating-point arithmetic).
In the second code snippet, since linspace is inclusive at its end points, the sampling period is slightly different. So you don't have the same problem as above, and you do get a sinusoid. However, you have a different problem which is now made evident, namely aliasing due to insufficient sampling. Observe how the frequency of the plotted sinusoid is very different (much smaller) from what it should be.
The solution to both problems is to increase the sample rate. According to the Nyquist criterion, a sample rate at least twice the maximum signal frequency would be enough to reconstruct the original signal. But that does not mean that directly plotting the samples taken at that rate will produce a graph resembling the signal. For that you need a factor significantly greater than 2. Also, avoid choosing the sample rate as an integer multiple of the sinusoid frequency, to prevent problems caused by the sampling process being "coupled" to the signal variations as in your first snippet.
So, in your code, try for instance Fs = 100/3*Fm (you may need to zoom in to see the signal properly).

Fm=1000 #%1 kHz
here is the python version
import math
import matplotlib.pyplot as plt
Fs = 2*Fm
#t = 0:1/Fs:10 #( that is, time will run from 0 to 10 with a sample at every 1/2000th second )
t=np.linspace(0,10,Fs)
Am=1 #%amplitude
m=[ Am*math.sin(2*math.pi*Fm*value) for value in t]
plt.plot(m)
plt.show()

Related

Different plot shape for fft depending on time sample spacing

I am having the following issue. I am trying to analyse the input and output signal of my filter using fft. However, I am not sure if my fft is correct. My input signal is the product of a sawtooth and sine waveforms both with frequencies 6kHz and 32kHz, respectively. Both individual signals have an amplitude of 1 before being multiplied.
Depending on my time values I get different result for my fft plots. If I use values of time spaced out by the period of my sampling frequency, I get a "nice" looking graph with clear peaks as you would expect in a Fourier Transform (see Fig.1). However, if I use values of time spaced out by the period of the signal being sampled, the graph has more frequency components (see Fig. 2). I really don't know which graph is correctly displays my FFT. Also I have the problem that I used an online tutorial to achieve my FFT but I do not understand why the guy did what he did in his code which I do not understand. However, if I plot the absolute values of FFT, I get graphs with similar shapes but the amplitudes jump up to 30 or 40 more (see Fig. 3 and 4). Also for Fig.2 why is there a small wiggle at the start of the filtered signal (time domain) vs time ? Please your help in performing FFT accurately would be of great help. Thanks.
Figures are in Google Drive since website won't allow me to upload more than 1 file:
Fig. 1: https://drive.google.com/file/d/1XHc4jJfMudVOd2E8cluDB4Z8PvfKGsbt/view
Fig. 2: https://drive.google.com/file/d/1pOUhSTSFRwwrKVrwYEa-jYoahqGiYxMA/view
Fig. 3: https://drive.google.com/file/d/10346ttMYZN_Ur_WuwqvbGchYbqmQ6l1F/view
Fig. 4: https://drive.google.com/file/d/17G_FgZznGPNimwgBmGIvqvvcuRvOh80F/view
%Time values using sampling frequency period.
fsampling = 80000;
tsampling = 0:1/fsampling:5000000*Tsampling;
%Time values using sawtooth frequency period.
fsampling = 80000;
fsawtooth = 6000;
Tsawtooth = (1/fsawtooth);
tsawtooth = 0:1/fssampling:20*Tsawtooth;
%Piece of code to use FFT that I don't understand.
L0 = length(product);
NFFT0 = 2^nextpow2(L0);
Y0 = fft(product,NFFT0)/L0;
FreqDom0 = fs/2*linspace(0,1,NFFT0/2+1);
plot(FreqDom0, 2*abs(Y0(1:NFFT0/2+1)));
%Performing FFT using just abs.
IPFFT = abs(fft(product));
plot(t, IPFFT);

Why doesn't matlab give me an 8KHz sinewave for 16KHz sampling frequency?

I have the following matlab code, and I am trying to get 64 samples of various sinewave frequencies at 16KHz sampling frequency:
close all; clear; clc;
dt=1/16000;
freq = 8000;
t=-dt;
for i=1:64,
t=t+dt;a(i)=sin(2*pi*freq*t);
end
plot(a,'-o'); grid on;
for freq = 1000, the output graph is
The graph seems normal upto 2000, but at 3000, the graph is
We can see that the amplitude changes during every cycle
Again, at 4000 the graph is
Not exactly a sinewave, but the amplitude is as expected during every cycle and if I play it out it sounds like a single frequency tone
But again at 6000 we have
and at 8000 we have
Since the sampling frequency is 16000 I was assuming that I should be able to generate sinewave samples for upto 8000, and I was expecting the graph I got at 4000 to appear at 8000. Instead, even at 3000, the graph starts to look weird
If I change the sampling frequency to 32000 and the sinewave frequency to 16000, I get the same graph that I am getting now at 8000. Why does matlab behave this way?
EDIT:
at freq = 7900
This is just an artifact of aliasing. Notice how the vertical axis for the 8kHz graph only goes up to 1.5E-13? Ideally the graph should be all zeros; what you're seeing is rounding error.
Looking at the expression for computing the samples at 16kHz:
x(n) = sin(2 * pi * freq * n / 16000)
Where x is the signal, n is the integer sample number, and freq is the frequency in hertz. So, when freq is 8kHz, it's equivalent to:
x(n) = sin(2 * pi * 8000 * n / 16000) = sin(pi * n)
Because n is an integer, sin(pi * n) will always be zero. 8kHz is called the Nyquist frequency for a sampling rate of 16kHz for this reason; in general, the Nyquist frequency is always half the sample frequency.
At 3kHz, the signal "looks weird" because some of the peaks are at non-integer multiples of 16kHz, because 16 is not evenly divisible by 3. Same goes for the 6kHz signal.
The reason they still sound like pure sine tones is because of how the amplitude is interpolated between samples. The graph uses simple linear interpolation, which gives the impression of harsh edges at the samples. However, a physical loudspeaker (more precisely, the circuitry which drives it) does not use linear interpolation directly. Instead, a small filter circuit is used to smooth out those harsh edges (aka anti-aliasing) which removes the artificial frequencies above the aforementioned Nyquist frequency.
That is problem of matlab but a nature of sampling.
16KHz sampling makes 16K (16,000) sampled data per second. 8KHz signal has 8K (8000) cycles per second. So two sample data per a cycle.
Two is minimum number of data per cycle. This is know a part of "sampling theorem".
Let try to show two cycles with three points on graph, you may understand that its impossible to show two cycles by three points. In the same way, you can't show 2N cycles by (2N-1) points.
The effect seen for 8 kHz is as all other answers already mention aliasing effects and arises due to that the sine wave for 8 kHz is sin(2*pi*n*8000*1/16000) = sin(n*pi), which is explained in Drew McGovens answer. Luckily the amplitude is not the only parameter that defines the signal. The other parameter that is required to completely define the signal is the phase. This means that when doing for fourier analysis of the signal, it is still possible to find the right frequency. Try:
close all; clear; clc;
dt=1/16000;
freq = 7300;
t=-dt;
for i=1:64,
t=t+dt;a(i)=sin(2*pi*freq*t);
end
plot(a,'-o'); grid on;
figure; plot( linspace(1,16000,1000), abs(fft(a)) );
A side comment: some people might argue against using i as index variable since that can also be used as the imagiary number i. Personally I have nothing against using i since the runtime and overhead only is affected slightly and I always uses 1i. However, just make sure to use 1i consistently for the imaginary unit then.

Playing a varying frequency in Hertz in matlab?

I have some matlab code which produces frequency (in hertz) of a sound over 5 seconds. The code as it stands outputs 100 samples per second, and I want to play the 5 second block to see what this sounds like, but I'm having issues with sampling rate and sound / soundsc commands.
My frequency oscillates (data here ) and I'd be very grateful if someone could help me convert this data into some kind of real-time approximation of what it should sound like.
Something like this may be helpful
Fs=2000; %sample rate, Hz
t=0:1/Fs:5; %time vector
F=298+sin(2*pi*t); %put your own F here
S=sin(2*pi*F.*t); %here is the sound vector
%visual check
figure(1);
plot(t,S)
figure(2);
plot(t,F)
%listen
wavplay(S,Fs)
This is like FM modulation, but different. If you have an Fold vector with a different sample rate, you can convert it with the command
F=interp1(told,Fold,t); %told and Fold are F at a different sample rate
%check it
plot(told,Fold,t,F)
First, your sampling rate should be at least twice the maximum frequency according the Nyquist–Shannon sampling theorem.
Next, you need to generate a sinusoid:
Signal = sin(2*pi*Phi);
where Phi is the phase corresponding to the desired frequency pattern, which is simply an integral of the frequency (which you can do numerically or analytically).

Time delay estimation using crosscorrelation

I have two sensors seperated by some distance which receive a signal from a source. The signal in its pure form is a sine wave at a frequency of 17kHz. I want to estimate the TDOA between the two sensors. I am using crosscorrelation and below is my code
x1; % signal as recieved by sensor1
x2; % signal as recieved by sensor2
len = length(x1);
nfft = 2^nextpow2(2*len-1);
X1 = fft(x1);
X2 = fft(x2);
X = X1.*conj(X2);
m = ifft(X);
r = [m(end-len+1) m(1:len)];
[a,i] = max(r);
td = i - length(r)/2;
I am filtering my signals x1 and x2 by removing all frequencies below 17kHz.
I am having two problems with the above code:
1. With the sensors and source at the same place, I am getting different values of 'td' at each time. I am not sure what is wrong. Is it because of the noise? If so can anyone please provide a solution? I have read many papers and went through other questions on stackoverflow so please answer with code along with theory instead of just stating the theory.
2. The value of 'td' is sometimes not matching with the delay as calculated using xcorr. What am i doing wrong? Below is my code for td using xcorr
[xc,lags] = xcorr(x1,x2);
[m,i] = max(xc);
td = lags(i);
One problem you might have is the fact that you only use a single frequency. At f = 17 kHz, and an estimated speed-of-sound v = 340 m/s (I assume you use ultra-sound), the wavelength is lambda = v / f = 2 cm. This means that your length measurement has an unambiguity range of 2 cm (sorry, cannot find a good link, google yourself). This means that you already need to know your distance to better than 2 cm, before you can use the result of your measurement to refine the distance.
Think of it in another way: when taking the cross-correlation between two perfect sines, the result should be a 'comb' of peaks with spacing equal to the wavelength. If they overlap perfectly, and you displace one signal by one wavelength, they still overlap perfectly. This means that you first have to know which of these peaks is the right one, otherwise a different peak can be the highest every time purely by random noise. Did you make a plot of the calculated cross-correlation before trying to blindly find the maximum?
This problem is the same as in interferometry, where it is easy to measure small distance variations with a resolution smaller than a wavelength by measuring phase differences, but you have no idea about the absolute distance, since you do not know the absolute phase.
The solution to this is actually easy: let your source generate more frequencies. Even using (band-limited) white-noise should work without problems when calculating cross-correlations, and it removes the ambiguity problem. You should see the white noise as a collection of sines. The cross-correlation of each of them will generate a comb, but with different spacing. When adding all those combs together, they will add up significantly only in a single point, at the delay you are looking for!
White Noise, Maximum Length Sequency or other non-periodic signals should be used as the test signal for time delay measurement using cross correleation. This is because non-periodic signals have only one cross correlation peak and there will be no ambiguity to determine the time delay. It is possible to use the burst type of periodic signals to do the job, but with degraded SNR. If you have to use a continuous periodic signal as the test signal, then you can only measure a time delay within one period of the periodic test signal. This should explain why, in your case, using lower frequency sine wave as the test signal works while using higher frequency sine wave does not. This is demonstrated in these videos: https://youtu.be/L6YJqhbsuFY, https://youtu.be/7u1nSD0RlwY .

matlab FFT. Stuck understanding relationship between frequency and result

We're trying to analyse flow around circular cylinder and we have a set of Cp values that we got from wind tunnel experiment. Initially, we started off with a sample frequency of 20 Hz and tried to find the frequency of vortex shedding using FFT in matlab. We got a frequency of around 7 Hz. Next, we did the same experiment, but the only thing we changed was the sampling frequency- from 20 Hz to 200 Hz. We got the frequency of the vortex shedding to be around 70 Hz (this is where the peak is located in the graph). The graph doesn't change regardless of the Cp data that we enter. The only time the peak differs is when we change the sample frequency. It seems like the increase in the frequency of vortex shedding is proportional to the sample frequency and this doesn't seem to make sense at all. Any help regarding establishing a relation between sample frequency and vortex shedding frequency would be greatly appreaciated.
The problem you are seeing is related to "data aliasing" due to limitations of the FFT being able to detect frequencies higher than the Nyquist Frequency (half-the sampling frequency).
With data aliasing, a peak in real frequency will be centered around (real frequency modulo Nyquist frequency). In your 20 Hz sampling (assuming 70 Hz is the true frequency, that results in zero frequency which means you're not seeing the real information. One thing that can help you with this is to use FFT "windowing".
Another problem that you may be experiencing is related to noisy data generation via single-FFT measurement. It's better to take lots of data, use windowing with overlap, and make sure you have at least 5 FFTs which you average to find your result. As Steven Lowe mentioned, you should also sample at faster rates if possible. I would recommend sampling at the fastest rate your instruments can sample.
Lastly, I would recommend that you read some excerpts from Numerical Recipes in C (<-- link):
Section 12.0 -- Introduction to FFT
Section 12.1 (Discusses data aliasing)
Section 13.4 (Discusses FFT windowing)
You don't need to read the C source code -- just the explanations. Numerical Recipes for C has excellent condensed information on the subject.
If you have any more questions, leave them in the comments. I'll try to do my best in answering them.
Good luck!
this is probably not a programming problem, it sounds like an experiment-measurement problem
i think the sampling frequency has to be at least twice the rate of the oscillation frequency, otherwise you get artifacts; this might explain the difference. Note that the ratio of the FFT frequency to the sampling frequency is 0.35 in both cases. Can you repeat the experiment with higher sampling rates? I'm thinking that if this is a narrow cylinder in a strong wind, it may be vibrating/oscillating faster than the sampling rate can detect..
i hope this helps - there's a 97.6% probability that i don't know what i'm talking about ;-)
If it's not an aliasing problem, it sounds like you could be plotting the frequency response on a normalised frequency scale, which will change with sample frequency. Here's an example of a reasonably good way to plot a frequency response of a signal in Matlab:
Fs = 100;
Tmax = 10;
time = 0:1/Fs:Tmax;
omega = 2*pi*10; % 10 Hz
signal = 10*sin(omega*time) + rand(1,Tmax*Fs+1);
Nfft = 2^8;
[Pxx,freq] = pwelch(signal,Nfft,[],[],Fs)
plot(freq,Pxx)
Note that the sample frequency must be explicitly passed to the pwelch command in order to output the “real” frequency data. Otherwise, when you change the sample frequency the bin where the resonance occurs will seem to shift, which is similar to the problem you describe.
Methinks you need to do some serious reading on digital signal processing before you can even begin to understand all the nuances of the DFT (FFT). If I was you, I'd get grounded in it first with this great book:
Discrete-Time Signal Processing
If you want more of a mathematical treatment that will really expand your abilities,
Fourier Analysis by Körner
Take a look at this related question. While it was originally asked about asked about VB the responses are generically about FFTs
I tried using the frequency response code as above but it seems that I dont have the appropriate toolbox in Matlab. Is there any way to do the same thing without using fft command? So far, this is what I have:
% FFT Algorithm
Fs = 200; % Sampling frequency
T = 1/Fs; % Sample time
L = 65536; % Length of signal
t = (0:L-1)*T; % Time vector
y = data1; % Your CP values go in this vector
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(y,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2);
% Plot single-sided amplitude spectrum.
loglog(f,2*abs(Y(1:NFFT/2)))
title(' y(t)')
xlabel('Frequency (Hz)')
ylabel('|Y(f)|')
I think there might be something wrong with the code I am using. I'm not sure what though.
A colleague of mine has written some nice GPL-licenced functions for spectral analysis:
http://www.mecheng.adelaide.edu.au/~pvl/octave/
(Update: this code is now part of one of the Octave modules:
http://octave.svn.sourceforge.net/viewvc/octave/trunk/octave-forge/main/signal/inst/.
But it might be tricky to extract just the pieces you need from there.)
They're written for both Matlab and Octave and serve mostly as a drop-in replacement for the analogous functions in the Signal Processing Toolbox. (So the code above should still work fine.)
It may help with your data analysis; better than rolling your own with fft and the like.