基于九轴传感器 + K-means 聚类的振动异常检测实战教程

(嵌入式 / 工业监测场景:设备振动、电机故障、结构松动、碰撞异常实时检测)

一、前言(你能学到什么)

这篇文章不讲虚的,直接带你做一个工业级轻量异常检测系统

  • LSM6DS3TR-C(6 轴)+ 磁力计 = 九轴传感器 采集振动数据
  • K-means 无监督聚类算法 做异常侦测
  • 全程不需要标签、不需要深度学习、单片机可跑
  • 原理 + 代码 + 工程思路 一次性讲透

适合:设备监测、预测性维护、物联网边缘计算、嵌入式 AI 入门。


二、系统整体原理(一句话讲清楚)

核心逻辑

  1. 正常设备振动 = 稳定、规律、特征集中
  2. 异常振动 = 剧烈、突变、偏离正常模式
  3. K-means 任务 :学习正常振动的 "特征分布",把偏离分布的数据判定为异常

为什么用 K-means?

  • 无监督:只需要正常数据,不需要异常样本
  • 超轻量:可跑在 STM32 / ESP32 上
  • 可解释性强:靠距离判断异常
  • 工业界最常用的传统异常检测算法

三、硬件与数据基础

1. 九轴传感器组成

你用的 LSM6DS3TR-C 是:

  • 加速度计 ACC(X/Y/Z)→ 振动核心数据
  • 陀螺仪 GYRO(X/Y/Z)→ 角速度 / 抖动
  • 外加磁力计 MAG(X/Y/Z)→ 9 轴

振动检测主要依赖:加速度计(ACC)

2. 振动数据是什么?

设备运行时,三轴加速度会周期性小幅波动:

  • 正常:波动小、稳定
  • 异常:波动大、突变、冲击、噪声

原始数据是时序信号 ,不能直接喂 K-means,必须提取特征


四、核心原理:为什么 K-means 能检测异常?

1. K-means 是什么

K-means 是无监督聚类算法,自动把相似数据分成 K 组。

2. 异常检测原理(关键)

  • 大量正常振动数据训练 K-means
  • 算法会把正常数据聚成几个紧凑的簇
  • 新数据进来后:
    • 计算到最近簇中心的距离
    • 距离 > 阈值 = 异常

一句话:K-means 异常检测 = 距离异常检测


五、完整工程流程(一步都不跳)

流程总览

  1. 传感器采集原始加速度数据
  2. 滑动窗口截取一段振动
  3. 提取振动特征(RMS、方差、均值等)
  4. 用正常特征训练 K-means 模型
  5. 实时推理:计算距离 → 判断异常

六、特征工程(最重要!不能直接用原始数据)

原始三轴加速度是时序波形,必须转成固定长度特征向量

最适合振动的特征(工业标准)

  1. RMS 均方根 → 振动强度
  2. STD 标准差 → 波动程度
  3. Mean 均值 → 基线偏移
  4. Max / Min → 冲击峰值
  5. 频域能量(可选)

最终特征向量(6~9 维)

plaintext

复制代码
[
    RMS_X, RMS_Y, RMS_Z,
    STD_X, STD_Y, STD_Z,
    MEAN_X, MEAN_Y, MEAN_Z
]

这就是 K-means 的输入。


七、完整 Python 代码(可直接运行)

1. 导入库

python

运行

复制代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

2. 模拟九轴传感器振动采集(真实工程可替换为 I2C 读取)

模拟:正常振动 + 异常振动(松动 / 碰撞)

python

运行

复制代码
# ======================
# 模拟传感器采集:正常数据(大量)
# ======================
np.random.seed(42)
N_NORMAL = 500
normal_acc_X = np.random.normal(loc=0, scale=0.08, size=N_NORMAL)
normal_acc_Y = np.random.normal(loc=0, scale=0.07, size=N_NORMAL)
normal_acc_Z = np.random.normal(loc=1, scale=0.09, size=N_NORMAL)

# ======================
# 模拟异常数据(少量)
# ======================
N_ABNORMAL = 50
abn_acc_X = np.random.normal(loc=0, scale=0.8, size=N_ABNORMAL)
abn_acc_Y = np.random.normal(loc=0, scale=0.7, size=N_ABNORMAL)
abn_acc_Z = np.random.normal(loc=1, scale=0.9, size=N_ABNORMAL)

3. 滑动窗口 + 特征提取

python

运行

复制代码
def extract_features(acc_x, acc_y, acc_z, window_size=32):
    """ 振动特征提取 """
    features = []
    for i in range(0, len(acc_x) - window_size, window_size):
        x = acc_x[i:i+window_size]
        y = acc_y[i:i+window_size]
        z = acc_z[i:i+window_size]

        # 振动核心特征
        rms_x = np.sqrt(np.mean(x**2))
        rms_y = np.sqrt(np.mean(y**2))
        rms_z = np.sqrt(np.mean(z**2))

        std_x = np.std(x)
        std_y = np.std(y)
        std_z = np.std(z)

        mean_x = np.mean(x)
        mean_y = np.mean(y)
        mean_z = np.mean(z)

        feat = [rms_x, rms_y, rms_z,
                std_x, std_y, std_z,
                mean_x, mean_y, mean_z]
        features.append(feat)
    return np.array(features)

