Home | History | Annotate | Download | only in mpu9150
      1 /*
      2  * Author: Jon Trulson <jtrulson (at) ics.com>
      3  * Copyright (c) 2015 Intel Corporation.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sublicense, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be
     14  * included in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 #pragma once
     25 
     26 #include <string>
     27 #include <mraa/common.hpp>
     28 #include <mraa/i2c.hpp>
     29 
     30 #define AK8975_I2C_BUS 0
     31 #define AK8975_DEFAULT_I2C_ADDR 0x0c
     32 
     33 namespace upm {
     34 
     35   /**
     36    * @library mpu9150
     37    * @sensor ak8975
     38    * @comname AK8975 3-axis Magnetometer
     39    * @altname AK9875
     40    * @type compass
     41    * @man grove
     42    * @con i2c
     43    *
     44    * @brief API for the AK8975 magnetometer
     45    *
     46    * This is a 3-axis magnetometer, which can be used alone, or
     47    * coupled with another device (such as the mcu9150 9-axis motion
     48    * sensor).
     49    *
     50    * @snippet ak8975.cxx Interesting
     51    */
     52   class AK8975 {
     53   public:
     54 
     55     /**
     56      * AK8975 registers
     57      */
     58     typedef enum {
     59       REG_WIA                   = 0x00, // device id
     60 
     61       REG_INFO                  = 0x01, // undocumented (AK proprietary data)
     62 
     63       REG_ST1                   = 0x02, // status 1
     64 
     65       REG_HXL                   = 0x03, // magnetometer data, X axis low byte
     66       REG_HXH                   = 0x04, // magnetometer data, X axis high byte
     67       REG_HYL                   = 0x05,
     68       REG_HYH                   = 0x06,
     69       REG_HZL                   = 0x07,
     70       REG_HZH                   = 0x08,
     71 
     72       REG_ST2                   = 0x09, // status 2
     73 
     74       REG_CNTL                  = 0x0a, // control
     75 
     76       // REG_RSV 0x0b reserved
     77 
     78       REG_ASTC                  = 0x0c, // self test (internal mag field)
     79 
     80       // REG_TS1, REG_TS2 0x0d, 0x0e reserved/factory test
     81 
     82       // REG_I2CDIS 0x0f, I2C disable.  Not a good idea to use or support.
     83       //  write a 0x1b to disable i2c.  This requires a power cycle to undo.
     84 
     85       // These registers hold factory calibrated co-efficients needed to
     86       // properly compensate for production variations.  They can only be
     87       // read when device is in fuse mode.  They are used to adjust the
     88       // measured mag field values.
     89       REG_ASAX                  = 0x10, // X calibration
     90       REG_ASAY                  = 0x11,
     91       REG_ASAZ                  = 0x12
     92     } AK8975_REG_T;
     93 
     94     /**
     95      * ST1 bits
     96      */
     97     typedef enum {
     98       ST1_DRDY                  = 0x01 // data ready bit
     99     } ST1_BITS_T;
    100 
    101     /**
    102      * ST2 bits
    103      */
    104     typedef enum {
    105       ST2_DERR                  = 0x04, // data error
    106       ST2_HOFL                  = 0x08  // measurement overflow
    107     } ST2_BITS_T;
    108 
    109     /**
    110      * CNTL register, operating mode values
    111      */
    112     typedef enum {
    113       CNTL_PWRDWN               = 0x00, // power down
    114       CNTL_MEASURE              = 0x01, // single measurement
    115       CNTL_SELFTEST             = 0x08,
    116       CNTL_FUSE_ACCESS          = 0x0f  // access fuse (coeff) registers
    117     } CNTL_MODES_T;
    118 
    119     /**
    120      * ASTC (self test control) bits
    121      */
    122     typedef enum {
    123       ASTC_SELF                 = 0x40 // enable self test
    124     } ASTC_BITS_T;
    125 
    126     /**
    127      * ak8975 constructor
    128      *
    129      * @param bus i2c bus to use
    130      * @param address the address for this device
    131      */
    132     AK8975(int bus=AK8975_I2C_BUS, uint8_t address=AK8975_DEFAULT_I2C_ADDR);
    133 
    134     /**
    135      * AK8975 Destructor
    136      */
    137     ~AK8975();
    138 
    139     /**
    140      * set up initial values and start operation
    141      *
    142      * @param dsr the data sampling rate: one of the DSR_BITS_T values
    143      * @return true if successful
    144      */
    145     bool init();
    146 
    147     /**
    148      * put the chip into a specific mode
    149      *
    150      * @param mode one of the CNTL_MODES_T values
    151      * @return true if successful
    152      */
    153     bool setMode(CNTL_MODES_T mode);
    154 
    155     /**
    156      * check to see if the ST1_DRDY bit is set, indicating the device
    157      * can accept commands
    158      *
    159      * @return true if device is ready, false otherwise
    160      */
    161     bool isReady();
    162 
    163     /**
    164      * check to see if device is ready and sleep/retry if not.
    165      * Returns once device indicates it's ready.
    166      *
    167      * @return true if device is ready, false if retries exhausted
    168      */
    169     bool waitforDeviceReady();
    170 
    171     /**
    172      * take a measurement
    173      *
    174      * @param selfTest true if we are running a self test, false
    175      * (default) otherwise.
    176      * @return true if successful, false otherwise
    177      */
    178     bool update(bool selfTest=false);
    179 
    180     /**
    181      * do a self test sequence.  When self test is executed, the
    182      * device activates internal calibrated magnets, and measures
    183      * them, updating the measurement registers.  Once complete, the
    184      * data can be read as usual (getMagnetometer()) and the returned
    185      * values compared against the following limits to determine
    186      * correctness:
    187      *
    188      * -100 < X < +100; -100 < Y < +100; -1000 < Z < -300
    189      *
    190      * @return true if successful, false otherwise
    191      */
    192     bool selfTest();
    193 
    194     /**
    195      * return the compensated values for the x, y, and z axes.  The
    196      * unit of measurement is in micro-teslas (uT).
    197      *
    198      * @param x pointer to returned X axis value
    199      * @param y pointer to returned Y axis value
    200      * @param z pointer to returned Z axis value
    201      */
    202     void getMagnetometer(float *x, float *y, float *z);
    203 
    204 
    205   protected:
    206     /**
    207      * compute a compensated magnetometer axis value, based on the raw
    208      * axis value and a per-device, per-axis adjustment coefficient
    209      * that was read and stored at init() time.
    210      *
    211      * @param value the raw axis value to compensate
    212      * @param adj the adjustment coefficient
    213      * @return true if successful
    214      */
    215     float adjustValue(float value, float adj);
    216 
    217     // compensation coefficients (factory set) for this device
    218     float m_xCoeff;
    219     float m_yCoeff;
    220     float m_zCoeff;
    221 
    222     // uncompensated magnetometer readings
    223     float m_xData;
    224     float m_yData;
    225     float m_zData;
    226 
    227   private:
    228     mraa::I2c m_i2c;
    229     uint8_t m_addr;
    230 
    231   };
    232 }
    233 
    234 
    235