首先我的数据并没有做任何任何的处理,本来我是打算加一个直流滤波的,首先是效果不太好,其次是我都用上机器学习了我为什么还要自己处理数据?机器学习本事的目的就是节约我们的脑子,利用机器来提取特征,而不是我们自己去提取特征(直流偏置本身也是一种特征),就算我的信号有其他的误差,我们可以处理一下提高分辨度,但是!对于机器而言,这些本身就是他的特征,我们只需要告诉机器,哪些特征是对的,哪些特征是错的!# `) T( L1 X' n6 l; Z/ h* E/ W
% F' V) r% ]% v6 n3 U! V! j
训练模型方面,我们使用MAX30102每10ms采样一次,每128次采样作为一组数据上传。
: K. `2 h, o* Z9 `% o
& K/ ]0 q* s. K* K2 V5 C- int i = 0;7 Q' d1 V$ j B& Q3 J
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
# }; k1 s4 H0 F8 t* O4 t2 o9 C& Q - {3 N; F/ U- [: ~( \" N3 e
- maxim_max30102_read_fifo(&red,&ir);! e3 n9 Q, L8 ~' ^
- printf("%ld ",ir);
5 b) T8 b) U ?: L m - i++;8 ]( f2 e" M) W
- if(i==128)
2 T1 w, E5 n7 ]/ R# @; |8 ` - {3 t4 u& ~! c j% ^
- i=0;- N# k% i6 g3 R3 `/ R: _
- printf("\n");
3 [/ }0 G+ {. K- U& u/ a - }
+ i$ o5 w/ m% D3 l - }
复制代码 0 X, }( Z5 w& j1 V
这里我们不对数据进行任何处理,因为既然我们选择了机器学习就是为了节省我们对于数据的处理,节省对于特征的提取。
6 I6 |& S+ W* }, y+ z& P% Q' `( ~0 v! s: q& w
模型训练
" j% _0 K2 w. C+ @3 r8 T. N我们打开NanoEdge AI Studio,这次的项目我们选择异常检测。/ r& x2 K8 P1 o! d O
$ |" n! v' `( g$ s' z' ]/ F7 V" i
3 f+ L @* J. _* p: w
) B+ u5 r2 J9 \4 E8 i s7 X1 j7 |3 w
( M) V4 I! a0 Z3 _
! x+ }# `% g, z
传感器选择通用传感器,轴数为1,芯片型号选择自己所需要的芯片型号。0 \# f8 m8 Z( Q2 c) B
- }9 b7 K- `& b7 i
; P1 y( F2 M" b
' w" t& x0 R9 l" L$ W' [* o
Regualr signals 常规数据
, `1 O! ?6 k8 VAbnormal signals 异常数据
0 m" F3 h& @8 S" [; x5 Q+ U. k; L2 }* y6 j8 t9 g
我们通过串口(USB)分别导入正常的信号和异常的信号。0 g6 F @) e, L1 q
& C) h$ S: v: l/ A8 @, K# R
* T8 I9 V$ V/ Z; q) a% b$ [& o6 a$ p- ]3 x
# v% y# q7 Q4 C" A
, H# p5 b% ]$ ?8 j V数据集尽可能多且广泛并且经典。. d6 ?8 a8 k! x8 L5 g: j
) q, w6 j0 Y+ N& ^4 y
5 k2 z+ ^2 F w% p! e4 D
. D6 E( `! k. [# O7 F我们总共导入了两百组信号,这些信号包含了大拇指,中指以及稍微靠前的位置和稍微靠后的位置,保证数据集的范围足够的广泛。
3 k" b) g- H8 u7 c" s
$ ]; L# a+ T# I. e
% c5 |2 L% @! L$ Z E- Q
* Z: b( e, D2 E5 g- Z异常信号就非常简单,我们放在那里空置信号,晃动信号这里我放在那里测了总共三百多组(打游戏打忘记了)。
" Y. l" L% s- O- e \# c& P% w) X% D+ R, }
然后利用这两组信号进行训练。1 Q& K+ i/ j! E4 D& T
+ I/ Z& b7 ?! v$ s
9 |# o3 E0 T$ X
% m/ k5 g6 E7 C我们将异常信号和正常信号全部选上,之后进行训练。; O# X# B1 u) b Q
- x( W+ @! [0 @# y* R
: Z: j6 v$ R) S- p0 a3 U5 ]
5 Y- u+ ^9 _ \ S: \+ i- C" B9 a& s
之后查看训练详情,等待模型训练完成。
C: R! w% @( c8 |' H
+ D x2 |% Z3 P# m9 M* @, |
" O% B' m, W# o* U; C; C L' P$ j2 X$ w1 i6 U
可以看到,训练完的模型无论是准确率还是RAM大小Flash大小,都相当的合适,接下来我们测试一下我们的模型。
; R- W. N* M- Y+ S1 C1 }5 p+ o( z% o
% q3 _9 M% h: w
/ g$ Q* S- \( r8 s7 R) s" [这边可以查看训练过程中的模型。
4 Y) J. i; @ H- F& n* `8 X/ n9 `0 P! z. w6 F
8 U L8 I6 e/ P6 T0 W, E
* F. O6 r$ z' y' l0 b
验证我们的模型。9 u. Z4 Z# S8 H* f5 I
8 x4 J; J% Z6 a0 _
: b" |. v, {% {2 a( O
l& h' x% B/ o# Y这里需要注意的是,我们第一次导入数据会先进行训练,异常检测需要有一个学习环节。
# q" V7 ^7 Y1 s4 `; @+ S; @( e* |" _9 s& n2 g0 C
官方的手册中推荐了至少十组正常数据进行学习。8 f8 G: ]' ]; T
/ Q( Q% a0 K& U% ?2 q
* x3 D3 c5 X! t! b
} j A% P0 t我录了21组正常数据进行学习。5 O5 @3 B$ A1 ]3 b! @9 M, y0 X
" ?$ w: w3 Z2 |6 v; H4 F
然后就可以对模型进行验证。6 e' s5 r |: D- G) h( Y7 k$ U
d- X/ m8 f/ A9 q9 G
0 ~4 k% Q6 B0 y0 `/ e* j" Y. |
. ]* M8 J! b) r" N
$ U0 v+ j+ m' m* }
部署我们的模型,其中需要他的.a文件和.h文件。
, M" L+ J9 Z" \# l# ]
& J* o }: L! H% P& c
i5 L _4 I$ e$ ^1 [2 ?5 n' F
! Y8 W% B/ _- C- e" h2 h3 H# b3 M. S这里我们需要使用CubeIDE来编程。因为这里的.a文件是静态文件,静态文件使用keil编程有点麻烦,需要安装GCC编译器,STM32CubeIDE集成好了可以编译.a文件。
* |' C0 O1 t3 x6 g- k7 @& }, D, ]' J8 B Y4 N- H; ?9 k
9 Z3 X. E- m+ @3 Q. [) L# Q( ~4 c @* J( ?$ ~6 q: ^. r
在属性中添加静态库的路径。
; q0 Q2 y3 P) s z- D
7 x/ o! `$ V" {6 J5 [% l. p
5 N1 ?; d/ V9 `8 x- ?! a3 S
2 Q1 Y! n! n; F8 f' p) t2 N0 v
在库中添加路径,我们的.a文件是libneai.a,这里需要省略lib和后缀.a4 ]: P# M* \9 J/ K
7 d8 Q2 l: ^ f3 v! d+ J
, V& e- x* T4 N. m2 v* ?
% Q; e; J/ ^! p$ J( S* q导入NanoEdgeAI的库函数。
% ?' T! ?( e) H1 S' S! b1 Y5 t1 b' _) _. L
4 l8 ?- f- s' s9 Q5 ~1 F c! p$ |4 F
) p) z5 w; c3 c$ }& v可以看到这里有三个函数,初始化函数,学习函数以及预测函数。6 Z) w2 c( u/ V0 M3 X T
* m9 c: L9 Y( i4 p2 k, [! ]1 f+ h( ^- t
定义一个枚举变量用来存放标志位。* w; c4 @1 K6 U1 V2 a5 d* O
- MyState = neai_anomalydetection_init();//初始化
复制代码 ; e2 ?. q2 T1 m0 Y
初始化我们的模型。 u4 m) m: s/ T6 |7 G0 m3 |
- float IRD[128];. l5 h" Y6 B, s9 h' n! z5 k/ e. @
- int i = 0;
$ @2 K2 H4 C. {! C - int LeranTime= 0;9 Q; Q: ?3 w. P B( k0 S0 p
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim); w: T0 W$ y( B
- {8 b! ?2 p3 H! Z$ O; w' Z
- uint8_t yuce;3 d5 {8 _- W4 F/ n J
- maxim_max30102_read_fifo(&red,&ir);# Z* K. k" i5 C: B: j6 x
- IRD[i] = ir;
q9 H9 V# V2 E9 r, [ - i++;3 |. o0 w8 y5 U4 A
) i, m* T) `/ ~4 T$ d4 S- if(i==128)0 u0 \" @9 S: Y- L: U) j- u
- {# M0 r6 X3 k" c5 G# U# l8 G9 H: ^
- if(LeranTime<10)
' R! G* G, j c3 G+ M: \9 c3 y - {! q, p5 R' e- X! G9 s
- HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_9);//LED翻转, ` }) _! `. z& \1 n0 L
- neai_anomalydetection_learn(IRD);
5 _/ Q7 z {$ R2 \* p4 o; m - }, U: y$ `' Q& y% m# Q: i
- else
9 k3 V( h5 j. Z+ ^ - {
4 k3 N- E7 H7 t4 e; o; B; T+ R' b - neai_anomalydetection_detect(IRD, &yuce);# ^8 `. i+ h% }. E" L, _
- if(yuce>80), q6 v1 X2 A8 g. P, p: |
- {" Z( d' n5 P, U
- HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, 1);( W; V' l+ G5 K! {/ N% ]
- }; \# ~. h+ X- M2 o
- else
" d* j8 V, S3 ^" W; i: I - {
3 t, B- O. e2 V! o, {* S - HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, 0);
0 [- b# j/ y4 L - }
( P9 C! S s! [: w* | - }: W6 m" x4 s( l+ A' A/ {- ?
- LeranTime++;
1 k5 o% h' F/ w1 g( ?2 x - i = 0;; x4 w1 p3 h! X4 o% S% b; f0 n
- }
' e6 a; n7 A8 ~: ^ - }
复制代码 , g d8 I) ?9 |' W
1 Q3 |9 K# t0 L4 {/ M8 m我们在定时器回调函数中调用,上电之后前十次为学习阶段,之后对测量值进行预测,当预期值>80即认为状态正常,则灯灭。" f% ~/ M6 x- D5 ]- ^
如果预期值<80则报警灯想起。
* M3 w @! b+ k9 l, x% r {' [5 C) X( o# n+ @2 h. A+ D( P
9 a6 p0 S/ D7 B3 p7 ~- i! y4 A( L# m2 @: ]0 l
转载自:电路小白 r; F- g7 j% S. ^: V+ g
如有侵权请联系删除
5 ~+ u) R- A' K6 t! g3 b. a6 K$ f L' b8 K& z# B& z9 ^
) P$ Q( Y+ i: U2 C: ~; x/ `
5 m! n3 x: _" Y
|