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

相关推荐
BUG_yechiyu2 小时前
STM32CubeMX使用9 配置Time4 PWM(DMA)输出
stm32·单片机·嵌入式硬件
学嵌入式的小杨同学2 小时前
STM32 进阶封神之路(三十五):TFT LCD 工程化实战 ——FSMC 高速驱动、多图层界面、中英文显示与图形引擎(完整可落地)
stm32·单片机·嵌入式硬件·mcu·硬件架构·硬件工程·智能硬件
网易独家音乐人Mike Zhou2 小时前
【Python】TXT、BIN文件的十六进制相互转换小程序
python·单片机·mcu·小程序·嵌入式·ti毫米波雷达
凌盛羽3 小时前
ESP32-S3定时器组Timer Group0/1的使用
stm32·单片机·嵌入式硬件·链表·esp32·定时器
我不是程序猿儿3 小时前
【嵌入式】第2讲:USB CDC 从“插上电脑”到“出现 COM 口”,枚举过程到底发生了什么
服务器·stm32·单片机·嵌入式硬件·电脑·负载均衡
学嵌入式的小杨同学11 小时前
STM32 进阶封神之路(三十三):W25Q64 任意长度写入深度实战 —— 从页限制到工业级通用读写(附完整代码 + 避坑指南)
stm32·单片机·嵌入式硬件·架构·硬件架构·嵌入式·flash
Hello_Embed13 小时前
嵌入式上位机开发入门(三):TCP 编程 —— Server 端实现
笔记·单片机·网络协议·tcp/ip·嵌入式
Hello World . .15 小时前
ARM裸机学习6——UART
arm开发·单片机·嵌入式硬件
Zarek枫煜16 小时前
[特殊字符] C3语言:传承C之高效,突破C之局限
c语言·开发语言·c++·单片机·嵌入式硬件·物联网·算法