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

如何利用Scipy计算含噪变频率正弦波的平均峰峰值电压?

如何利用Scipy计算含噪变频率正弦波的平均峰峰值电压?

嘿,看起来你已经成功用Scipy的find_peaks定位到了含噪正弦波的峰值,效果还不错!要计算平均峰峰值电压其实并不难,咱们可以基于你现有的代码扩展,或者用一些更鲁棒的方法来适配变频率、带噪声的信号,下面给你详细讲讲:

方法一:基于现有峰值检测逻辑扩展

峰峰值的本质是峰值电压与对应谷值电压的差值,所以你只需要同时检测出谷值,再将峰谷配对计算即可:

  1. 检测谷值:把原始信号反转后,用同样的find_peaks方法就能得到谷值的位置——毕竟谷值就是反转信号的峰值。
  2. 配对峰谷:由于信号频率是变化的,咱们可以按顺序取峰、谷数组中长度较小的那个作为配对基准,避免出现不匹配的情况。
  3. 计算平均峰峰值:算出每一组峰谷的电压差,再取所有差值的平均值。

给你写了个扩展函数,直接就能用:

from scipy.signal import find_peaks
import numpy as np
import matplotlib.pyplot as plt

def calculate_avg_peak_to_peak(data_mV, sampling_rate, signal_frequency):
    # 复用你原来的距离参数,保证峰谷检测的一致性
    distance = (sampling_rate / signal_frequency) - 100
    
    # 检测峰值
    peaks, _ = find_peaks(data_mV, distance=distance)
    # 检测谷值(反转信号找峰值)
    valleys, _ = find_peaks(-data_mV, distance=distance)
    
    # 按顺序配对峰谷,取两者中较短的长度避免不匹配
    min_length = min(len(peaks), len(valleys))
    peak_voltages = data_mV[peaks[:min_length]]
    valley_voltages = data_mV[valleys[:min_length]]
    
    # 计算每组峰峰值并求平均
    peak_to_peak_values = peak_voltages - valley_voltages
    avg_peak_to_peak = np.mean(peak_to_peak_values)
    
    # 可视化验证(可选)
    plt.plot(data_mV, label="Original Signal")
    plt.plot(peaks, peak_voltages, "x", color="orange", label="Peaks")
    plt.plot(valleys, valley_voltages, "o", color="green", label="Valleys")
    plt.plot(np.zeros_like(data_mV), "--", color="gray")
    plt.title(f"Average Peak-to-Peak Voltage: {avg_peak_to_peak:.2f} mV")
    plt.legend()
    plt.show()
    
    return avg_peak_to_peak

方法二:先滤波降噪,再计算(更鲁棒)

虽然你现在的峰值检测效果不错,但噪声可能会在频率变化时干扰谷值的准确性。可以先给信号做低通滤波,滤除高频噪声后再进行峰谷检测,结果会更可靠:

先实现一个简单的巴特沃斯低通滤波器,再用滤波后的信号计算平均峰峰值:

from scipy.signal import butter, filtfilt

def butter_lowpass_filter(data, cutoff_frequency, sampling_rate, order=5):
    nyquist_freq = 0.5 * sampling_rate
    normalized_cutoff = cutoff_frequency / nyquist_freq
    # 构建低通滤波器
    b, a = butter(order, normalized_cutoff, btype='low', analog=False)
    # 双向滤波避免相位偏移
    filtered_data = filtfilt(b, a, data)
    return filtered_data

# 示例:用信号频率的1.2倍作为截止频率,滤除高于信号的噪声
filtered_data = butter_lowpass_filter(data_mV, signal_frequency * 1.2, sampling_rate)
# 用滤波后的信号计算平均峰峰值
avg_pp_voltage = calculate_avg_peak_to_peak(filtered_data, sampling_rate, signal_frequency)

针对你的问题补充一句:Scipy本身没有专门的“计算平均峰峰值”的内置函数,但它提供了find_peaks、滤波工具这些基础组件,咱们完全可以组合出可靠的计算逻辑,适配你这种含噪、变频率的信号场景。

备注:内容来源于stack exchange,提问作者Lukas Petrikas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 18:18:13