▼點(diǎn)擊下方名片,關(guān)注公眾號,獲取更多精彩內(nèi)容▼
大家好,我是賀老師,嵌入式 AI工程師,《嵌入式AI:讓單片機(jī)學(xué)會思考》課程主理人,專注AI在MCU上的落地實(shí)踐。
攝像頭識別很吸引人,但不適合作為新手入門。新手還沒搞懂模型輸入是什么,就會被攝像頭初始化、幀緩存、顏色格式、LCD 顯示、外部 RAM 拖走。最后看起來是在學(xué) TinyML,實(shí)際是在修硬件接口。
電機(jī)振動異常檢測更干凈。輸入是三軸加速度,數(shù)據(jù)量小;異常現(xiàn)象可以人為制造;特征可以打印出來;模型可以很小;部署到 STM32 后,也能用串口把每一步結(jié)果查清楚。
本文中賀老師給大家提供一個(gè)“通過部署AI模型實(shí)現(xiàn)電機(jī)震動異常檢測的簡化版步驟”。其中含有了:
可落地的硬件和參數(shù)
如何做特征提取?
如何穩(wěn)定采樣?
應(yīng)該驗(yàn)證哪些參數(shù)?
入門學(xué)習(xí)可以不用一開始就追求工業(yè)級。可以先把鏈路跑通,再談傳感器帶寬和安裝結(jié)構(gòu)。
開發(fā)板:STM32F401、STM32F411、STM32G4、STM32U5 都可以做入門版本。只要能穩(wěn)定采樣、能跑一個(gè)小模型、串口日志夠用,就能講清楚核心問題。
傳感器:課堂演示可以用 MPU6050、ADXL345、LIS3DH、LSM6DSOX。真正做工業(yè)振動,要看帶寬和噪聲密度,ST 的 IIS3DWB 這類寬帶振動傳感器更合適。
電機(jī):5V 或 12V 小直流電機(jī)即可。正常狀態(tài)采一組;螺絲輕微松動采一組;軸上貼一點(diǎn)偏心膠帶采一組;用紙片輕觸外殼制造摩擦再采一組。不要一開始就搞復(fù)雜故障,先讓數(shù)據(jù)差異可見。
推薦起步參數(shù):采樣率 800 Hz 或 1000 Hz,窗口長度 512 點(diǎn),步長 256 點(diǎn),三軸同時(shí)采樣。這樣每個(gè)窗口約半秒,延遲可接受,頻域分辨率也夠做入門演示。
振動項(xiàng)目第一版,先做特征工程。不是因?yàn)樯窠?jīng)網(wǎng)絡(luò)不重要,而是因?yàn)樘卣髂茏寣W(xué)生看懂“模型到底吃了什么”。如果第一步就把 512 × 3 的原始數(shù)據(jù)塞進(jìn) 1D CNN,效果可能也能出來,但實(shí)際學(xué)習(xí)到的東西也不多。
一個(gè)窗口里至少算這些特征:每個(gè)軸的均值、標(biāo)準(zhǔn)差、RMS、峰峰值、最大值、最小值;再加上合加速度模長的 RMS、峰值因子、主要頻段能量。最后得到二十多個(gè)特征,一個(gè)小 MLP 或異常檢測模型就夠用了。
單窗口特征建議:
x_mean, y_mean, z_mean
x_std, y_std, z_std
x_rms, y_rms, z_rms
x_p2p, y_p2p, z_p2p
mag_rms = rms(sqrt(x*x + y*y + z*z))
crest_factor = peak(abs(mag)) / rms(mag)
band_energy_1, band_energy_2, band_energy_3數(shù)據(jù)少的時(shí)候,先做異常檢測。正常數(shù)據(jù)很容易收集,故障數(shù)據(jù)很難收集,這是工業(yè)現(xiàn)場的常態(tài)。先讓模型學(xué)會“什么是正常振動”,再用異常分?jǐn)?shù)判斷偏離程度,比硬湊三四類故障更靠譜。
如果必須做分類,建議先只做三類:正常、松動、摩擦。每類至少采 3 到 5 分鐘,按時(shí)間段切分訓(xùn)練集和測試集,不要把連續(xù)窗口隨機(jī)打散。連續(xù)窗口太像了,隨機(jī)切分會讓準(zhǔn)確率虛高。
這個(gè)項(xiàng)目成敗,第一看采樣。模型再好,輸入窗口如果時(shí)間間隔亂、樣本丟失、DMA 覆蓋未處理數(shù)據(jù),結(jié)果都會飄。
建議用定時(shí)器驅(qū)動采樣。低速演示可以 I2C,高一點(diǎn)的采樣率盡量用 SPI。采樣數(shù)據(jù)放進(jìn)環(huán)形緩沖區(qū),湊夠一個(gè)窗口再計(jì)算特征。不要在中斷里做模型推理,中斷里只做標(biāo)記或搬運(yùn)數(shù)據(jù)。
#define FS_HZ 1000
#define WIN_SIZE 512
#define HOP_SIZE 256
static float ax[WIN_SIZE];
static float ay[WIN_SIZE];
static float az[WIN_SIZE];
static volatile uint16_t wr = 0;
static volatile uint8_t window_ready = 0;
void imu_sample_tick(void)
{
read_accel_g(&ax[wr], &ay[wr], &az[wr]);
wr++;
if (wr >= WIN_SIZE) {
wr = WIN_SIZE - HOP_SIZE;
memmove(ax, &ax[HOP_SIZE], wr * sizeof(float));
memmove(ay, &ay[HOP_SIZE], wr * sizeof(float));
memmove(az, &az[HOP_SIZE], wr * sizeof(float));
window_ready = 1;
}
}
void main_loop(void)
{
if (window_ready) {
window_ready = 0;
make_features(ax, ay, az, features);
run_model(features, &score);
update_alarm_state(score);
}
}上面的代碼只表達(dá)結(jié)構(gòu),產(chǎn)品里不要在采樣函數(shù)里直接 memmove 大數(shù)組。更好的做法是雙緩沖或環(huán)形緩沖。課堂第一版可以先這樣講清楚窗口和步長,第二版再優(yōu)化成 DMA + double buffer。
板上驗(yàn)證至少打印四類信息:窗口編號、特征摘要、異常分?jǐn)?shù)、連續(xù)觸發(fā)次數(shù)。只打印“normal”或“fault”意義不大,因?yàn)槟悴恢厘e(cuò)在傳感器、特征、模型還是閾值。
推薦串口日志:
[WIN 128] rms=0.182 p2p=0.734 crest=3.21 e1=0.44 e2=0.18 e3=0.05
[MODEL] anomaly_score=0.71 threshold=0.65
[STATE] hit=2/3 alarm=0
[WIN 129] rms=0.196 p2p=0.801 crest=3.48 e1=0.51 e2=0.21 e3=0.07
[MODEL] anomaly_score=0.76 threshold=0.65
[STATE] hit=3/3 alarm=1報(bào)警不要單窗口觸發(fā)。需要在檢測到連續(xù) 3 個(gè)窗口都超過閾值時(shí)再報(bào)警,低于閾值連續(xù) 3 個(gè)窗口再恢復(fù)。
最后一定要做“同一條數(shù)據(jù)對齊”:
(1)把 STM32 采到的原始窗口導(dǎo)出到 Python,算一遍特征和模型輸出;
(2)再把 STM32 端算出的特征打印出來。當(dāng)兩邊特征差異很大時(shí),先修采樣和預(yù)處理,不需要急著換模型。
本文參考資料的鏈接
ST:Condition Monitoring and Predictive Maintenance
ST:Condition monitoring solution
ST:STM32 Edge AI tools
Edge Impulse:Brushless DC Motor Anomaly Detection



