I want to measure the low pulse length of a signal and then plot it to see if the pwm ratio changes during run time of that signal.
The signal it self was acquired using an oscilloscope and stored as a cvs file, channel 2 is a pulse signal where i want to evaluate in which boundaries the pulses are steady or not.
with d = dutycycle(CH2)
i could get the duty cycle from my signal
How can i plot the dutycycle or low pulse time as a graphical line or field to see its changes over time?
Both Files for Testing are here:
First
Second
Your signal is quite clean, so you could just use simple thresholding. If you needed to handle a little more noise, here's one way.
The basic approach is to decompose the signal piecewise (into a sequence of constant segments). Changepoint identification gives you the start and end time as well as magnitude of each segment.
Then, all the even times are rising edges and odd times are falling edges (or vice versa). The differences between these two vectors give high and low duration of each pulse, and differences between rising edges gives per-pulse duration.
rising = TIME(1+est.time(2:2:end));
falling = TIME(1+est.time(1:2:end));
hightime = falling(2:end) - rising(1:end-1);
lowtime = rising(2:end) - falling(2:end);
plot([lowtime hightime diff(rising)])
legend('Low Time', 'High Time', 'Pulse Duration')
Duty cycle is then hightime ./ diff(rising), and you can proceed with your jitter calculations.
For performing the segmentation, I used code from my thesis, but this simple case (piecewise constant) was already solved by Killick et. al (2012)
R. Killick, P. Fearnhead, and I. A. Eckley. Optimal detection of changepoints with a linear computational cost. Journal of the American Statistical Association, 107(500):1590–1598, Dec 2012. doi: 10.1080/01621459.2012.737745.
Related
I am working on steering wheel angle sensor that measures absolute angle of steering wheel. As steering angle sensors uses gears and several joints which is totally hardware related so in spite of calibration in start with the passage of time due to usage of mechanical parts and also due to some environmental and road conditions some errors occurs in the values of sensors (e.g. offset, phase change, flattening of signal, delay).
In short due to these errors in the measurements our aim gets distracted means If I am viewing velocity vs time curve so if in the original or calibrated sensor in short close to ideal condition sensor my velocity shows a peak in amplitude but due to error (hysteresis) in measured signal I am not getting peak in velocity curve or I am getting flattening of curve so it will affect my final task.
I have a tolerance let say 1.20 degree for hysteresis so that’s why I am having detailed idea about my signal and want to observe my signal if some changes means offset, delay, lowering has occurred in my signal or not. This will not only provide me an idea that whether to lessen the amount of sensors used for my task or made some changes in hardware of sensor to lessen the amount of hysteresis or do some other actions to reduce it.
What I have done uptill now in which uptill now I am not sure that whether I am right or wrong. I am getting some values for hysteresis but I have few questions regarding one of the technique I am using. If someone provides me an idea about it how to improve this technique or provide me a better approach then it will be nice and great guidance.
I have an ideal sensor signal (under ideal conditions which we want) and values from 1 sensor I have data of 6 different drives from car. I am explaining just 1 example of my first drive and its relation with my reference sensor data.
Given the data reference signal and sensor signal data of size 1x1626100 and 1 x 1626100 double for one reading from sensor but in all readings values from Ideal and measured signal w.r.t to time are same.
In short I want to find out the Hysteresis difference of sensor signal from measured signal.
In this method I have applied Regression lines Technique (On upper and lower values of difference signal).
I took difference of my signals (Ref – measured value of signal after applying my limitation on signal).
Applied regression technique by putting a threshold by myself above and below the difference signal means on upper values and on lower values separately and difference between upper and lower values regression lines is called as Hysteresis (Loss). Please have a look at figure 3 and 4 for clear view.
The Problem here with this technique is that I define the values for upper and lower regression line by myself after looking into data like up= 0.4, low= -0.4.
Question:
IS it possible that I could be able to write a program which decides the best line of fit by itself rather than giving a threshold?
Means is there any way that my code draw the best regression line for above values and best regression line for lower values and calculate Hysteresis.
I shall be really grateful to you all as I remained unable to find solution for this problem.
Thanks in anticipation.
clear all
clc
drv(6)=load('20170420__142024.mat');
t=drv(6).q_T0;
ref=drv(6).Pos;
lws_7=drv(6).SteeringWheelAngle;
swav=drv(6).SteeringWhellRotSpd;
vel=drv(6).KBI_angez_Geschw;
sig_diff=ref-lws_7;
mean_sig_diff = mean(sig_diff);
offset_removed_sig_diff = detrend(sig_diff ,'constant' );
offset_removed_mean_sig_diff = detrend(mean_sig_diff ,'constant');
figure(1)
ax11=subplot(321);
histfit(sig_diff)
dum=['Drive ' num2str(i) ': Differnce Signal With offset Removed for drive '];
title(dum)
hold on
plot([mean_sig_diff mean_sig_diff],[0 10000],'r')
hold off
ax12=subplot(322);
histfit(offset_removed_sig_diff)
dum=['Drive ' num2str(i) ': Differnce Signal With offset Removed'];
title(dum)
hold on
plot([offset_removed_mean_sig_diff offset_removed_mean_sig_diff],[0 10000],'r')
hold off
swvel_thres=20;
vehvel=60;
SAmax=90;
t_lim=t(((lws_7<SAmax)&(lws_7>-SAmax)&(swav<swvel_thres)&(vel>vehvel)));
sig_diff_lim = sig_diff((lws_7<SAmax)&(lws_7>-SAmax)& (swav<swvel_thres)&(vel>vehvel));
offset_rem_sig_diff_lim = detrend(sig_diff_lim,'constant');
mean_sig_diff_lim = mean(sig_diff_lim);
offsetmean_sig_diff_lim = detrend(mean_sig_diff_lim,'constant');
figure(2)
ax21=subplot(321);
histfit(sig_diff_lim)
dum=['Drive ' num2str(i) ': Limited Differnce Signal With offset Removed for drive '];
title(dum)
hold on
plot([ mean_sig_diff_lim mean_sig_diff_lim],[0 10000],'r')
hold off
ax22=subplot(322);
histfit(offset_rem_sig_diff_lim )
dum=['Drive ' num2str(i) ': Limited Differnce Signal With offset Removed'];
title(dum)
hold on
plot([offsetmean_sig_diff_lim offsetmean_sig_diff_lim],[0 10000],'r')
hold off
up=0.4;
low=-up;
stats_up = regstats(offset_rem_sig_diff_lim((offset_rem_sig_diff_lim>up)),t_lim((offset_rem_sig_diff_lim>up)), 'linear', {'beta'}); %calculate linear regression for upper values
intercept_up=stats_up.beta(1);
slope_up=stats_up.beta(2);
stats_low = regstats(offset_rem_sig_diff_lim((offset_rem_sig_diff_lim<low)),t_lim((offset_rem_sig_diff_lim<low)), 'linear', {'beta'}); %calculate linear regression for upper values
intercept_low=stats_low.beta(1);
slope_low=stats_low.beta(2);
Hysteresis_LinReg = abs(intercept_low)+abs(intercept_up);
figure(4)
% ax31=subplot(321);
plot(t_lim, offset_rem_sig_diff_lim ,t_lim, t_lim*slope_up+intercept_up, t_lim ,t_lim*slope_low+intercept_low);grid
legend('diff','reg up','reg low')
title(' Limited Differnce Signal With offset Removed with regression lines for drive ')
figure(5)
histfit(offset_rem_sig_diff_lim)
dum=['Drive ' num2str(i) ':Offset Removed Limited Difference Signal with Regression Lines for drive '];
title(dum)
hold on
plot([ intercept_up intercept_up],[0 12000],'r')
hold off
hold on
plot([intercept_low intercept_low],[0 12000],'r')
hold off
You can try a 1D version of the k-means algorithm. k-means divides the data set into k sets (called clusters) - in your case k = 3 (middle points, upper points, lower points) - in terms of how close they are to each other.
You can use the kmeans() function provided by Matlab. It is a 2D version AFAIK, but you can reduce the dimensionality of your problem by setting the first (i.e. time) coordinate of each point to 0, leaving only the "y" (i.e. signal) values.
After k-means is done just select the points, whose mean value is the lowest and the highest, which would give you upper and lower points. You can get the means of each cluster by using this version of the function (see the linked docs):
[idx,C] = kmeans(___)
Matrix C will contain the means, and idx shows which point belongs to which set (cluster).
Then just fit lines to your chosen sets of points.
I am trying to implement a frequency domain phase shift but there are few points on which I am not sure.
1- I am able to get a perfect reconstruction from a sine or sweep signal using a hanning window with a hop size of 50%. Nevertheless, how should I normalise my result when using a hop size > 50%?
2- When shifting the phase of low frequency signals (f<100, window size<1024, fs=44100) I can clearly see some non-linearity in my result. Is this because of the window size being to short for low frequencies?
Thank you very much for your help.
clear
freq=500;
fs=44100;
endTime=0.02;
t = 1/fs:1/fs:(endTime);
f1=linspace(freq,freq,fs*endTime);
x = sin(2*pi*f1.*t);
targetLength=numel(x);
L=1024;
w=hanning(L);
H=L*.50;% Hopsize of 50%
N=1024;
%match input length with window length
x=[zeros(L,1);x';zeros(L+mod(length(x),H),1)];
pend=length(x)- L ;
pin=0;
count=1;
X=zeros(N,1);
buffer0pad= zeros(N,1);
outBuffer0pad= zeros(L,1);
y=zeros(length(x),1);
delay=-.00001;
df = fs/N;
f= -fs/2:df:fs/2 - df;
while pin<pend
buffer = x(pin+1:pin+L).*w;
%append zero padding in the middle
buffer0pad(1:(L)/2)=buffer((L)/2+1: L);
buffer0pad(N-(L)/2+1:N)=buffer(1:(L)/2);
X = fft(buffer0pad,N);
% Phase modification
X = abs(X).*exp(1i*(angle(X))-(1i*2*pi*f'*delay));
outBuffer=real(ifft(X,N));
% undo zero padding----------------------
outBuffer0pad(1:L/2)=outBuffer(N-(L/2-1): N);
outBuffer0pad(L/2+1:L)=outBuffer(1:(L)/2);
%Overlap-add
y(pin+1:pin+L) = y(pin+1:pin+L) + outBuffer0pad;
pin=pin+H;
count=count+1;
end
%match output length with original input length
output=y(L+1:numel(y)-(L+mod(targetLength,H)));
figure(2)
plot(t,x(L+1:numel(x)-(L+mod(targetLength,H))))
hold on
plot(t,output)
hold off
Anything below 100 Hz has less than two cycles in your FFT window. Note that a DFT or FFT represents any waveform, including a single non-integer-periodic sinusoid, by possibly summing up of a whole bunch of sinusoids of very different frequencies. e.g. a lot more than just one. That's just how the math works.
For a von Hann window containing less than 2 cycles, these are often a bunch of mostly completely different frequencies (possibly very far away in terms of percentage from your low frequency). Shifting the phase of all those completely different frequencies may or may not shift your windowed low frequency sinusoid by the desired amount (depending on how different in frequency your signal is from being integer-periodic).
Also for low frequencies, the complex conjugate mirror needs to be shifted in the opposite direction in phase in order to still represent a completely real result. So you end up mixing 2 overlapped and opposite phase changes, which again is mostly a problem if the low frequency signal is far from being integer periodic in the DFT aperture.
Using a longer window in time and samples allows more cycles of a given frequency to fit inside it (thus possibly needing a lesser power of very different frequency sinusoids to be summed up in order to compose, make up or synthesize your low frequency sinusoid); and the complex conjugate is farther away in terms of FFT result bin index, thus reducing interference.
A sequence using any hop of a von Hann window that in 50% / (some-integer) in length is non-lossy (except for the very first or last window). All other hop sizes modulate or destroy information, and thus can't be normalized by a constant for reconstruction.
I have two sensors seperated by some distance which receive a signal from a source. The signal in its pure form is a sine wave at a frequency of 17kHz. I want to estimate the TDOA between the two sensors. I am using crosscorrelation and below is my code
x1; % signal as recieved by sensor1
x2; % signal as recieved by sensor2
len = length(x1);
nfft = 2^nextpow2(2*len-1);
X1 = fft(x1);
X2 = fft(x2);
X = X1.*conj(X2);
m = ifft(X);
r = [m(end-len+1) m(1:len)];
[a,i] = max(r);
td = i - length(r)/2;
I am filtering my signals x1 and x2 by removing all frequencies below 17kHz.
I am having two problems with the above code:
1. With the sensors and source at the same place, I am getting different values of 'td' at each time. I am not sure what is wrong. Is it because of the noise? If so can anyone please provide a solution? I have read many papers and went through other questions on stackoverflow so please answer with code along with theory instead of just stating the theory.
2. The value of 'td' is sometimes not matching with the delay as calculated using xcorr. What am i doing wrong? Below is my code for td using xcorr
[xc,lags] = xcorr(x1,x2);
[m,i] = max(xc);
td = lags(i);
One problem you might have is the fact that you only use a single frequency. At f = 17 kHz, and an estimated speed-of-sound v = 340 m/s (I assume you use ultra-sound), the wavelength is lambda = v / f = 2 cm. This means that your length measurement has an unambiguity range of 2 cm (sorry, cannot find a good link, google yourself). This means that you already need to know your distance to better than 2 cm, before you can use the result of your measurement to refine the distance.
Think of it in another way: when taking the cross-correlation between two perfect sines, the result should be a 'comb' of peaks with spacing equal to the wavelength. If they overlap perfectly, and you displace one signal by one wavelength, they still overlap perfectly. This means that you first have to know which of these peaks is the right one, otherwise a different peak can be the highest every time purely by random noise. Did you make a plot of the calculated cross-correlation before trying to blindly find the maximum?
This problem is the same as in interferometry, where it is easy to measure small distance variations with a resolution smaller than a wavelength by measuring phase differences, but you have no idea about the absolute distance, since you do not know the absolute phase.
The solution to this is actually easy: let your source generate more frequencies. Even using (band-limited) white-noise should work without problems when calculating cross-correlations, and it removes the ambiguity problem. You should see the white noise as a collection of sines. The cross-correlation of each of them will generate a comb, but with different spacing. When adding all those combs together, they will add up significantly only in a single point, at the delay you are looking for!
White Noise, Maximum Length Sequency or other non-periodic signals should be used as the test signal for time delay measurement using cross correleation. This is because non-periodic signals have only one cross correlation peak and there will be no ambiguity to determine the time delay. It is possible to use the burst type of periodic signals to do the job, but with degraded SNR. If you have to use a continuous periodic signal as the test signal, then you can only measure a time delay within one period of the periodic test signal. This should explain why, in your case, using lower frequency sine wave as the test signal works while using higher frequency sine wave does not. This is demonstrated in these videos: https://youtu.be/L6YJqhbsuFY, https://youtu.be/7u1nSD0RlwY .
Cross correlation is to be used to measure distance to an aircraft by transmitting a
known wide-band signal and correlating the transmitted signal with incoming signals
received via the radar reception dish
The transmitted signal x(n) is of length N=512 while the received signal y(n) is of length N=2048.
y(n)=kx(n-d)+w(n); where 'kx(n-d)' is x(n) delayed by d samples and attenuated by a factor k, and w(n) is reception noise.
i am trying to write a MATLAB program to cross correlate x(n) with the y(n) to determine the value of d, the number of samples delay.
And also Determine a suitable sampling frequency if the distance to the aircraft is to be
determined within 50 km to an accuracy of 50 m, given that the transmitted
and received data is travelling at the speed of light.
The easiest way to do this is with the "xcorr" function. This is part of the Signal Processing toolbox for matlab, but should be available for GNU Octave here. I have not checked if the octave script is completely MATLAB compatible.
You can use the xcorr function as:
[correlation,lags] = xcorr(x,y);
The lag value can be found using
delay = lags(find(correlation==max(correlation)))
At the speed of light, the signal will be travelling at 3 x 10^8 m/s, so to have a resolution of 50m, you should be sampling at at least (3e8/50m) = 6MHz. At this sampling rate, each lag will be 1/6000000 second. If you multiply your delay by this value, you get your total time intervel between transmission and reception of the signal. Multiply this time intervel by the speed of light to get your distance.
You can use generalized Cross correlation -Phase transform GCC PHAT
The following is the MATLAB code for it
function time=GCCPHAT_testmode(b1,b2)
b1f=fft(b1);
b2f=fft(b2);
b2fc=conj(b2f);
neuma=(b1f).*(b2fc);
deno=abs((b1f).*(b2fc));
GPHAT=neuma./deno;
GPHATi=ifft(GPHAT);
[maxval ind]= max(GPHATi);
samp=ind
end
we can ignore the 'find' function in matlab, the command could be changed to
delay = lags(correlation==max(correlation))
'xcorr' suits for vectors with long length;
'gcc' prefer frame by frame.
Aj463's comment above is good, indeed GCC-PHAT is better than unweighted correlation for estimating delay of wide-band signals.
I would suggest a small improvement to the code posted above: to add a small value epsilon to the denominator, epsilon -> 0, in order to avoid eventual division by zero.
Thus, I would change the line
deno=abs((b1f).*(b2fc));
to
deno=abs((b1f).*(b2fc)) + epsilon;
Is there some process that can determine / remove an unknown DC offset from a non-periodic discrete time signal?
The signal in in question has a sample rate of 25Hz and has harmonics of interest between 0.25 and 3 Hz.
I have tried using highpass filters mixed results, first I used a 10th order guassian with Fc = 0Hz, this did a good job of removing the offset but it severly attenuated the AC aswell although it did leave the signal shape intact, next I used a 168th order equilripple with a stopband at 0Hz and passband at 0.25Hz, the phase shift was too severe and the signal shape too distorted, the distortion could probably be reduced if the pass-band was brought down to 0.1Hz but this would just further increase the phase shift which I need to keep to the very minimum.
Before and after applying x - LPF(x), as suggested by Paul R
I recommend using a notch filter at DC and using filtfilt to make it zero phase.
a = [1 , -0.98]; b = [1,-1];
y = filtfilt(b,a,x);
The closer the second value of a gets to -1 the narrower your notch will be.
A DC offset means that some constant value was added to the signal (the name originates from adding a DC voltage to an analog AC signal). If the DC component is really constant (and not changing really slowly), then you don't have to design some high-order (and potentially unstable) high-pass filters - you can just subtract the average of your signal from the signal - which is, of course, a high-pass filter as well (averaging is a type of a low-pass, and '1 minus the average' is high-apss) --- but a very simple one.
If, on the other hand, you have a reason to believe that the DC component is not really a DC, but rather an AC with very low frequency, then you'd better average segments of your signal and not the signal as a whole, which is the same as using a low-pass filter with impulse response which is shorter then the length of the signal. In this case you have to make some assumptions about the "DC" component.
Rather than implementing a high pass filter directly (which can be rather tricky for very low frequencies - you end up with a large number of coefficients and various issues with stability and passband ripple etc), you might instead want to consider implementing a low pass filter which will give you an estimate of the DC offset value, and then subtract this filtered offset from your signal, i.e. rather than:
y = HPF(x)
do this:
y = x - LPF(x)
The low pass filter can probably just be quite a simple filter with a relatively small number of terms. The big advantage of this implementation is that your higher frequency components should not have any unwanted artefacts due to phase, ripple, etc, since all you are doing is subtracting an almost stationary DC value from the samples.
The only potential downside is that if the DC offset is large you may have quite a long initial settling time before the estimate of the DC offset is accurate (although this is also true of any other implementation such as a direct high pass filter of course). If you have any a priori knowledge of what the offset value is likely to be (e.g. if it doesn't change very much from run to run, and you know the value from the previous run) then you can use this to optimise the settling time, by initialising the LPF state variables to a suitable value rather than 0.
As others have said, to remove a DC offset, you can simply subtract the mean. Your signal does not need to be periodic, but it does need to be long enough to get a good estimate of the DC component.
If you still wish to go with a filtering approach, you can eliminate the severe distortion due to phase lag by using filtfilt. This function filters your timeseries once in the forwards direction and then once in the reverse direction, so that phase distortions cancel out.
You can design a symmetric FIR filter as the low-pass filter that estimates the DC and then subtract the output from your input signal. This filter has constant group-delay.