How to determine the phase shift of a sampled signal? - Page 1
Forum section: electronics / projects

author: littleboot
author_rank: Regular Contributor
timestamp: December 30, 2017, 09:21:57 pm
content: Hello eevblog member,I'm currently working on a project were i need to determine the phase of a sampled sine wave (sampled with a STM32 MCU).I know this involves some DSP but I don't know were to start and I'm wondering if someone could point me to any literature regarding this topic?Further explanation of the requirements:The total period of the sine wave = 512*T, T=5.6uS. (sine period = 2.87mS) this does not change (the frequency of the sine stays constant)I take a sample of the signal every 16T resulting in 32 samples that represent the sampled signal. (512/16=32)From these 32 samples I want to determine the phase shift of the signal from 0 to 512T. (if the peak of the sine is at T0 the phaseshift is 0% if the peak of the sine is at T256 the phaseshift is 50% ect.)Currently I'm only able to determine the phase in a 1/32 T resolution just looking at every value in the array and looking for the highest sample value and storing the sample number a phase shift. Is there a method/algorithm that meets my requirements and can be implemented on a MCU (real time)?I attached a screen recording(GIF format) of my samples plotted in a bar graph (real time using a debugger to read the variables from RAM) that shows the sampled signal of which I need to determine the phase. You can also see the peak value I compute using the method described above.Thanks in advance!Update:Thanks for all the feedback this is great, I'm watching FFT videos to refresh my memory about this topic.I didn't think I Explain very well what I'm trying to measure so I made some Images to explain it better.This is a overview of the signals:I would like to calculate the Phase shift between signal 1 and signal 2.Signal 1 is a modulated sine wave.Signal 2 is a puls of 1T (5.6uS) High every 512T = ~2.86mS = ~350HzThe ADC conversion trigger is used to trigger the ADC conversion in the STM32, the end of conversion trigger a DMA request to store the samples in a circular buffer.Examples:Pos1Pos2Pos3Depending on external conditions the phase shift between signal 1 and 2 chages, above are 3 different different phase shifts Pos1, Pos2, Pos3.What I would like to do is calculate this phase shift on the MCU. As final output I want to have a number from 0 to 511 to indicate this phase shift.Note that the amplitude of signal 1 can vary, I'm only interested in the phase shift not the amplitude.

author: nctnico
author_rank: Super Contributor
timestamp: December 30, 2017, 10:08:41 pm
content: Simply interpolate around the zero crossing.

author: MasterT
author_rank: Frequent Contributor
timestamp: December 30, 2017, 10:24:33 pm
content: Run an FFT, I know STM has DSP library, and moderate performance Radix-4 implementation. I didn't try their code (it doesn't fit my arduino programming style, and you didn't tell us what is your IDE programming environment), but what I've read in Application Note (UM0585 User manual STM32F10x DSP library)is quite impressive, estimated FFT code through-output probably 200-300 ksps.If input freq. is constant, and synchronous to sampling, you may try to find Goertzel algorithm.Though I'd recommend stick to FFT, there is not big difference in a calculation.

author: littleboot
author_rank: Regular Contributor
timestamp: December 31, 2017, 12:20:46 am
content: Thanks for the Tip, I will have a look at it.The programming IDE: System Workbench for STM32 (Eclipse based, FREE and works very well) "http://www.openstm32.org/HomePage"Reading and displaying the Variables I use:STM Studio run-time variables monitoring and visualization tool for STM32 microcontrollershttp://www.st.com/en/development-tools/stm-studio-stm32.htmlThe board I'm working on:https://www.aliexpress.com/item/1pcs-STM32F103C8T6-ARM-STM32-Minimum-System-Development-Board-Module-For-arduino/32583160323.html

author: rhb
author_rank: Super Contributor
timestamp: December 31, 2017, 02:00:16 am
content: Compute the FFTs of both signals. Compute the phase of each signal at each frequency. Subtract the two.That's the idea. The reality is rather more complex. Do you want the delay between two signals? Fit a line to the phase difference. Do you want phase delay as a function of frequency? How precise do you want to be? Do you have a physical model? Does the phase wrap? How fast? If it's fast it gets really nasty to sort out unwrapping the phase.Gnu Octave is the tool of choice for this. Get set up so you can load your data into that and I'll walk you through the math. It's quite easy to do. There are probably a dozen YouTube videos on this, but watching them is more work than doing it. But then, I went to grad school to learn this which was far more work than watching a YouTube video.

author: coppice
author_rank: Super Contributor
timestamp: December 31, 2017, 02:38:02 am
content: 1) Are you trying to measure the phase as a one off event, based on capturing a single cycle of the sine wave, or are you trying to track the phase shift over time?2) What precision are you looking for in measuring the phase shift?

author: hamster_nz
author_rank: Super Contributor
timestamp: December 31, 2017, 05:29:13 am
content: Multiply two cycle's with of samples by a reference sin() and sum the result.The multiply the same samples by a reference cos() and sum the result.The resulting totalled values will form a vector, with the angle of the phase of the signal, and a length proportional to the amplitude.You can then use atan2() to get phase.

author: dmills
author_rank: Super Contributor
timestamp: December 31, 2017, 12:24:04 pm
content: Now if we write the summation as a continuous time integral, and use Eulers famous equivalence to get the sine and cosine, then do this for all integer multiples of the....I think we have just reinvented the Fourier transform!Regards, Dan.