# 提取正常特征
normal_feats = extract_features(normal_acc_X, normal_acc_Y, normal_acc_Z)

# 提取异常特征
abnormal_feats = extract_features(abn_acc_X, abn_acc_Y, abn_acc_Z)

4. 训练 K-means(只使用正常数据!)

python

运行

复制代码
# 标准化(非常重要)
scaler = StandardScaler()
normal_feats_scaled = scaler.fit_transform(normal_feats)

# K-means 训练
K = 3  # 正常振动一般分 2~4 类足够
kmeans = KMeans(n_clusters=K, random_state=42)
kmeans.fit(normal_feats_scaled)

5. 异常检测核心:距离计算

python

运行

复制代码
def detect_anomaly(feature, scaler, kmeans, threshold=1.2):
    feat_scaled = scaler.transform(feature.reshape(1,-1))
    dists = kmeans.transform(feat_scaled)  # 到每个簇中心的距离
    min_dist = np.min(dists)
    return min_dist, min_dist > threshold

6. 测试效果

python

运行

复制代码
print("==== 测试正常样本 ====")
test_normal = normal_feats[0]
dist, is_abnormal = detect_anomaly(test_normal, scaler, kmeans)
print(f"距离:{dist:.2f}, 异常:{is_abnormal}")

print("\n==== 测试异常样本 ====")
test_abnormal = abnormal_feats[0]
dist, is_abnormal = detect_anomaly(test_abnormal, scaler, kmeans)
print(f"距离:{dist:.2f}, 异常:{is_abnormal}")

7. 可视化(直观看到聚类效果)

python

运行

复制代码
plt.figure(figsize=(10,5))
plt.scatter(normal_feats_scaled[:,0], normal_feats_scaled[:,1], label="Normal", alpha=0.5)
plt.scatter(kmeans.cluster_centers_[:,0], kmeans.cluster_centers_[:,1], c='red', s=200, label="Cluster Center")
plt.title("K-means 聚类正常振动特征")
plt.legend()
plt.show()

八、原理深度解释(看懂就是嵌入式 AI 入门)

1. 为什么要标准化?

振动各特征量纲不同(RMS、STD、MEAN),必须归一化,否则 K-means 会失效。

2. 为什么只训练正常数据?

异常样本太少、类型不可预测。K-means 只需要学习正常分布,偏离就是异常。

3. 阈值怎么定?

  • 训练完正常数据后,取最大距离 × 1.1~1.5
  • 工业常用:1.0~2.0

4. K 值怎么选?

  • 设备振动:K=2~4 足够
  • 用肘部法则(elbow method)简单判断

九、真实嵌入式工程(STM32 / ESP32)可直接移植

你在单片机上只需要实现:

  1. I2C 读取 LSM6DS3
  2. 滑动窗口(32~128 点)
  3. 特征计算(RMS、STD、MEAN)
  4. K-means 纯 C 语言版本
  5. 距离计算 + 阈值判断

这套方案100% 可在嵌入式运行,是工业预测性维护标准入门方案。


十、总结(这篇文章的核心)

  • 九轴传感器采集振动 → 加速度计最重要
  • 时序振动 → 特征向量(必须做)
  • K-means 只学习正常数据
  • 距离 > 阈值 = 异常
  • 轻量、无监督、可嵌入式落地、工业可用

这就是传感器 + K-means 异常检测的全部原理与代码

相关推荐
小麦嵌入式32 分钟前
FPGA入门(三):3-8 译码器 仿真波形解读
stm32·单片机·嵌入式硬件·mcu·fpga开发·硬件工程
Elihuss2 小时前
关于RK3506 的MCU软复位后跑不起问题
linux·单片机·嵌入式硬件
fengfuyao9852 小时前
GRBL 1.1 移植到 STM32 (HAL库)
stm32·单片机·嵌入式硬件
biyezuopinvip2 小时前
基于STC89C51单片机的多波形信号发生器设计与Proteus仿真
单片机·proteus·课程设计·proteus仿真·基于stc89c51单片机的·多波形·信号发生器设计
项目題供诗2 小时前
STM32-定时器定时中断&定时器外部时钟(十一)
stm32·单片机·嵌入式硬件
披着假发的程序唐2 小时前
STM32 H743 MPU的配置使用方法
linux·c语言·c++·驱动开发·stm32·单片机·mcu
踏着七彩祥云的小丑2 小时前
嵌入式测试学习第 9 天:单片机、MCU、开发板、固件
单片机·嵌入式硬件
张健11564096483 小时前
MSP主堆栈指针
单片机
qxl_7999155 小时前
Windows 显卡掉线无报警|模型推理全套防呆方案(实操完整版)
windows·stm32·单片机·推理显卡掉线误报警防呆
hhb_6185 小时前
Armbian 的 root 密码“总被修改”
stm32·单片机·嵌入式硬件