首先我的数据并没有做任何任何的处理,本来我是打算加一个直流滤波的,首先是效果不太好,其次是我都用上机器学习了我为什么还要自己处理数据?机器学习本事的目的就是节约我们的脑子,利用机器来提取特征,而不是我们自己去提取特征(直流偏置本身也是一种特征),就算我的信号有其他的误差,我们可以处理一下提高分辨度,但是!对于机器而言,这些本身就是他的特征,我们只需要告诉机器,哪些特征是对的,哪些特征是错的!3 W0 Q, M) n9 V. }8 A% A
( b0 W! p& k2 C0 S
训练模型方面,我们使用MAX30102每10ms采样一次,每128次采样作为一组数据上传。
% f# \6 H D, p
$ Q: S6 L- S' r( p( s5 B- int i = 0;* D/ X' y% I4 `& S/ Z& [# `) q" O
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
3 w+ z' v6 ^* Q2 C3 J( z - {, b5 g2 c: Y! y" w( ~( q- D
- maxim_max30102_read_fifo(&red,&ir);
7 \" O& F- }. P$ T7 p' C+ p - printf("%ld ",ir);5 e7 A6 t/ Y- P! |2 }8 P2 E8 n
- i++;
7 u7 z5 S3 }/ ?% U9 w K" j6 ] - if(i==128)
4 r& _2 u' K9 B" I3 p. i - {
* @4 I; W& C1 O" |& N1 q - i=0;3 q4 k$ L% P. h5 `& P
- printf("\n");( e' N, C- ^9 e6 r$ ?& o; a
- }
1 p% P2 R9 l: I& @: f0 ] H& o* D - }
复制代码 0 ^! R5 l& d8 n" N+ v4 b
这里我们不对数据进行任何处理,因为既然我们选择了机器学习就是为了节省我们对于数据的处理,节省对于特征的提取。
& |5 C. p: M) f0 m0 u
/ x& n7 U' F( T+ Q$ c i4 D7 E模型训练
2 n! Z3 c; L3 y! k我们打开NanoEdge AI Studio,这次的项目我们选择异常检测。
1 b; E1 G: _* W8 E* v
! p: e/ z) I6 b! m0 A) }
# `; l! q- c m3 p Z0 R& n+ S+ [ z7 \ j
: m" e- C% b7 Z# `# L+ q! w
: W3 j6 c% R5 O, g% }
传感器选择通用传感器,轴数为1,芯片型号选择自己所需要的芯片型号。
# ]+ p- Q# s6 R6 M0 b% v# X% r5 _* L0 n
8 U6 f3 ^, D6 d3 G3 _( \4 }
/ z& u- D3 [: O0 U
Regualr signals 常规数据& x; r3 N! Y. G" M7 ]
Abnormal signals 异常数据
1 u' F& Z' T5 k6 e7 o; o( M) i3 E i- B* \2 d! a4 |5 j
我们通过串口(USB)分别导入正常的信号和异常的信号。9 O& S; S; f. h
) j2 t+ ?' C$ \+ ~5 R
1 S, t5 D3 a9 j/ D k& T1 _
; R3 x7 H6 z: m
3 M5 K" g3 O, @5 q* [
0 J4 _7 t2 o' \* \8 \9 h
数据集尽可能多且广泛并且经典。
9 S& [: A# v( G8 R( d
5 ~& H5 w {$ P' c
9 a( _7 a' Y4 I, M+ k) n! b8 u/ \5 X
我们总共导入了两百组信号,这些信号包含了大拇指,中指以及稍微靠前的位置和稍微靠后的位置,保证数据集的范围足够的广泛。
# _, H# \3 T/ M) W" _4 W0 [# }) V
4 N6 T6 u/ f' N1 W. M# ~
& `, U7 Z4 @ }1 d$ r( Z7 U) ^( q" ?
异常信号就非常简单,我们放在那里空置信号,晃动信号这里我放在那里测了总共三百多组(打游戏打忘记了)。, A. {9 V: C0 N% T4 v% o% {5 f0 p
$ g) J! \* R6 j8 }2 Z! U
然后利用这两组信号进行训练。* k: V, `4 h" D3 ?4 V2 C7 k
) y) p8 W2 Q, {, S) m
5 i+ S, ?! T, ]$ a% q+ Y. q
" O/ J' Z+ p% h7 g
我们将异常信号和正常信号全部选上,之后进行训练。" g4 ~. q0 [( Y( [
1 E' D* R% S5 T, ^2 y4 E
- B, o3 X: H$ A" g- l
6 }+ W A' O# r# T+ U* s4 Y; O" N之后查看训练详情,等待模型训练完成。
& X* F* M$ D: J3 f4 o+ \5 D. f: Y1 z+ P5 D# o* V
) a- R- r* O! O i$ i
4 G" y: N: p1 T! Z5 M可以看到,训练完的模型无论是准确率还是RAM大小Flash大小,都相当的合适,接下来我们测试一下我们的模型。
2 E* G3 T$ @5 O' V# X2 R" Q7 J2 f! ]
5 J# h4 ^& w {: p- P
F4 l8 ]) X/ y- o! C$ g
这边可以查看训练过程中的模型。0 E# |* ]0 x0 F; L
) i& o: f" O4 W9 Y
. Q; x5 O. r1 S% P+ t( @! o2 s! X" S3 k% N
验证我们的模型。
, U+ e/ t0 E2 l9 N; t* |5 G) w2 P. m' u9 J; h, y h2 Y: \
+ A6 o% j+ e' m" A& ^: o
) n# m2 m9 e) Y! U$ i) n! V这里需要注意的是,我们第一次导入数据会先进行训练,异常检测需要有一个学习环节。
7 y! N- L7 C- v1 b3 T
6 ?4 d6 |/ u3 \$ G' `/ f/ S% q官方的手册中推荐了至少十组正常数据进行学习。' g, I6 J q! K6 j! W" ^
6 I x: }3 b1 W+ h, g. v
: C9 F- M% r O8 R" ]# j0 x8 P# `
: [2 p' \8 j' _. L. Q! R, s我录了21组正常数据进行学习。* M- I% x1 a6 p6 E8 z
+ ^; B' W2 r* j# w! o# u然后就可以对模型进行验证。
. ~5 N, ^/ N' x6 A0 W/ S- m5 s6 q' Q' J' ^* v& `" @
4 s4 `2 U: p5 r- j9 e5 k: \
& ?6 \- a& Y9 P! X# N7 `
' d. O4 y0 u, @4 l部署我们的模型,其中需要他的.a文件和.h文件。8 D, p, K0 m5 ?) l. t
8 a6 V3 Y5 M; ^/ i( J
; {$ D! L& o! T# X' M/ F2 C2 A; B3 A/ a
这里我们需要使用CubeIDE来编程。因为这里的.a文件是静态文件,静态文件使用keil编程有点麻烦,需要安装GCC编译器,STM32CubeIDE集成好了可以编译.a文件。2 f9 \$ v! x/ }" s+ w) U3 N
1 _/ O" G' _& V w. _! T
/ C) Z& _# @! i
' V% o) z8 L$ m在属性中添加静态库的路径。
4 X) p* o9 C$ f' v, c! S$ N" b
9 j9 G3 r$ l$ _
0 H! y5 ~' v% B! Y# v4 @; t& [ l) @
% { t1 J% N+ r7 x: S7 }2 d, `! K在库中添加路径,我们的.a文件是libneai.a,这里需要省略lib和后缀.a! N3 Y' `7 C2 Y% f$ U
" a( f5 T' y& i# l: q3 e# P
, O/ z/ c8 _9 R8 u, s9 W
3 @+ s! m' ^5 U" F$ C4 N+ b/ ]" R" J/ @
导入NanoEdgeAI的库函数。* F9 G; ]6 D# z' Y
9 u1 U' U! }7 x+ N3 j* E
5 y, E$ M9 {5 q8 q1 }5 }2 W' L
5 G. V; g3 }9 q+ i( r& g1 R4 W可以看到这里有三个函数,初始化函数,学习函数以及预测函数。
1 _# I' U* k, u# o$ Q5 l% g; J6 X/ C: ^; W
$ P0 e, W. s- a B% I# n; a
定义一个枚举变量用来存放标志位。
) a3 ?+ c! K. }! |( n' E+ f$ h- MyState = neai_anomalydetection_init();//初始化
复制代码 % c6 N( T1 |4 c) \
初始化我们的模型。
- T7 g: D6 i \1 E! ?- float IRD[128];
+ e" }& }" ~: `& V$ t# t3 ~ - int i = 0;" p+ s: o0 Y$ g$ t U
- int LeranTime= 0;
: v0 t; N% G! S - void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)% C) V0 N- w' }& i2 T2 {5 x
- {
# b0 m2 |5 V- x - uint8_t yuce;. d$ W- z. A! g* C
- maxim_max30102_read_fifo(&red,&ir);
" n7 m0 |- `. Z0 e - IRD[i] = ir;: D. o3 ?: y& |3 c: h* ~0 W8 g
- i++;, @2 e. `+ }2 l% W G' d
- 1 u% `+ t* @) r! T0 z! f
- if(i==128)
: {' |5 z Z* C/ B) G$ e% L( c - {4 s' r& M: Y! l3 [3 k, K+ p7 K
- if(LeranTime<10)! b" V6 j, i$ b! w
- {* f0 r7 y& C% h. E: ?6 j) \
- HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_9);//LED翻转
7 E6 i% D9 _- D. w0 R, c0 Y - neai_anomalydetection_learn(IRD);
" h5 @3 d; l7 D - }
2 f+ I" }# f* g4 j# O& f - else+ z# o6 C2 w2 z
- {: R4 ]- @8 `$ O+ F
- neai_anomalydetection_detect(IRD, &yuce);
; j2 q3 J+ B3 m* r9 ? - if(yuce>80)
; G0 k- O3 V6 N) t+ q+ V! B( e - {- c. `6 f( C. k+ v- ~
- HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, 1);
! K" F9 ^& U: `6 Y1 t - }
: v. N% I% R; k8 Q6 b - else, ?) @) I: [1 G' z& Y
- {
7 f; T9 b& c/ u0 C& ^% f - HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, 0);" p$ H- U5 `. d; }% N
- }6 ]3 g' Z: n& F( {' k8 B- b
- }
, k% q' L/ [7 E# G7 j5 \, x( | i8 H - LeranTime++;
4 K( G5 X+ J) b$ ] - i = 0;3 g4 K I' |9 |% a
- }; k0 Y8 E# H7 u5 o* t6 }
- }
复制代码 4 J5 c' _' B Z% X: l1 j7 A" k
$ {- z; S' s+ `& K: s
我们在定时器回调函数中调用,上电之后前十次为学习阶段,之后对测量值进行预测,当预期值>80即认为状态正常,则灯灭。' q* {2 F+ H7 L1 N
如果预期值<80则报警灯想起。
2 d% @- n1 y3 |9 j% `# O! \7 F, k# {
. V% F& m8 U3 V, b/ t$ P7 Q* c7 x& x4 J
1 h" s9 C1 w1 c1 O转载自:电路小白& t1 P1 E f# L7 T$ @. k- M/ q
如有侵权请联系删除
8 T* b' C2 j# E# T* @8 _$ Z" y# E" z1 l) L% U9 n
4 }5 T5 F! _2 l n' V9 |
1 E( R5 u' W2 X+ l6 c |