Attempting to publish a tree

Dependencies:   BLE_API mbed-dev-bin nRF51822

Fork of microbit-dal by Lancaster University

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MicroBitAccelerometer.h Source File

MicroBitAccelerometer.h

00001 /*
00002 The MIT License (MIT)
00003 
00004 Copyright (c) 2016 British Broadcasting Corporation.
00005 This software is provided by Lancaster University by arrangement with the BBC.
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a
00008 copy of this software and associated documentation files (the "Software"),
00009 to deal in the Software without restriction, including without limitation
00010 the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011 and/or sell copies of the Software, and to permit persons to whom the
00012 Software is furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00020 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00022 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00023 DEALINGS IN THE SOFTWARE.
00024 */
00025 
00026 #ifndef MICROBIT_ACCELEROMETER_H
00027 #define MICROBIT_ACCELEROMETER_H
00028 
00029 #include "mbed.h"
00030 #include "MicroBitConfig.h"
00031 #include "MicroBitComponent.h"
00032 #include "MicroBitCoordinateSystem.h"
00033 #include "MicroBitI2C.h"
00034 
00035 /**
00036   * Relevant pin assignments
00037   */
00038 #define MICROBIT_PIN_ACCEL_DATA_READY          P0_28
00039 
00040 /**
00041   * Status flags
00042   */
00043 #define MICROBIT_ACCEL_PITCH_ROLL_VALID           0x02
00044 #define MICROBIT_ACCEL_ADDED_TO_IDLE              0x04
00045 
00046 /**
00047   * I2C constants
00048   */
00049 #define MMA8653_DEFAULT_ADDR    0x3A
00050 
00051 /**
00052   * MMA8653 Register map (partial)
00053   */
00054 #define MMA8653_STATUS          0x00
00055 #define MMA8653_OUT_X_MSB       0x01
00056 #define MMA8653_WHOAMI          0x0D
00057 #define MMA8653_XYZ_DATA_CFG    0x0E
00058 #define MMA8653_CTRL_REG1       0x2A
00059 #define MMA8653_CTRL_REG2       0x2B
00060 #define MMA8653_CTRL_REG3       0x2C
00061 #define MMA8653_CTRL_REG4       0x2D
00062 #define MMA8653_CTRL_REG5       0x2E
00063 
00064 
00065 /**
00066   * MMA8653 constants
00067   */
00068 #define MMA8653_WHOAMI_VAL      0x5A
00069 
00070 #define MMA8653_SAMPLE_RANGES   3
00071 #define MMA8653_SAMPLE_RATES    8
00072 
00073 /**
00074   * Accelerometer events
00075   */
00076 #define MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE              1
00077 
00078 /**
00079   * Gesture events
00080   */
00081 #define MICROBIT_ACCELEROMETER_EVT_TILT_UP                  1
00082 #define MICROBIT_ACCELEROMETER_EVT_TILT_DOWN                2
00083 #define MICROBIT_ACCELEROMETER_EVT_TILT_LEFT                3
00084 #define MICROBIT_ACCELEROMETER_EVT_TILT_RIGHT               4
00085 #define MICROBIT_ACCELEROMETER_EVT_FACE_UP                  5
00086 #define MICROBIT_ACCELEROMETER_EVT_FACE_DOWN                6
00087 #define MICROBIT_ACCELEROMETER_EVT_FREEFALL                 7
00088 #define MICROBIT_ACCELEROMETER_EVT_3G                       8
00089 #define MICROBIT_ACCELEROMETER_EVT_6G                       9
00090 #define MICROBIT_ACCELEROMETER_EVT_8G                       10
00091 #define MICROBIT_ACCELEROMETER_EVT_SHAKE                    11
00092 
00093 /**
00094   * Gesture recogniser constants
00095   */
00096 #define MICROBIT_ACCELEROMETER_REST_TOLERANCE               200
00097 #define MICROBIT_ACCELEROMETER_TILT_TOLERANCE               200
00098 #define MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE           400
00099 #define MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE              1000
00100 #define MICROBIT_ACCELEROMETER_3G_TOLERANCE                 3072
00101 #define MICROBIT_ACCELEROMETER_6G_TOLERANCE                 6144
00102 #define MICROBIT_ACCELEROMETER_8G_TOLERANCE                 8192
00103 #define MICROBIT_ACCELEROMETER_GESTURE_DAMPING              10
00104 #define MICROBIT_ACCELEROMETER_SHAKE_DAMPING                10
00105 
00106 #define MICROBIT_ACCELEROMETER_REST_THRESHOLD               (MICROBIT_ACCELEROMETER_REST_TOLERANCE * MICROBIT_ACCELEROMETER_REST_TOLERANCE)
00107 #define MICROBIT_ACCELEROMETER_FREEFALL_THRESHOLD           (MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE * MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE)
00108 #define MICROBIT_ACCELEROMETER_3G_THRESHOLD                 (MICROBIT_ACCELEROMETER_3G_TOLERANCE * MICROBIT_ACCELEROMETER_3G_TOLERANCE)
00109 #define MICROBIT_ACCELEROMETER_6G_THRESHOLD                 (MICROBIT_ACCELEROMETER_6G_TOLERANCE * MICROBIT_ACCELEROMETER_6G_TOLERANCE)
00110 #define MICROBIT_ACCELEROMETER_8G_THRESHOLD                 (MICROBIT_ACCELEROMETER_8G_TOLERANCE * MICROBIT_ACCELEROMETER_8G_TOLERANCE)
00111 #define MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD        4
00112 
00113 struct MMA8653Sample
00114 {
00115     int16_t         x;
00116     int16_t         y;
00117     int16_t         z;
00118 };
00119 
00120 struct MMA8653SampleRateConfig
00121 {
00122     uint32_t        sample_period;
00123     uint8_t         ctrl_reg1;
00124 };
00125 
00126 struct MMA8653SampleRangeConfig
00127 {
00128     uint8_t         sample_range;
00129     uint8_t         xyz_data_cfg;
00130 };
00131 
00132 
00133 extern const MMA8653SampleRangeConfig MMA8653SampleRange[];
00134 extern const MMA8653SampleRateConfig MMA8653SampleRate[];
00135 
00136 enum BasicGesture
00137 {
00138     GESTURE_NONE,
00139     GESTURE_UP,
00140     GESTURE_DOWN,
00141     GESTURE_LEFT,
00142     GESTURE_RIGHT,
00143     GESTURE_FACE_UP,
00144     GESTURE_FACE_DOWN,
00145     GESTURE_FREEFALL,
00146     GESTURE_3G,
00147     GESTURE_6G,
00148     GESTURE_8G,
00149     GESTURE_SHAKE
00150 };
00151 
00152 struct ShakeHistory
00153 {
00154     uint16_t    shaken:1,
00155                 x:1,
00156                 y:1,
00157                 z:1,
00158                 count:4,
00159                 timer:8;
00160 };
00161 
00162 /**
00163  * Class definition for MicroBit Accelerometer.
00164  *
00165  * Represents an implementation of the Freescale MMA8653 3 axis accelerometer
00166  * Also includes basic data caching and on demand activation.
00167  */
00168 class MicroBitAccelerometer : public MicroBitComponent
00169 {
00170     uint16_t        address;            // I2C address of this accelerometer.
00171     uint16_t        samplePeriod;       // The time between samples, in milliseconds.
00172     uint8_t         sampleRange;        // The sample range of the accelerometer in g.
00173     MMA8653Sample   sample;             // The last sample read.
00174     DigitalIn       int1;               // Data ready interrupt.
00175     float           pitch;              // Pitch of the device, in radians.
00176     MicroBitI2C&    i2c;                // The I2C interface to use.
00177     float           roll;               // Roll of the device, in radians.
00178     uint8_t         sigma;              // the number of ticks that the instantaneous gesture has been stable.
00179     BasicGesture    lastGesture;        // the last, stable gesture recorded.
00180     BasicGesture    currentGesture;     // the instantaneous, unfiltered gesture detected.
00181     ShakeHistory    shake;              // State information needed to detect shake events.
00182 
00183     public:
00184 
00185     /**
00186       * Constructor.
00187       * Create a software abstraction of an accelerometer.
00188       *
00189       * @param _i2c an instance of MicroBitI2C used to communicate with the onboard accelerometer.
00190       *
00191       * @param address the default I2C address of the accelerometer. Defaults to: MMA8653_DEFAULT_ADDR.
00192       *
00193       * @param id the unique EventModel id of this component. Defaults to: MICROBIT_ID_ACCELEROMETER
00194       *
00195       * @code
00196       * MicroBitI2C i2c = MicroBitI2C(I2C_SDA0, I2C_SCL0);
00197       *
00198       * MicroBitAccelerometer accelerometer = MicroBitAccelerometer(i2c);
00199       * @endcode
00200      */
00201     MicroBitAccelerometer(MicroBitI2C &_i2c, uint16_t address = MMA8653_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_ACCELEROMETER);
00202 
00203     /**
00204       * Configures the accelerometer for G range and sample rate defined
00205       * in this object. The nearest values are chosen to those defined
00206       * that are supported by the hardware. The instance variables are then
00207       * updated to reflect reality.
00208       *
00209       * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the accelerometer could not be configured.
00210       */
00211     int configure();
00212 
00213     /**
00214       * Reads the acceleration data from the accelerometer, and stores it in our buffer.
00215       * This only happens if the accelerometer indicates that it has new data via int1.
00216       *
00217       * On first use, this member function will attempt to add this component to the
00218       * list of fiber components in order to constantly update the values stored
00219       * by this object.
00220       *
00221       * This technique is called lazy instantiation, and it means that we do not
00222       * obtain the overhead from non-chalantly adding this component to fiber components.
00223       *
00224       * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the read request fails.
00225       */
00226     int updateSample();
00227 
00228     /**
00229       * Attempts to set the sample rate of the accelerometer to the specified value (in ms).
00230       *
00231       * @param period the requested time between samples, in milliseconds.
00232       *
00233       * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails.
00234       *
00235       * @code
00236       * // sample rate is now 20 ms.
00237       * accelerometer.setPeriod(20);
00238       * @endcode
00239       *
00240       * @note The requested rate may not be possible on the hardware. In this case, the
00241       * nearest lower rate is chosen.
00242       */
00243     int setPeriod(int period);
00244 
00245     /**
00246       * Reads the currently configured sample rate of the accelerometer.
00247       *
00248       * @return The time between samples, in milliseconds.
00249       */
00250     int getPeriod();
00251 
00252     /**
00253       * Attempts to set the sample range of the accelerometer to the specified value (in g).
00254       *
00255       * @param range The requested sample range of samples, in g.
00256       *
00257       * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails.
00258       *
00259       * @code
00260       * // the sample range of the accelerometer is now 8G.
00261       * accelerometer.setRange(8);
00262       * @endcode
00263       *
00264       * @note The requested range may not be possible on the hardware. In this case, the
00265       * nearest lower range is chosen.
00266       */
00267     int setRange(int range);
00268 
00269     /**
00270       * Reads the currently configured sample range of the accelerometer.
00271       *
00272       * @return The sample range, in g.
00273       */
00274     int getRange();
00275 
00276     /**
00277       * Attempts to read the 8 bit ID from the accelerometer, this can be used for
00278       * validation purposes.
00279       *
00280       * @return the 8 bit ID returned by the accelerometer, or MICROBIT_I2C_ERROR if the request fails.
00281       *
00282       * @code
00283       * accelerometer.whoAmI();
00284       * @endcode
00285       */
00286     int whoAmI();
00287 
00288     /**
00289       * Reads the value of the X axis from the latest update retrieved from the accelerometer.
00290       *
00291       * @param system The coordinate system to use. By default, a simple cartesian system is provided.
00292       *
00293       * @return The force measured in the X axis, in milli-g.
00294       *
00295       * @code
00296       * accelerometer.getX();
00297       * @endcode
00298       */
00299     int getX(MicroBitCoordinateSystem system = SIMPLE_CARTESIAN);
00300 
00301     /**
00302       * Reads the value of the Y axis from the latest update retrieved from the accelerometer.
00303       *
00304       * @return The force measured in the Y axis, in milli-g.
00305       *
00306       * @code
00307       * accelerometer.getY();
00308       * @endcode
00309       */
00310     int getY(MicroBitCoordinateSystem system = SIMPLE_CARTESIAN);
00311 
00312     /**
00313       * Reads the value of the Z axis from the latest update retrieved from the accelerometer.
00314       *
00315       * @return The force measured in the Z axis, in milli-g.
00316       *
00317       * @code
00318       * accelerometer.getZ();
00319       * @endcode
00320       */
00321     int getZ(MicroBitCoordinateSystem system = SIMPLE_CARTESIAN);
00322 
00323     /**
00324       * Provides a rotation compensated pitch of the device, based on the latest update retrieved from the accelerometer.
00325       *
00326       * @return The pitch of the device, in degrees.
00327       *
00328       * @code
00329       * accelerometer.getPitch();
00330       * @endcode
00331       */
00332     int getPitch();
00333 
00334     /**
00335       * Provides a rotation compensated pitch of the device, based on the latest update retrieved from the accelerometer.
00336       *
00337       * @return The pitch of the device, in radians.
00338       *
00339       * @code
00340       * accelerometer.getPitchRadians();
00341       * @endcode
00342       */
00343     float getPitchRadians();
00344 
00345     /**
00346       * Provides a rotation compensated roll of the device, based on the latest update retrieved from the accelerometer.
00347       *
00348       * @return The roll of the device, in degrees.
00349       *
00350       * @code
00351       * accelerometer.getRoll();
00352       * @endcode
00353       */
00354     int getRoll();
00355 
00356     /**
00357       * Provides a rotation compensated roll of the device, based on the latest update retrieved from the accelerometer.
00358       *
00359       * @return The roll of the device, in radians.
00360       *
00361       * @code
00362       * accelerometer.getRollRadians();
00363       * @endcode
00364       */
00365     float getRollRadians();
00366 
00367     /**
00368       * Retrieves the last recorded gesture.
00369       *
00370       * @return The last gesture that was detected.
00371       *
00372       * Example:
00373       * @code
00374       * MicroBitDisplay display;
00375       *
00376       * if (accelerometer.getGesture() == SHAKE)
00377       *     display.scroll("SHAKE!");
00378       * @endcode
00379       */
00380     BasicGesture getGesture();
00381 
00382     /**
00383       * A periodic callback invoked by the fiber scheduler idle thread.
00384       *
00385       * Internally calls updateSample().
00386       */
00387     virtual void idleTick();
00388 
00389     /**
00390       * Returns 0 or 1. 1 indicates data is waiting to be read, zero means data is not ready to be read.
00391       *
00392       * We check if any data is ready for reading by checking the interrupt flag on the accelerometer.
00393       */
00394     virtual int isIdleCallbackNeeded();
00395 
00396     /**
00397       * Destructor for MicroBitButton, where we deregister this instance from the array of fiber components.
00398       */
00399     ~MicroBitAccelerometer();
00400 
00401     private:
00402 
00403     /**
00404       * Issues a standard, 2 byte I2C command write to the accelerometer.
00405       *
00406       * Blocks the calling thread until complete.
00407       *
00408       * @param reg The address of the register to write to.
00409       *
00410       * @param value The value to write.
00411       *
00412       * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the the write request failed.
00413       */
00414     int writeCommand(uint8_t reg, uint8_t value);
00415 
00416     /**
00417       * Issues a read command, copying data into the specified buffer.
00418       *
00419       * Blocks the calling thread until complete.
00420       *
00421       * @param reg The address of the register to access.
00422       *
00423       * @param buffer Memory area to read the data into.
00424       *
00425       * @param length The number of bytes to read.
00426       *
00427       * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER or MICROBIT_I2C_ERROR if the the read request failed.
00428       */
00429     int readCommand(uint8_t reg, uint8_t* buffer, int length);
00430 
00431     /**
00432       * Recalculate roll and pitch values for the current sample.
00433       *
00434       * @note We only do this at most once per sample, as the necessary trigonemteric functions are rather
00435       *       heavyweight for a CPU without a floating point unit.
00436       */
00437     void recalculatePitchRoll();
00438 
00439     /**
00440       * Updates the basic gesture recognizer. This performs instantaneous pose recognition, and also some low pass filtering to promote
00441       * stability.
00442       */
00443     void updateGesture();
00444 
00445     /**
00446       * A service function.
00447       * It calculates the current scalar acceleration of the device (x^2 + y^2 + z^2).
00448       * It does not, however, square root the result, as this is a relatively high cost operation.
00449       *
00450       * This is left to application code should it be needed.
00451       *
00452       * @return the sum of the square of the acceleration of the device across all axes.
00453       */
00454     int instantaneousAccelerationSquared();
00455 
00456     /**
00457      * Service function.
00458      * Determines a 'best guess' posture of the device based on instantaneous data.
00459      *
00460      * This makes no use of historic data, and forms this input to the filter implemented in updateGesture().
00461      *
00462      * @return A 'best guess' of the current posture of the device, based on instanataneous data.
00463      */
00464     BasicGesture instantaneousPosture();
00465 };
00466 
00467 #endif