zero crossings with interpolation

Hi guys!
I have Ac singal as what Im attaching here(see photo down) , ofcourse , my AC signal ofcourse it's implicitly vector sized as 1X32000 samples. (vectors that its values are samples). Im trying to do zero crossing in matlab in order to detect where I have edges! , I's preferable to do that and find the approximated point on the edge that I have the zero crossings by interpolation(if there's another good way and it's optimal approximation to find the point at which there's the zero crossing would be accepted .. but to be assure Im dealing with AC signal this means analog "continues values" and not discrete .. so interpolation is very good for me to find zero crossings), once again it's right that my ac signal is a vector of samples but I take time (x-axis) into consideration .. so it's continues .. and it's suitable and better in my case to detect zero crossings by interpolation!
Any help please how can I do zero crossings by interpolation in matlab? really appreciated for any help.
lets assume that my ac signal (vector of samples) is variable b, also I want to plot the zero crossings as returned values and to show on the same ac signal(my input) the zero cossings like dots/marks when there's zero crossings.
why I need to do interpolation method for zero crossings in my case? because my signal is about samples that I sampled .. attaching down a photo of what I mean :

Risposte (2)

LOTS of ways to do this!
i've 'over-commented' this code to show the logic - this is deliberately not the fastest or most compact way, but should be understandable... :)
good luck!
% commented find zero crossings
%% set up arbitrary signal (sum of 2 sines for demo)
x = 0:0.01:4;
sin1 = 10*sin(10*x); sin2 = 42*sin(6*x);
signal = sin1+sin2;
% plot to show signal
figure;
plot(x, signal, 'bo-');
hold on;
plot(x, zeros(1,legth(x)), 'k:');
%% find next point after zero crossing
sigPos = logical(signal>0); % find all positive points
cross = sigPos - circshift(sigPos,1); % find changeover points
% add to plot
plot(x(logical(cross)), signal(logical(cross)), 'ko');
%% assume straight line approximation between adjacent points
crossInd = find(cross); % x indices of cross points
nCross = length(crossInd); % number of cross points found
x0 = NaN(1,nCross); % vector of x-values for cross points
for aa = 1:nCross
thisCross = crossInd(aa);
% interpolate to get x coordinate of approx 0
x1 = thisCross-1; % before-crossing x-value
x2 = thisCross; % after-crossing x-value
y1 = signal(thisCross-1); % before-crossing y-value
y2 = signal(thisCross); % after-crossing y-value
ratio = (0-y1) / (y2-y1); % interpolate between to find 0
x0(aa) = x(x1) + (ratio*(x(x2)-x(x1))); % estimate of x-value
end
% add to plot
plot(x0, zeros(1,nCross), 'ro');

16 Commenti

but once again lots of ways! all I need is by interpolation because Im dealing with AC signal "continues and not discrete samples! (I deal with time as x axis! ) ...
could you please help me how I can do this zero detecting which I have input signal called b variable by method of interpolation?! thanks alot
@Star Strider could you please help me here?! I really appreciate your effort and Im stuck on ! , my input signal for instance is called b for your use if needed
guys I guess you don't understand me! , I need to do zero crossings by interpolation because my signal is like samples .. like this: ( I dont have real sinusudial signal!! ) so in order to find the zero crossings in my case I want to do interpolation methods ! .. any help please how can I do that in matlab? "the dots that I drew in my photo down is a samples of my signal .. "
did you run the code? it does exactly this. run the code, look at the plot, zoom in on the red circles. it looks remarkably like your drawing... :)
Mohamed Jamal
Mohamed Jamal il 13 Lug 2020
Modificato: Mohamed Jamal il 13 Lug 2020
Hi !
I appreciate your help and sorry for not clarifying in my reply why what you attached isn't good for me.
I tried this code (To note that I change your input signal by my signal, my signal is variable a)
x = 0:0.01:4; % Im not using this so I don't know why I need this!
sin1 = a
signal = sin1+sin2;
% plot to show signal
figure;
plot(x, signal, 'bo-');
hold on;
plot(x, zeros(1,legth(x)), 'k:');
%% find next point after zero crossing
sigPos = logical(signal>0); % find all positive points
cross = sigPos - circshift(sigPos,1); % find changeover points
% add to plot
plot(x(logical(cross)), signal(logical(cross)), 'ko');
%% assume straight line approximation between adjacent points
crossInd = find(cross); % x indices of cross points
nCross = length(crossInd); % number of cross points found
x0 = NaN(1,nCross); % vector of x-values for cross points
for aa = 1:nCross
thisCross = crossInd(aa);
% interpolate to get x coordinate of approx 0
x1 = thisCross-1; % before-crossing x-value
x2 = thisCross; % after-crossing x-value
y1 = signal(thisCross-1); % before-crossing y-value
y2 = signal(thisCross); % after-crossing y-value
ratio = (0-y1) / (y2-y1); % interpolate between to find 0
x0(aa) = x(x1) + (ratio*(x(x2)-x(x1))); % estimate of x-value
end
% add to plot
plot(x0, zeros(1,nCross), 'ro');
it doesn't work! , secondly I noted in the code above about variable x , is it the bit period or what? I mean is it the sampling frequency period? in other words is it the time between every sample I sampled? Im sampling in frequency 20480khz! so what x should be for my case because maybe that's the error?( to clear more Im sampling by a dongle that sample another transmitted signal, the signal that Im transmitted is bit 0101010101 and the bit rate for transmitter is 50Kboud) , thanks alot.
hi mohamed,
obvisouly, we can't write this precisely for you, the code i gave you just uses a dummy signal to show the manipulations. you will always ned to adjust the code provided to fit your variables. so, basically, you will need:
x variable. i have called mine x, you can call it whatever, but this is the time index of your signal (its your x-variable in the plot you showed!). so you can work it out in real time (each increment is your sampling time) if you care about that, or just give it something arbitrary (x = 1:32000, or however many samples you have. but it has to match, in length, to your...
y variable. i called mine 'signal', you can just give it 'a' - or, if you want to use the rest of my code as written (and i promise you there are probably better ways of doing the same thing, i'm no expert!), just get rid of
%% set up arbitrary signal (sum of 2 sines for demo)
x = 0:0.01:4;
sin1 = 10*sin(10*x); sin2 = 42*sin(6*x);
signal = sin1+sin2;
and instead specify:
signal = a;
x = 1:length(signal);
good luck!
n.
Mohamed Jamal
Mohamed Jamal il 13 Lug 2020
Modificato: Mohamed Jamal il 13 Lug 2020
first, thanks alot!
what you're telling me Im totally with you, I understand that!
but you are saying that my real time actually is sampling time this means it should be 1/2048khz , but you are telling me below that x should be 1:length(signal) .. so here Im stuck and not understanding you.
if x should be my sampling time ..so why should I do x=1:length(signal)? it should be as what you said above .. sampling time no? because Im sampling at frequency 2048khz so it has sampling time aka 1/2048khz.
to be assure that Im not missing something, 1:length(signal) means that the x variable is a vector of time that its steps/values is incremented by 1 from 1 to length(signal).
dude, call it what you want! what did you use for the plot you showed? its that variable!
i'm using x = 1:32000 because i don't know what you're using, its just the simplest version to sat that each signal sample has a 'sample number', given in the variable x, which is the same index of that sample value in the signal varible. so the x0 result gives you the 'sample location' (which is interpolated, so won't be a round number) for the crossing.
if you are sampling wth 2048 kHz and want to reflect that in x, fine, then your x will represent sample time and not sample index. but its still just a vector, right? each new sample point represents 1/2048000 seconds real time difference from the preceding point. so use that if you want, then your x0 result gives you the real-time of the crossing from the start of the signal (assuming it starts at zero) instead of just the 'signal sample number'.
but: they behave exactly the same :)
samplingFreq = 2048000;
samplingTime = 1/samplingFreq;
actualStartTimeInSeconds = 1234; % whatever; you might not know/care about this
numberOfSamples = 32000;
x = (1:numberOfSamples)*samplingTime + actualStartTimeInSeconds;
Mohamed Jamal
Mohamed Jamal il 14 Lug 2020
Modificato: Mohamed Jamal il 14 Lug 2020
Hi neil, I tried exactly as what you said , also I understood your code! but what your code gives me isn't the zero crossings point that it's actually the x axis , I want to do interpolation that gives me the zero crossings points which it's should be intersection with x axis (time(sec)); what should I do/update in your code in order to get the zero crossings point on the intersections with x axis(x axis is represent time in sec) ?
attaching down my plot that I get from your code:
Moreover, once I run your code I get "Array indices must be positive integers or logical values." and I don't know why if you could help!
secondly, the zero crossings points you're saving them on vector/array x0 , how can I loop on that array in order to find the difference between each two adjacent zero crossing points? I mean (xo(i+1)-x0(i)) , substraction between every two adjacent zero crossings points. my purpose for substraction that Im going to put all and save all the substractions that I do (substraction between two adjacent zero crossings points) into another array/vector to use it for other purposes, could you help me to do that? thanks.
thanks for your help in advance.
Any help please? thanks
Ya same problem with me did you managed to solve the problem? I get this "Array indices must be positive integers or logical values" too
hi ivy
i don't want to spend much time on this, but if i just copy and paste the code above (and correct 'legth' -> length), then it works. i hope that is the same for you.
i get the 'array indices...' message a lot in other stuff, and it means that you are trying to tell matlab to access an array using something other than a regular integer, and it can't do that (nobody can do that!). so if have an array [1 2 3 4], what is the "2.34"-th element? well, that doesn't have a meaning, so you get an error. its like asking "what is the first-and-a-half letter of your name"? doesn't work! :)
thisArray = [2 4 6 8 10];
a = thisArray(2); % no problem! a is second element, = 4
b = thisArray(3); % b = 6; all good :)
c = thisArray(2.21); % array indices error! because ther is no "2.21"th element
so you need to go through your code and find the line corresponding to where the error is created, and look for where you are doing this sort of thing - using a non-integer (most likely in a variable) as the index for an array.
thisArray = [2 4 6 8 10];
a = 2.21;
b = thisArray(a); % :(
hope that explains this error and why it comes about. try doing some basic debugging by running with a breakpoint on your error line, and just before you would get the error, hover over the variables and look for when you are trying to ask for an element of an array using something that isn't an integer. if you still can't see it, you need to start extracting individual pasrts (while still paused at the breakpoints) and running them separately to explore. this can be harder to see when you work with very large arrays, so you could also try taking small arrays as test data first, etc. all the usual tricks.
for this specific code, we were talking about zero crossing in a signal and there seemed to be some confusion as to what the x-axis values were. there is a distinction between your x-variable, which could well be non-integers (eg fractions of a second), and the x variable array, where you talk about each element of the array and each element is accessed by what number element of the array it is - and that has to be an integer, or you get the error as above..
x = 1:100; % just a list of numbers
here, the values in the array are the same as the element indices. i do this a lot for testing/examples, but it can cause confusion. so let's imagine i have a time signal being sampled at some random frequency, 240 Hz, and i want the x data to be the time of the samples (and starting from zero):
nSamples = 1000; % there are 1000 samples in my recording
freq = 240; % my sampling frequency
startTime = 0; % start recording at zero time
x = startTime + [1:nSamples]*(1/freq);
now, x is a list of times (in seconds), telling me when each sample was recorded, but i still acess & work with them based on their indices (which still have to be integers!).
so. run my code above with no edits, and see that:
x is a list of sample 'times', which are not integers.
crossInd are the indices (which must be integers) of the points where the signal seems to cross zero. if you want a list of the times that the signal seems to cross zero, you could access the values at those indices you found (which are close to the crossing) using crossTimes = x(crossInd). in the code, i do a simple interpolation between the two points at the crossing to get the time values, which i call x0.
good luck!
I was able to fix the error mentioned by Mohamed and Ivy by making sure that there wasn't an erroneous zero crossing detected by having opposite signal(1) and signal (end) signs.
crossInd = find(cross); % x indices of cross points
if crossInd(1) == 1
crossInd(1) = [];
end
nCross = length(crossInd); % number of cross points found
For whomever may show up and find this very useful code later!

Accedi per commentare.

Tag

Richiesto:

il 13 Lug 2020

Commentato:

il 6 Gen 2023

Community Treasure Hunt

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

Start Hunting!

Translated by