Azzera filtri
Azzera filtri

Zero-crossing calculation

35 visualizzazioni (ultimi 30 giorni)
Jayanta Deb
Jayanta Deb il 12 Ago 2017
Commentato: GIULIA CISOTTO il 3 Nov 2020
Hi all, I need a script which can calculate zero crossing of the signal. I have the value of x and y. The script should be able to calculate the exact position of zero crossing points. Help!

Risposta accettata

Star Strider
Star Strider il 12 Ago 2017
This is reasonably robust:
function ZC = ZeroX(x,y)
zci = @(v) find(v(:).*circshift(v(:), [-1 0]) <= 0); % Returns Approximate Zero-Crossing Indices Of Argument Vector
zxidx = zci(y);
for k1 = 1:numel(zxidx)
idxrng = max([1 zxidx(k1)-1]):min([zxidx(k1)+1 numel(y)]);
xrng = x(idxrng);
yrng = y(idxrng);
ZC(k1) = interp1( yrng(:), xrng(:), 0, 'linear', 'extrap' );
end
end
x = linspace(0, 11*pi, 42); % Create Data
y = sin(x); % Create Data
ZC = ZeroX(x,y);
figure(1)
plot(x, y, '-r')
hold on
plot(ZC, zeros(size(ZC)), 'pg')
hold off
grid
  5 Commenti
Ike Brown
Ike Brown il 19 Ott 2019
Thanks for posting this Star Strider! I found this very helpful. Here is a slight modification in order to avoid the following error "grid vectors not strictly monotonic increasing". This modification is based off of a forum answer by Jos (10584)
% ZeroX has been modified so as to avoid the following error "Error using griddedInterpolant
% The grid vectors are not strictly monotonic increasing."
%
% The following modifications are based off of this MatLab forum answer:
% https://www.mathworks.com/matlabcentral/answers/283718-grid-vectors-not-strictly-monotonic-increasing
function ZC = ZeroX(x,y)
zci = @(v) find(v(:).*circshift(v(:), [-1 0]) <= 0); % Returns Approximate Zero-Crossing Indices Of Argument Vector
zxidx = zci(y);
for k1 = 1:numel(zxidx)
idxrng = max([1 zxidx(k1)-1]):min([zxidx(k1)+1 numel(y)]);
xrng = x(idxrng);
yrng = y(idxrng);
% Beginning of ZeroX2 modifications. The naming conventions follow
% those in the referenced MatLab forum, except that "X" is "yrng" and
% "Y" is "xrng".
[yrng2, ~, jyrng] = unique(yrng); %yrng is a new array containing the unique values of yrng. jyrng contains the indices in yrng that correspond to the original vector. yrng = yrng2(jyrng)
xrng2 = accumarray(jyrng, xrng, [], @mean); %This function creates a new array "xrng2" by applying the function "@mean" to all elements in "xrng" that have identical indices in "jyrng". Any elements with identical X values will have identical indices in jyrng. Thus, this function creates a new array by averaging values with identical X values in the original array.
ZC(k1) = interp1( yrng2(:), xrng2(:), 0, 'linear', 'extrap' );
end
end
GIULIA CISOTTO
GIULIA CISOTTO il 3 Nov 2020
Dear Ike Brown,
thank you for sharing your code. However, I would like to let you know that it seems to incorrectly detect ZC points.
I wrote an alternative Matlab script (myZC.m) to find the ZC. Here, you can find it.
To test the difference between ZeroX and myZC, you can run a modified version of your toy example as follows:
rng(shuffle)
x = linspace(0, 11*pi, 42); % Create Data
y = sin(x); % Create Data
n = 1 + 2.*randn(1,length(y)); % add Gaussian noise
y = y+n;
% myZC
[myZC, myZCx, myZCy, ys] = myZC(x,y);
% Comparison with ZeroX
ZC = ZeroX(x,y);
% Print ZC values
[length(myZC), length(ZC)]
% Plot figure
figure, hold all
plot(x,y,'k'), xlabel('No. samples'), ylabel('Amplitude [A.U.]')
plot(x,ys,'b:')
plot(x(myZC), zeros(size(myZC)), 'bs', 'markerface', 'b')
plot(myZCx, myZCy, 'cd', 'markerface', 'c')
plot(ZC, zeros(size(ZC)), 'pr'), grigrid on, legend('y', 'ys', 'myZC', 'myZC-refined', 'ZC')
In attach, you can also find a representative plot: you can notice that ZeroX can mostly correctly detect the zero-crossigs, but sometimes it misses one (between sample no.17 and sample no.18) or it detects a false one (at sample 27).
ZeroX returns a correct number of zero-crossings, but when plotted, they are mismatched to the raw signal, while myZC can correctly compute the number of zero-crossing and precisely get their locations.

Accedi per commentare.

Più risposte (1)

MSP
MSP il 12 Ago 2017
zeroindex=find(y==0)
x(zeroindex)
  3 Commenti
Shubhashree Bal
Shubhashree Bal il 2 Lug 2019
It is not necessary that there is sample at amplitude equal to 0.
Example:
x = [ 1 2 3 4 5];
y = [1 -1 -2 -3 -4];
k= find (y==0);
Conclusion: Instead of having zero crossing it will not return any index. Thus, we can check sign change for finding zero crossing accurately.
Thanks!
GIULIA CISOTTO
GIULIA CISOTTO il 3 Nov 2020
Dear Shubhashree, this is not actually true: zero-crossing is defined as the number of times a signal changes its sign. If you apply your computation, then you might have an incorrect number of ZC. Let's consider a signal with a number of consecutive samples set to zero: then, you will add all of them to the ZC counter. However, you would be wrong in that. Please, check my answer above for the correct computation of ZC.

Accedi per commentare.

Community Treasure Hunt

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

Start Hunting!

Translated by