(嵌入式 / 工业监测场景:设备振动、电机故障、结构松动、碰撞异常实时检测)
一、前言(你能学到什么)
这篇文章不讲虚的,直接带你做一个工业级轻量异常检测系统:
- 用 LSM6DS3TR-C(6 轴)+ 磁力计 = 九轴传感器 采集振动数据
- 用 K-means 无监督聚类算法 做异常侦测
- 全程不需要标签、不需要深度学习、单片机可跑
- 原理 + 代码 + 工程思路 一次性讲透
适合:设备监测、预测性维护、物联网边缘计算、嵌入式 AI 入门。
二、系统整体原理(一句话讲清楚)
核心逻辑
- 正常设备振动 = 稳定、规律、特征集中
- 异常振动 = 剧烈、突变、偏离正常模式
- 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 异常检测 = 距离异常检测
五、完整工程流程(一步都不跳)
流程总览
- 传感器采集原始加速度数据
- 滑动窗口截取一段振动
- 提取振动特征(RMS、方差、均值等)
- 用正常特征训练 K-means 模型
- 实时推理:计算距离 → 判断异常
六、特征工程(最重要!不能直接用原始数据)
原始三轴加速度是时序波形,必须转成固定长度特征向量。
最适合振动的特征(工业标准)
- RMS 均方根 → 振动强度
- STD 标准差 → 波动程度
- Mean 均值 → 基线偏移
- Max / Min → 冲击峰值
- 频域能量(可选)
最终特征向量(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)可直接移植
你在单片机上只需要实现:
- I2C 读取 LSM6DS3
- 滑动窗口(32~128 点)
- 特征计算(RMS、STD、MEAN)
- K-means 纯 C 语言版本
- 距离计算 + 阈值判断
这套方案100% 可在嵌入式运行,是工业预测性维护标准入门方案。
十、总结(这篇文章的核心)
- 九轴传感器采集振动 → 加速度计最重要
- 时序振动 → 特征向量(必须做)
- K-means 只学习正常数据
- 距离 > 阈值 = 异常
- 轻量、无监督、可嵌入式落地、工业可用
这就是传感器 + K-means 异常检测的全部原理与代码