上一篇贴子已经知道怎么通过osxMFX_output数据分析鼓棒的落点
https://bbs.eeworld.com.cn/thread-527695-1-1.html
下一步是落棒检测,通过鼓棒动作判断是否敲了下去,我让SensorTile输出osxMFX_output的rotation_9X[2](俯仰数据)到上位机
通过C#写了一个程序能够把数据用拆线的方式显示出来
截取一段数据如下图显示,图中的红点是我每次落棒时的样子
分析发现落棒的数据有点像心电图或加速度计步的数据,找个心率检测的代码看了下没看懂,发贴求助后得到一些帮助
https://bbs.eeworld.com.cn/thread-523626-1-1.html
最后决定 自己写这个检测算法
再次采集一次模拟敲鼓的数据,用图形显示
截取728~897的数据通过EXCEL分析如下,蓝色是每一次抬棒时的最小值,红色是每一次落棒时的最大值
index | val | D = val[index] - val[index - 1] | if(D > 100 COUNTER = +1 else if(D < -100 COUNTER = -1 else COUNTER = 0 |
[980] | -1256 | | |
[981] | -1295 | -39 | 0 |
[982] | -1025 | 270 | 1 |
[983] | -623 | 402 | 1 |
[984] | -190 | 433 | 1 |
[985] | 270 | 460 | 1 |
[986] | 734 | 464 | 1 |
[987] | 1174 | 440 | 1 |
[988] | 1560 | 386 | 1 |
[989] | 1888 | 328 | 1 |
[990] | 2151 | 263 | 1 |
[991] | 2351 | 200 | 1 |
[992] | 2437 | 86 | 0 |
[993] | 2552 | 115 | 1 |
[994] | 2580 | 28 | 0 |
[995] | 2598 | 18 | 0 |
[996] | 2618 | 20 | 0 |
[997] | 2662 | 44 | 0 |
[998] | 2728 | 66 | 0 |
[999] | 2818 | 90 | 0 |
[1000] | 2933 | 115 | 1 |
[1001] | 3072 | 139 | 1 |
[1002] | 3226 | 154 | 1 |
[1003] | 3407 | 181 | 1 |
[1004] | 3617 | 210 | 1 |
[1005] | 3851 | 234 | 1 |
[1006] | 4116 | 265 | 1 |
[1007] | 4402 | 286 | 1 |
[1008] | 4703 | 301 | 1 |
[1009] | 4988 | 285 | 1 |
[1010] | 5196 | 208 | 1 |
[1011] | 5379 | 183 | 1 |
[1012] | 5514 | 135 | 1 |
[1013] | 5576 | 62 | 0 |
[1014] | 5577 | 1 | 0 |
[1015] | 5560 | -17 | 0 |
[1016] | 5503 | -57 | 0 |
[1017] | 5390 | -113 | -1 |
[1018] | 5223 | -167 | -1 |
[1019] | 5001 | -222 | -1 |
[1020] | 4728 | -273 | -1 |
[1021] | 4397 | -331 | -1 |
[1022] | 3983 | -414 | -1 |
[1023] | 3472 | -511 | -1 |
[1024] | 2873 | -599 | -1 |
[1025] | 2207 | -666 | -1 |
[1026] | 1496 | -711 | -1 |
[1027] | 747 | -749 | -1 |
[1028] | 12 | -735 | -1 |
[1029] | -520 | -532 | -1 |
[1030] | -843 | -323 | -1 |
[1031] | -1024 | -181 | -1 |
[1032] | -923 | 101 | 1 |
[1033] | -597 | 326 | 1 |
[1034] | -52 | 545 | 1 |
[1035] | 574 | 626 | 1 |
[1036] | 1284 | 710 | 1 |
[1037] | 2019 | 735 | 1 |
[1038] | 2719 | 700 | 1 |
[1039] | 3370 | 651 | 1 |
[1040] | 3859 | 489 | 1 |
[1041] | 4192 | 333 | 1 |
[1042] | 4382 | 190 | 1 |
[1043] | 4387 | 5 | 0 |
[1044] | 4224 | -163 | -1 |
[1045] | 3878 | -346 | -1 |
[1046] | 3378 | -500 | -1 |
[1047] | 2737 | -641 | -1 |
[1048] | 1944 | -793 | -1 |
[1049] | 1037 | -907 | -1 |
[1050] | 78 | -959 | -1 |
[1051] | -759 | -837 | -1 |
[1052] | -1398 | -639 | -1 |
[1053] | -1862 | -464 | -1 |
[1054] | -2051 | -189 | -1 |
[1055] | -1926 | 125 | 1 |
[1056] | -1611 | 315 | 1 |
[1057] | -1135 | 476 | 1 |
[1058] | -557 | 578 | 1 |
[1059] | 77 | 634 | 1 |
[1060] | 727 | 650 | 1 |
[1061] | 1363 | 636 | 1 |
[1062] | 1945 | 582 | 1 |
[1063] | 2469 | 524 | 1 |
[1064] | 2932 | 463 | 1 |
[1065] | 3331 | 399 | 1 |
[1066] | 3673 | 342 | 1 |
[1067] | 3961 | 288 | 1 |
[1068] | 4173 | 212 | 1 |
[1069] | 4184 | 11 | 0 |
[1070] | 4010 | -174 | -1 |
[1071] | 3607 | -403 | -1 |
[1072] | 2973 | -634 | -1 |
[1073] | 2131 | -842 | -1 |
[1074] | 1113 | -1018 | -1 |
[1075] | 332 | -781 | -1 |
[1076] | -286 | -618 | -1 |
[1077] | -674 | -388 | -1 |
[1078] | -774 | -100 | 0 |
[1079] | -610 | 164 | 1 |
[1080] | -227 | 383 | 1 |
[1081] | 214 | 441 | 1 |
[1082] | 684 | 470 | 1 |
[1083] | 1178 | 494 | 1 |
[1084] | 1635 | 457 | 1 |
[1085] | 2041 | 406 | 1 |
[1086] | 2371 | 330 | 1 |
[1087] | 2612 | 241 | 1 |
[1088] | 2773 | 161 | 1 |
[1089] | 2865 | 92 | 0 |
[1090] | 2912 | 47 | 0 |
[1091] | 2937 | 25 | 0 |
[1092] | 2950 | 13 | 0 |
[1093] | 2951 | 1 | 0 |
[1094] | 2945 | -6 | 0 |
[1095] | 2931 | -14 | 0 |
[1096] | 2915 | -16 | 0 |
[1097] | 2920 | 5 | 0 |
[1098] | 2936 | 16 | 0 |
[1099] | 2975 | 39 | 0 |
[1100] | 3036 | 61 | 0 |
[1101] | 3137 | 101 | 1 |
[1102] | 3276 | 139 | 1 |
[1103] | 3461 | 185 | 1 |
[1104] | 3670 | 209 | 1 |
[1105] | 3917 | 247 | 1 |
[1106] | 4197 | 280 | 1 |
[1107] | 4488 | 291 | 1 |
[1108] | 4747 | 259 | 1 |
[1109] | 4946 | 199 | 1 |
[1110] | 5132 | 186 | 1 |
[1111] | 5266 | 134 | 1 |
[1112] | 5331 | 65 | 0 |
[1113] | 5358 | 27 | 0 |
[1114] | 5381 | 23 | 0 |
[1115] | 5382 | 1 | 0 |
[1116] | 5355 | -27 | 0 |
[1117] | 5300 | -55 | 0 |
[1118] | 5143 | -157 | -1 |
[1119] | 4823 | -320 | -1 |
[1120] | 4380 | -443 | -1 |
[1121] | 3752 | -628 | -1 |
[1122] | 2909 | -843 | -1 |
[1123] | 1925 | -984 | -1 |
[1124] | 881 | -1044 | -1 |
[1125] | 41 | -840 | -1 |
[1126] | -512 | -553 | -1 |
[1127] | -904 | -392 | -1 |
[1128] | -996 | -92 | 0 |
[1129] | -795 | 201 | 1 |
通过2点差值的大小来判断提棒和落棒速度
设差值参考值Dref为100
当D = val[index] - val[index - 1]大于100时认为是高速上升
val[index] - val[index - 1]小于-100时认为是高速下降
其它情况为非高速上升和下降,无变化
得到每一个波谷到波峰的计数
和每一个波峰到波谷的计数
计算最大为+24,最小为-8
考虑到可能会有更短或更长的波形,将计数最大值Cmax定为30 ~ 最小值Cmin为6
上升和下降少于6为上升下降时间不足
排除干扰
一个带有干扰的波形如下图
干扰分为上升干扰B,b1
下降干扰c1,D
D=val[index] – val[index-1];
max=0;
counter = 0;
rCounter = 0;
fCounter = 0;
每得到一个数据counter++;
Counter > 60时重置所有变量 max,counter,rCounter,fCounter
当D > 100时且val > max时开始上升计数rCounter++;fCounter=0; max = val;(A~B)
当D < -100时开始下降计数fCounter++(B~b1)
当再次D > 100时继续上升计数rCounter++;fCounter = 0(b1~C)
当D<-100时开始下降计数(C~c1) fCounter ++;
当D > 100但val < max时忽略(c1~D)
当D < -100时继续下降计数(D~E) fCounter++;
当fCounter > 8 时判断 rCounter是否大于8,满足视为一次完整的峰波
否则重置所有变量 max,counter,rCounter,fCounter
写成C函数就是下边的样子
//保存数据最大值(在一次谷~峰~谷数据内) int32_t max = 0; //数据计数,一次谷~峰~谷必需在指定样本数量内完成 uint32_t counter = 0; uint32_t rCounter = 0; uint32_t fCounter = 0; uint32_t oldSample = 0; //sample当前样本 //minD = 两点间的最小差值,d值越大要求上升下降速度越快 //minCount 当两点差值大于d时counter++,如果counter少于minCount说明上升和下降时间不够 //maxSampleCount一次谷~峰~谷允许的最大样本数量 uint8_t PeakCounter(int32_t sample,uint32_t minD,uint32_t minCount,uint32_t maxSampleCount) { int32_t d = sample - oldSample; //在指定样本数量内(maxSampleCount)没有检测到谷峰谷 if(counter++ > maxSampleCount) { max = 0; counter = 0; rCounter = 0; fCounter = 0; } //上升 if(d > minD && sample > max) { //保存最大值 max = sample; //上升计数 rCounter++; //清除下降计数 fCounter = 0; }else if(d < -100)//下降 { fCounter++; //如果下降满足条件判断上升是否满足条件,如果下降不满足条件还可能会继续上升 //所以下降不满足条件前不判断上升 if(fCounter >= minCount) { //判断如果上升满足条件 if(rCounter >= minCount) { max = 0; counter = 0; rCounter = 0; fCounter = 0; //返回计数 return 1; }else { //上升不满足条件,重头开始 max = 0; counter = 0; rCounter = 0; fCounter = 0; } } //下降不满足条件时不处理 //如果一直不满足条件最后由if(counter++ > maxSampleCount)重置 } else { } oldSample = sample; //不满足条件时返回0 return 0; } |