如何用Python计算未知不同频率两信号间的相位差?
不同频率信号的相位差计算(Python实现)
首先明确核心事实:不同频率的周期信号,相位差是随时间线性变化的,公式为:
φ(t) = 2π(f₁ - f₂)t + (φ₀₁ - φ₀₂)
其中f₁、f₂是两个信号的频率,φ₀₁、φ₀₂是各自的初始相位。若只需初始相位差,取φ₀₁ - φ₀₂即可;若要任意时刻的相位差,代入对应时间t计算就行。
下面是两种实用的Python实现方案:
方法一:基于FFT的快速参数估计
适合信噪比高的实验信号,能快速提取信号的频率和初始相位:
import numpy as np from scipy.fft import fft, fftfreq # 替换成你的实验数据 fs = 1000 # 采样频率 t = np.linspace(0, 1, fs, endpoint=False) # 示例信号(实际使用时替换为你的sig1、sig2) sig1 = np.sin(2*np.pi*50*t + np.pi/4) + 0.1*np.random.randn(len(t)) sig2 = np.sin(2*np.pi*70*t + np.pi/3) + 0.1*np.random.randn(len(t)) # 计算FFT n = len(t) yf1, yf2 = fft(sig1), fft(sig2) xf = fftfreq(n, 1/fs)[:n//2] # 定位主频率分量 idx1 = np.argmax(np.abs(yf1[:n//2])) idx2 = np.argmax(np.abs(yf2[:n//2])) # 估计频率与初始相位 est_f1, est_f2 = xf[idx1], xf[idx2] est_phi0_1, est_phi0_2 = np.angle(yf1[idx1]), np.angle(yf2[idx2]) # 计算初始相位差并转换到[-π, π]区间 initial_phase_diff = np.mod(est_phi0_1 - est_phi0_2 + np.pi, 2*np.pi) - np.pi # 定义随时间变化的相位差函数 def get_phase_diff(t_val): return 2*(est_f1 - est_f2)*np.pi*t_val + initial_phase_diff # 输出结果 print(f"信号1估计频率: {est_f1:.2f} Hz") print(f"信号2估计频率: {est_f2:.2f} Hz") print(f"初始相位差: {initial_phase_diff:.2f} 弧度") print(f"t=0.5s时的相位差: {get_phase_diff(0.5):.2f} 弧度")
方法二:基于曲线拟合的稳健参数估计
针对噪声较大的实验信号,用曲线拟合能得到更可靠的参数:
import numpy as np from scipy.optimize import curve_fit # 定义正弦拟合模型 def sine_model(t, amp, freq, phi, offset): return amp * np.sin(2*np.pi*freq*t + phi) + offset # 替换成你的实验数据 fs = 1000 t = np.linspace(0, 1, fs, endpoint=False) sig1 = 1.2*np.sin(2*np.pi*50*t + np.pi/4) + 0.2*np.random.randn(len(t)) + 0.3 sig2 = 0.8*np.sin(2*np.pi*70*t + np.pi/3) + 0.2*np.random.randn(len(t)) + 0.1 # 拟合信号1(初始参数猜测:振幅、频率、初始相位、直流偏移) p0_1 = [np.ptp(sig1), 50, 0, np.mean(sig1)] params1, _ = curve_fit(sine_model, t, sig1, p0=p0_1) amp1, est_f1, est_phi0_1, offset1 = params1 # 拟合信号2 p0_2 = [np.ptp(sig2), 70, 0, np.mean(sig2)] params2, _ = curve_fit(sine_model, t, sig2, p0=p0_2) amp2, est_f2, est_phi0_2, offset2 = params2 # 计算初始相位差并标准化 initial_phase_diff = np.mod(est_phi0_1 - est_phi0_2 + np.pi, 2*np.pi) - np.pi # 随时间变化的相位差函数 def get_phase_diff(t_val): return 2*(est_f1 - est_f2)*np.pi*t_val + initial_phase_diff # 输出结果 print(f"信号1拟合结果: 振幅={amp1:.2f}, 频率={est_f1:.2f}Hz, 初始相位={est_phi0_1:.2f}rad") print(f"信号2拟合结果: 振幅={amp2:.2f}, 频率={est_f2:.2f}Hz, 初始相位={est_phi0_2:.2f}rad") print(f"初始相位差: {initial_phase_diff:.2f}rad") print(f"t=0.5s时的相位差: {get_phase_diff(0.5):.2f}rad")
关键注意事项
- 若信号含杂波,先通过
scipy.signal.butter设计带通滤波提取目标频率成分。 - 相位差结果建议转换到[-π, π]或[0, 2π]区间,用
np.mod即可实现标准化。 - 当信号频率接近采样频率的一半(奈奎斯特频率)时,FFT精度会下降,建议适当提高采样率。
内容的提问来源于stack exchange,提问作者juv
相关产品推荐
相关产品推荐

