首先我的数据并没有做任何任何的处理,本来我是打算加一个直流滤波的,首先是效果不太好,其次是我都用上机器学习了我为什么还要自己处理数据?机器学习本事的目的就是节约我们的脑子,利用机器来提取特征,而不是我们自己去提取特征(直流偏置本身也是一种特征),就算我的信号有其他的误差,我们可以处理一下提高分辨度,但是!对于机器而言,这些本身就是他的特征,我们只需要告诉机器,哪些特征是对的,哪些特征是错的!
/ c1 z* \- @9 ]$ `2 J) ~# n) k$ s& {# D5 L
训练模型方面,我们使用MAX30102每10ms采样一次,每128次采样作为一组数据上传。
1 a* Y+ j w1 P: t8 v
4 ], p2 o: Z8 y2 M+ d- int i = 0;+ \ h, Z1 i7 T, e. I
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim), J% [! v0 u+ a: M z0 _" @
- { Y& P2 m9 f0 d7 e J+ i: h
- maxim_max30102_read_fifo(&red,&ir);
1 l7 V/ v* p7 l; s1 a4 i% T - printf("%ld ",ir);
3 B, v9 J* O7 P( F - i++;$ Q) t7 e2 V3 N5 V* r& T
- if(i==128)- q7 k' w1 |2 w h3 n3 h, i h% T
- {
- F" Z* p2 w& \: X; r& F - i=0;% ]/ O1 e5 P8 {9 ^$ c s! B
- printf("\n");% l, p. l$ i- h8 t. r9 b, U
- }
; D; Y" {/ H. H - }
复制代码
# u+ e; x4 \5 {0 e* N这里我们不对数据进行任何处理,因为既然我们选择了机器学习就是为了节省我们对于数据的处理,节省对于特征的提取。4 T; y" e$ l: }8 L
) K) z2 Q0 j3 w+ @
模型训练# q0 |+ ~: B2 a" ]& I/ p
我们打开NanoEdge AI Studio,这次的项目我们选择异常检测。
3 e: {# i+ S" i5 H/ S0 l+ N2 `' C& w8 d& r ~% w6 q
( d0 g- L h6 f9 U. U3 l
5 I& m! U) \! h- g4 X8 H! m
7 ?9 P, u+ N7 W2 l8 ?3 r$ Z0 U5 |
1 f5 X5 B( z0 ~' ]$ w8 M5 n9 }传感器选择通用传感器,轴数为1,芯片型号选择自己所需要的芯片型号。
2 S, T, V9 ^" F& ^' y8 ^/ |" l6 k! `: m9 D7 |9 G" a! Q
# r9 s3 P" O" L9 f
% ^# f; K) S- ?9 q- gRegualr signals 常规数据
6 Z8 w4 q4 O0 h7 q* ?) uAbnormal signals 异常数据
9 @( b- Z$ p1 O7 Q0 u" `
/ ^' ]- I; m! z/ D0 y* {, [我们通过串口(USB)分别导入正常的信号和异常的信号。
* j u% @) Y1 r& _" W4 f1 K- O+ q
0 ?+ x9 x! c. S9 e4 c C* y# U& P: W
' E# | L. n, m& X/ D* K
/ m+ m i% T& N# ] G1 y
8 J! Y( m& C3 s# g6 r3 W
0 b( ]7 ]" v+ J% S: y3 h
数据集尽可能多且广泛并且经典。
3 p0 Z v% g& |" `
4 v: l4 r; R' k$ b7 l1 K- E' O u
0 _* M$ s( a7 U$ f
; K/ ^ Z) E# ~8 T
我们总共导入了两百组信号,这些信号包含了大拇指,中指以及稍微靠前的位置和稍微靠后的位置,保证数据集的范围足够的广泛。: n5 i( w7 k6 v( {3 r
1 I5 A, d2 L9 h0 V
% m) g. ?! X" h) z0 |; D2 k. ^: _
: C5 K% G7 c' G2 W7 e5 U" N
异常信号就非常简单,我们放在那里空置信号,晃动信号这里我放在那里测了总共三百多组(打游戏打忘记了)。
4 N) V) o$ c0 ]& o |; q% T6 F9 [* f$ t* Z& \+ t5 ?7 z
然后利用这两组信号进行训练。, n& O, F2 ~6 R- B' d! E
, X' i6 H! G* c$ a4 a% r
- f$ ]. K, ~( N3 o& ~: k7 M! Y
# D$ o# f; y8 r$ N* @4 P9 G
我们将异常信号和正常信号全部选上,之后进行训练。
4 F+ M: |; q$ Q. W
: Y# C" p6 u9 C
9 @$ L- A6 E; T7 h3 n
; v7 i0 G, p: E/ z" U之后查看训练详情,等待模型训练完成。' B( S) D$ G) a
) g d# ~' D5 v& I
* P; l. t5 g. j9 Q: U8 B! v
) D I! I6 n* l) H {- c; a
可以看到,训练完的模型无论是准确率还是RAM大小Flash大小,都相当的合适,接下来我们测试一下我们的模型。
8 }& z" x1 G: |/ i$ B; j% i
8 V: N/ c8 R6 X3 L1 w( l& ?) s: ~
" v) S, x2 |6 o9 z: Q3 ~
! t. P5 Z3 r8 D4 b. `; } g这边可以查看训练过程中的模型。: w1 [( d. N; _- n+ F: r* r
$ ^, O F4 L/ Z1 k. n$ Y2 Z4 r
$ r" q: x1 e* F
0 _( m+ J3 p9 e
验证我们的模型。
3 O9 ]# Y% m9 O+ s. w; n
" C* \3 u" @( |: B
! X2 b* U3 M( C. ^
# V, G: n( }8 v. Q! I. k9 G
这里需要注意的是,我们第一次导入数据会先进行训练,异常检测需要有一个学习环节。: [; D0 d. Q, A# l4 y
0 ? B& b: l/ f W7 O
官方的手册中推荐了至少十组正常数据进行学习。- O( W* B/ Y$ V8 A2 ?4 \* j; t
* I# J3 q. q- m6 T) W6 T' L' f, H
9 s7 I7 h$ }# G% H; Z$ P
- J# r" F2 [" x$ e' f1 Z
我录了21组正常数据进行学习。
1 K' u) R& `2 O. z' v, n! n/ z, x6 f, d3 S' g+ G- R
然后就可以对模型进行验证。$ V& ~* s6 D5 ^/ o+ L% y) X0 v
7 E9 G! @; i& ]2 F3 D9 D
' c3 E( N$ U. w: l% r$ K2 W
; u+ C( Y; _% }2 s+ i
; D) ]% ~, z$ ~$ }: c2 ^9 I+ k6 W部署我们的模型,其中需要他的.a文件和.h文件。
# n) e7 W& d; `3 P: s' R! \ n8 k+ H/ g
, p: a2 a6 E1 ]. \3 S5 x1 K6 W6 G7 V9 n' G* g) I
这里我们需要使用CubeIDE来编程。因为这里的.a文件是静态文件,静态文件使用keil编程有点麻烦,需要安装GCC编译器,STM32CubeIDE集成好了可以编译.a文件。$ m1 m; x# x H3 Y
, S" }7 T" V/ \ z
) j b7 g! I1 _2 v" L
6 ^2 C8 i6 K; Z2 b. l$ {在属性中添加静态库的路径。
# O3 q' d) C0 A {) A4 Y. O& Z. H- p: V
5 T) A) {5 F3 E9 R* G
9 r* L# d$ ]! P: }- i
在库中添加路径,我们的.a文件是libneai.a,这里需要省略lib和后缀.a r+ R: |6 F7 I# s+ d& L: K$ P
+ o0 j5 H3 V# R. q/ |4 x' w, Z4 a) V
7 \# i0 A2 H0 g6 w; ^
2 v3 W' T6 H W3 X) k* u/ l/ ~
导入NanoEdgeAI的库函数。& W! D% a: p. f) h4 Q
3 E, `- [0 W) \& z! y6 { {7 [! N
( R& D7 _* m0 g/ d# }5 {
, O# U* C, d8 y( a% E7 G
可以看到这里有三个函数,初始化函数,学习函数以及预测函数。 e" D! Z) d! ^: \& M
2 v/ J+ j* J% L: e4 c
* F1 A8 e$ z) K' Z( O% g$ I6 A定义一个枚举变量用来存放标志位。
2 y5 |5 h9 H$ G- @) _9 v1 Z- MyState = neai_anomalydetection_init();//初始化
复制代码
% v3 K* a$ l5 }& i H3 g初始化我们的模型。! g9 {4 `& A% \
- float IRD[128];
$ |& F# J9 k' t v) W Q" F - int i = 0; s* m( s) g9 P5 C" @ u# j+ e9 o
- int LeranTime= 0;( Z9 f7 ^0 ~3 o
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
: ^ Q% ~+ Z! r# x% K7 g - {) j6 Y6 e6 _8 ?4 ~7 W4 i; |
- uint8_t yuce;* E7 F+ X7 |. _, T- k$ l1 m
- maxim_max30102_read_fifo(&red,&ir);8 i p: E7 a+ }6 L' {1 Z
- IRD[i] = ir;
+ v/ |. d6 D6 u/ g! x - i++;
5 z4 J+ |/ N( a9 ^7 p
" N2 h% o9 H; U2 J- if(i==128)
( f9 ^2 d% h0 V+ U: E2 f2 F: _; x - {
8 q3 d* p5 T5 W7 y! v% h3 D - if(LeranTime<10)
7 b+ y+ Z5 ?9 Q2 e5 G - {7 T- P I- e+ t9 A |; r
- HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_9);//LED翻转
, x2 n6 x/ A2 J. t5 v( A# s; ~ - neai_anomalydetection_learn(IRD);1 X+ I# C, f9 x/ [: f* h7 p: |
- }
1 L% u/ _7 D9 s; E+ J2 U - else* O1 X. s: f [ H* { a7 c+ @7 [
- {5 F5 c! O- }* }6 F' K5 B" V
- neai_anomalydetection_detect(IRD, &yuce);
. i8 F/ n& p5 F2 _ - if(yuce>80)
" H, C9 |( y e$ Q - {
8 X9 j' W) h; t$ P3 v" c - HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, 1);# R5 \3 q- o5 a- T* H, \9 E: {/ S
- }( I8 o- K: I$ O/ U
- else
6 z7 z8 f8 c |$ }! d) D9 e3 b - {3 K4 h$ u( K3 U" }
- HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, 0);& \* w2 p! ~: J" _0 F6 z6 i2 \0 I- w5 B
- }
/ s7 b, h+ k: H - }: W$ U6 w: M0 ~
- LeranTime++;$ N2 D/ Q: _- u% x( ~- r
- i = 0;
# j2 d: C1 m* m7 \0 D& z* X - }
1 C$ I& A- _& H m) n& Y3 x* C6 b - }
复制代码 + i# ?/ L* k( g# _. g
1 ]. d8 y6 X; m我们在定时器回调函数中调用,上电之后前十次为学习阶段,之后对测量值进行预测,当预期值>80即认为状态正常,则灯灭。
, _$ s+ x8 j) _如果预期值<80则报警灯想起。( M0 D. \# o6 J1 E3 G+ Q; T
( x( \3 K5 F, `( h$ R- @7 r* @8 l5 U. X! f2 e
* j. r# }3 B M0 C6 n3 l4 M
转载自:电路小白/ [- m+ [ n5 E
如有侵权请联系删除4 k. s' r2 n& E- ]
7 L0 v9 F5 w4 H- l8 l$ u3 t
+ ^" R& _" h. }; ]( b) I! z9 B! U$ {6 L& i. Z9 f) H
|