基于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的频率)
咨询问题
- 为何添加塑料片后加速度数值变化不大?
- 为何FFT始终显示0.0频率?
- 我的代码存在哪些错误?
问题解答
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
相关产品推荐
相关产品推荐

