Zero-crossing calculation

조회 수: 13 (최근 30일)
Jayanta Deb
Jayanta Deb 2017년 8월 12일
댓글: GIULIA CISOTTO 2020년 11월 3일
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!

채택된 답변

Star Strider
Star Strider 2017년 8월 12일
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
Ike Brown
Ike Brown 2019년 10월 19일
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 2020년 11월 3일
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.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

MSP
MSP 2017년 8월 12일
zeroindex=find(y==0)
x(zeroindex)
  댓글 수: 3
Shubhashree Bal
Shubhashree Bal 2019년 7월 2일
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 2020년 11월 3일
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.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by