用该传感器判断是食指还是中指还是其他指头。( ]8 W' |3 x: U! V6 v
3 S/ j0 C% j/ g- {7 {对于我们的三个指头(5个也好)本质上是一种多分类网络问题,我们将输入信号划分成不同的分类。) m* }3 ]8 q3 @5 g- I
小拇指
5 I8 A p. s5 t O% S+ R大拇指
% `" O/ P* @' l: j: i: F+ g中指(后来用了食指方便)8 \! \% ]' f) ?. i
没有指头(空置)
6 O0 N9 |) F5 U3 F+ d* @
" W5 T1 |$ w- d' R) X( R因此我们利用多分类神经网络来实现判断功能。2 L6 `# j$ u ?" Q
- I& z' U% Y: a. Y) s/ I1 B
( R8 k- M0 G9 I- int i = 0;; V6 X. F' |/ y
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
; e q: K( r9 [: p4 J - {: |4 i5 H Q) K4 l' `
- maxim_max30102_read_fifo(&red,&ir);
9 C4 H: A" U+ l0 N1 _ - printf("%ld ",ir);4 e8 G2 F: g1 B
- i++;
0 e2 C# d- l! n! h# Z, m - if(i==128)
9 y0 V' y! e: R - {
( @: f1 W5 E6 t: E* V% ? - i=0;
{4 d. I4 H B7 {8 ~2 `; c8 T+ o - printf("\n");
& c3 h$ M8 g8 `( ]1 b - }% W3 B9 v! h2 q/ v- n! ^8 i5 q
- }
复制代码 - U9 @7 H! j! }! l9 G8 r- Z
信号的输入部分则和上期一样,100HZ的采样率,128的采样长度。, F0 f6 D' i1 l+ q+ l! P
+ h0 K, f1 l9 Q) l9 s$ c4 A
# G2 ?- v0 C+ h& z. h9 B, ?: g
. n% F/ Y2 }- t6 l9 W1 V8 R/ K创建一个n-Class n分类神经网络。! o/ t% W0 s- h$ n* e6 j
, ^) X3 I! h6 J" t, r9 M/ [
E# \4 x: B: l8 ?( H' B9 h
5 ]( Y f1 @4 p3 g
其他设置都和上期的保持一样,使用通用一轴传感器。
" }/ N6 X- j, [. \% i. B
8 l. M+ }" ~; n _5 \
/ l7 }7 }$ g- f: v, s: T! i
+ \, t) u' n) e& b3 z$ v8 x9 |: }但是信号输入的地方,我们利用串口导入各个类别的数据(这里是不同的指头)
( B5 b& z' ?, b; w8 Q g) H# s& b7 I& x0 ^& X0 J' I# R
! v X* {( R9 @. z6 ]3 s8 _
7 X' k) C* g/ S* B; y" m需要注意的是,这里的标签即代表着我们的分类,不像之前那样子可以一个类别下面可以使用多组数据。- O2 G O# G: \% G& o' Q' A7 C A
! x2 M9 }$ P" i1 ~
0 l) K$ h0 a% ]4 F
9 D6 `" h0 C, L. U( M
训练我们的模型,这里可以选择我们的分类(其实这里我觉得要是把某组数据能添加到某个分类就好了,这里让我研究一下)。) y- r) }1 n, U9 u# e, y: q9 u
$ u+ v: u% E9 S) c3 B8 A
- D; n8 E4 r+ o$ m( M0 D; `
8 S {$ n7 j* ]! w n7 y训练好我们的模型,这里可以关注各指标。
B8 u4 S; ^4 ]+ O% O4 q2 A- b1 c7 Q0 A% G( r8 F: X, Q. e3 i# Q, d
接着就是验证我们的模型,验证的过程可以参考文章开头的视频。$ U+ f" `, _4 {* O
, h$ o! e k8 v) T. r* B
: O2 b+ P% W0 E! Q/ T' J3 U4 b. W3 l ~
部署完我们的模型之后,查看生成的.ZIP文件,其中相比于异常识别多了一个knowledge的头文件。: C8 @ v# K& a) }: |
* U$ K" ~) h, g; l8 D
( \; }+ i/ [1 c: }; M; Z) w
3 ^# k: D* Z/ ~
这里我们需要libneai.a以及两个.h文件
( G T. A- H$ B% R- b, j/ [
2 d% e4 B" x$ M2 N8 H0 e5 _( pSTM32中用机器学习实现正确率99.95%的心率异常检测! t i& E4 q( k" H* r2 ^
' ]2 f! W* B) G! N F( O怎么导入文件请查看这篇文章。
: O: I( X$ P; S7 j. N
) d* n6 ~/ l' r5 B! Q' \# h: h& w
& o% B+ V+ X# \7 {) q# Z; D0 {/ |. F" @8 m( G3 t( o" _& [7 w2 Q) w
初始化函数中,我们需要导入一个数组,这个数组就定义在knowledge.h这个文件中。: n" Y* W. S( [1 A( Z, E# g) W' Z( z6 u
) d; Q2 C3 k4 e% k5 h
& l; J" ]# j1 i2 @9 }+ E' a
q9 [4 z, A. C# ~7 c( j* }- neai_classification_init(knowledge);
复制代码
6 E+ G# U! Q2 Z l3 h9 O5 X初始化的时候,需要以这个数组为参数。
& R( F+ L1 P3 q1 t+ \+ E K. G3 B9 k) W" R5 b: M
之后我们在定时器中,采集到128个数据之后进行预测。
) L. ^/ u$ D* r* `9 A, I5 x; E+ w7 @9 B* g+ V. N$ ~
- float IRD[128];
0 t( }, d) X/ b7 y5 C8 X8 L6 P& s - int i = 0;! y/ b2 R+ K7 p6 W
- int LeranTime= 0;
$ G3 r" T' _2 B/ d5 N- v$ M% r - const char *id2class[CLASS_NUMBER + 1] = { // Buffer for mapping class id to class name
+ y. ~, a, G% B) {; g. K$ q - "unknown",
9 E5 ~/ c( \4 a$ W: B' V* i* C, g - "zhongzhi",
/ T; T. Q. _' I4 G - "Error"," ]. P" T# ], C9 |8 p1 z6 K
- "xiaomuzhi2",
' |1 k) h0 C- B% k, Z- @ - "damuzhi",
9 j0 ?3 Q6 z! p7 t Y: y - };) _# O+ C2 d& d3 c! y3 |
- float Output[4];
: X, F3 Y) F" F - void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)4 _/ O' b$ D* h2 J0 N
- {8 v+ Z/ F# L/ P
- uint16_t yuce;4 Z1 |" D3 C6 g6 ~
- maxim_max30102_read_fifo(&red,&ir);
/ o& x" g4 ]- `; U* E% g$ r* n - IRD = ir;- O/ N2 k0 \; u
- i++;! E V. L" P1 ~6 c
- //printf("%d ",ir);1 f7 W3 S- i5 a: H
- if(i==128)
, R1 [1 |7 N" t. R# {+ `6 w! s - {) R- T; g2 p3 o3 a1 {2 p
4 L' @: j6 T$ Q. x; H- . ~( u1 ?- j+ e6 y9 C/ {1 p
- neai_classification(IRD,Output,&yuce);
$ u" c0 @$ H% o9 `4 O% z0 e - 6 T K1 w0 c# ^6 K8 N, F
- : e3 C6 P9 m8 u' |
- printf("\n\n\n");' U- ?+ _: N4 C F7 u* l: `
- printf("zhongzhi:%.2f\r\n",Output[0]);+ u% \: D9 U7 G8 L; ]1 s
- printf("Error:%.2f\r\n",Output[1]);
+ M/ Z; B; y: o4 J) T - printf("xiaomuzhi:%.2f\r\n",Output[2]);9 W& _% \4 g) M. E, j% G6 m% h/ d
- printf("damuzhi:%.2f\r\n",Output[3]);
5 O* K# V: P0 }; A5 b4 t6 K0 @! B: l- h - LeranTime++;
+ ~! J+ w. ]9 H1 ^# c' z - i = 0;
' {( y7 X+ t5 ^3 s) U2 e8 U7 y - }
, U0 i2 H: K5 p* R' }- _ - }
复制代码
3 ^* ?. B* ]( f9 Z# L这里的 预测函数有三个参数,第一个参数是输入数组,第二参数是输出数组,输出数组中包含着对于各个分类的参数预测值,第三个参数输入一个指针,这个指针会指向预测最大值的索引。
^- O1 F8 n$ l1 \% L3 [7 Q9 Y) g, W3 \8 t0 Y7 C' {1 y. l
- [9 K1 |! s" ~/ }3 o
- @2 ^7 e T; P5 Z. B烧入我们的代码,可以看到,空置的时候,Error的预测值是最大的。4 F9 l+ _! @7 |! r+ K' s# H
- U7 i% r, a5 A4 M
( |0 k1 d& w+ \
- v# W' \6 y6 w. E当我们放上中指的时候,检测到中指的概率是最大的。# ?) p9 T7 s1 v h8 F7 ^
; U9 V0 k1 L6 F; d1 J" }. i
) L. Q( Z0 X& P# u- w1 F0 u
: Z9 M- m1 w1 R5 Z+ J小拇指也是可以正常的检测。
: y, g1 @2 r4 H. t* P B7 A* ^5 `! @, e' C
; P B+ Y) F2 K& v' v7 v
; N. a4 E, U9 N7 H. F' z转载自:电路小白
7 d# C& d. C2 j, y t1 J) }如有侵权请联系删除
% N6 @) y0 \5 Q4 p3 O( s! l, \ q0 k' i2 X. |
7 f* c( E4 h/ Q+ _! L5 t
5 h- y, I- h- n8 n% m* |; c. r
|