MME ELEC3810 / BNO055_fusion

Dependents:   Shared-1BNO055

Fork of BNO055_fusion by Kenji Arai

Files at this revision

API Documentation at this revision

Comitter:
kenjiArai
Date:
Sun Apr 05 04:12:58 2015 +0000
Child:
1:cb7e19c0a702
Commit message:
BNO055 Intelligent 9-axis absolute orientation sensor by Bosch Sensortec.; It includes ACC, MAG and GYRO sensors and Cortex-M0+ processor.

Changed in this revision

BNO055.cpp Show annotated file Show diff for this revision Revisions of this file
BNO055.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BNO055.cpp	Sun Apr 05 04:12:58 2015 +0000
@@ -0,0 +1,444 @@
+/*
+ * mbed library program
+ *  BNO055 Intelligent 9-axis absolute orientation sensor
+ *  by Bosch Sensortec
+ *
+ * Copyright (c) 2015 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  http://mbed.org/users/kenjiArai/
+ *      Created: March     30th, 2015
+ *      Revised: April      5th, 2015
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "mbed.h"
+#include "BNO055.h"
+
+BNO055::BNO055 (PinName p_sda, PinName p_scl, uint8_t addr, uint8_t mode):
+    _i2c(p_sda, p_scl)
+{
+    _i2c.frequency(400000);
+    chip_addr = addr;
+    chip_mode = mode;
+    initialize ();
+}
+
+BNO055::BNO055 (PinName p_sda, PinName p_scl) :
+    _i2c(p_sda, p_scl)
+{
+    _i2c.frequency(400000);
+    chip_addr = BNO055_G_CHIP_ADDR;
+    chip_mode = MODE_NDOF;
+    initialize ();
+}
+
+BNO055::BNO055 (I2C& p_i2c,  uint8_t addr, uint8_t mode) :
+    _i2c(p_i2c)
+{
+    _i2c.frequency(400000);
+    chip_addr = addr;
+    chip_mode = mode;
+    initialize ();
+}
+
+BNO055::BNO055 (I2C& p_i2c) :
+    _i2c(p_i2c)
+{
+    _i2c.frequency(400000);
+    chip_addr = BNO055_G_CHIP_ADDR;
+    chip_mode = MODE_NDOF;
+    initialize ();
+}
+
+/////////////// Read data & normalize /////////////////////
+void BNO055::get_Euler_Angles(BNO055_EULER_TypeDef *el)
+{
+    uint8_t deg_or_rad;
+    int16_t h,p,r;
+
+    select_page(0);
+    dt[0] = BNO055_UNIT_SEL;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 1, false);
+    if (dt[0] & 0x04) {
+        deg_or_rad = 1; // Radian
+    } else {
+        deg_or_rad = 0; // Degree
+    }
+    dt[0] = BNO055_EULER_H_LSB;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 6, false);
+    h = dt[1] << 8 | dt[0];
+    p = dt[3] << 8 | dt[2];
+    r = dt[5] << 8 | dt[4];
+    if (deg_or_rad) {
+        el->h = (double)(h / 900);
+        el->p = (double)(p / 900);
+        el->r = (double)(r / 900);
+    } else {
+        el->h = (double)(h / 16);
+        el->p = (double)(p / 16);
+        el->r = (double)(r / 16);
+    }
+}
+
+void BNO055::get_quaternion(BNO055_QUATERNION_TypeDef *qua)
+{
+    select_page(0);
+    dt[0] = BNO055_QUATERNION_W_LSB;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 8, false);
+    qua->w = dt[1] << 8 | dt[0];
+    qua->x = dt[3] << 8 | dt[2];
+    qua->y = dt[5] << 8 | dt[4];
+    qua->z = dt[7] << 8 | dt[6];
+}
+
+void BNO055::get_linear_accel(BNO055_LIN_ACC_TypeDef *la)
+{
+    uint8_t ms2_or_mg;
+    int16_t x,y,z;
+
+    select_page(0);
+    dt[0] = BNO055_UNIT_SEL;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 1, false);
+    if (dt[0] & 0x01) {
+        ms2_or_mg = 1; // mg
+    } else {
+        ms2_or_mg = 0; // m/s*s
+    }
+    dt[0] = BNO055_LINEAR_ACC_X_LSB;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 6, false);
+    x = dt[1] << 8 | dt[0];
+    y = dt[3] << 8 | dt[2];
+    z = dt[5] << 8 | dt[4];
+    if (ms2_or_mg) {
+        la->x = (double)x;
+        la->y = (double)y;
+        la->z = (double)z;
+    } else {
+        la->x = (double)(x / 100);
+        la->y = (double)(y / 100);
+        la->z = (double)(z / 100);
+    }
+}
+
+void BNO055::get_gravity(BNO055_GRAVITY_TypeDef *gr)
+{
+    uint8_t ms2_or_mg;
+    int16_t x,y,z;
+
+    select_page(0);
+    dt[0] = BNO055_UNIT_SEL;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 1, false);
+    if (dt[0] & 0x01) {
+        ms2_or_mg = 1; // mg
+    } else {
+        ms2_or_mg = 0; // m/s*s
+    }
+    dt[0] = BNO055_GRAVITY_X_LSB;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 6, false);
+    x = dt[1] << 8 | dt[0];
+    y = dt[3] << 8 | dt[2];
+    z = dt[5] << 8 | dt[4];
+    if (ms2_or_mg) {
+        gr->x = (double)x;
+        gr->y = (double)y;
+        gr->z = (double)z;
+    } else {
+        gr->x = (double)(x / 100);
+        gr->y = (double)(y / 100);
+        gr->z = (double)(z / 100);
+    }
+}
+
+void BNO055::get_chip_temperature(BNO055_TEMPERATURE_TypeDef *tmp)
+{
+    uint8_t c_or_f;
+
+    select_page(0);
+    dt[0] = BNO055_UNIT_SEL;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 1, false);
+    if (dt[0] & 0x10) {
+        c_or_f = 1; // Fahrenheit
+    } else {
+        c_or_f = 0; // degrees Celsius
+    }
+    dt[0] = BNO055_TEMP_SOURCE;
+    dt[1] = 0;
+    _i2c.write(chip_addr, dt, 2, false);
+    wait_ms(1); // Do I need to wait?
+    dt[0] = BNO055_TEMP;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 1, false);
+    if (c_or_f) {
+        tmp->acc_chip = (int8_t)dt[0] * 2;
+    } else {
+        tmp->acc_chip = (int8_t)dt[0];
+    }
+    dt[0] = BNO055_TEMP_SOURCE;
+    dt[1] = 1;
+    _i2c.write(chip_addr, dt, 2, false);
+    wait_ms(1); // Do I need to wait?
+    dt[0] = BNO055_TEMP;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 1, false);
+    if (c_or_f) {
+        tmp->gyr_chip = (int8_t)dt[0] * 2;
+    } else {
+        tmp->gyr_chip = (int8_t)dt[0];
+    }
+}
+
+/////////////// Initialize ////////////////////////////////
+void BNO055::initialize (void)
+{
+    // Check Acc & Mag & Gyro are available of not
+    check_id();
+    // Set initial data
+    set_initial_dt_to_regs();
+    // Unit selection
+    unit_selection();
+    // Set fusion mode
+    change_fusion_mode(chip_mode);
+}
+
+void BNO055::unit_selection(void)
+{
+    select_page(0);
+    dt[0] = BNO055_UNIT_SEL;
+    dt[1] = UNIT_ORI_WIN + UNIT_ACC_MSS + UNIT_GYR_DPS + UNIT_EULER_DEG + UNIT_TEMP_C;
+    _i2c.write(chip_addr, dt, 2, false);
+}
+
+uint8_t BNO055::select_page(uint8_t page)
+{
+    dt[0] = BNO055_PAGE_ID;
+    if (page == 1) {
+        dt[1] = 1;  // select page 1
+    } else {
+        dt[1] = 0;  // select page 0
+    }
+    _i2c.write(chip_addr, dt, 2, false);
+    dt[0] = BNO055_PAGE_ID;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 1, false);
+    return dt[0];
+}
+
+////// Set initialize data to related registers ///////////
+void BNO055::set_initial_dt_to_regs(void)
+{
+    // select_page(0);
+    // current setting is only used default values
+}
+
+/////////////// Check Who am I? ///////////////////////////
+void BNO055::check_id(void)
+{
+    select_page(0);
+    // ID
+    dt[0] = BNO055_CHIP_ID;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 7, false);
+    chip_id = dt[0];
+    if (chip_id == I_AM_BNO055_CHIP) {
+        ready_flg = 1;
+    } else {
+        ready_flg = 0;
+    }
+    acc_id = dt[1];
+    if (acc_id == I_AM_BNO055_ACC) {
+        ready_flg |= 2;
+    }
+    mag_id = dt[2];
+    if (mag_id == I_AM_BNO055_MAG) {
+        ready_flg |= 4;
+    }
+    gyr_id = dt[3];
+    if (mag_id == I_AM_BNO055_MAG) {
+        ready_flg |= 8;
+    }
+    bootldr_rev_id = dt[5]<< 8 | dt[4];
+    sw_rev_id = dt[6];
+}
+
+void BNO055::read_id_inf(BNO055_ID_INF_TypeDef *id)
+{
+    id->chip_id = chip_id;
+    id->acc_id = acc_id;
+    id->mag_id = mag_id;
+    id->gyr_id = gyr_id;
+    id->bootldr_rev_id = bootldr_rev_id;
+    id->sw_rev_id = sw_rev_id;
+}
+
+/////////////// Check chip ready or not  //////////////////
+uint8_t BNO055::chip_ready()
+{
+    if (ready_flg == 0x0f) {
+        return 1;
+    }
+    return 0;
+}
+
+/////////////// Change Fusion mode  ///////////////////////
+void BNO055::change_fusion_mode(uint8_t mode)
+{
+    uint8_t current_mode;
+
+    select_page(0);
+    current_mode = check_operating_mode();
+    switch (mode) {
+        case CONFIGMODE:
+            dt[0] = BNO055_OPR_MODE;
+            dt[1] = mode;
+            _i2c.write(chip_addr, dt, 2, false);
+            wait_ms(19);    // wait 19mS
+            break;
+        case MODE_IMU:
+        case MODE_COMPASS:
+        case MODE_M4G:
+        case MODE_NDOF_FMC_OFF:
+        case MODE_NDOF:
+            if (current_mode != CONFIGMODE) {   // Can we change the mode directry?
+                dt[0] = BNO055_OPR_MODE;
+                dt[1] = CONFIGMODE;
+                _i2c.write(chip_addr, dt, 2, false);
+                wait_ms(19);    // wait 19mS
+            }
+            dt[0] = BNO055_OPR_MODE;
+            dt[1] = mode;
+            _i2c.write(chip_addr, dt, 2, false);
+            wait_ms(7);    // wait 7mS
+            break;
+        default:
+            break;
+    }
+}
+
+uint8_t BNO055::check_operating_mode(void)
+{
+    select_page(0);
+    dt[0] = BNO055_OPR_MODE;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 1, false);
+    return dt[0];
+}
+
+/////////////// Set Mouting position  /////////////////////
+void BNO055::set_mounting_position(uint8_t position)
+{
+    uint8_t remap_config;
+    uint8_t remap_sign;
+    uint8_t current_mode;
+
+    current_mode = check_operating_mode();
+    change_fusion_mode(CONFIGMODE);
+    switch (position) {
+        case MT_P0:
+            remap_config = 0x21;
+            remap_sign = 0x04;
+            break;
+        case MT_P2:
+            remap_config = 0x24;
+            remap_sign = 0x06;
+            break;
+        case MT_P3:
+            remap_config = 0x21;
+            remap_sign = 0x02;
+            break;
+        case MT_P4:
+            remap_config = 0x24;
+            remap_sign = 0x03;
+            break;
+        case MT_P5:
+            remap_config = 0x21;
+            remap_sign = 0x01;
+            break;
+        case MT_P6:
+            remap_config = 0x21;
+            remap_sign = 0x07;
+            break;
+        case MT_P7:
+            remap_config = 0x24;
+            remap_sign = 0x05;
+            break;
+        case MT_P1:
+        default:
+            remap_config = 0x24;
+            remap_sign = 0x00;
+            break;
+    }
+    dt[0] = BNO055_AXIS_MAP_CONFIG;
+    dt[1] = remap_config;
+    dt[2] = remap_sign;
+    _i2c.write(chip_addr, dt, 3, false);
+    change_fusion_mode(current_mode);
+}
+
+/////////////// I2C Freq. /////////////////////////////////
+void BNO055::frequency(int hz)
+{
+    _i2c.frequency(hz);
+}
+
+/////////////// Read/Write specific register //////////////
+uint8_t BNO055::read_reg0(uint8_t addr)
+{
+    select_page(0);
+    dt[0] = addr;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 1, false);
+    return (uint8_t)dt[0];
+}
+
+uint8_t BNO055::write_reg0(uint8_t addr, uint8_t data)
+{
+    uint8_t current_mode;
+    uint8_t d;
+
+    current_mode = check_operating_mode();
+    change_fusion_mode(CONFIGMODE);
+    dt[0] = addr;
+    dt[1] = data;
+    _i2c.write(chip_addr, dt, 2, false);
+    d = dt[0];
+    change_fusion_mode(current_mode);
+    return d;
+}
+
+uint8_t BNO055::read_reg1(uint8_t addr)
+{
+    select_page(1);
+    dt[0] = addr;
+    _i2c.write(chip_addr, dt, 1, true);
+    _i2c.read(chip_addr, dt, 1, false);
+    return (uint8_t)dt[0];
+}
+
+uint8_t BNO055::write_reg1(uint8_t addr, uint8_t data)
+{
+    uint8_t current_mode;
+    uint8_t d;
+
+    current_mode = check_operating_mode();
+    change_fusion_mode(CONFIGMODE);
+    select_page(1);
+    dt[0] = addr;
+    dt[1] = data;
+    _i2c.write(chip_addr, dt, 2, false);
+    d = dt[0];
+    change_fusion_mode(current_mode);
+    return d;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BNO055.h	Sun Apr 05 04:12:58 2015 +0000
@@ -0,0 +1,454 @@
+/*
+ * mbed library program
+ *  BNO055 Intelligent 9-axis absolute orientation sensor
+ *  by Bosch Sensortec
+ *
+ * Copyright (c) 2015 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  http://mbed.org/users/kenjiArai/
+ *      Created: March     30th, 2015
+ *      Revised: April      5th, 2015
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+/*
+ *---------------- REFERENCE ----------------------------------------------------------------------
+ * Original Information
+ *  https://www.bosch-sensortec.com/en/homepage/products_3/sensor_hubs/iot_solutions/bno055_1/bno055_4
+ *  Intelligent 9-axis absolute orientation sensor / Data Sheet  BST_BNO055_DS000_12 Nov. 2014 rev.1.2
+ *  Sample software   https://github.com/BoschSensortec/BNO055_driver
+ * Sensor board
+ *  https://www.rutronik24.com/product/bosch+se/bno055+shuttle+board+mems/6431291.html
+ *  http://microcontrollershop.com/product_info.php?products_id=7140&osCsid=10645k86db2crld4tfi0vol5g5
+ */
+
+#ifndef BNO055_H
+#define BNO055_H
+
+#include "mbed.h"
+
+//  BNO055
+//  7bit address = 0b010100x(0x28 or 0x29 depends on COM3)
+#define BNO055_G_CHIP_ADDR      (0x28 << 1) // COM3 = GND
+#define BNO055_V_CHIP_ADDR      (0x29 << 1) // COM3 = Vdd
+
+// Fusion mode
+#define CONFIGMODE              0x00
+#define MODE_IMU                0x08
+#define MODE_COMPASS            0x09
+#define MODE_M4G                0x0a
+#define MODE_NDOF_FMC_OFF       0x0b
+#define MODE_NDOF               0x0c
+
+//  UNIT
+#define UNIT_ACC_MSS            0x00    // acc m/s2
+#define UNIT_ACC_MG             0x01    // acc mg
+#define UNIT_GYR_DPS            0x00    // gyro Dps
+#define UNIT_GYR_RPS            0x02    // gyro Rps
+#define UNIT_EULER_DEG          0x00    // euler Degrees
+#define UNIT_EULER_RAD          0x04    // euler Radians
+#define UNIT_TEMP_C             0x00    // temperature degC
+#define UNIT_TEMP_F             0x10    // temperature degF
+#define UNIT_ORI_WIN            0x00    // Windows orientation
+#define UNIT_ORI_ANDROID        0x80    // Android orientation
+
+//  ID's
+#define I_AM_BNO055_CHIP        0xa0    // CHIP ID
+#define I_AM_BNO055_ACC         0xfb    // ACC ID
+#define I_AM_BNO055_MAG         0x32    // MAG ID
+#define I_AM_BNO055_GYR         0x0f    // GYR ID
+
+////////////// DATA TYPE DEFINITION ///////////////////////
+typedef struct {
+    uint8_t  chip_id;
+    uint8_t  acc_id;
+    uint8_t  mag_id;
+    uint8_t  gyr_id;
+    uint8_t  bootldr_rev_id;
+    uint16_t sw_rev_id;
+} BNO055_ID_INF_TypeDef;
+
+typedef struct {
+    double h;
+    double r;
+    double p;
+} BNO055_EULER_TypeDef;
+
+typedef struct {
+    int16_t x;
+    int16_t y;
+    int16_t z;
+    int16_t w;
+} BNO055_QUATERNION_TypeDef;
+
+typedef struct {
+    double x;
+    double y;
+    double z;
+} BNO055_LIN_ACC_TypeDef;
+
+typedef struct {
+    double x;
+    double y;
+    double z;
+} BNO055_GRAVITY_TypeDef;
+
+typedef struct {
+    int8_t acc_chip;
+    int8_t gyr_chip;
+} BNO055_TEMPERATURE_TypeDef;
+
+enum {MT_P0 = 0, MT_P1, MT_P2, MT_P3, MT_P4, MT_P5, MT_P6, MT_P7};
+
+/** Interface for Bosch Sensortec Intelligent 9-axis absolute orientation sensor
+ *      Chip: BNO055
+ *
+ * @code
+ * #include    "mbed.h"
+ * #include    "BNO055.h"
+ *
+ * Serial pc(USBTX,USBRX);
+ * I2C    i2c(PB_9, PB_8);         // SDA, SCL
+ * BNO055 imu(i2c);
+ *
+ * BNO055_ID_INF_TypeDef bno055_id_inf;
+ * BNO055_EULER_TypeDef  euler_angles;
+ *
+ * int main() {
+ *     pc.printf("Bosch Sensortec BNO055 test program on " __DATE__ "/" __TIME__ "\r\n");
+ *     if (imu.chip_ready() == 0){
+ *         pc.printf("Bosch BNO055 is NOT avirable!!\r\n");
+ *     }
+ *     imu.read_id_inf(&bno055_id_inf);
+ *     pc.printf("CHIP:0x%02x, ACC:0x%02x, MAG:0x%02x, GYR:0x%02x, , SW:0x%04x, , BL:0x%02x\r\n",
+ *                bno055_id_inf.chip_id, bno055_id_inf.acc_id, bno055_id_inf.mag_id,
+ *                bno055_id_inf.gyr_id, bno055_id_inf.sw_rev_id, bno055_id_inf.bootldr_rev_id);
+ *     while(1) {
+ *         imu.get_Euler_Angles(&euler_angles);
+ *         pc.printf("Heading:%+6.1f [deg], Roll:%+6.1f [deg], Pich:%+6.1f [deg]\r\n",
+ *                    euler_angles.h, euler_angles.r, euler_angles.p);
+ *         wait(0.5);
+ *     }
+ * }
+ * @endcode
+ */
+
+class BNO055
+{
+public:
+    /** Configure data pin
+      * @param data SDA and SCL pins
+      * @param device address
+      */
+    BNO055(PinName p_sda, PinName p_scl, uint8_t addr, uint8_t mode);
+
+    /** Configure data pin
+      * @param data SDA and SCL pins
+      * @param Other parameters are set default data
+      */
+    BNO055(PinName p_sda, PinName p_scl);
+
+    /** Configure data pin (with other devices on I2C line)
+      * @param I2C previous definition
+      * @param device address
+      */
+    BNO055(I2C& p_i2c, uint8_t addr, uint8_t mode);
+
+    /** Configure data pin (with other devices on I2C line)
+      * @param I2C previous definition
+      * @param Other parameters are set default data
+      */
+    BNO055(I2C& p_i2c);
+
+    /** Get Euler Angles
+     * @param double type of 3D data address
+     */
+    void get_Euler_Angles(BNO055_EULER_TypeDef *el);
+
+    /** Get Quaternion XYZ&W
+     * @param int16_t type of 4D data address
+     */
+    void get_quaternion(BNO055_QUATERNION_TypeDef *qua);
+
+    /** Get Linear accel data
+     * @param double type of 3D data address
+     */
+    void get_linear_accel(BNO055_LIN_ACC_TypeDef *la);
+
+    /** Get Gravity data
+     * @param double type of 3D data address
+     */
+    void get_gravity(BNO055_GRAVITY_TypeDef *gr);
+
+    /** Get Chip temperature data both Acc & Gyro
+     * @param int8_t type of data address
+     */
+    void get_chip_temperature(BNO055_TEMPERATURE_TypeDef *tmp);
+
+    /** Change fusion mode
+      * @param fusion mode
+      * @return none
+      */
+    void change_fusion_mode(uint8_t mode);
+
+    /** Set Mouting position
+      *  Please make sure your mounting direction of BNO055 chip
+      *  refrence: BNO055 data sheet BST-BNO055-DS000-12 3.4 Axis remap
+      * @param Set P0 to P7 mounting position data
+      * @return none
+      */
+    void set_mounting_position(uint8_t position);
+
+    /** Read BNO055 ID information
+      * @param ID information address
+      * @return none
+      */
+    void read_id_inf(BNO055_ID_INF_TypeDef *id);
+
+    /** Check chip is avairable or not
+      * @param none
+      * @return OK = 1, NG = 0;
+      */
+    uint8_t chip_ready(void);
+
+    /** Set I2C clock frequency
+      * @param freq.
+      * @return none
+      */
+    void frequency(int hz);
+
+    /** Read page 0 register
+      * @param register's address
+      * @return register data
+      */
+    uint8_t read_reg0(uint8_t addr);
+
+    /** Write page 0 register
+      * @param register's address
+      * @param data
+      * @return register data
+      */
+    uint8_t write_reg0(uint8_t addr, uint8_t data);
+
+    /** Read page 1 register
+      * @param register's address
+      * @return register data
+      */
+    uint8_t read_reg1(uint8_t addr);
+
+    /** Write page 1 register
+      * @param register's address
+      * @param data
+      * @return register data
+      */
+    uint8_t write_reg1(uint8_t addr, uint8_t data);
+
+protected:
+    void initialize(void);
+    void check_id(void);
+    void set_initial_dt_to_regs(void);
+    void unit_selection(void);
+    uint8_t check_operating_mode(void);
+    uint8_t select_page(uint8_t page);
+
+    I2C _i2c;
+
+private:
+    char     dt[10];      // working buffer
+    uint8_t  chip_addr;
+    uint8_t  chip_mode;
+    uint8_t  ready_flg;
+
+    uint8_t  chip_id;
+    uint8_t  acc_id;
+    uint8_t  mag_id;
+    uint8_t  gyr_id;
+    uint8_t  bootldr_rev_id;
+    uint16_t sw_rev_id;
+
+};
+
+//---------------------------------------------------------
+//----- Register's definition -----------------------------
+//---------------------------------------------------------
+// Page id register definition
+#define BNO055_PAGE_ID          0x07
+
+//----- page0 ---------------------------------------------
+#define BNO055_CHIP_ID          0x00
+#define BNO055_ACCEL_REV_ID     0x01
+#define BNO055_MAG_REV_ID       0x02
+#define BNO055_GYRO_REV_ID      0x03
+#define BNO055_SW_REV_ID_LSB    0x04
+#define BNO055_SW_REV_ID_MSB    0x05
+#define BNO055_BL_REV_ID        0x06
+
+// Accel data register*/
+#define BNO055_ACC_X_LSB        0x08
+#define BNO055_ACC_X_MSB        0x09
+#define BNO055_ACC_Y_LSB        0x0a
+#define BNO055_ACC_Y_MSB        0x0b
+#define BNO055_ACC_Z_LSB        0x0c
+#define BNO055_ACC_Z_MSB        0x0d
+
+// Mag data register
+#define BNO055_MAG_X_LSB        0x0e
+#define BNO055_MAG_X_MSB        0x0f
+#define BNO055_MAG_Y_LSB        0x10
+#define BNO055_MAG_Y_MSB        0x11
+#define BNO055_MAG_Z_LSB        0x12
+#define BNO055_MAG_Z_MSB        0x13
+
+// Gyro data registers
+#define BNO055_GYR_X_LSB        0x14
+#define BNO055_GYR_X_MSB        0x15
+#define BNO055_GYR_Y_LSB        0x16
+#define BNO055_GYR_Y_MSB        0x17
+#define BNO055_GYR_Z_LSB        0x18
+#define BNO055_GYR_Z_MSB        0x19
+
+// Euler data registers
+#define BNO055_EULER_H_LSB      0x1a
+#define BNO055_EULER_H_MSB      0x1b
+
+#define BNO055_EULER_R_LSB      0x1c
+#define BNO055_EULER_R_MSB      0x1d
+
+#define BNO055_EULER_P_LSB      0x1e
+#define BNO055_EULER_P_MSB      0x1f
+
+// Quaternion data registers
+#define BNO055_QUATERNION_W_LSB 0x20
+#define BNO055_QUATERNION_W_MSB 0x21
+#define BNO055_QUATERNION_X_LSB 0x22
+#define BNO055_QUATERNION_X_MSB 0x23
+#define BNO055_QUATERNION_Y_LSB 0x24
+#define BNO055_QUATERNION_Y_MSB 0x25
+#define BNO055_QUATERNION_Z_LSB 0x26
+#define BNO055_QUATERNION_Z_MSB 0x27
+
+// Linear acceleration data registers
+#define BNO055_LINEAR_ACC_X_LSB 0x28
+#define BNO055_LINEAR_ACC_X_MSB 0x29
+#define BNO055_LINEAR_ACC_Y_LSB 0x2a
+#define BNO055_LINEAR_ACC_Y_MSB 0x2b
+#define BNO055_LINEAR_ACC_Z_LSB 0x2c
+#define BNO055_LINEAR_ACC_Z_MSB 0x2d
+
+// Gravity data registers
+#define BNO055_GRAVITY_X_LSB    0x2e
+#define BNO055_GRAVITY_X_MSB    0x2f
+#define BNO055_GRAVITY_Y_LSB    0x30
+#define BNO055_GRAVITY_Y_MSB    0x31
+#define BNO055_GRAVITY_Z_LSB    0x32
+#define BNO055_GRAVITY_Z_MSB    0x33
+
+// Temperature data register
+#define BNO055_TEMP             0x34
+
+// Status registers
+#define BNO055_CALIB_STAT       0x35
+#define BNO055_SELFTEST_RESULT  0x36
+#define BNO055_INTR_STAT        0x37
+#define BNO055_SYS_CLK_STAT     0x38
+#define BNO055_SYS_STAT         0x39
+#define BNO055_SYS_ERR          0x3a
+
+// Unit selection register
+#define BNO055_UNIT_SEL         0x3b
+#define BNO055_DATA_SELECT      0x3c
+
+// Mode registers
+#define BNO055_OPR_MODE         0x3d
+#define BNO055_PWR_MODE         0x3e
+#define BNO055_SYS_TRIGGER      0x3f
+#define BNO055_TEMP_SOURCE      0x40
+
+// Axis remap registers
+#define BNO055_AXIS_MAP_CONFIG  0x41
+#define BNO055_AXIS_MAP_SIGN    0x42
+
+// SIC registers
+#define BNO055_SIC_MTRX_0_LSB   0x43
+#define BNO055_SIC_MTRX_0_MSB   0x44
+#define BNO055_SIC_MTRX_1_LSB   0x45
+#define BNO055_SIC_MTRX_1_MSB   0x46
+#define BNO055_SIC_MTRX_2_LSB   0x47
+#define BNO055_SIC_MTRX_2_MSB   0x48
+#define BNO055_SIC_MTRX_3_LSB   0x49
+#define BNO055_SIC_MTRX_3_MSB   0x4a
+#define BNO055_SIC_MTRX_4_LSB   0x4b
+#define BNO055_SIC_MTRX_4_MSB   0x4c
+#define BNO055_SIC_MTRX_5_LSB   0x4d
+#define BNO055_SIC_MTRX_5_MSB   0x4e
+#define BNO055_SIC_MTRX_6_LSB   0x4f
+#define BNO055_SIC_MTRX_6_MSB   0x50
+#define BNO055_SIC_MTRX_7_LSB   0x51
+#define BNO055_SIC_MTRX_7_MSB   0x52
+#define BNO055_SIC_MTRX_8_LSB   0x53
+#define BNO055_SIC_MTRX_8_MSB   0x54
+
+// Accelerometer Offset registers
+#define ACCEL_OFFSET_X_LSB      0x55
+#define ACCEL_OFFSET_X_MSB      0x56
+#define ACCEL_OFFSET_Y_LSB      0x57
+#define ACCEL_OFFSET_Y_MSB      0x58
+#define ACCEL_OFFSET_Z_LSB      0x59
+#define ACCEL_OFFSET_Z_MSB      0x5a
+
+// Magnetometer Offset registers
+#define MAG_OFFSET_X_LSB        0x5b
+#define MAG_OFFSET_X_MSB        0x5c
+#define MAG_OFFSET_Y_LSB        0x5d
+#define MAG_OFFSET_Y_MSB        0x5e
+#define MAG_OFFSET_Z_LSB        0x5f
+#define MAG_OFFSET_Z_MSB        0x60
+
+// Gyroscope Offset registers
+#define GYRO_OFFSET_X_LSB       0x61
+#define GYRO_OFFSET_X_MSB       0x62
+#define GYRO_OFFSET_Y_LSB       0x63
+#define GYRO_OFFSET_Y_MSB       0x64
+#define GYRO_OFFSET_Z_LSB       0x65
+#define GYRO_OFFSET_Z_MSB       0x66
+
+// Radius registers
+#define ACCEL_RADIUS_LSB        0x67
+#define ACCEL_RADIUS_MSB        0x68
+#define MAG_RADIUS_LSB          0x69
+#define MAG_RADIUS_MSB          0x6a
+
+//----- page1 ---------------------------------------------
+// Configuration registers
+#define ACCEL_CONFIG            0x08
+#define MAG_CONFIG              0x09
+#define GYRO_CONFIG             0x0a
+#define GYRO_MODE_CONFIG        0x0b
+#define ACCEL_SLEEP_CONFIG      0x0c
+#define GYRO_SLEEP_CONFIG       0x0d
+#define MAG_SLEEP_CONFIG        0x0e
+
+// Interrupt registers
+#define INT_MASK                0x0f
+#define INT                     0x10
+#define ACCEL_ANY_MOTION_THRES  0x11
+#define ACCEL_INTR_SETTINGS     0x12
+#define ACCEL_HIGH_G_DURN       0x13
+#define ACCEL_HIGH_G_THRES      0x14
+#define ACCEL_NO_MOTION_THRES   0x15
+#define ACCEL_NO_MOTION_SET     0x16
+#define GYRO_INTR_SETING        0x17
+#define GYRO_HIGHRATE_X_SET     0x18
+#define GYRO_DURN_X             0x19
+#define GYRO_HIGHRATE_Y_SET     0x1a
+#define GYRO_DURN_Y             0x1b
+#define GYRO_HIGHRATE_Z_SET     0x1c
+#define GYRO_DURN_Z             0x1d
+#define GYRO_ANY_MOTION_THRES   0x1e
+#define GYRO_ANY_MOTION_SET     0x1f
+
+#endif      // BNO055_H