mbed.org local branch of microbit-dal. The real version lives in git at https://github.com/lancaster-university/microbit-dal

Dependencies:   BLE_API nRF51822 mbed-dev-bin

Dependents:   microbit Microbit IoTChallenge1 microbit ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MicroBitCompass.h Source File

MicroBitCompass.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_COMPASS_H
00027 #define MICROBIT_COMPASS_H
00028 
00029 #include "mbed.h"
00030 #include "MicroBitConfig.h"
00031 #include "MicroBitComponent.h"
00032 #include "MicroBitCoordinateSystem.h"
00033 #include "MicroBitAccelerometer.h"
00034 #include "MicroBitStorage.h"
00035 
00036 /**
00037   * Relevant pin assignments
00038   */
00039 #define MICROBIT_PIN_COMPASS_DATA_READY          P0_29
00040 
00041 /**
00042   * I2C constants
00043   */
00044 #define MAG3110_DEFAULT_ADDR    0x1D
00045 
00046 /**
00047   * MAG3110 Register map
00048   */
00049 #define MAG_DR_STATUS 0x00
00050 #define MAG_OUT_X_MSB 0x01
00051 #define MAG_OUT_X_LSB 0x02
00052 #define MAG_OUT_Y_MSB 0x03
00053 #define MAG_OUT_Y_LSB 0x04
00054 #define MAG_OUT_Z_MSB 0x05
00055 #define MAG_OUT_Z_LSB 0x06
00056 #define MAG_WHOAMI    0x07
00057 #define MAG_SYSMOD    0x08
00058 #define MAG_OFF_X_MSB 0x09
00059 #define MAG_OFF_X_LSB 0x0A
00060 #define MAG_OFF_Y_MSB 0x0B
00061 #define MAG_OFF_Y_LSB 0x0C
00062 #define MAG_OFF_Z_MSB 0x0D
00063 #define MAG_OFF_Z_LSB 0x0E
00064 #define MAG_DIE_TEMP  0x0F
00065 #define MAG_CTRL_REG1 0x10
00066 #define MAG_CTRL_REG2 0x11
00067 
00068 /**
00069   * Configuration options
00070   */
00071 struct MAG3110SampleRateConfig
00072 {
00073     uint32_t        sample_period;
00074     uint8_t         ctrl_reg1;
00075 };
00076 
00077 extern const MAG3110SampleRateConfig MAG3110SampleRate[];
00078 
00079 #define MAG3110_SAMPLE_RATES                    11
00080 
00081 /**
00082   * Compass events
00083   */
00084 #define MICROBIT_COMPASS_EVT_CAL_REQUIRED       1               // DEPRECATED
00085 #define MICROBIT_COMPASS_EVT_CAL_START          2               // DEPRECATED
00086 #define MICROBIT_COMPASS_EVT_CAL_END            3               // DEPRECATED
00087 
00088 #define MICROBIT_COMPASS_EVT_DATA_UPDATE        4
00089 #define MICROBIT_COMPASS_EVT_CONFIG_NEEDED      5
00090 #define MICROBIT_COMPASS_EVT_CALIBRATE          6
00091 
00092 /**
00093   * Status Bits
00094   */
00095 #define MICROBIT_COMPASS_STATUS_CALIBRATED      2
00096 #define MICROBIT_COMPASS_STATUS_CALIBRATING     4
00097 #define MICROBIT_COMPASS_STATUS_ADDED_TO_IDLE   8
00098 
00099 /**
00100   * Term to convert sample data into SI units
00101   */
00102 #define MAG3110_NORMALIZE_SAMPLE(x) (100*x)
00103 
00104 /**
00105   * MAG3110 MAGIC ID value
00106   * Returned from the MAG_WHO_AM_I register for ID purposes.
00107   */
00108 #define MAG3110_WHOAMI_VAL 0xC4
00109 
00110 struct CompassSample
00111 {
00112     int     x;
00113     int     y;
00114     int     z;
00115 
00116     CompassSample()
00117     {
00118         this->x = 0;
00119         this->y = 0;
00120         this->z = 0;
00121     }
00122 
00123     CompassSample(int x, int y, int z)
00124     {
00125         this->x = x;
00126         this->y = y;
00127         this->z = z;
00128     }
00129 
00130     bool operator==(const CompassSample& other) const
00131     {
00132         return x == other.x && y == other.y && z == other.z;
00133     }
00134 
00135     bool operator!=(const CompassSample& other) const
00136     {
00137         return !(x == other.x && y == other.y && z == other.z);
00138     }
00139 };
00140 
00141 /**
00142   * Class definition for MicroBit Compass.
00143   *
00144   * Represents an implementation of the Freescale MAG3110 I2C Magnetmometer.
00145   * Also includes basic caching, calibration and on demand activation.
00146   */
00147 class MicroBitCompass : public MicroBitComponent
00148 {
00149     uint16_t                address;                  // I2C address of the magnetmometer.
00150     uint16_t                samplePeriod;             // The time between samples, in millseconds.
00151 
00152     CompassSample           average;                  // Centre point of sample data.
00153     CompassSample           sample;                   // The latest sample data recorded.
00154     DigitalIn               int1;                     // Data ready interrupt.
00155     MicroBitI2C&            i2c;                      // The I2C interface the sensor is connected to.
00156     MicroBitAccelerometer*  accelerometer;            // The accelerometer to use for tilt compensation.
00157     MicroBitStorage*        storage;                  // An instance of MicroBitStorage used for persistence.
00158 
00159     public:
00160 
00161     /**
00162       * Constructor.
00163       * Create a software representation of an e-compass.
00164       *
00165       * @param _i2c an instance of i2c, which the compass is accessible from.
00166       *
00167       * @param _accelerometer an instance of the accelerometer, used for tilt compensation.
00168       *
00169       * @param _storage an instance of MicroBitStorage, used to persist calibration data across resets.
00170       *
00171       * @param address the default address for the compass register on the i2c bus. Defaults to MAG3110_DEFAULT_ADDR.
00172       *
00173       * @param id the ID of the new MicroBitCompass object. Defaults to MAG3110_DEFAULT_ADDR.
00174       *
00175       * @code
00176       * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
00177       *
00178       * MicroBitAccelerometer accelerometer(i2c);
00179       *
00180       * MicroBitStorage storage;
00181       *
00182       * MicroBitCompass compass(i2c, accelerometer, storage);
00183       * @endcode
00184       */
00185     MicroBitCompass(MicroBitI2C& _i2c, MicroBitAccelerometer& _accelerometer, MicroBitStorage& _storage, uint16_t address = MAG3110_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_COMPASS);
00186 
00187     /**
00188       * Constructor.
00189       * Create a software representation of an e-compass.
00190       *
00191       * @param _i2c an instance of i2c, which the compass is accessible from.
00192       *
00193       * @param _accelerometer an instance of the accelerometer, used for tilt compensation.
00194       *
00195       * @param address the default address for the compass register on the i2c bus. Defaults to MAG3110_DEFAULT_ADDR.
00196       *
00197       * @param id the ID of the new MicroBitCompass object. Defaults to MAG3110_DEFAULT_ADDR.
00198       *
00199       * @code
00200       * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
00201       *
00202       * MicroBitAccelerometer accelerometer(i2c);
00203       *
00204       * MicroBitCompass compass(i2c, accelerometer, storage);
00205       * @endcode
00206       */
00207     MicroBitCompass(MicroBitI2C& _i2c, MicroBitAccelerometer& _accelerometer, uint16_t address = MAG3110_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_COMPASS);
00208 
00209     /**
00210       * Constructor.
00211       * Create a software representation of an e-compass.
00212       *
00213       * @param _i2c an instance of i2c, which the compass is accessible from.
00214       *
00215       * @param _storage an instance of MicroBitStorage, used to persist calibration data across resets.
00216       *
00217       * @param address the default address for the compass register on the i2c bus. Defaults to MAG3110_DEFAULT_ADDR.
00218       *
00219       * @param id the ID of the new MicroBitCompass object. Defaults to MAG3110_DEFAULT_ADDR.
00220       *
00221       * @code
00222       * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
00223       *
00224       * MicroBitStorage storage;
00225       *
00226       * MicroBitCompass compass(i2c, storage);
00227       * @endcode
00228       */
00229     MicroBitCompass(MicroBitI2C& _i2c, MicroBitStorage& _storage, uint16_t address = MAG3110_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_COMPASS);
00230 
00231     /**
00232       * Constructor.
00233       * Create a software representation of an e-compass.
00234       *
00235       * @param _i2c an instance of i2c, which the compass is accessible from.
00236       *
00237       * @param address the default address for the compass register on the i2c bus. Defaults to MAG3110_DEFAULT_ADDR.
00238       *
00239       * @param id the ID of the new MicroBitCompass object. Defaults to MAG3110_DEFAULT_ADDR.
00240       *
00241       * @code
00242       * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
00243       *
00244       * MicroBitCompass compass(i2c);
00245       * @endcode
00246       */
00247     MicroBitCompass(MicroBitI2C& _i2c, uint16_t address = MAG3110_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_COMPASS);
00248 
00249     /**
00250       * Configures the compass for the sample rate defined in this object.
00251       * The nearest values are chosen to those defined that are supported by the hardware.
00252       * The instance variables are then updated to reflect reality.
00253       *
00254       * @return MICROBIT_OK or MICROBIT_I2C_ERROR if the magnetometer could not be configured.
00255       */
00256     int configure();
00257 
00258     /**
00259       * Attempts to set the sample rate of the compass to the specified value (in ms).
00260       *
00261       * @param period the requested time between samples, in milliseconds.
00262       *
00263       * @return MICROBIT_OK or MICROBIT_I2C_ERROR if the magnetometer could not be updated.
00264       *
00265       * @code
00266       * // sample rate is now 20 ms.
00267       * compass.setPeriod(20);
00268       * @endcode
00269       *
00270       * @note The requested rate may not be possible on the hardware. In this case, the
00271       * nearest lower rate is chosen.
00272       */
00273     int setPeriod(int period);
00274 
00275     /**
00276       * Reads the currently configured sample rate of the compass.
00277       *
00278       * @return The time between samples, in milliseconds.
00279       */
00280     int getPeriod();
00281 
00282     /**
00283       * Gets the current heading of the device, relative to magnetic north.
00284       *
00285       * If the compass is not calibrated, it will raise the MICROBIT_COMPASS_EVT_CALIBRATE event.
00286       *
00287       * Users wishing to implement their own calibration algorithms should listen for this event,
00288       * using MESSAGE_BUS_LISTENER_IMMEDIATE model. This ensures that calibration is complete before
00289       * the user program continues.
00290       *
00291       * @return the current heading, in degrees. Or MICROBIT_CALIBRATION_IN_PROGRESS if the compass is calibrating.
00292       *
00293       * @code
00294       * compass.heading();
00295       * @endcode
00296       */
00297     int heading();
00298 
00299     /**
00300       * Attempts to read the 8 bit ID from the magnetometer, this can be used for
00301       * validation purposes.
00302       *
00303       * @return the 8 bit ID returned by the magnetometer, or MICROBIT_I2C_ERROR if the request fails.
00304       *
00305       * @code
00306       * compass.whoAmI();
00307       * @endcode
00308       */
00309     int whoAmI();
00310 
00311     /**
00312       * Reads the value of the X axis from the latest update retrieved from the magnetometer.
00313       *
00314       * @param system The coordinate system to use. By default, a simple cartesian system is provided.
00315       *
00316       * @return The magnetic force measured in the X axis, in nano teslas.
00317       *
00318       * @code
00319       * compass.getX();
00320       * @endcode
00321       */
00322     int getX(MicroBitCoordinateSystem system = SIMPLE_CARTESIAN);
00323 
00324     /**
00325       * Reads the value of the Y axis from the latest update retrieved from the magnetometer.
00326       *
00327       * @param system The coordinate system to use. By default, a simple cartesian system is provided.
00328       *
00329       * @return The magnetic force measured in the Y axis, in nano teslas.
00330       *
00331       * @code
00332       * compass.getY();
00333       * @endcode
00334       */
00335     int getY(MicroBitCoordinateSystem system = SIMPLE_CARTESIAN);
00336 
00337     /**
00338       * Reads the value of the Z axis from the latest update retrieved from the magnetometer.
00339       *
00340       * @param system The coordinate system to use. By default, a simple cartesian system is provided.
00341       *
00342       * @return The magnetic force measured in the Z axis, in nano teslas.
00343       *
00344       * @code
00345       * compass.getZ();
00346       * @endcode
00347       */
00348     int getZ(MicroBitCoordinateSystem system = SIMPLE_CARTESIAN);
00349 
00350     /**
00351       * Determines the overall magnetic field strength based on the latest update from the magnetometer.
00352       *
00353       * @return The magnetic force measured across all axis, in nano teslas.
00354       *
00355       * @code
00356       * compass.getFieldStrength();
00357       * @endcode
00358       */
00359     int getFieldStrength();
00360 
00361     /**
00362       * Reads the current die temperature of the compass.
00363       *
00364       * @return the temperature in degrees celsius, or MICROBIT_I2C_ERROR if the temperature reading could not be retreived
00365       *         from the accelerometer.
00366       */
00367     int readTemperature();
00368 
00369     /**
00370       * Perform a calibration of the compass.
00371       *
00372       * This method will be called automatically if a user attempts to read a compass value when
00373       * the compass is uncalibrated. It can also be called at any time by the user.
00374       *
00375       * The method will only return once the compass has been calibrated.
00376       *
00377       * @return MICROBIT_OK, MICROBIT_I2C_ERROR if the magnetometer could not be accessed,
00378       * or MICROBIT_CALIBRATION_REQUIRED if the calibration algorithm failed to complete successfully.
00379       *
00380       * @note THIS MUST BE CALLED TO GAIN RELIABLE VALUES FROM THE COMPASS
00381       */
00382     int calibrate();
00383 
00384     /**
00385       * Configure the compass to use the calibration data that is supplied to this call.
00386       *
00387       * Calibration data is comprised of the perceived zero offset of each axis of the compass.
00388       *
00389       * After calibration this should now take into account trimming errors in the magnetometer,
00390       * and any "hard iron" offsets on the device.
00391       *
00392       * @param calibration A CompassSample containing the offsets for the x, y and z axis.
00393       */
00394     void setCalibration(CompassSample calibration);
00395 
00396     /**
00397       * Provides the calibration data currently in use by the compass.
00398       *
00399       * More specifically, the x, y and z zero offsets of the compass.
00400       *
00401       * @return calibration A CompassSample containing the offsets for the x, y and z axis.
00402       */
00403     CompassSample getCalibration();
00404 
00405     /**
00406       * Updates the local sample, only if the compass indicates that
00407       * data is stale.
00408       *
00409       * @note Can be used to trigger manual updates, if the device is running without a scheduler.
00410       *       Also called internally by all get[X,Y,Z]() member functions.
00411       */
00412     int updateSample();
00413 
00414     /**
00415       * Periodic callback from MicroBit idle thread.
00416       *
00417       * Calls updateSample().
00418       */
00419     virtual void idleTick();
00420 
00421     /**
00422       * Returns 0 or 1. 1 indicates that the compass is calibrated, zero means the compass requires calibration.
00423       */
00424     int isCalibrated();
00425 
00426     /**
00427       * Returns 0 or 1. 1 indicates that the compass is calibrating, zero means the compass is not currently calibrating.
00428       */
00429     int isCalibrating();
00430 
00431     /**
00432       * Clears the calibration held in persistent storage, and sets the calibrated flag to zero.
00433       */
00434     void clearCalibration();
00435 
00436     /**
00437       * Destructor for MicroBitCompass, where we deregister this instance from the array of fiber components.
00438       */
00439     ~MicroBitCompass();
00440 
00441     private:
00442 
00443     /**
00444       * Issues a standard, 2 byte I2C command write to the accelerometer.
00445       *
00446       * Blocks the calling thread until complete.
00447       *
00448       * @param reg The address of the register to write to.
00449       *
00450       * @param value The value to write.
00451       *
00452       * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the the write request failed.
00453       */
00454     int writeCommand(uint8_t reg, uint8_t value);
00455 
00456     /**
00457       * Issues a read command, copying data into the specified buffer.
00458       *
00459       * Blocks the calling thread until complete.
00460       *
00461       * @param reg The address of the register to access.
00462       *
00463       * @param buffer Memory area to read the data into.
00464       *
00465       * @param length The number of bytes to read.
00466       *
00467       * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER or MICROBIT_I2C_ERROR if the the read request failed.
00468       */
00469     int readCommand(uint8_t reg, uint8_t* buffer, int length);
00470 
00471     /**
00472       * Issues a read of a given address, and returns the value.
00473       *
00474       * Blocks the calling thread until complete.
00475       *
00476       * @param reg The address of the 16 bit register to access.
00477       *
00478       * @return The register value, interpreted as a 16 but signed value, or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
00479       */
00480     int read16(uint8_t reg);
00481 
00482     /**
00483       * Issues a read of a given address, and returns the value.
00484       *
00485       * Blocks the calling thread until complete.
00486       *
00487       * @param reg The address of the 16 bit register to access.
00488       *
00489       * @return The register value, interpreted as a 8 bit unsigned value, or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
00490       */
00491     int read8(uint8_t reg);
00492 
00493     /**
00494       * Calculates a tilt compensated bearing of the device, using the accelerometer.
00495       */
00496     int tiltCompensatedBearing();
00497 
00498     /**
00499       * Calculates a non-tilt compensated bearing of the device.
00500       */
00501     int basicBearing();
00502 
00503     /**
00504       * An initialisation member function used by the many constructors of MicroBitCompass.
00505       *
00506       * @param id the unique identifier for this compass instance.
00507       *
00508       * @param address the base address of the magnetometer on the i2c bus.
00509       */
00510     void init(uint16_t id, uint16_t address);
00511 };
00512 
00513 #endif