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.cpp

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
 */

#include "BMC050.h"

BMC050::BMC050 (
    PinName p_sda, PinName p_scl,
    const BMC050ACC_TypeDef *acc_parameter,
    const BMC050MAG_TypeDef *mag_parameter)
 : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p)
{
    initialize (acc_parameter, mag_parameter);
}

BMC050::BMC050 (
    I2C& p_i2c,
    const BMC050ACC_TypeDef *acc_parameter,
    const BMC050MAG_TypeDef *mag_parameter)
 :  _i2c(p_i2c)
{
    initialize (acc_parameter, mag_parameter);
}

void BMC050::initialize (
    const BMC050ACC_TypeDef *acc_parameter,
    const BMC050MAG_TypeDef *mag_parameter)
{
    /////////////// Magnetometer Configuration /////////////////
    // after power-on, mag chip is keeping "Suspend mode"!!
    //      -> Need to go "Normal mode" via "Sleep mode"
    // step 1/start 
    mag_addr = mag_parameter->addr;
    if (mag_addr != BMC050_MAG_NOT_USED_ADDR) {
        dbf[0] = BMC050_M_POWER_MODE;
        dbf[1] = 0x01;  // Power control bit on
        _i2c.write(mag_addr, dbf, 2);
        dbf[0] = BMC050_M_OPERATION;
        dbf[1] = 0;
        _i2c.write(mag_addr, dbf, 2);
    }
    /////////////// Accelerometer configuration ////////////////
    // Check acc chip is available of not
    // step 1/start
    acc_addr = acc_parameter->addr;
    dbf[0] = BMC050_A_WHO_AM_I; 
    _i2c.write(acc_addr, dbf, 1); 
    _i2c.read(acc_addr, dbf, 1);
    if (dbf[0] == I_AM_BMC050_ACC){ acc_ready = 1;
    } else {                        acc_ready = 0; }
    /////////////// Magnetometer Configuration /////////////////
    // after power-on, mag chip is keeping "Suspend mode"!!
    //      -> Need to go "Normal mode" via "Sleep mode"
    // step 2 
    if (mag_addr != BMC050_MAG_NOT_USED_ADDR) {
        _i2c.write(mag_addr, dbf, 2);
        dbf[0] = BMC050_M_OPERATION;
        dbf[1] = 0;
        _i2c.write(mag_addr, dbf, 2);
    }
    /////////////// Accelerometer configuration ////////////////
    // step 2/last
    if ( acc_ready == 1){
        // set g-range
        dbf[0] = BMC050_A_G_RANGE;
        dbf[1] = acc_parameter->g_range;
        switch (dbf[1]){
        case BMC050_FS_2G:
            fs_factor_acc = 256;
            break;
        case BMC050_FS_4G:
            fs_factor_acc = 128;
            break;
        case BMC050_FS_8G:
            fs_factor_acc = 64;
            break;
        case BMC050_FS_16G:
            fs_factor_acc = 32;
            break;
        default:
            fs_factor_acc = 256;
            dbf[1] = BMC050_FS_2G;
        }          
        _i2c.write(acc_addr, dbf, 2);
        // set bandwidth
        dbf[1] = acc_parameter->bandwith;
        if (dbf[1] == BMC050_NOT_FILTERED){
            dbf[0] = BMC050_A_FILTER;
            dbf[1] = 0x80;
        } else {
            dbf[0] = BMC050_A_BANDWIDTH;
        }
        _i2c.write(acc_addr, dbf, 2);
    }
    /////////////// Magnetometer Configuration /////////////////
    // Check mag chip is available of not
    // step 3/last
    if (mag_addr != BMC050_MAG_NOT_USED_ADDR) {
        dbf[0] = BMC050_M_WHO_AM_I; 
        _i2c.write(mag_addr, dbf, 1); 
        _i2c.read(mag_addr, dbf, 1);
        if (dbf[0] == I_AM_BMC050_MAG){ mag_ready = 1;
        } else {                        mag_ready = 0; }
        if ( mag_ready == 1){
            // set output data rate
            dbf[0] = BMC050_M_OPERATION;
            dbf[1] = mag_parameter->data_rate;
            _i2c.write(mag_addr, dbf, 2);
        }
    }      
}

/////////////// Accelerometer ///////////////////
void BMC050::read_data_acc(float *dt) {
char data[6];

    if (acc_ready == 0){
        dt[0] = dt[1] = dt[2] = 0;
        return;  
    }
    // X,Y &Z
    dbf[0] = BMC050_A_OUT_X_L; 
    _i2c.write(acc_addr, dbf, 1, true); 
    _i2c.read(acc_addr, data, 6, false);
    // change data type
    dt[0] = float((short(data[1] << 8 | data[0] & 0xc0))>> 6) * GRAVITY / fs_factor_acc;
    dt[1] = float((short(data[3] << 8 | data[2] & 0xc0))>> 6) * GRAVITY / fs_factor_acc;
    dt[2] = float((short(data[5] << 8 | data[4] & 0xc0))>> 6) * GRAVITY / fs_factor_acc;
}

