2015-08-12 10:53:41 +00:00
|
|
|
#ifndef MICROBIT_ACCELEROMETER_H
|
|
|
|
#define MICROBIT_ACCELEROMETER_H
|
|
|
|
|
|
|
|
#include "mbed.h"
|
2015-09-11 15:39:38 +00:00
|
|
|
#include "MicroBitComponent.h"
|
2015-08-12 10:53:41 +00:00
|
|
|
|
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Relevant pin assignments
|
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
#define MICROBIT_PIN_ACCEL_DATA_READY P0_28
|
|
|
|
|
|
|
|
/*
|
|
|
|
* I2C constants
|
|
|
|
*/
|
|
|
|
#define MMA8653_DEFAULT_ADDR 0x3A
|
|
|
|
|
|
|
|
/*
|
|
|
|
* MMA8653 Register map (partial)
|
|
|
|
*/
|
|
|
|
#define MMA8653_STATUS 0x00
|
|
|
|
#define MMA8653_OUT_X_MSB 0x01
|
|
|
|
#define MMA8653_WHOAMI 0x0D
|
|
|
|
#define MMA8653_XYZ_DATA_CFG 0x0E
|
|
|
|
#define MMA8653_CTRL_REG1 0x2A
|
|
|
|
#define MMA8653_CTRL_REG2 0x2B
|
|
|
|
#define MMA8653_CTRL_REG3 0x2C
|
|
|
|
#define MMA8653_CTRL_REG4 0x2D
|
|
|
|
#define MMA8653_CTRL_REG5 0x2E
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* MMA8653 constants
|
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
#define MMA8653_WHOAMI_VAL 0x5A
|
|
|
|
|
2015-09-08 22:16:15 +00:00
|
|
|
#define MMA8653_SAMPLE_RANGES 3
|
|
|
|
#define MMA8653_SAMPLE_RATES 8
|
|
|
|
|
2015-09-19 20:00:38 +00:00
|
|
|
/*
|
|
|
|
* Accelerometer events
|
|
|
|
*/
|
2016-01-05 15:44:57 +00:00
|
|
|
#define MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE 1
|
2015-12-03 15:11:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Gesture events
|
|
|
|
*/
|
2016-01-05 15:44:57 +00:00
|
|
|
#define MICROBIT_ACCELEROMETER_EVT_TILT_UP 1
|
|
|
|
#define MICROBIT_ACCELEROMETER_EVT_TILT_DOWN 2
|
|
|
|
#define MICROBIT_ACCELEROMETER_EVT_TILT_LEFT 3
|
|
|
|
#define MICROBIT_ACCELEROMETER_EVT_TILT_RIGHT 4
|
|
|
|
#define MICROBIT_ACCELEROMETER_EVT_FACE_UP 5
|
|
|
|
#define MICROBIT_ACCELEROMETER_EVT_FACE_DOWN 6
|
|
|
|
#define MICROBIT_ACCELEROMETER_EVT_FREEFALL 7
|
|
|
|
#define MICROBIT_ACCELEROMETER_EVT_3G 8
|
|
|
|
#define MICROBIT_ACCELEROMETER_EVT_6G 9
|
|
|
|
#define MICROBIT_ACCELEROMETER_EVT_8G 10
|
|
|
|
#define MICROBIT_ACCELEROMETER_EVT_SHAKE 11
|
2015-12-03 15:11:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Gesture recogniser constants
|
|
|
|
*/
|
2016-01-05 15:44:57 +00:00
|
|
|
#define MICROBIT_ACCELEROMETER_REST_TOLERANCE 200
|
|
|
|
#define MICROBIT_ACCELEROMETER_TILT_TOLERANCE 200
|
|
|
|
#define MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE 200
|
|
|
|
#define MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE 1000
|
|
|
|
#define MICROBIT_ACCELEROMETER_3G_TOLERANCE 3072
|
|
|
|
#define MICROBIT_ACCELEROMETER_6G_TOLERANCE 6144
|
|
|
|
#define MICROBIT_ACCELEROMETER_8G_TOLERANCE 8192
|
|
|
|
#define MICROBIT_ACCELEROMETER_GESTURE_DAMPING 10
|
|
|
|
#define MICROBIT_ACCELEROMETER_SHAKE_DAMPING 10
|
|
|
|
|
|
|
|
#define MICROBIT_ACCELEROMETER_REST_THRESHOLD (MICROBIT_ACCELEROMETER_REST_TOLERANCE * MICROBIT_ACCELEROMETER_REST_TOLERANCE)
|
|
|
|
#define MICROBIT_ACCELEROMETER_FREEFALL_THRESHOLD (MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE * MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE)
|
|
|
|
#define MICROBIT_ACCELEROMETER_3G_THRESHOLD (MICROBIT_ACCELEROMETER_3G_TOLERANCE * MICROBIT_ACCELEROMETER_3G_TOLERANCE)
|
|
|
|
#define MICROBIT_ACCELEROMETER_6G_THRESHOLD (MICROBIT_ACCELEROMETER_6G_TOLERANCE * MICROBIT_ACCELEROMETER_6G_TOLERANCE)
|
|
|
|
#define MICROBIT_ACCELEROMETER_8G_THRESHOLD (MICROBIT_ACCELEROMETER_8G_TOLERANCE * MICROBIT_ACCELEROMETER_8G_TOLERANCE)
|
|
|
|
#define MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD 4
|
2015-09-08 22:16:15 +00:00
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
struct MMA8653Sample
|
|
|
|
{
|
|
|
|
int16_t x;
|
|
|
|
int16_t y;
|
|
|
|
int16_t z;
|
|
|
|
};
|
|
|
|
|
2015-09-08 22:16:15 +00:00
|
|
|
struct MMA8653SampleRateConfig
|
|
|
|
{
|
|
|
|
uint32_t sample_period;
|
|
|
|
uint8_t ctrl_reg1;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct MMA8653SampleRangeConfig
|
|
|
|
{
|
|
|
|
uint8_t sample_range;
|
|
|
|
uint8_t xyz_data_cfg;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern const MMA8653SampleRangeConfig MMA8653SampleRange[];
|
|
|
|
extern const MMA8653SampleRateConfig MMA8653SampleRate[];
|
|
|
|
|
2015-12-03 15:11:31 +00:00
|
|
|
enum BasicGesture
|
|
|
|
{
|
2016-01-05 15:44:57 +00:00
|
|
|
GESTURE_NONE,
|
|
|
|
GESTURE_UP,
|
|
|
|
GESTURE_DOWN,
|
|
|
|
GESTURE_LEFT,
|
|
|
|
GESTURE_RIGHT,
|
|
|
|
GESTURE_FACE_UP,
|
|
|
|
GESTURE_FACE_DOWN,
|
|
|
|
GESTURE_FREEFALL,
|
|
|
|
GESTURE_3G,
|
|
|
|
GESTURE_6G,
|
|
|
|
GESTURE_8G,
|
|
|
|
GESTURE_SHAKE
|
2015-12-03 15:11:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ShakeHistory
|
|
|
|
{
|
2016-01-05 15:44:57 +00:00
|
|
|
uint16_t shaken:1,
|
|
|
|
x:1,
|
|
|
|
y:1,
|
|
|
|
z:1,
|
|
|
|
count:4,
|
|
|
|
timer:8;
|
2015-12-03 15:11:31 +00:00
|
|
|
};
|
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Class definition for MicroBit Accelerometer.
|
|
|
|
*
|
|
|
|
* Represents an implementation of the Freescale MMA8653 3 axis accelerometer
|
|
|
|
* Also includes basic data caching and on demand activation.
|
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
class MicroBitAccelerometer : public MicroBitComponent
|
|
|
|
{
|
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Unique, enumerated ID for this component.
|
|
|
|
* Used to track asynchronous events in the event bus.
|
|
|
|
*/
|
|
|
|
|
|
|
|
MMA8653Sample sample; // The last sample read.
|
|
|
|
DigitalIn int1; // Data ready interrupt.
|
|
|
|
uint16_t address; // I2C address of this accelerometer.
|
|
|
|
uint16_t samplePeriod; // The time between samples, in milliseconds.
|
|
|
|
uint8_t sampleRange; // The sample range of the accelerometer in g.
|
|
|
|
uint8_t sigma; // the number of ticks that the instantaneous gesture has been stable.
|
|
|
|
BasicGesture lastGesture; // the last, stable gesture recorded.
|
|
|
|
BasicGesture currentGesture; // the instantaneous, unfiltered gesture detected.
|
|
|
|
ShakeHistory shake; // State information needed to detect shake events.
|
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
public:
|
2016-01-05 15:44:57 +00:00
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Constructor.
|
|
|
|
* Create an accelerometer representation with the given ID.
|
|
|
|
* @param id the ID of the new object.
|
|
|
|
* @param address the default base address of the accelerometer.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* accelerometer(MICROBIT_ID_ACCELEROMETER, MMA8653_DEFAULT_ADDR)
|
|
|
|
* @endcode
|
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
MicroBitAccelerometer(uint16_t id, uint16_t address);
|
2016-01-05 15:44:57 +00:00
|
|
|
|
2015-09-08 22:16:15 +00:00
|
|
|
/**
|
|
|
|
* Configures the accelerometer for G range and sample rate defined
|
|
|
|
* in this object. The nearest values are chosen to those defined
|
|
|
|
* that are supported by the hardware. The instance variables are then
|
|
|
|
* updated to reflect reality.
|
2015-10-25 21:51:33 +00:00
|
|
|
*
|
|
|
|
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the accelerometer could not be configured.
|
2015-09-08 22:16:15 +00:00
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int configure();
|
2015-09-08 22:16:15 +00:00
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Reads the acceleration data from the accelerometer, and stores it in our buffer.
|
|
|
|
* This is called by the tick() member function, if the interrupt is set.
|
|
|
|
*
|
|
|
|
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the read request fails.
|
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int update();
|
2016-01-05 15:44:57 +00:00
|
|
|
|
2015-09-08 22:16:15 +00:00
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Attempts to set the sample rate of the accelerometer to the specified value (in ms).
|
|
|
|
* n.b. the requested rate may not be possible on the hardware. In this case, the
|
|
|
|
* nearest lower rate is chosen.
|
|
|
|
* @param period the requested time between samples, in milliseconds.
|
|
|
|
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails.
|
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int setPeriod(int period);
|
2015-09-08 22:16:15 +00:00
|
|
|
|
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Reads the currently configured sample rate of the accelerometer.
|
|
|
|
* @return The time between samples, in milliseconds.
|
|
|
|
*/
|
2015-09-08 22:16:15 +00:00
|
|
|
int getPeriod();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Attempts to set the sample range of the accelerometer to the specified value (in g).
|
|
|
|
* n.b. the requested range may not be possible on the hardware. In this case, the
|
|
|
|
* nearest lower rate is chosen.
|
|
|
|
* @param range The requested sample range of samples, in g.
|
2015-10-25 21:51:33 +00:00
|
|
|
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails.
|
2015-09-08 22:16:15 +00:00
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int setRange(int range);
|
2015-09-08 22:16:15 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads the currently configured sample range of the accelerometer.
|
|
|
|
* @return The sample range, in g.
|
|
|
|
*/
|
|
|
|
int getRange();
|
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Attempts to determine the 8 bit ID from the accelerometer.
|
|
|
|
* @return the 8 bit ID returned by the accelerometer, or MICROBIT_I2C_ERROR if the request fails.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* uBit.accelerometer.whoAmI();
|
|
|
|
* @endcode
|
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
int whoAmI();
|
|
|
|
|
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Reads the X axis value of the latest update from the accelerometer.
|
|
|
|
* Currently limited to +/- 2g
|
|
|
|
* @return The force measured in the X axis, in milli-g.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* uBit.accelerometer.getX();
|
|
|
|
* @endcode
|
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
int getX();
|
2016-01-05 15:44:57 +00:00
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Reads the Y axis value of the latest update from the accelerometer.
|
|
|
|
* Currently limited to +/- 2g
|
|
|
|
* @return The force measured in the Y axis, in milli-g.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* uBit.accelerometer.getY();
|
|
|
|
* @endcode
|
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
int getY();
|
2016-01-05 15:44:57 +00:00
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Reads the Z axis value of the latest update from the accelerometer.
|
|
|
|
* Currently limited to +/- 2g
|
|
|
|
* @return The force measured in the Z axis, in milli-g.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* uBit.accelerometer.getZ();
|
|
|
|
* @endcode
|
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
int getZ();
|
|
|
|
|
2015-12-03 15:11:31 +00:00
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Reads the last recorded gesture detected.
|
|
|
|
* @return The last gesture detected.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* if (uBit.accelerometer.getGesture() == SHAKE)
|
|
|
|
* @endcode
|
|
|
|
*/
|
2015-12-03 15:11:31 +00:00
|
|
|
BasicGesture getGesture();
|
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* periodic callback from MicroBit idle thread.
|
|
|
|
* Check if any data is ready for reading by checking the interrupt flag on the accelerometer
|
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
virtual void idleTick();
|
2016-01-05 15:44:57 +00:00
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Returns 0 or 1. 1 indicates data is waiting to be read, zero means data is not ready to be read.
|
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
virtual int isIdleCallbackNeeded();
|
2016-01-05 15:44:57 +00:00
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
private:
|
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Issues a standard, 2 byte I2C command write to the accelerometer.
|
|
|
|
* Blocks the calling thread until complete.
|
|
|
|
*
|
|
|
|
* @param reg The address of the register to write to.
|
|
|
|
* @param value The value to write.
|
|
|
|
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the the write request failed.
|
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int writeCommand(uint8_t reg, uint8_t value);
|
2016-01-05 15:44:57 +00:00
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
/**
|
2016-01-05 15:44:57 +00:00
|
|
|
* Issues a read command into the specified buffer.
|
|
|
|
* Blocks the calling thread until complete.
|
|
|
|
*
|
|
|
|
* @param reg The address of the register to access.
|
|
|
|
* @param buffer Memory area to read the data into.
|
|
|
|
* @param length The number of bytes to read.
|
|
|
|
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER or MICROBIT_I2C_ERROR if the the read request failed.
|
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int readCommand(uint8_t reg, uint8_t* buffer, int length);
|
2015-12-03 15:11:31 +00:00
|
|
|
|
2016-01-05 15:44:57 +00:00
|
|
|
/**
|
|
|
|
* Updates the basic gesture recognizer. This performs instantaneous pose recognition, and also some low pass filtering to promote
|
|
|
|
* stability.
|
|
|
|
*/
|
|
|
|
void updateGesture();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Service function. Calculates the current scalar acceleration of the device (x^2 + y^2 + z^2).
|
|
|
|
* It does not, however, square root the result, as this is a relatively high cost operation.
|
|
|
|
* This is left to application code should it be needed.
|
|
|
|
* @return the sum of the square of the acceleration of the device across all axes.
|
|
|
|
*/
|
|
|
|
int instantaneousAccelerationSquared();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Service function. Determines the best guess posture of the device based on instantaneous data.
|
|
|
|
* This makes no use of historic data, and forms this input to th filter implemented in updateGesture().
|
|
|
|
* @return A best guess of the curret posture of the device, based on instanataneous data.
|
|
|
|
*/
|
|
|
|
BasicGesture instantaneousPosture();
|
2015-08-12 10:53:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|