You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:23:23