from bbc microbit library
Dependencies: BLE_API mbed-dev-bin nRF51822
Fork of microbit-dal by
Revision 38:1a9e8e5e23f2, committed 2016-07-13
- Comitter:
- LancasterUniversity
- Date:
- Wed Jul 13 12:18:17 2016 +0100
- Parent:
- 37:b624ae5e94a5
- Child:
- 39:112df23f039f
- Commit message:
- Synchronized with git rev b5846f06
Author: Joe Finney
microbit: Fixed unreachable High-G gesture events [issue #109]
Ammended basic gesture recogniser to correclty generate threshold events for
high G forces (3G, 6G and 8G threshold events).
Also refined semantics such that events for any given impulse will be
generated for ALL thresholds below that below. e.g a 7G impulse will now raise
both the 3G and 6G threshold events.
Changed in this revision
--- a/inc/drivers/MicroBitAccelerometer.h Wed Jul 13 12:18:16 2016 +0100 +++ b/inc/drivers/MicroBitAccelerometer.h Wed Jul 13 12:18:17 2016 +0100 @@ -155,8 +155,12 @@ x:1, y:1, z:1, + unused, + impulse_3, + impulse_6, + impulse_8, count:4, - timer:8; + timer:4; }; /** @@ -176,6 +180,7 @@ MicroBitI2C& i2c; // The I2C interface to use. float roll; // Roll of the device, in radians. uint8_t sigma; // the number of ticks that the instantaneous gesture has been stable. + uint8_t impulseSigma; // the number of ticks since an impulse event has been generated. BasicGesture lastGesture; // the last, stable gesture recorded. BasicGesture currentGesture; // the instantaneous, unfiltered gesture detected. ShakeHistory shake; // State information needed to detect shake events. @@ -464,4 +469,4 @@ BasicGesture instantaneousPosture(); }; -#endif +#endif \ No newline at end of file
--- a/source/drivers/MicroBitAccelerometer.cpp Wed Jul 13 12:18:16 2016 +0100 +++ b/source/drivers/MicroBitAccelerometer.cpp Wed Jul 13 12:18:17 2016 +0100 @@ -189,6 +189,7 @@ // Initialise gesture history this->sigma = 0; + this->impulseSigma = 0; this->lastGesture = GESTURE_NONE; this->currentGesture = GESTURE_NONE; this->shake.x = 0; @@ -196,6 +197,10 @@ this->shake.z = 0; this->shake.count = 0; this->shake.timer = 0; + this->shake.tap = 1; + this->shake.impulse_3 = 1; + this->shake.impulse_6 = 1; + this->shake.impulse_8 = 1; // Configure and enable the accelerometer. if (this->configure() == MICROBIT_OK) @@ -318,9 +323,9 @@ */ BasicGesture MicroBitAccelerometer::instantaneousPosture() { - int force = instantaneousAccelerationSquared(); bool shakeDetected = false; + // Test for shake events. // We detect a shake by measuring zero crossings in each axis. In other words, if we see a strong acceleration to the left followed by // a strong acceleration to the right, then we can infer a shake. Similarly, we can do this for each axis (left/right, up/down, in/out). @@ -358,21 +363,11 @@ } } + // Shake events take the highest priority, as under high levels of change, other events + // are likely to be transient. if (shake.shaken) return GESTURE_SHAKE; - if (force < MICROBIT_ACCELEROMETER_FREEFALL_THRESHOLD) - return GESTURE_FREEFALL; - - if (force > MICROBIT_ACCELEROMETER_3G_THRESHOLD) - return GESTURE_3G; - - if (force > MICROBIT_ACCELEROMETER_6G_THRESHOLD) - return GESTURE_6G; - - if (force > MICROBIT_ACCELEROMETER_8G_THRESHOLD) - return GESTURE_8G; - // Determine our posture. if (getX() < (-1000 + MICROBIT_ACCELEROMETER_TILT_TOLERANCE)) return GESTURE_LEFT; @@ -401,6 +396,39 @@ */ void MicroBitAccelerometer::updateGesture() { + // Check for High/Low G force events - typically impulses, impacts etc. + // Again, during such spikes, these event take priority of the posture of the device. + // For these events, we don't perform any low pass filtering. + int force = instantaneousAccelerationSquared(); + + if (force > MICROBIT_ACCELEROMETER_3G_THRESHOLD) + { + if (force > MICROBIT_ACCELEROMETER_3G_THRESHOLD && !shake.impulse_3) + { + MicroBitEvent e(MICROBIT_ID_GESTURE, GESTURE_3G); + shake.impulse_3 = 1; + } + if (force > MICROBIT_ACCELEROMETER_6G_THRESHOLD && !shake.impulse_6) + { + MicroBitEvent e(MICROBIT_ID_GESTURE, GESTURE_6G); + shake.impulse_6 = 1; + } + if (force > MICROBIT_ACCELEROMETER_8G_THRESHOLD && !shake.impulse_8) + { + MicroBitEvent e(MICROBIT_ID_GESTURE, GESTURE_8G); + shake.impulse_8 = 1; + } + + impulseSigma = 0; + } + + // Reset the impulse event onve the acceleration has subsided. + if (impulseSigma < MICROBIT_ACCELEROMETER_GESTURE_DAMPING) + impulseSigma++; + else + shake.impulse_3 = shake.impulse_6 = shake.impulse_8 = 0; + + // Determine what it looks like we're doing based on the latest sample... BasicGesture g = instantaneousPosture();