|
| 1 | +/** |
| 2 | + * |
| 3 | + * \file I2CBNO55IMU.h |
| 4 | + * \author Vincent Crocher |
| 5 | + * \version 0.1 |
| 6 | + * \date 2026-02-27 |
| 7 | + * \copyright Copyright (c) 2026 |
| 8 | + * |
| 9 | + * \brief Class allowing communication with a BNO055 IMU (Adafruit breakout board) via I2C on a BeagleBone (and maybe other) |
| 10 | + * Use registers definition from Adafruit Arduino code (https://github.com/adafruit/Adafruit_BNO055/blob/master/Adafruit_BNO055.h). |
| 11 | + * Use i2cdetect -y -r 1 command to list adresses of devices connected on the bus 1 (/dev/i2c-1) of the BB. |
| 12 | + * |
| 13 | + */ |
| 14 | + |
| 15 | +#ifndef I2CBNO55IMU_H |
| 16 | +#define I2CBNO55IMU_H |
| 17 | +#include <Eigen/Dense> |
| 18 | + |
| 19 | +#include "InputDevice.h" |
| 20 | +#include "I2CDevice.h" |
| 21 | + |
| 22 | +struct IMUData { |
| 23 | + Eigen::VectorXd rawAcc = Eigen::VectorXd::Zero(3); // 3D vector for x,y,z acceleration |
| 24 | + Eigen::VectorXd linAcc = Eigen::VectorXd::Zero(3); // 3D vector for x,y,z linear acceleration |
| 25 | + Eigen::VectorXd quat = Eigen::VectorXd::Zero(4); // 4D vector for w,x,y,z quaternion |
| 26 | + Eigen::VectorXd grav = Eigen::VectorXd::Zero(3); // 3D vector for gravity vector |
| 27 | +}; |
| 28 | + |
| 29 | + |
| 30 | +/** Operation mode settings **/ |
| 31 | +typedef enum { |
| 32 | + OPERATION_MODE_CONFIG = 0X00, |
| 33 | + OPERATION_MODE_ACCONLY = 0X01, |
| 34 | + OPERATION_MODE_MAGONLY = 0X02, |
| 35 | + OPERATION_MODE_GYRONLY = 0X03, |
| 36 | + OPERATION_MODE_ACCMAG = 0X04, |
| 37 | + OPERATION_MODE_ACCGYRO = 0X05, |
| 38 | + OPERATION_MODE_MAGGYRO = 0X06, |
| 39 | + OPERATION_MODE_AMG = 0X07, |
| 40 | + OPERATION_MODE_IMUPLUS = 0X08, |
| 41 | + OPERATION_MODE_COMPASS = 0X09, |
| 42 | + OPERATION_MODE_M4G = 0X0A, |
| 43 | + OPERATION_MODE_NDOF_FMC_OFF = 0X0B, |
| 44 | + OPERATION_MODE_NDOF = 0X0C |
| 45 | +} bno055_opmode_t; |
| 46 | + |
| 47 | +/** BNO055 Registers **/ |
| 48 | +typedef enum { |
| 49 | + /* Page id register definition */ |
| 50 | + BNO055_PAGE_ID_ADDR = 0X07, |
| 51 | + |
| 52 | + /* PAGE0 REGISTER DEFINITION START*/ |
| 53 | + BNO055_CHIP_ID_ADDR = 0x00, |
| 54 | + BNO055_ACCEL_REV_ID_ADDR = 0x01, |
| 55 | + BNO055_MAG_REV_ID_ADDR = 0x02, |
| 56 | + BNO055_GYRO_REV_ID_ADDR = 0x03, |
| 57 | + BNO055_SW_REV_ID_LSB_ADDR = 0x04, |
| 58 | + BNO055_SW_REV_ID_MSB_ADDR = 0x05, |
| 59 | + BNO055_BL_REV_ID_ADDR = 0X06, |
| 60 | + |
| 61 | + /* Accel data register */ |
| 62 | + BNO055_ACCEL_DATA_X_LSB_ADDR = 0X08, |
| 63 | + BNO055_ACCEL_DATA_X_MSB_ADDR = 0X09, |
| 64 | + BNO055_ACCEL_DATA_Y_LSB_ADDR = 0X0A, |
| 65 | + BNO055_ACCEL_DATA_Y_MSB_ADDR = 0X0B, |
| 66 | + BNO055_ACCEL_DATA_Z_LSB_ADDR = 0X0C, |
| 67 | + BNO055_ACCEL_DATA_Z_MSB_ADDR = 0X0D, |
| 68 | + |
| 69 | + /* Mag data register */ |
| 70 | + BNO055_MAG_DATA_X_LSB_ADDR = 0X0E, |
| 71 | + BNO055_MAG_DATA_X_MSB_ADDR = 0X0F, |
| 72 | + BNO055_MAG_DATA_Y_LSB_ADDR = 0X10, |
| 73 | + BNO055_MAG_DATA_Y_MSB_ADDR = 0X11, |
| 74 | + BNO055_MAG_DATA_Z_LSB_ADDR = 0X12, |
| 75 | + BNO055_MAG_DATA_Z_MSB_ADDR = 0X13, |
| 76 | + |
| 77 | + /* Gyro data registers */ |
| 78 | + BNO055_GYRO_DATA_X_LSB_ADDR = 0X14, |
| 79 | + BNO055_GYRO_DATA_X_MSB_ADDR = 0X15, |
| 80 | + BNO055_GYRO_DATA_Y_LSB_ADDR = 0X16, |
| 81 | + BNO055_GYRO_DATA_Y_MSB_ADDR = 0X17, |
| 82 | + BNO055_GYRO_DATA_Z_LSB_ADDR = 0X18, |
| 83 | + BNO055_GYRO_DATA_Z_MSB_ADDR = 0X19, |
| 84 | + |
| 85 | + /* Euler data registers */ |
| 86 | + BNO055_EULER_H_LSB_ADDR = 0X1A, |
| 87 | + BNO055_EULER_H_MSB_ADDR = 0X1B, |
| 88 | + BNO055_EULER_R_LSB_ADDR = 0X1C, |
| 89 | + BNO055_EULER_R_MSB_ADDR = 0X1D, |
| 90 | + BNO055_EULER_P_LSB_ADDR = 0X1E, |
| 91 | + BNO055_EULER_P_MSB_ADDR = 0X1F, |
| 92 | + |
| 93 | + /* Quaternion data registers */ |
| 94 | + BNO055_QUATERNION_DATA_W_LSB_ADDR = 0X20, |
| 95 | + BNO055_QUATERNION_DATA_W_MSB_ADDR = 0X21, |
| 96 | + BNO055_QUATERNION_DATA_X_LSB_ADDR = 0X22, |
| 97 | + BNO055_QUATERNION_DATA_X_MSB_ADDR = 0X23, |
| 98 | + BNO055_QUATERNION_DATA_Y_LSB_ADDR = 0X24, |
| 99 | + BNO055_QUATERNION_DATA_Y_MSB_ADDR = 0X25, |
| 100 | + BNO055_QUATERNION_DATA_Z_LSB_ADDR = 0X26, |
| 101 | + BNO055_QUATERNION_DATA_Z_MSB_ADDR = 0X27, |
| 102 | + |
| 103 | + /* Linear acceleration data registers */ |
| 104 | + BNO055_LINEAR_ACCEL_DATA_X_LSB_ADDR = 0X28, |
| 105 | + BNO055_LINEAR_ACCEL_DATA_X_MSB_ADDR = 0X29, |
| 106 | + BNO055_LINEAR_ACCEL_DATA_Y_LSB_ADDR = 0X2A, |
| 107 | + BNO055_LINEAR_ACCEL_DATA_Y_MSB_ADDR = 0X2B, |
| 108 | + BNO055_LINEAR_ACCEL_DATA_Z_LSB_ADDR = 0X2C, |
| 109 | + BNO055_LINEAR_ACCEL_DATA_Z_MSB_ADDR = 0X2D, |
| 110 | + |
| 111 | + /* Gravity data registers */ |
| 112 | + BNO055_GRAVITY_DATA_X_LSB_ADDR = 0X2E, |
| 113 | + BNO055_GRAVITY_DATA_X_MSB_ADDR = 0X2F, |
| 114 | + BNO055_GRAVITY_DATA_Y_LSB_ADDR = 0X30, |
| 115 | + BNO055_GRAVITY_DATA_Y_MSB_ADDR = 0X31, |
| 116 | + BNO055_GRAVITY_DATA_Z_LSB_ADDR = 0X32, |
| 117 | + BNO055_GRAVITY_DATA_Z_MSB_ADDR = 0X33, |
| 118 | + |
| 119 | + /* Temperature data register */ |
| 120 | + BNO055_TEMP_ADDR = 0X34, |
| 121 | + |
| 122 | + /* Status registers */ |
| 123 | + BNO055_CALIB_STAT_ADDR = 0X35, |
| 124 | + BNO055_SELFTEST_RESULT_ADDR = 0X36, |
| 125 | + BNO055_INTR_STAT_ADDR = 0X37, |
| 126 | + |
| 127 | + BNO055_SYS_CLK_STAT_ADDR = 0X38, |
| 128 | + BNO055_SYS_STAT_ADDR = 0X39, |
| 129 | + BNO055_SYS_ERR_ADDR = 0X3A, |
| 130 | + |
| 131 | + /* Unit selection register */ |
| 132 | + BNO055_UNIT_SEL_ADDR = 0X3B, |
| 133 | + |
| 134 | + /* Mode registers */ |
| 135 | + BNO055_OPR_MODE_ADDR = 0X3D, |
| 136 | + BNO055_PWR_MODE_ADDR = 0X3E, |
| 137 | + |
| 138 | + BNO055_SYS_TRIGGER_ADDR = 0X3F, |
| 139 | + BNO055_TEMP_SOURCE_ADDR = 0X40, |
| 140 | + |
| 141 | + /* Axis remap registers */ |
| 142 | + BNO055_AXIS_MAP_CONFIG_ADDR = 0X41, |
| 143 | + BNO055_AXIS_MAP_SIGN_ADDR = 0X42, |
| 144 | + |
| 145 | + /* SIC registers */ |
| 146 | + BNO055_SIC_MATRIX_0_LSB_ADDR = 0X43, |
| 147 | + BNO055_SIC_MATRIX_0_MSB_ADDR = 0X44, |
| 148 | + BNO055_SIC_MATRIX_1_LSB_ADDR = 0X45, |
| 149 | + BNO055_SIC_MATRIX_1_MSB_ADDR = 0X46, |
| 150 | + BNO055_SIC_MATRIX_2_LSB_ADDR = 0X47, |
| 151 | + BNO055_SIC_MATRIX_2_MSB_ADDR = 0X48, |
| 152 | + BNO055_SIC_MATRIX_3_LSB_ADDR = 0X49, |
| 153 | + BNO055_SIC_MATRIX_3_MSB_ADDR = 0X4A, |
| 154 | + BNO055_SIC_MATRIX_4_LSB_ADDR = 0X4B, |
| 155 | + BNO055_SIC_MATRIX_4_MSB_ADDR = 0X4C, |
| 156 | + BNO055_SIC_MATRIX_5_LSB_ADDR = 0X4D, |
| 157 | + BNO055_SIC_MATRIX_5_MSB_ADDR = 0X4E, |
| 158 | + BNO055_SIC_MATRIX_6_LSB_ADDR = 0X4F, |
| 159 | + BNO055_SIC_MATRIX_6_MSB_ADDR = 0X50, |
| 160 | + BNO055_SIC_MATRIX_7_LSB_ADDR = 0X51, |
| 161 | + BNO055_SIC_MATRIX_7_MSB_ADDR = 0X52, |
| 162 | + BNO055_SIC_MATRIX_8_LSB_ADDR = 0X53, |
| 163 | + BNO055_SIC_MATRIX_8_MSB_ADDR = 0X54, |
| 164 | + |
| 165 | + /* Accelerometer Offset registers */ |
| 166 | + ACCEL_OFFSET_X_LSB_ADDR = 0X55, |
| 167 | + ACCEL_OFFSET_X_MSB_ADDR = 0X56, |
| 168 | + ACCEL_OFFSET_Y_LSB_ADDR = 0X57, |
| 169 | + ACCEL_OFFSET_Y_MSB_ADDR = 0X58, |
| 170 | + ACCEL_OFFSET_Z_LSB_ADDR = 0X59, |
| 171 | + ACCEL_OFFSET_Z_MSB_ADDR = 0X5A, |
| 172 | + |
| 173 | + /* Magnetometer Offset registers */ |
| 174 | + MAG_OFFSET_X_LSB_ADDR = 0X5B, |
| 175 | + MAG_OFFSET_X_MSB_ADDR = 0X5C, |
| 176 | + MAG_OFFSET_Y_LSB_ADDR = 0X5D, |
| 177 | + MAG_OFFSET_Y_MSB_ADDR = 0X5E, |
| 178 | + MAG_OFFSET_Z_LSB_ADDR = 0X5F, |
| 179 | + MAG_OFFSET_Z_MSB_ADDR = 0X60, |
| 180 | + |
| 181 | + /* Gyroscope Offset register s*/ |
| 182 | + GYRO_OFFSET_X_LSB_ADDR = 0X61, |
| 183 | + GYRO_OFFSET_X_MSB_ADDR = 0X62, |
| 184 | + GYRO_OFFSET_Y_LSB_ADDR = 0X63, |
| 185 | + GYRO_OFFSET_Y_MSB_ADDR = 0X64, |
| 186 | + GYRO_OFFSET_Z_LSB_ADDR = 0X65, |
| 187 | + GYRO_OFFSET_Z_MSB_ADDR = 0X66, |
| 188 | + |
| 189 | + /* Radius registers */ |
| 190 | + ACCEL_RADIUS_LSB_ADDR = 0X67, |
| 191 | + ACCEL_RADIUS_MSB_ADDR = 0X68, |
| 192 | + MAG_RADIUS_LSB_ADDR = 0X69, |
| 193 | + MAG_RADIUS_MSB_ADDR = 0X6A |
| 194 | +} bno055_reg_t; |
| 195 | + |
| 196 | +/** BNO055 power settings */ |
| 197 | +typedef enum { |
| 198 | + POWER_MODE_NORMAL = 0X00, |
| 199 | + POWER_MODE_LOWPOWER = 0X01, |
| 200 | + POWER_MODE_SUSPEND = 0X02 |
| 201 | +} bno055_powermode_t; |
| 202 | + |
| 203 | + |
| 204 | + |
| 205 | +/** |
| 206 | + * \ingroup IO |
| 207 | + * \brief Class inherit InputDevice to handle an I2C based BNO 055 IMU. |
| 208 | + */ |
| 209 | +class I2CBNO55IMU: public InputDevice, public I2CDevice { |
| 210 | + private: |
| 211 | + IMUData data; |
| 212 | + |
| 213 | + /** |
| 214 | + * \brief Update quat values from IMU. |
| 215 | + */ |
| 216 | + void readQuat(); |
| 217 | + /** |
| 218 | + * \brief Update linear accel. from IMU. |
| 219 | + */ |
| 220 | + void readLinAcc(); |
| 221 | + /** |
| 222 | + * \brief Update gravity vector from IMU. |
| 223 | + */ |
| 224 | + void readGrav(); |
| 225 | + |
| 226 | + public: |
| 227 | + I2CBNO55IMU(unsigned char _DeviceAddress, int _BusId=1); |
| 228 | + |
| 229 | + void setDeviceAddress( unsigned char _DeviceAddress ){ DeviceAddress = _DeviceAddress; }; |
| 230 | + void setBusId( int _BusId ) { BusId = _BusId; }; |
| 231 | + |
| 232 | + /** |
| 233 | + * \brief Update all relevant IMU values: linear acceleration, gravity vector and quaternion. |
| 234 | + */ |
| 235 | + void updateInput(); |
| 236 | + |
| 237 | + /** |
| 238 | + * \brief Select (set) IMU working mode. |
| 239 | + * \param Default is NDOF: full 9DoF fusion. |
| 240 | + */ |
| 241 | + void setMode(bno055_opmode_t mode = OPERATION_MODE_NDOF) { writeReg(BNO055_OPR_MODE_ADDR, mode); }; |
| 242 | + /** |
| 243 | + * \brief Set IMU in SI units ( radians, rps, m/s2, celsius). |
| 244 | + */ |
| 245 | + void setSIUnits() { writeReg(BNO055_UNIT_SEL_ADDR, 0x06); }; |
| 246 | + |
| 247 | + void setFastAccOnly() { setMode(OPERATION_MODE_ACCONLY); writeReg(0x08, 0x1D); } |
| 248 | + |
| 249 | + /** |
| 250 | + * \brief Read and return temperature of IMU. |
| 251 | + */ |
| 252 | + int getTemp() { return readRegisterRdwr(BNO055_TEMP_ADDR); }; |
| 253 | + |
| 254 | + /** |
| 255 | + * \brief Get the linear acceleration readings from IMU |
| 256 | + * |
| 257 | + * \return Eigen::VectorXd x,y,z axis of linear acceleration |
| 258 | + */ |
| 259 | + Eigen::VectorXd& getLinAcc() { return data.linAcc; }; |
| 260 | + |
| 261 | + /** |
| 262 | + * \brief Get the quaternion readings from the IMU |
| 263 | + * |
| 264 | + * \return Eigen::VectorXd w,x,y,z quaternion |
| 265 | + */ |
| 266 | + Eigen::VectorXd& getQuat() { return data.quat; }; |
| 267 | + |
| 268 | + /** |
| 269 | + * \brief Get the gravity vector from the IMU |
| 270 | + * |
| 271 | + * \return Eigen::VectorXd 3D gravity direction vector |
| 272 | + */ |
| 273 | + Eigen::VectorXd& getGravityVec() { return data.grav; }; |
| 274 | + |
| 275 | +}; |
| 276 | +#endif |
0 commit comments