I have the .csv file that has the frequency of 2000 Hz. I am using the Sine fit function but when I run it and print it I am not getting the 2000 Hz as print output.

37 vues (au cours des 30 derniers jours)
The samle rate of this csv file is 7.69231e+06Hz and it has 8192 sample points. I am using the Sine fit function but whenever I try to run it I didn't print out the correct output insted it print out a very low output like 2.6647 Hz or even less than that. So can you please take a look on this and help me out on why I am not getting the correct frequency eveyrtime I run the code with either new csv file or same csv file data.
Also this code supposed to just read the csv file and get the data from colum 1 time and column 2 voltage and finds out the frequency on its own. I tried using Sine fit() function but I am not getting the correct frequency. So can you please take a look on the code and tell me why I am not getting the correct frequnecy and please help me to fix the code. My code is:
% Vandit Shah
close all;
clear all;
clc;
% Reading the data from the CSV file
X = csvread('points.csv',16,0);
% Column 1 Time (s)
T = X(:,1);
% Column 2 Channel 1 (V)
V = X(:,2);
% Sine fit function
F = fit(T, V, 'sin1');
% Printing the output to screen using fprintf
fprintf(['Frequency of the sound = ', num2str(F.b1/(2*pi)), ' Hz']);

Réponse acceptée

Walter Roberson
Walter Roberson le 4 Déc 2022
filename = 'points.csv';
% Vandit Shah
format long g
% Reading the data from the CSV file
X = csvread(filename,16,0);
% Column 1 Time (s)
T = X(:,1);
% Column 2 Channel 1 (V)
V = X(:,2);
% Sine fit function
F = fit(T, V, 'sin1', 'startpoint', [-1 2000 0]);
% Printing the output to screen using fprintf
coeffnames(F)
ans = 3×1 cell array
{'a1'} {'b1'} {'c1'}
coeffvalues(F)
ans = 1×3
4.17746941820325 24.669884946404 -3.94806494613018
figure;
subplot(2,1,1); plot(T, V - min(V)); title('original')
subplot(2,1,2); plot(T(1:100), V(1:100) - min(V)); title('zoomed')
Look at the original signal: there are about 2 cycles of the obvious signal, which is consistent with 2000-ish Hz for time (8192 samples / 7.69231e+06 samples/second)
But look at the zoomed signal: there is obviously a high frequency signal overlaying the 2000-ish Hz. And that leads to ambiguity: are you looking for the signal with the largest amplitude, or are you looking for the modifying frequency?
fprintf(['Frequency of the sound = ', num2str(F.b1/(2*pi)), ' Hz']);
Frequency of the sound = 3.9263 Hz
Fv = fft(V);
sample_period = mean(diff(T))
sample_period =
1.29999999999998e-07
L = length(T);
Fs = 1/sample_period
Fs =
7692307.6923078
coeffs = Fv(1:floor(end/2));
freqs = Fs * (0:length(coeffs)-1) / L;
[~, idx] = max(real(coeffs(2:end)))
idx =
2
peak_freq = freqs(idx+1);
fprintf('fft peak frequence: %g Hz\n', peak_freq);
fft peak frequence: 1878.23 Hz
1878 Hz looks plausible, if we say that your original "2000 Hz" was an approximation.
This 1878 Hz is the frequency associated with the largest amplitude
figure();
plot(freqs(2:20), real(coeffs(2:20))); title('zoomed frequencies')
... which is early on. So a problem here is that the bin resolution is
Fs / L
ans =
939.117042156978
Hz. You cannot get 2000 Hz exactly with this data even if the signal is exactly 2000 Hz
figure();
plot(freqs(2:end), abs(real(coeffs(2:end))));
title('real(fft)');
xlabel('frequency');
offset = 1;
[~, sortidx] = sort(real(coeffs(offset+1:end)), 'descend');
secondaryidx = offset+sortidx(1:5);
secondaries = freqs(secondaryidx);
secondarycoeffs = abs(real(coeffs(secondaryidx)));
compose("secondary frequency: %g @ %.2f Hz", secondarycoeffs(:), secondaries(:))
ans = 5×1 string array
"secondary frequency: 9.4526 @ 1878.23 Hz" "secondary frequency: 9.15205 @ 980438.19 Hz" "secondary frequency: 3.82959 @ 981377.31 Hz" "secondary frequency: 1.85517 @ 10330.29 Hz" "secondary frequency: 1.64281 @ 5634.70 Hz"
hold on;
scatter(secondaries, secondarycoeffs)
hold off;
legend({'real', 'peaks'});
I had a bit of trouble getting the secondary frequencies. The key turned out to be taking the absolute value of the real part of the fft coefficients -- not the absolute value of the fft coefficients, and not just the real part of the fft coefficients as some of them go negative (I think)
So although the frequency with the peak amplitude is about 1878 Hz (closest you can get to 2000 Hz), there is a second frequency nearly the same amplitude at about 980438 +/- 469 Hz. Perhaps 981000 Hz, considering the leaking into the next bin.
figure();
scatter(T, V, '+');
hold on
v = F(T);
plot(T, v);
hold off
legend({'original', 'fit'})
  2 commentaires
Vandit
Vandit le 4 Déc 2022
I was only looking to find the frequency from the .csv file which has times (s) in column 1 and voltage (v) in column 2. I also tried using different frequency .csv file and I do get almost close to the frequency that file belongs with the modified code that you posted. The percentage difference after finding the frequency shouldn't be more than 15% and which is true because I got around 7% as a percent difference. Thank you so much Mr. Roberson for the help and very detailed answer. Have a good day.
Walter Roberson
Walter Roberson le 4 Déc 2022
The problem is that "the" frequency is not well defined. I showed that the file has two peak frequencies of close to the same amplitude. Also due to spectral leakage, the next bin after the 1878 Hz also has non-trivial content.

Connectez-vous pour commenter.

Plus de réponses (0)

Tags

Produits


Version

R2022b

Community Treasure Hunt

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

Start Hunting!

Translated by