author: littleboot
author_rank: Regular Contributor
timestamp: December 31, 2017, 01:12:12 pm
content: Quote from: rhb on December 31, 2017, 02:00:16 amI know the frequency of the signal beforehand, I listed a better explanation with examples above.Yes the phase wraps.I will collect some data and import it in octave (matlab). I'll upload it when ready. (thanks in advance)

author: Kleinstein
author_rank: Super Contributor
timestamp: December 31, 2017, 01:31:36 pm
content: The suggestion of hamster_nz is a good way. It is calculating the Fourier transform for the one frequency of interest. With just 32 samples for a period it is easy to have a table for the sin() cos() values. So the computational effort is rather low.

author: rhb
author_rank: Super Contributor
timestamp: December 31, 2017, 02:21:15 pm
content: OK. Signal 1 is a spike series multiplied by a sine wave. That's important because that means that the FT is also a spike series in frequency. The multiplication in the time domain is a convolution in the frequency domain. So each spike in the frequency domain has two spikes adjacent to it, one above and one below. Think classic modulated sine wave theory. A sine wave in time is a single spike in frequency.It gets sticky depending upon the relative frequency of the spike series and the sine wave. If the spikes are too far apart you get aliasing. For the example you show that is not an issue. But it could be if the relative frequencies change.If the signal 1 spikes are in constant phase with the ADC clock then just store the samples in a ring buffer and use signal 2 to trigger a short FFT, pick the largest amplitude in the FFT and compute the phase angle. So long as the delay between triggers does not vary by more than a single period of the sine wave you're all set.A more robust solution is to calculate the phase angle at all frequencies of the FFT and fit a line to it by least squares. That's the standard way to measure the time delay between two noisy signals. That also has the advantage that it accounts for wrapping.If the spikes in signal 1 are NOT in constant phase with the ADC clock, the spikes are aliased and you'll need to substantially increase your ADC clock rate. If that is the case, then the sine wave modulation is probably an aliasing artifact.To measure the phase between a sine wave and a spike series, I suggest considering using a comparator to start a timer on signal 2 and another to read the timer at the zero crossings of the sine wave and average a small number. That's much less resource intensive than using an FFT. Put a low pass filter on signal 1 to get rid of the spikes.

author: Brutte
author_rank: Frequent Contributor
timestamp: December 31, 2017, 02:25:56 pm
content: You have n samples of [a*sin(x)+b] and m samples of [c*sin(x+phi)+d] and you want to get phi..Here the question arrises if in your case it may be assumed a==c, if n==m, b==d==0 or perhaps it this is a continuous process, with trends, or as new samples arrive a phi is actually phi(t), or may it be assumed that within those n samples phi(t)=const etc.If everything is fixed, known, equal and perfect then:sin(x+y) = sin(x)cos(y) + cos(x)sin(y)You already have sin(x+y) and sin(x) is the reference so you just need to find y that satisfies this equation with least error (in some sense) on some n-sample horizon.

author: coppice
author_rank: Super Contributor
timestamp: December 31, 2017, 02:27:02 pm
content: Quote from: Kleinstein on December 31, 2017, 01:31:36 pmYes, quadrature correlation is a very standard and very effective technique for this type of problem, but there are two things that might create issues here:Just how well is the received frequency known? If the received signal stems from a signal transmitted by the same equipment, then things will be very easy. If the transmitted signal's frequency is not known with high precision, then it might be necessary to synthesise a phase locked local sine/cos wave to correlate with.If the sample data the OP posted is supposed to be a pure sine wave, then its a very noisy one. This will limit the accuracy the quadrature correlation achieves. Its still the most effective technique for isolating the fundamental component in a noisy signal, but the OP will have to investigate just how long a data set they need to process to achieve the phase measurement accuracy they are looking for.

author: rhb
author_rank: Super Contributor
timestamp: December 31, 2017, 04:32:23 pm
content: Looking more closely at the figures, it appears that signal 1 is the superposition of a constant amplitude spike series and a sinusoidally modulated pulse train. What is the source of that signal? Plot the FFT of signal 1 and your ADC clock in the same figure.Oh, and please just load the images to EEVblog rather than linking to another location. It's a nuisance and the link will eventually break making responses less useful.

author: Kleinstein
author_rank: Super Contributor
timestamp: December 31, 2017, 05:11:01 pm
content: The original signal seems to be a sequence of pulses, but it looks like sampling can be timed in a good way, to get the amplitude of the pulses. So after sampling there seem to be no more big spikes, just a rather low noise sine wave.

author: bson
author_rank: Unknown
timestamp: January 01, 2018, 09:28:17 pm
content: Just as a note, instead of looking for peaks, look for zero crossings. This is most easily done by keeping a running average of some window, say the last 32 samples, and looking for pairs of samples that result in crossing this average (below-above and above-below pairs), perhaps with a little smoothing and/or hysteresis. Many uC's also have timer capture-comparator functionality, giving you the time resolution of the timer's peripheral clock, rather than the ADC sample clock. Of course, in this case zero crossing data will arrive skewed with ADC sample data, so some additional legwork is needed to deskew.