基于九轴传感器 + 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 异常检测的全部原理与代码

相关推荐
FreakStudio2 天前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
✎ ﹏梦醒͜ღ҉繁华落℘7 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
zd8451015007 天前
RS485 总线详解
单片机·嵌入式硬件
✎ ﹏梦醒͜ღ҉繁华落℘7 天前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展7 天前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件
集芯微电科技有限公司7 天前
四通道2A输出集成功率电感降压模块专为紧凑型方案设计
人工智能·单片机·嵌入式硬件·生成对抗网络·计算机外设
踏着七彩祥云的小丑7 天前
嵌入式测试学习第 37 天:异常场景测试:断电、拔插、干扰、非法指令
单片机·嵌入式硬件·学习
意法半导体STM327 天前
【官方原创】如何为STM32CubeMX2配置Visual Studio Code配置方案
vscode·stm32·单片机·嵌入式硬件·策略模式·stm32cubemx·嵌入式开发
雾削木7 天前
B语言经典教程现代化重构
java·前端·stm32·单片机·嵌入式硬件
Hello-FPGA7 天前
Camera Link 与 CoaXPress 技术对比 如何选择你的相机接口
单片机·嵌入式硬件