/////////////// Accelerometer ///////////////////
void BMC050::read_mg_acc(float *dt) {
char data[6];

    if (acc_ready == 0){
        dt[0] = 0;
        dt[1] = 0;
        dt[2] = 0;
        return;  
    }
    // X,Y &Z
    dbf[0] = BMC050_A_OUT_X_L; 
    _i2c.write(acc_addr, dbf, 1, true); 
    _i2c.read(acc_addr, data, 6, false);
    // change data type
    dt[0] = float((short(data[1] << 8 | data[0] & 0xc0))>> 6) / fs_factor_acc;
    dt[1] = float((short(data[3] << 8 | data[2] & 0xc0))>> 6) / fs_factor_acc;
    dt[2] = float((short(data[5] << 8 | data[4] & 0xc0))>> 6) / fs_factor_acc;
}

/////////////// Magnetometer ////////////////////
void BMC050::read_data_mag(float *dt) {
char data[6];

    if (mag_ready == 0){
        dt[0] = dt[1] = dt[2] = 0;
        return;  
    }
    // X,Y &Z
    dbf[0] = BMC050_M_OUT_X_L; 
    _i2c.write(mag_addr, dbf, 1, true); 
    _i2c.read(mag_addr, data, 6, false);
    // change data type
    dt[0] = float((short(data[1] << 8 | data[0] & 0xf8))>> 3);
    dt[1] = float((short(data[3] << 8 | data[2] & 0xf8))>> 3);
    dt[2] = float((short(data[5] << 8 | data[4] & 0xfe))>> 1);
}

/////////////// Accelerometer ///////////////////
float BMC050::read_temp() {
    dbf[0] = BMC050_A_OUT_TEMP; 
    _i2c.write(acc_addr, dbf, 1); 
    _i2c.read(acc_addr, dbf, 1);
    return ((float)dbf[0] * 0.5f + 24.0f);
}

/////////////// Accelerometer ///////////////////
uint8_t BMC050::read_id_acc() {
    dbf[0] = BMC050_A_WHO_AM_I; 
    _i2c.write(acc_addr, dbf, 1); 
    _i2c.read(acc_addr, dbf, 1);
    return (uint8_t)dbf[0];
}

/////////////// Magnetometer ////////////////////
uint8_t BMC050::read_id_mag() {
    dbf[0] = BMC050_M_WHO_AM_I; 
    _i2c.write(mag_addr, dbf, 1); 
    _i2c.read(mag_addr, dbf, 1);
    return (uint8_t)dbf[0];
}

/////////////// Accelerometer ///////////////////
uint8_t BMC050::data_ready_acc() {
    if (acc_ready == 1){
        dbf[0] = BMC050_A_OUT_X_L; 
        _i2c.write(acc_addr, dbf, 1); 
        _i2c.read(acc_addr, dbf, 1);
        if (!(dbf[0] & 0x01)){
            return 0;
        }
    }
    return 1;
}

/////////////// Magnetometer ////////////////////
uint8_t BMC050::data_ready_mag() {
    if (mag_ready == 1){
        dbf[0] = BMC050_M_HALL_L; 
        _i2c.write(mag_addr, dbf, 1); 
        _i2c.read(mag_addr, dbf, 1);
        if (!(dbf[0] & 0x01)){
            return 0;
        }
    }
    return 1;
}

/////////////// Accelerometer ///////////////////
uint8_t BMC050::read_reg_acc(uint8_t addr) {
    if (acc_ready == 1){
        dbf[0] = addr; 
        _i2c.write(acc_addr, dbf, 1); 
        _i2c.read(acc_addr, dbf, 1);
    } else {
        dbf[0] = 0xff;
    }
    return (uint8_t)dbf[0];
}

/////////////// Magnetometer ////////////////////
uint8_t BMC050::read_reg_mag(uint8_t addr) {
    if (mag_ready == 1){
        dbf[0] = addr; 
        _i2c.write(mag_addr, dbf, 1); 
        _i2c.read(mag_addr, dbf, 1);
    } else {
        dbf[0] = 0xff;
    }
    return (uint8_t)dbf[0];
}

/////////////// Accelerometer ///////////////////
void BMC050::write_reg_acc(uint8_t addr, uint8_t data) {
    if (acc_ready == 1){
        dbf[0] = addr;
        dbf[1] = data; 
        _i2c.write(acc_addr, dbf, 2); 
    }
}

/////////////// Magnetometer ////////////////////
void BMC050::write_reg_mag(uint8_t addr, uint8_t data) {
    if (mag_ready == 1){
        dbf[0] = addr;
        dbf[1] = data; 
        _i2c.write(mag_addr, dbf, 2); 
    }
}

/////////////// Common //////////////////////////
void BMC050::frequency(int hz) {
    _i2c.frequency(hz);
}