0
$\begingroup$

I have two signals of the same frequency. Both have frequencies of 13.56Mhz, and I want to find the phase difference between these two frequencies.

The function generator generates a sinusoidal function of 13.56 mhz and has data obtained when measuring data. where the sampling frequency is 500Mhz and the number of data is 20000.

I want to find the phase difference between these two frequency data.

I turned the FFT to create a complex number of these two data, and tried to print out the result using the np.angle function, but I didn't get the result I wanted.

How can I get the phase difference between the two frequencies?

$\endgroup$
3
  • 4
    $\begingroup$ can you show the code that you used? what si the output that you got that wasn't the expected output? Can you please add a Minimal Reproducible Example? $\endgroup$ Commented Aug 24, 2021 at 10:38
  • 3
    $\begingroup$ Should this have been migrated to the signal processing Stack? $\endgroup$
    – Dave
    Commented Aug 24, 2021 at 15:07
  • 1
    $\begingroup$ @Dave I think this question is Ok to stay here too if the signals are noisy, or the solution is statistical $\endgroup$
    – Aksakal
    Commented Aug 27, 2021 at 21:30

1 Answer 1

2
$\begingroup$

The simplest technique in your case is to calculate the correlation $r$ of de-meaned signals, then get the phase difference as $\phi=\arccos(r/\pi)$ if the signals are harmonic, i.e. single frequency sine waves.

Another way of doing this is with cross-correlation function. The idea is to calculate the correlation between one signal and the lagged second signal. When the number of lags is closest to the phase shift, you'll get the maximum correlation. The advantage of this technique is that it doesn't depend on the shape of your signal, while the first method is best for harmonic signals.

correlation method

Why should this work for you? At the sampling frequency of 500MHz, you have at least 36 points of each wave of your 13.56MHz signal. With 20000 samples gives you hundreds of full waves measured, which means that the average of signals will be very close to the means and the partial waves at the beginning and end of your samples will not be important. Thus, after de-meaning the signals, the correlation simply boils down to the following equation: $$r\approx\frac{\int_0^{2\pi}sin(x)sin(x+\phi)}{\int_0^{2\pi}sin(x)^2}=\cos(\phi)$$

Here's a piece of Python code to demonstrate how this works for noise/signal ratio 10%.

import numpy as np
import math

# create fake data
nsr = 1e-1
r = np.random.normal(size=(20000,2)) * nsr
phdiff = math.pi * np.random.uniform()
print('true phase diff (radians):', phdiff, '\t(degrees):', phdiff / (2 * math.pi) * 360)
omega = 13.56e6
t = np.arange(20000) / 500e6
rdata = np.zeros((len(t), 2))
ph0 = 2 * math.pi * np.random.uniform()
rdata[:,0] = np.sin(2 * math.pi * omega * t + ph0)
rdata[:,1] = np.sin(2 * math.pi * omega * t + phdiff + ph0)
rdata = rdata + r

# scale
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(rdata)
data = scaler.transform(rdata)

import matplotlib.pyplot as plt
plt.figure()
plt.plot(data[1:100,:])
plt.show()

# phase difference determination
plt.figure(figsize=(4,4))
plt.title('Phase diagram')
plt.scatter(data[1:100,0],data[1:100,1])
plt.show()

c = np.cov(np.transpose(data))
print('cov: ', c)
phi = np.arccos(c[0,1] )
print('phase estimate (radians): ', phi, '(degrees): ', phi / math.pi * 180)

Output:

true phase diff (radians): 1.049746982742775    (degrees): 60.146071667753475

cov:  [[1.00005    0.48973754]
 [0.48973754 1.00005   ]]
phase estimate (radians):  1.059007630672643 (degrees):  60.67666770969148

enter image description here

enter image description here

cross-correlation method

Here's a piece of code to demonstrate how it could work.

from statsmodels.tsa.stattools import ccf
xc = ccf(data[:,0], data[:,1])
plt.figure()
angle = t * omega * 2 * math.pi

n = math.ceil(fs / omega)
plt.plot(angle[:n], xc[:n])
plt.show()
print(angle)

maxa = max(np.abs(xc[:int(n/2)]))
maxangle = angle[np.abs(xc)==maxa]
print('phase shift (radians): ',maxangle)

Output:

enter image description here

phase shift (radians):  [2.3855998]

PCA

My initial answer with PCA, but it's more complicated. You can run PCA on the standardized signals, then the ratio of explained variances will contain information about the phase difference of the signals.

$\endgroup$
6
  • $\begingroup$ @Askakal: I wasn't even aware there was a statistical way of answering the question so your answer is a real eye opener to me.. Is there some book or paper that relates the concept of PCA to digital signal processing ? I don't see the connection but there clearly is one given your answer. Thanks. $\endgroup$
    – mlofton
    Commented Sep 6, 2021 at 3:38
  • $\begingroup$ I doubt there’s a book. I didn’t try this method myself but it should work $\endgroup$
    – Aksakal
    Commented Sep 6, 2021 at 13:17
  • $\begingroup$ So, the first series is viewed as the first column of the data set, the second series is viewed as the second column and then the resulting 2 by 2 covariance matrix of the data set is used in the PCA ? I'll have to review PCA and try to figure why that works. Thanks for interesting answer. $\endgroup$
    – mlofton
    Commented Sep 6, 2021 at 16:12
  • $\begingroup$ For anyone who has the same question as I did, this link looks interesting at a gaance. link.springer.com/article/10.1155/2007/74580) $\endgroup$
    – mlofton
    Commented Sep 6, 2021 at 16:18
  • $\begingroup$ @mlofton, I simplified the answer $\endgroup$
    – Aksakal
    Commented Sep 7, 2021 at 14:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.