How can I find and plot the change in frequency of a signal?
32 views (last 30 days)
Show older comments
I have the following signal:
I'm looking for a way to find the change in the frequency and then plot it (ideally, I would like to find the equation that represents the change in frequency of the signal).
I've tried using the spectrogram function, along with various methods using ffts but I can't seem to figure out a way to do this at all. Everything seems to be dedicated to finding variations in amplitude or deconstructing the signal into its basic frequency components (as with a fourier transform). Is such an analysis possible, and if so how might I go about doing this?
As always, thank you in advance for your help.
-Chris
0 Comments
Answers (2)
Star Strider
on 13 Jul 2016
The easiest way I can think of is to find the zero-crossings of the signal and take the inverse to calculate the frequency.
Example:
x = linspace(0,10*pi,1E+5); % Create Data
y = sin(1./(x+0.01)); % Create Data
zci = @(v) find(v(:).*circshift(v(:), [-1 0]) <= 0); % Returns Approximate Zero-Crossing Indices Of Argument Vector
dy = zci(y); % Indices of Approximate Zero-Crossings
for k1 = 1:size(dy,1)-1
b = [[1;1] [x(dy(k1)); x(dy(k1)+1)]]\[y(dy(k1)); y(dy(k1)+1)]; % Linear Fit Near Zero-Crossings
x0(k1) = -b(1)/b(2); % Interpolate ‘Exact’ Zero Crossing
mb(:,k1) = b; % Store Parameter Estimates (Optional)
end
freq = 1./(2*diff(x0)); % Calculate Frequencies By Cycle
figure(1)
plot(x, y)
hold on
plot(x0, zeros(size(x0)), '+r')
hold off
grid
axis([0 1 ylim])
The ‘freq’ calculation multiplies the difference by 2 because it is actually calculating the half-cycle frequencies otherwise. To calculate the full-cycle frequencies (the correct result), it is necessary to multiply the half-cycle frequencies by 2.
The plot simply demonstrates that the linear interpolation is approximately accurate. It is not necessary for the code.
I don’t have your data, but it should work with it. It might give an anomalous result for the end value because it may calculate a zero-crossing there even if there is not one. Just discard it. My code is reasonably robust but cannot account for absolutely all possible conditions with such real-world data.
0 Comments
Greg Dionne
on 21 Oct 2016
Assuming you have the Signal Processing Toolbox and your data x is uniformly sampled with sample rate Fs:
z = hilbert(x);
f = angle(z(2:end).*conj(z(1:end-1))).*(Fs / (2*pi));
That should get you started.
If you're comfortable with filtering concepts, look up Hilbert filtering, you can often design a pair of filters that can filter out unwanted noise / signals all in one go.
Take a look at FMDEMOD if you are simply oscillating within a narrow frequency range.
0 Comments
See Also
Categories
Find more on Transforms in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!