eCompass (6-axes electronic compass) / Electronic Compass with Three-axis Magnetic Field Sensor and Three-axis Accelerometer by Bosch Sensortech

Dependents:   BLE_EddystoneBeacon_w_ACC_TY51822

BMC050.h

Committer:
kenjiArai
Date:
2017-08-23
Revision:
3:24aa4d5fa7de
Parent:
2:93141eb80862

File content as of revision 3:24aa4d5fa7de:

/*
 * mbed library program 
 *  BMC050 COMPASS 6 AXIS, made by Bosch Sensortec
 *      http://jp.bosch-sensortec.com/content/language1/html/5033.htm
 *
 * Copyright (c) 2014,'16,'17 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created: July       19th, 2014 
 *      Revised: August     23rd, 2017
 */

#ifndef BMC050_H
#define BMC050_H

#include "mbed.h"

////////////// ADDRESS DEFINITION ///////////////
//  BMC050 Address/accelerometer
//  7bit address = 0b001100x(0x18 or 0x19 depends on SDO)
//      -> 8bit = 0b001100x0(0x30,0x32) -> 0x31,0x33(Read) or 0x30,0x32(Write)
#define BMC050_A_G_CHIP_ADDR   0x30    // SDO pin = Ground
#define BMC050_A_V_CHIP_ADDR   0x32    // SDO pin = Vdd
//  BMC050 Address/magnetometer
//  7bit address = 0b001000x(0x10,0x11,0x12 or 0x13 depends on SDO and CSB2)
//      -> 8bit = 0b00100xx0(0x20,0x22,0x24,0x26)
#define BMC050_M_GG_CHIP_ADDR  0x20    // CSB2 pin = Ground, SDO pin = Ground
#define BMC050_M_GV_CHIP_ADDR  0x22    // CSB2 pin = Ground, SDO pin = Vdd
#define BMC050_M_VG_CHIP_ADDR  0x24    // CSB2 pin = Vdd, SDO pin = Ground
#define BMC050_M_VV_CHIP_ADDR  0x26    // CSB2 pin = Vdd, SDO pin = Vdd
#define BMC050_MAG_NOT_USED_ADDR  0xff // If you only used acc and keep mag as suspend

//   BMC050 ACC ID
#define I_AM_BMC050_ACC          0x03
//   BMC050 ACC ID
#define I_AM_BMC050_MAG          0x32

////////////// REGISTER DEFINITION //////////////
//      accelerometer
#define BMC050_A_WHO_AM_I        0x00
// reserved
#define BMC050_A_OUT_X_L         0x02
#define BMC050_A_OUT_X_H         0x03
#define BMC050_A_OUT_Y_L         0x04
#define BMC050_A_OUT_Y_H         0x05
#define BMC050_A_OUT_Z_L         0x06
#define BMC050_A_OUT_Z_H         0x07
#define BMC050_A_OUT_TEMP        0x08
#define BMC050_A_STATUS_REG0     0x09
#define BMC050_A_STATUS_REG1     0x0a
#define BMC050_A_STATUS_REG2     0x0b
#define BMC050_A_STATUS_REG3     0x0c
// reserved
// reserved
#define BMC050_A_G_RANGE         0x0f
#define BMC050_A_BANDWIDTH       0x10
#define BMC050_A_POWER_MODE      0x11
// reserved
#define BMC050_A_FILTER          0x13
#define BMC050_A_SW_RESET        0x14
// not implement yet 0x15 to 0x35
#define BMC050_A_OFST_COMP0      0x36
#define BMC050_A_OFST_COMP1      0x37
#define BMC050_A_OFST_COMP_DX    0x38
#define BMC050_A_OFST_COMP_DY    0x39
#define BMC050_A_OFST_COMP_DZ    0x3a
#define BMC050_A_OFST_COMP_DX_UF 0x3b
#define BMC050_A_OFST_COMP_DY_UF 0x3c
#define BMC050_A_OFST_COMP_DZ_UF 0x3d

//      magnetometer
#define BMC050_M_WHO_AM_I        0x40
// reserved
#define BMC050_M_OUT_X_L         0x42
#define BMC050_M_OUT_X_H         0x43
#define BMC050_M_OUT_Y_L         0x44
#define BMC050_M_OUT_Y_H         0x45
#define BMC050_M_OUT_Z_L         0x46
#define BMC050_M_OUT_Z_H         0x47
#define BMC050_M_HALL_L          0x48
#define BMC050_M_HALL_H          0x49
#define BMC050_M_INTERRUPT       0x4a
#define BMC050_M_POWER_MODE      0x4b
#define BMC050_M_OPERATION       0x4c
// not implement yet 0x4d to 0x50
#define BMC050_M_REPETITION_XY   0x51
#define BMC050_M_REPETITION_Z    0x51

////////////// CONTROL DEFINITION ///////////////
// Full Scale
#define BMC050_FS_2G           0x03
#define BMC050_FS_4G           0x05
#define BMC050_FS_8G           0x08
#define BMC050_FS_16G          0x0c
// Bandwidth (Low pass)
#define BMC050_NOT_FILTERED    0x00
#define BMC050_BW_7R81         0x08
#define BMC050_BW_15R63        0x09
#define BMC050_BW_31R25        0x0a
#define BMC050_BW_62R5         0x0b
#define BMC050_BW_125          0x0c
#define BMC050_BW_250          0x0d
#define BMC050_BW_500          0x0e
#define BMC050_BW_1000         0x0f

// Output Data Rate (ODR)
#define BMC050_DR_10           0
#define BMC050_DR_2            1
#define BMC050_DR_6            2
#define BMC050_DR_8            3
#define BMC050_DR_15           4
#define BMC050_DR_20           5
#define BMC050_DR_25           6
#define BMC050_DR_30           7

