-
Notifications
You must be signed in to change notification settings - Fork 17
/
ADXL335MotonManager.cpp
227 lines (173 loc) · 5.03 KB
/
ADXL335MotonManager.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
This file is part of the Universal Saber library.
The Universal Saber library is free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
The Universal Saber library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Universal Saber library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* ADXL335MotonManager.cpp
*
* Created on: Oct 2, 2016
* Author: JakeSoft
*/
#include "motion/ADXL335MotionManager.h"
#include <Arduino.h>
#define ADXL335_HISTORY_SIZE 5 //Must be at least 2
#define CLASH_DEBOUCE_TIME 100 //Minimum time (in milliseconds) between clash events
Adxl335MotionManager::Adxl335MotionManager(int aXPin, int aYPin, int aZPin, Adxl335TolData* apTolData)
{
mXPin = aXPin;
mYPin = aYPin;
mZPin = aZPin;
mpTolData = apTolData;
mIsSwing = false;
mIsClash = false;
mLastUpdateTime = millis();
mSwingMagnitude = eeSmall;
mLastClashTime = millis();
}
Adxl335MotionManager::~Adxl335MotionManager()
{
}
void Adxl335MotionManager::Init()
{
pinMode(mXPin, INPUT);
pinMode(mYPin, INPUT);
pinMode(mZPin, INPUT);
//Pre-fill history buffer. Guarantees a certain size.
while(this->mHistoryBuffer.size() < ADXL335_HISTORY_SIZE)
{
Update();
}
}
bool Adxl335MotionManager::IsSwing()
{
return mIsSwing;
}
bool Adxl335MotionManager::IsClash()
{
bool lTemp = mIsClash;
mIsClash = false;
return lTemp;
}
void Adxl335MotionManager::Update()
{
//Don't update more than once per millisecond
if(millis() - mLastUpdateTime < 1)
{
return;
}
else
{
//Capture the current time and proceed with update
mLastUpdateTime = millis();
}
//Capture current readings from ADXL335
AxisData lCurrentReading;
lCurrentReading.mTimeStamp = millis();
lCurrentReading.mnX = analogRead(mXPin) * 10;
lCurrentReading.mnY = analogRead(mYPin) * 10;
lCurrentReading.mnZ = analogRead(mZPin) * 10;
//Store current readings
mHistoryBuffer.add(lCurrentReading);
//Check and correct for history buffer size overflow
if(mHistoryBuffer.size() > ADXL335_HISTORY_SIZE)
{
//Chop off the first entry
mHistoryBuffer.shift();
}
//Check for clashes
mIsClash = ClashDetect();
//Only try to detect swings if a clash isn't happening
if(false == mIsClash)
{
mIsSwing = SwingDetect();
}
else
{
mIsSwing = false;
}
}
EMagnitudes Adxl335MotionManager::GetSwingMagnitude()
{
return mSwingMagnitude;
}
bool Adxl335MotionManager::SwingDetect()
{
bool lSwingDetected = false;
int lSwingCount = 0; //Counts how many samples are beyond the swing threshold
int lVectorDeltaMax = 0; //Maxium detected vector delta
//Compare most recent reading to all previous readings to detect swings
for(int lIdx = mHistoryBuffer.size() - 1;
lIdx > 0;
lIdx--)
{
AxisData lData1 = mHistoryBuffer.get(lIdx);
AxisData lData2 = mHistoryBuffer.get(lIdx-1);
int lVectorDelta = CalculateVectorDelta(lData1, lData2);
//Detect if motion is beyond tolerance threashold.
//Ignore swings for a short time after a clash
if(abs(lVectorDelta) >= mpTolData->mSwingSmall && millis() - mLastClashTime > CLASH_DEBOUCE_TIME)
{
lSwingCount++;
lVectorDeltaMax = max(lVectorDeltaMax, abs(lVectorDelta));
}
}
if(lSwingCount >= mHistoryBuffer.size() - 1)
{
lSwingDetected = true;
mSwingMagnitude = eeSmall;
if(lVectorDeltaMax >= (int)mpTolData->mSwingMedium)
{
mSwingMagnitude = eeMedium;
}
if(lVectorDeltaMax >= (int)mpTolData->mSwingLarge)
{
mSwingMagnitude = eeLarge;
}
}
return lSwingDetected;
}
bool Adxl335MotionManager::ClashDetect()
{
bool lClashDetected = false;
int lCurIdx = mHistoryBuffer.size() - 1;
AxisData lCurrent = mHistoryBuffer.get(lCurIdx);
AxisData lPrev = mHistoryBuffer.get(lCurIdx - 1);
int lVectorDelta = CalculateVectorDelta(lPrev, lCurrent);
if(abs(lVectorDelta) > mpTolData->mClash && millis() - mLastClashTime >= CLASH_DEBOUCE_TIME)
{
mLastClashTime = millis();
lClashDetected = true;
}
return lClashDetected;
}
int Adxl335MotionManager::CalculateVector(AxisData& arAxisDataIn)
{
int lVector = 0;
float lXaxis = (float)arAxisDataIn.mnX;
float lYaxis = (float)arAxisDataIn.mnY;
float lZaxis = (float)arAxisDataIn.mnZ;
float lVectorFloat = (lXaxis*lXaxis) + (lYaxis*lYaxis) + (lZaxis*lZaxis);
lVectorFloat = sqrt(lVectorFloat);
lVector = (int)lVectorFloat;
return lVector;
}
int Adxl335MotionManager::CalculateVectorDelta(AxisData& arFirst, AxisData& arSecond)
{
int lDelta = 0;
int lFirstVector = CalculateVector(arFirst);
int lSecondVector = CalculateVector(arSecond);
lDelta = lFirstVector - lSecondVector;
//Now factor in the time delta
unsigned long lTimeDelta = arFirst.mTimeStamp - arSecond.mTimeStamp;
lDelta = lDelta / (int) lTimeDelta;
return lDelta;
}