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

基于Raspberry PI 5与ISM330DHCX的电机振动FFT检测问题咨询

电机异常振动检测问题

设备与当前实现

使用的设备:

  • Raspberry PI 5
  • Adafruit加速度计ISM330DHCX

已完成的工作:

  • 以2000Hz采样率读取传感器数据,计算加速度绝对值(但数值变化不明显)
  • 使用numpy.fft计算FFT并保存结果到CSV

传感器读取代码

def read_sensor():
    global data
    target_duration = 1 / SAMPLE_RATE

    # Connect to sensor
    ...

    while True:
        loop_start_time = time.perf_counter()

        x, y, z = accelerometer.acceleration
        acceleration = np.sqrt(x**2 + y**2 + z**2)
        data = np.roll(data, -1)
        data[-1] = acceleration

        # Try to get exactly SAMPLE_RATE per second
        loop_duration = time.perf_counter() - loop_start_time
        sleep_time = max(0, target_duration - loop_duration)
        end_time = time.perf_counter() + sleep_time
        while time.perf_counter() < end_time: pass

FFT计算代码

n = len(data)
fft = abs(np.fft.fft(data * np.blackman(n)))[:n//2]
amplitudes = np.abs(fft) / n

# Identify max frequencies
max_amplitude = np.max(amplitudes)
max_index = np.argmax(amplitudes)
frequencies = np.fft.fftfreq(n, d=1/n)[:n//2]

# Generate summary
result = {
    'mean': round(data.mean(), 4),
    'std': round(data.std(), 4),
    'max': round(data.max(), 4),
    'min': round(data.min(), 4),
    'range': round(data.max() - data.min(), 4),
    'fft_mean': round(np.mean(fft), 4),
    'fft_std': round(np.std(fft), 4),
    'max_freq': round(frequencies[max_index], 4),
    'max_amp': round(max_amplitude, 4),
    'speed': duty_cycle
}

CSV数据示例

mean,std,max,min,range,fft_mean,fft_std,max_freq,max_amp,speed
9.9587,0.1261,10.599,9.5467,1.0523,15.6502,308.3268,0.0,4.1798,47
9.9609,0.1287,10.599,9.5467,1.0523,16.2121,308.5345,0.0,4.1826,47

测试场景:电机安装螺旋桨,用软塑料敲击螺旋桨,了解奈奎斯特采样定理(仅能检测低于SAMPLE_RATE/2 Hz的频率)

咨询问题

  1. 为何添加塑料片后加速度数值变化不大?
  2. 为何FFT始终显示0.0频率?
  3. 我的代码存在哪些错误?

问题解答

1. 加速度数值变化不大的原因

  • 静态分量掩盖振动信号:你计算的合加速度里包含了约9.8m/s²的重力加速度,而电机振动产生的动态加速度幅度远小于重力,导致振动信号被静态分量完全淹没,看起来数值波动很小。
  • 传感器安装或量程问题:如果传感器没牢牢固定在电机振动最剧烈的位置(比如电机壳体而非支架),或者传感器量程设置过大,小幅度振动会被稀释,难以观察到明显变化。
  • 敲击的振动特性:软塑料敲击产生的振动要么幅度低,要么是高频信号,叠加在静态重力分量上后,整体数值变化自然不显著。

2. FFT始终显示0.0频率的原因

0Hz对应的是信号的直流分量(也就是合加速度的平均值,接近重力加速度),这个分量的幅度远大于振动产生的交流分量,所以FFT结果里0Hz的振幅是最大的,自然会被检测为峰值。核心原因是你没在FFT前去除直流分量,导致静态信号占据了FFT的主要能量。

3. 代码中的错误与改进点

传感器读取部分

  • 合加速度的局限性:直接计算合加速度会保留重力的静态分量,应该先对每个轴的加速度做校准(减去静态偏移),再计算动态振动的幅值;或者单独分析各个轴的振动(振动往往在某个轴上更明显)。
  • 采样精度不足:用time.perf_counter()加空循环的方式控制采样率,精度受系统调度影响很大,不如直接用传感器内置的FIFO或中断功能实现精准采样,避免采样时间不均匀导致的频率失真。

FFT计算部分

  • 未去除直流分量:FFT前必须减去信号的平均值,消除直流分量才能凸显振动的交流信号:
    data_dc_removed = data - data.mean()
    fft = abs(np.fft.fft(data_dc_removed * np.blackman(n)))[:n//2]
    
  • 频率计算参数错误:np.fft.fftfreq(n, d=1/n)里的d是采样间隔,应该设为1/SAMPLE_RATE,正确的频率计算应该是:
    frequencies = np.fft.fftfreq(n, d=1/SAMPLE_RATE)[:n//2]
    
    你当前的设置会导致频率轴被错误缩放,后续的频率值全部不准确。
  • 振幅归一化错误:amplitudes = np.abs(fft) / n的归一化方式不对,对于单边频谱(取前n//2),应该除以n/2才能得到正确振幅(直流分量单独处理):
    amplitudes = np.abs(fft) / (n / 2)
    amplitudes[0] = np.abs(fft)[0] / n  # 直流分量单独归一化
    

内容的提问来源于stack exchange,提问作者Manitoba

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 14:40:09