// definition for Nomalization 
//Gravity at Earth's surface in m/s/s
#define GRAVITY                (9.80665F)
#define BMC050_GAIN            (3.91F)
#define BMC050_DUMMY           0

////////////// DATA TYPE DEFINITION /////////////
typedef struct {
  uint8_t addr;
  uint8_t g_range;
  uint8_t bandwith;
  uint8_t filter;
} BMC050ACC_TypeDef;

typedef struct {
  uint8_t addr;
  uint8_t data_rate;
} BMC050MAG_TypeDef;

/** Interface for Bosch Sensortec COMPASS 6 AXIS
 *      Chip: BMC050, two chips configuration (Accelerometer 3axis & Magnetometer 3axis)
 *
 * @code
 * #include "mbed.h"
 *
 * const BMC050ACC_TypeDef acc_parameter = {
 *    BMC050_A_G_CHIP_ADDR, // I2C Address
 *    BMC050_FS_2G,         // G-range slection 
 *    BMC050_BW_250,        // Bandwidth
 * };
 * 
 * #if 1  
 * const BMC050MAG_TypeDef mag_parameter = {
 *    BMC050_M_GG_CHIP_ADDR,// I2C Address
 *    BMC050_DR_10          // Data Rate
 * };
 * #else // If you would like to keep "Suspend mode" for mag
 * const BMC050MAG_TypeDef mag_parameter = {
 *    BMC050_MAG_NOT_USED_ADDR,// Not use mag sensor
 *    BMC050_DUMMY          // dummy
 * };
 * #endif
 *
 * // I2C Communication
 * I2C i2c(dp5,dp27);       // SDA, SCL
 * BMC050 bmc050(i2c, &acc_parameter, &mag_parameter);
 *
 * int main() {
 * float fa[3];
 * float fg[3];
 *
 *   if (bmc050.read_id_acc() == I_AM_BMC050_ACC){
 *      bmc050.read_data_acc(fa);
 *   }
 *   if (bmc050.read_id_mag() == I_AM_BMC050_MAG){
 *      bmc050.read_data_mag(fg);
 *   }
 * }
 * @endcode
 */

class BMC050{
public:
    /** Configure data pin
      * @param data SDA and SCL pins
      * @param parameter address for acc (BMC050ACC_TypeDef)
      * @param parameter address for mag (BMC050MAG_TypeDef)
      */
    BMC050(PinName p_sda, PinName p_scl,
        const BMC050ACC_TypeDef *acc_parameter, const BMC050MAG_TypeDef *mag_parameter);
    
    /** Configure data pin (with other devices on I2C line)
      * @param I2C previous definition
      * @param other parameters -> please see BMC050(PinName p_sda, PinName p_scl,...)
      */
    BMC050(I2C& p_i2c,
        const BMC050ACC_TypeDef *acc_parameter, const BMC050MAG_TypeDef *mag_parameter);
  
    /** Read a float type data from accelerometer
      * @param float type of three arry's address, e.g. float dt[3];
      * @return acc motion data unit: m/s/s
      * @return dt[0]->x, dt[1]->y, dt[2]->z 
      */
    void read_data_acc(float *dt);

    /** Read a float type data from accelerometer
      * @param float type of three arry's address, e.g. float dt[3];
      * @return acc motion data unit: mg
      * @return dt[0]->x, dt[1]->y, dt[2]->z 
      */
    void read_mg_acc(float *dt);

    /** Read a float type data from magnetometer
      * @param float type of three arry's address, e.g. float dt[3];
      * @return magnettic field data unit: uT(micro T)
      * @return dt[0]->x, dt[1]->y, dt[2]->z 
      */
    void read_data_mag(float *dt);
  
    /** Read temperature data
      * @param none
      * @return temperature  unit: deg.C
      */
    float read_temp();
  
    /** Read a acc chip ID number
      * @param none
      * @return should be I_AM_BMC050_ACC(0x03)
      */
    uint8_t read_id_acc();

    /** Read a mag chip ID number
      * @param none
      * @return should be I_AM_BMC050_MAG(0x32)
      */
    uint8_t read_id_mag();

    /** Read Data Ready flag /Acc
      * @param none
      * @return 1 = Ready
      */
    uint8_t data_ready_acc();

    /** Read Data Ready flag /Mag
      * @param none
      * @return 1 = Ready
      */
    uint8_t data_ready_mag();

    /** Read register (general purpose)
      * @param register's address
      * @return register data
      */
    uint8_t read_reg_acc(uint8_t addr);
    
    /** Read register (general purpose)
      * @param register's address
      * @return register data
      */
    uint8_t read_reg_mag(uint8_t addr);

    /** Set I2C clock frequency
      * @param freq.
      * @return none
      */
    void frequency(int hz);

    /** Write register (general purpose)
      * @param register's address
      * @param data
      * @return none
      */
    void write_reg_acc(uint8_t addr, uint8_t data);

    /** Write register (general purpose)
      * @param register's address
      * @param data
      * @return none
      */
    void write_reg_mag(uint8_t addr, uint8_t data);

protected:
    void initialize(const BMC050ACC_TypeDef *acc_parameter,
                    const BMC050MAG_TypeDef *mag_parameter);

    I2C *_i2c_p;
    I2C &_i2c;
  
private:
    float   fs_factor_acc;  // full scale factor
    char    dbf[2];         // working buffer
    uint8_t acc_addr;   // acc sensor address
    uint8_t acc_id;     // acc ID
    uint8_t acc_ready;  // acc is on I2C line = 1, not = 0 
    uint8_t mag_addr;   // mag sensor address
    uint8_t mag_id;     // mag ID
    uint8_t mag_ready;  // mag is on I2C line = 1, not = 0    
};

#endif      // BMC050_H