comparison Discovery/Src/motion.c @ 370:77cdfbdaca8c MotionDetection

Changed function names from shake to pitch and improved detection function: Shake might be confusing for people reading the code because pitch values are ased for calculation => changed name to pitch to be more transparent
author ideenmodellierer
date Tue, 13 Aug 2019 21:13:54 +0200
parents bdf978d2a5d4
children fca370f847f8
comparison
equal deleted inserted replaced
369:210bffc496a3 370:77cdfbdaca8c
7 7
8 #include <stdint.h> 8 #include <stdint.h>
9 #include <string.h> 9 #include <string.h>
10 #include <math.h> 10 #include <math.h>
11 #include "motion.h" 11 #include "motion.h"
12 #include "data_central.h"
13 #include "t7.h"
12 14
13 #define STABLE_STATE_COUNT 2 /* number of count to declare a state as stable (at the moment based on 100ms) */ 15 #define STABLE_STATE_COUNT 2 /* number of count to declare a state as stable (at the moment based on 100ms) */
14 #define STABLE_STATE_TIMEOUT 5 /* Detection shall be aborted if a movement state is stable for more than 500ms */ 16 #define STABLE_STATE_TIMEOUT 5 /* Detection shall be aborted if a movement state is stable for more than 500ms */
15 #define MOVE_DELTA_SPEED 4 /* Delta speed needed to identify a valid movement */ 17 #define MOVE_DELTA_SPEED 4 /* Delta speed needed to identify a valid movement */
16 #define SHAKE_DELTA_COUNT 10 /* Delta count needed to identify a valid minima / maxima */ 18 #define PITCH_DELTA_COUNT 10 /* Delta count needed to identify a valid minima / maxima */
17 #define SHAKE_DELTA_END 10 /* Delta allowed between start and end position */ 19 #define PITCH_DELTA_END 10 /* Delta allowed between start and end position */
20
21
22 #define SECTOR_WINDOW 40.0 /* Pitch window which is used for custom view projection */
23 #define SECTOR_HYSTERY 3 /* Additional offset to avoid fast changing displays */
24 #define SECTOR_BORDER 400.0 /* Define a value which is out of limit to avoid not wanted key events */
25 #define SECTOR_FILTER 10 /* Define speed for calculated angle to follow real value */
26
18 27
19 static detectionState_t detectionState = DETECT_NOTHING; 28 static detectionState_t detectionState = DETECT_NOTHING;
20 29
21 /* Detect if user is generating an pitch including return to starting position (shake) */ 30 static uint8_t curSector;
31 static uint8_t targetSector;
32 static uint8_t sectorSize;
33 static uint8_t sectorCount;
34
35 SSector PitchSector[10]; /* max number of enabled custom views */
36
37
38 uint8_t GetSectorForPitch(float pitch)
39 {
40 static float lastPitch = 1000;
41 float newPitch;
42 uint8_t index;
43 uint8_t sector = 0;
44
45 if(lastPitch == 1000) /* init at first call */
46 {
47 lastPitch = pitch;
48 }
49
50 newPitch = lastPitch + (pitch / SECTOR_FILTER);
51
52 for(index = 1; index < sectorCount; index++)
53 {
54 if((pitch < PitchSector[index].upperlimit) && (pitch > PitchSector[index].lowerlimit ))
55 {
56 sector = index;
57 break;
58 }
59 }
60 lastPitch = newPitch;
61 return sector;
62 }
63
64 void DefinePitchSectors(float centerPitch)
65 {
66 uint8_t index;
67
68 sectorCount = t7_GetEnabled_customviews();
69 sectorSize = SECTOR_WINDOW / sectorCount;
70
71 PitchSector[0].upperlimit = centerPitch + (SECTOR_WINDOW / 2);
72 PitchSector[0].lowerlimit = PitchSector[0].upperlimit - sectorSize - SECTOR_HYSTERY;
73
74 for(index = 1; index < sectorCount; index++)
75 {
76 PitchSector[index].upperlimit = PitchSector[0].upperlimit - index * sectorSize + SECTOR_HYSTERY;
77 PitchSector[index].lowerlimit = PitchSector[0].upperlimit - (index + 1) * sectorSize - SECTOR_HYSTERY;
78 }
79
80 PitchSector[0].upperlimit = SECTOR_BORDER;
81 PitchSector[index - 1].lowerlimit = SECTOR_BORDER * -1.0;
82
83 /* get the current sector */
84 curSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch);
85 targetSector = curSector;
86 }
87
88 void InitMotionDetection(void)
89 {
90 targetSector = 0;
91 curSector = 0;
92 sectorSize = 0;
93 sectorCount = 0;
94 DefinePitchSectors(0);
95 }
96
97 /* Map the current pitch value to a sector and create button event in case the sector is left */
98 detectionState_t detectSectorButtonEvent(float curPitch)
99 {
100 static uint8_t lastTargetSector = 0;
101 uint8_t newTargetSector;
102 uint8_t PitchEvent = DETECT_NOTHING;
103
104 /* only change sector if reading is stable */
105 newTargetSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch);
106 if(lastTargetSector == newTargetSector)
107 {
108 targetSector = newTargetSector;
109 }
110 lastTargetSector = newTargetSector;
111 if(targetSector != curSector)
112 {
113 if(targetSector > curSector)
114 {
115 curSector++;
116 PitchEvent = DETECT_POS_PITCH;
117 }
118 else
119 {
120 curSector--;
121 PitchEvent = DETECT_NEG_PITCH;
122 }
123 }
124 return PitchEvent;
125 }
126
127
128 /* Detect if user is generating an pitch including return to starting position */
22 /* This is done by feeding the past movements value per value into a state machine */ 129 /* This is done by feeding the past movements value per value into a state machine */
23 detectionState_t detectShake(float currentPitch) 130 detectionState_t detectPitch(float currentPitch)
24 { 131 {
25 static uint8_t stableCnt = 0; 132 static uint8_t stableCnt = 0;
26 static float lastPitch = 0.0; 133 static float lastPitch = 0.0;
27 static float startPitch = 0.0; 134 static float startPitch = 0.0;
28 static float minmax = 0.0;
29 float curSpeed; 135 float curSpeed;
30 136
31 if((detectionState == DETECT_NEG_SHAKE) || (detectionState == DETECT_POS_SHAKE)) /* discard last detection */ 137
138 if((detectionState == DETECT_NEG_PITCH) || (detectionState == DETECT_POS_PITCH)) /* discard last detection */
32 { 139 {
33 detectionState = DETECT_NOTHING; 140 detectionState = DETECT_NOTHING;
34 } 141 }
35 142
36 curSpeed = currentPitch - lastPitch; 143 curSpeed = currentPitch - lastPitch;
40 { 147 {
41 case DETECT_NOTHING: if(fabsf(curSpeed) < MOVE_DELTA_SPEED) /* detect a stable condition before evaluating for the next move */ 148 case DETECT_NOTHING: if(fabsf(curSpeed) < MOVE_DELTA_SPEED) /* detect a stable condition before evaluating for the next move */
42 { 149 {
43 stableCnt++; 150 stableCnt++;
44 } 151 }
152 else
153 {
154 stableCnt=0;
155 }
156
45 if(stableCnt > STABLE_STATE_COUNT) 157 if(stableCnt > STABLE_STATE_COUNT)
46 { 158 {
47 detectionState = DETECT_START; 159 detectionState = DETECT_START;
48 stableCnt = 0; 160 stableCnt = 0;
49 } 161 }
69 } 181 }
70 else 182 else
71 { 183 {
72 if(stableCnt >= STABLE_STATE_COUNT) /* debounce movement */ 184 if(stableCnt >= STABLE_STATE_COUNT) /* debounce movement */
73 { 185 {
74 if(fabsf(startPitch - currentPitch) > SHAKE_DELTA_COUNT) 186 if(fabsf(startPitch - currentPitch) > PITCH_DELTA_COUNT)
75 { 187 {
76 detectionState++; 188 detectionState++;
77 minmax = lastPitch;
78 } 189 }
79 else 190 else
80 { 191 {
81 detectionState = DETECT_NOTHING; 192 detectionState = DETECT_NOTHING;
82 } 193 }
87 } 198 }
88 stableCnt = 0; 199 stableCnt = 0;
89 } 200 }
90 break; 201 break;
91 case DETECT_MINIMA: 202 case DETECT_MINIMA:
92 case DETECT_MAXIMA: if(fabsf(currentPitch - minmax ) < SHAKE_DELTA_COUNT) /* stay at maximum for short time to add a pattern for user interaction */ 203 case DETECT_MAXIMA: /* stay at maximum for short time to add a pattern for user interaction */
204 if(fabsf(curSpeed) < MOVE_DELTA_SPEED )
93 { 205 {
94 stableCnt++; 206 stableCnt++;
95 } 207 }
96 else 208 else
97 { 209 {
107 } 219 }
108 break; 220 break;
109 case DETECT_RISEBACK: 221 case DETECT_RISEBACK:
110 case DETECT_FALLBACK: if(fabsf(curSpeed) < MOVE_DELTA_SPEED) 222 case DETECT_FALLBACK: if(fabsf(curSpeed) < MOVE_DELTA_SPEED)
111 { 223 {
112 if(fabsf(startPitch - currentPitch) < SHAKE_DELTA_END) 224 if(fabsf(startPitch - currentPitch) < PITCH_DELTA_END)
113 { 225 {
114 detectionState++; 226 detectionState++;
115 } 227 }
116 } 228 }
117 stableCnt++; 229 stableCnt++;