├── DFRobot_BMI160.cpp ├── DFRobot_BMI160.h ├── LICENSE ├── README.md ├── README_CN.md ├── examples ├── accelGyro │ └── accelGyro.ino ├── stepCounterLowPower │ └── stepCounterLowPower.ino └── stepCounterNormal │ └── stepCounterNormal.ino ├── keywords.txt ├── library.properties ├── python └── raspberrypi │ ├── DFRobot_BMI160.py │ ├── README.md │ ├── README_CN.md │ └── examples │ ├── demo_get_accel_gyro.py │ ├── demo_step_counter_low_power.py │ └── demo_step_counter_normal.py ├── readme.md └── resources └── images └── SEN0250.png /DFRobot_BMI160.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file DFRobot_BMI160.cpp 3 | * @brief Define the basic structure of class DFRobot_BMI160 4 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 5 | * @license The MIT License (MIT) 6 | * @author DFRobot_haoJ(hao.jiang@dfrobot.com) 7 | * @version V1.0 8 | * @date 2017-12-01 9 | * @url https://github.com/DFRobot/DFRobot_BMI160 10 | */ 11 | 12 | #include"DFRobot_BMI160.h" 13 | 14 | const uint8_t int_mask_lookup_table[13] = { 15 | BMI160_INT1_SLOPE_MASK, 16 | BMI160_INT1_SLOPE_MASK, 17 | BMI160_INT2_LOW_STEP_DETECT_MASK, 18 | BMI160_INT1_DOUBLE_TAP_MASK, 19 | BMI160_INT1_SINGLE_TAP_MASK, 20 | BMI160_INT1_ORIENT_MASK, 21 | BMI160_INT1_FLAT_MASK, 22 | BMI160_INT1_HIGH_G_MASK, 23 | BMI160_INT1_LOW_G_MASK, 24 | BMI160_INT1_NO_MOTION_MASK, 25 | BMI160_INT2_DATA_READY_MASK, 26 | BMI160_INT2_FIFO_FULL_MASK, 27 | BMI160_INT2_FIFO_WM_MASK 28 | }; 29 | 30 | DFRobot_BMI160::DFRobot_BMI160() 31 | { 32 | Wire.begin(); 33 | Obmi160=(struct bmi160Dev *)malloc(sizeof(struct bmi160Dev)); 34 | //Obmi160->id = BMI160_I2C_ADDR; 35 | //Obmi160->interface = BMI160_I2C_INTF; 36 | Oaccel= (struct bmi160SensorData*)malloc(sizeof(struct bmi160SensorData)); 37 | Ogyro = (struct bmi160SensorData*)malloc(sizeof(struct bmi160SensorData)); 38 | } 39 | 40 | int8_t DFRobot_BMI160::I2cInit(int8_t i2c_addr) 41 | { 42 | Obmi160->id = i2c_addr; 43 | Obmi160->interface = BMI160_I2C_INTF; 44 | return DFRobot_BMI160::I2cInit(Obmi160); 45 | } 46 | 47 | int8_t DFRobot_BMI160::SPIInit() 48 | { 49 | //SPI.begin(); 50 | //pinMode(10,OUTPUT); 51 | //Obmi160->id = 0; 52 | //Obmi160->interface = BMI160_SPI_INTF; 53 | return BMI160_OK; 54 | } 55 | 56 | int8_t DFRobot_BMI160::SPIInit(struct bmi160Dev *dev) 57 | { 58 | return BMI160_OK; 59 | } 60 | 61 | int8_t DFRobot_BMI160::I2cInit(struct bmi160Dev *dev) 62 | { 63 | int8_t rslt=BMI160_OK; 64 | uint8_t chip_id=0; 65 | uint8_t data=0; 66 | if (dev==NULL){ 67 | return BMI160_E_NULL_PTR; 68 | } 69 | 70 | if (dev->interface == BMI160_SPI_INTF){ 71 | rslt = getRegs(BMI160_SPI_COMM_TEST_ADDR, &data, 1, dev); 72 | } 73 | if (rslt == BMI160_OK){ 74 | rslt = getRegs(BMI160_CHIP_ID_ADDR, &chip_id, 1, dev); 75 | if ((rslt == BMI160_OK)&&(chip_id==BMI160_CHIP_ID)){ 76 | dev->any_sig_sel = eBmi160BothAnySigMotionDisabled; 77 | dev->chipId = chip_id; 78 | rslt = softReset(dev); 79 | if (rslt==BMI160_OK){ 80 | rslt = setSensConf(dev); 81 | } 82 | }else{ 83 | rslt = BMI160_E_DEV_NOT_FOUND; 84 | } 85 | } 86 | return rslt; 87 | } 88 | 89 | int8_t DFRobot_BMI160::softReset() 90 | { 91 | int8_t rslt=BMI160_OK; 92 | if (Obmi160 == NULL){ 93 | rslt = BMI160_E_NULL_PTR; 94 | } 95 | rslt = softReset(Obmi160); 96 | return rslt; 97 | } 98 | 99 | int8_t DFRobot_BMI160::softReset(struct bmi160Dev *dev) 100 | { 101 | int8_t rslt=BMI160_OK; 102 | uint8_t data = BMI160_SOFT_RESET_CMD; 103 | if (dev==NULL){ 104 | rslt = BMI160_E_NULL_PTR; 105 | } 106 | rslt = DFRobot_BMI160::setRegs(BMI160_COMMAND_REG_ADDR, &data, 1, dev); 107 | delay(BMI160_SOFT_RESET_DELAY_MS); 108 | if (rslt == BMI160_OK){ 109 | DFRobot_BMI160::defaultParamSettg(dev); 110 | } 111 | return rslt; 112 | } 113 | 114 | void DFRobot_BMI160::defaultParamSettg(struct bmi160Dev *dev) 115 | { 116 | /* Initializing accel and gyro params with 117 | * default values */ 118 | dev->accelCfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4; 119 | dev->accelCfg.odr = BMI160_ACCEL_ODR_100HZ; 120 | dev->accelCfg.power = BMI160_ACCEL_SUSPEND_MODE; 121 | dev->accelCfg.range = BMI160_ACCEL_RANGE_2G; 122 | dev->gyroCfg.bw = BMI160_GYRO_BW_NORMAL_MODE; 123 | dev->gyroCfg.odr = BMI160_GYRO_ODR_100HZ; 124 | dev->gyroCfg.power = BMI160_GYRO_SUSPEND_MODE; 125 | dev->gyroCfg.range = BMI160_GYRO_RANGE_2000_DPS; 126 | 127 | /* To maintain the previous state of accel configuration */ 128 | dev->prevAccelCfg = dev->accelCfg; 129 | /* To maintain the previous state of gyro configuration */ 130 | dev->prevGyroCfg = dev->gyroCfg; 131 | } 132 | 133 | int8_t DFRobot_BMI160::setSensConf() 134 | { 135 | return DFRobot_BMI160::setSensConf(Obmi160); 136 | } 137 | 138 | int8_t DFRobot_BMI160::setSensConf(struct bmi160Dev *dev) 139 | { 140 | int8_t rslt = BMI160_OK; 141 | dev->accelCfg.odr = BMI160_ACCEL_ODR_1600HZ; 142 | dev->accelCfg.range = BMI160_ACCEL_RANGE_2G; 143 | dev->accelCfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4; 144 | 145 | dev->accelCfg.power = BMI160_ACCEL_NORMAL_MODE; 146 | 147 | dev->gyroCfg.odr = BMI160_GYRO_ODR_3200HZ; 148 | dev->gyroCfg.range = BMI160_GYRO_RANGE_2000_DPS; 149 | dev->gyroCfg.bw = BMI160_GYRO_BW_NORMAL_MODE; 150 | 151 | dev->gyroCfg.power = BMI160_GYRO_NORMAL_MODE; 152 | 153 | 154 | rslt = DFRobot_BMI160::setAccelConf(dev); 155 | if (rslt == BMI160_OK) { 156 | rslt = DFRobot_BMI160::setGyroConf(dev); 157 | if (rslt == BMI160_OK) { 158 | /* write power mode for accel and gyro */ 159 | rslt = DFRobot_BMI160::setPowerMode(dev); 160 | if (rslt == BMI160_OK) 161 | rslt = DFRobot_BMI160::checkInvalidSettg(dev); 162 | } 163 | } 164 | 165 | return rslt; 166 | } 167 | 168 | int8_t DFRobot_BMI160::setAccelConf(struct bmi160Dev *dev) 169 | { 170 | int8_t rslt = BMI160_OK; 171 | uint8_t data[2] = {0}; 172 | rslt = DFRobot_BMI160::checkAccelConfig(data, dev); 173 | if (rslt == BMI160_OK) { 174 | rslt = DFRobot_BMI160::setRegs(BMI160_ACCEL_CONFIG_ADDR, &data[0], 1, dev); 175 | if (rslt == BMI160_OK) { 176 | dev->prevAccelCfg.odr = dev->accelCfg.odr; 177 | dev->prevAccelCfg.bw = dev->accelCfg.bw; 178 | delay(BMI160_ONE_MS_DELAY); 179 | rslt = DFRobot_BMI160::setRegs(BMI160_ACCEL_RANGE_ADDR, &data[1], 1, dev); 180 | if (rslt == BMI160_OK){ 181 | dev->prevAccelCfg.range = dev->accelCfg.range; 182 | } 183 | } 184 | } 185 | return rslt; 186 | } 187 | 188 | int8_t DFRobot_BMI160::checkAccelConfig(uint8_t *data, struct bmi160Dev *dev) 189 | { 190 | int8_t rslt; 191 | 192 | /* read accel Output data rate and bandwidth */ 193 | rslt = DFRobot_BMI160::getRegs(BMI160_ACCEL_CONFIG_ADDR, data, 2, dev); 194 | if (rslt == BMI160_OK) { 195 | rslt = DFRobot_BMI160::processAccelOdr(&data[0], dev); 196 | if (rslt == BMI160_OK) { 197 | rslt = DFRobot_BMI160::processAccelBw(&data[0], dev); 198 | if (rslt == BMI160_OK) 199 | rslt = DFRobot_BMI160::processAccelRange(&data[1], dev); 200 | } 201 | } 202 | 203 | return rslt; 204 | } 205 | 206 | int8_t DFRobot_BMI160::processAccelOdr(uint8_t *data, struct bmi160Dev *dev) 207 | { 208 | int8_t rslt = 0; 209 | uint8_t temp = 0; 210 | uint8_t odr = 0; 211 | 212 | if (dev->accelCfg.odr <= BMI160_ACCEL_ODR_MAX) { 213 | if (dev->accelCfg.odr != dev->prevAccelCfg.odr) { 214 | odr = (uint8_t)dev->accelCfg.odr; 215 | temp = *data & ~BMI160_ACCEL_ODR_MASK; 216 | /* Adding output data rate */ 217 | *data = temp | (odr & BMI160_ACCEL_ODR_MASK); 218 | } 219 | } else { 220 | rslt = BMI160_E_OUT_OF_RANGE; 221 | } 222 | 223 | return rslt; 224 | } 225 | 226 | int8_t DFRobot_BMI160::processAccelBw(uint8_t *data, struct bmi160Dev *dev) 227 | { 228 | int8_t rslt = 0; 229 | uint8_t temp = 0; 230 | uint8_t bw = 0; 231 | 232 | if (dev->accelCfg.bw <= BMI160_ACCEL_BW_MAX) { 233 | if (dev->accelCfg.bw != dev->prevAccelCfg.bw) { 234 | bw = (uint8_t)dev->accelCfg.bw; 235 | temp = *data & ~BMI160_ACCEL_BW_MASK; 236 | /* Adding bandwidth */ 237 | *data = temp | ((bw << 4) & BMI160_ACCEL_ODR_MASK); 238 | } 239 | } else { 240 | rslt = BMI160_E_OUT_OF_RANGE; 241 | } 242 | 243 | return rslt; 244 | } 245 | 246 | int8_t DFRobot_BMI160::processAccelRange(uint8_t *data, struct bmi160Dev *dev) 247 | { 248 | int8_t rslt = 0; 249 | uint8_t temp = 0; 250 | uint8_t range = 0; 251 | 252 | if (dev->accelCfg.range <= BMI160_ACCEL_RANGE_MAX) { 253 | if (dev->accelCfg.range != dev->prevAccelCfg.range) { 254 | range = (uint8_t)dev->accelCfg.range; 255 | temp = *data & ~BMI160_ACCEL_RANGE_MASK; 256 | /* Adding range */ 257 | *data = temp | (range & BMI160_ACCEL_RANGE_MASK); 258 | } 259 | } else { 260 | rslt = BMI160_E_OUT_OF_RANGE; 261 | } 262 | 263 | return rslt; 264 | } 265 | 266 | int8_t DFRobot_BMI160::setGyroConf(struct bmi160Dev *dev) 267 | { 268 | int8_t rslt; 269 | uint8_t data[2]={0}; 270 | 271 | rslt = DFRobot_BMI160::checkGyroConfig(data, dev); 272 | 273 | if (rslt == BMI160_OK) { 274 | // Write output data rate and bandwidth 275 | rslt = DFRobot_BMI160::setRegs(BMI160_GYRO_CONFIG_ADDR, &data[0], 1, dev); 276 | if (rslt == BMI160_OK) { 277 | dev->prevGyroCfg.odr = dev->gyroCfg.odr; 278 | dev->prevGyroCfg.bw = dev->gyroCfg.bw; 279 | delay(BMI160_ONE_MS_DELAY); 280 | // Write gyro range 281 | rslt = DFRobot_BMI160::setRegs(BMI160_GYRO_RANGE_ADDR, &data[1], 1, dev); 282 | if (rslt == BMI160_OK) 283 | dev->prevGyroCfg.range = dev->gyroCfg.range; 284 | } 285 | } 286 | 287 | return rslt; 288 | } 289 | 290 | int8_t DFRobot_BMI160::checkGyroConfig(uint8_t *data, struct bmi160Dev *dev) 291 | { 292 | int8_t rslt; 293 | 294 | /* read gyro Output data rate and bandwidth */ 295 | rslt = DFRobot_BMI160::getRegs(BMI160_GYRO_CONFIG_ADDR, data, 2, dev); 296 | if (rslt == BMI160_OK) { 297 | rslt = DFRobot_BMI160::processGyroOdr(&data[0], dev); 298 | if (rslt == BMI160_OK) { 299 | rslt = DFRobot_BMI160::processGyroBw(&data[0], dev); 300 | if (rslt == BMI160_OK) 301 | rslt = DFRobot_BMI160::processGyroRange(&data[1], dev); 302 | } 303 | } 304 | 305 | return rslt; 306 | } 307 | 308 | int8_t DFRobot_BMI160::processGyroOdr(uint8_t *data, struct bmi160Dev *dev) 309 | { 310 | int8_t rslt = 0; 311 | uint8_t temp = 0; 312 | uint8_t odr = 0; 313 | 314 | if (dev->gyroCfg.odr <= BMI160_GYRO_ODR_MAX) { 315 | if (dev->gyroCfg.odr != dev->prevGyroCfg.odr) { 316 | odr = (uint8_t)dev->gyroCfg.odr; 317 | temp = (*data & ~BMI160_GYRO_ODR_MASK); 318 | /* Adding output data rate */ 319 | *data = temp | (odr & BMI160_GYRO_ODR_MASK); 320 | } 321 | } else { 322 | rslt = BMI160_E_OUT_OF_RANGE; 323 | } 324 | 325 | return rslt; 326 | } 327 | 328 | int8_t DFRobot_BMI160::processGyroBw(uint8_t *data, struct bmi160Dev *dev) 329 | { 330 | int8_t rslt = 0; 331 | uint8_t temp = 0; 332 | uint8_t bw = 0; 333 | 334 | if (dev->gyroCfg.bw <= BMI160_GYRO_BW_MAX) { 335 | bw = (uint8_t)dev->gyroCfg.bw; 336 | temp = *data & ~BMI160_GYRO_BW_MASK; 337 | /* Adding bandwidth */ 338 | *data = temp | ((bw << 4) & BMI160_GYRO_BW_MASK); 339 | } else { 340 | rslt = BMI160_E_OUT_OF_RANGE; 341 | } 342 | 343 | return rslt; 344 | } 345 | 346 | int8_t DFRobot_BMI160::processGyroRange(uint8_t *data, struct bmi160Dev *dev) 347 | { 348 | int8_t rslt = 0; 349 | uint8_t temp = 0; 350 | uint8_t range = 0; 351 | 352 | if (dev->gyroCfg.range <= BMI160_GYRO_RANGE_MAX) { 353 | if (dev->gyroCfg.range != dev->prevGyroCfg.range) { 354 | range = (uint8_t)dev->gyroCfg.range; 355 | temp = *data & ~BMI160_GYRO_RANGE_MSK; 356 | /* Adding range */ 357 | *data = temp | (range & BMI160_GYRO_RANGE_MSK); 358 | } 359 | } else { 360 | rslt = BMI160_E_OUT_OF_RANGE; 361 | } 362 | 363 | return rslt; 364 | } 365 | 366 | int8_t DFRobot_BMI160::setPowerMode(struct bmi160Dev *dev) 367 | { 368 | int8_t rslt = 0; 369 | rslt = DFRobot_BMI160::setAccelPwr(dev); 370 | if (rslt == BMI160_OK){ 371 | rslt = DFRobot_BMI160::setGyroPwr(dev); 372 | } 373 | return rslt; 374 | } 375 | 376 | int8_t DFRobot_BMI160::setAccelPwr(struct bmi160Dev *dev) 377 | { 378 | int8_t rslt = 0; 379 | uint8_t data = 0; 380 | 381 | if ((dev->accelCfg.power >= BMI160_ACCEL_SUSPEND_MODE) && 382 | (dev->accelCfg.power <= BMI160_ACCEL_LOWPOWER_MODE)) { 383 | if (dev->accelCfg.power != dev->prevAccelCfg.power) { 384 | rslt = DFRobot_BMI160::processUnderSampling(&data, dev); 385 | if (rslt == BMI160_OK) { 386 | /* Write accel power */ 387 | rslt = DFRobot_BMI160::setRegs(BMI160_COMMAND_REG_ADDR, &dev->accelCfg.power, 1, dev); 388 | /* Add delay of 5 ms */ 389 | if (dev->prevAccelCfg.power == BMI160_ACCEL_SUSPEND_MODE){ 390 | delay(BMI160_ACCEL_DELAY_MS); 391 | } 392 | dev->prevAccelCfg.power = dev->accelCfg.power; 393 | } 394 | } 395 | } else { 396 | rslt = BMI160_E_OUT_OF_RANGE; 397 | } 398 | 399 | return rslt; 400 | } 401 | 402 | int8_t DFRobot_BMI160::processUnderSampling(uint8_t *data, struct bmi160Dev *dev) 403 | { 404 | int8_t rslt; 405 | uint8_t temp = 0; 406 | uint8_t pre_filter = 0; 407 | 408 | rslt = DFRobot_BMI160::getRegs(BMI160_ACCEL_CONFIG_ADDR, data, 1, dev); 409 | if (rslt == BMI160_OK) { 410 | if (dev->accelCfg.power == BMI160_ACCEL_LOWPOWER_MODE) { 411 | temp = *data & ~BMI160_ACCEL_UNDERSAMPLING_MASK; 412 | /* Set under-sampling parameter */ 413 | *data = temp | ((1 << 7) & BMI160_ACCEL_UNDERSAMPLING_MASK); 414 | /* Write data */ 415 | rslt = setRegs(BMI160_ACCEL_CONFIG_ADDR, data, 1, dev); 416 | /* disable the pre-filter data in 417 | * low power mode */ 418 | if (rslt == BMI160_OK) 419 | /* Disable the Pre-filter data*/ 420 | rslt = DFRobot_BMI160::setRegs(BMI160_INT_DATA_0_ADDR, &pre_filter, 2, dev); 421 | } else { 422 | if (*data & BMI160_ACCEL_UNDERSAMPLING_MASK) { 423 | temp = *data & ~BMI160_ACCEL_UNDERSAMPLING_MASK; 424 | /* disable under-sampling parameter 425 | if already enabled */ 426 | *data = temp; 427 | /* Write data */ 428 | rslt = DFRobot_BMI160::setRegs(BMI160_ACCEL_CONFIG_ADDR, data, 1, dev); 429 | } 430 | } 431 | } 432 | 433 | return rslt; 434 | } 435 | 436 | int8_t DFRobot_BMI160::setGyroPwr(struct bmi160Dev *dev) 437 | { 438 | int8_t rslt = 0; 439 | if ((dev->gyroCfg.power == BMI160_GYRO_SUSPEND_MODE) || (dev->gyroCfg.power == BMI160_GYRO_NORMAL_MODE) 440 | || (dev->gyroCfg.power == BMI160_GYRO_FASTSTARTUP_MODE)) { 441 | if (dev->gyroCfg.power != dev->prevGyroCfg.power) { 442 | /* Write gyro power */ 443 | rslt = DFRobot_BMI160::setRegs(BMI160_COMMAND_REG_ADDR, &dev->gyroCfg.power, 1, dev); 444 | if (dev->prevGyroCfg.power == BMI160_GYRO_SUSPEND_MODE) { 445 | /* Delay of 81 ms */ 446 | delay(BMI160_GYRO_DELAY_MS); 447 | } else if ((dev->prevGyroCfg.power == BMI160_GYRO_FASTSTARTUP_MODE) 448 | && (dev->gyroCfg.power == BMI160_GYRO_NORMAL_MODE)) { 449 | /* This delay is required for transition from 450 | fast-startup mode to normal mode */ 451 | delay(10); 452 | } else { 453 | /* do nothing */ 454 | } 455 | dev->prevGyroCfg.power = dev->gyroCfg.power; 456 | } 457 | } else { 458 | rslt = BMI160_E_OUT_OF_RANGE; 459 | } 460 | 461 | return rslt; 462 | } 463 | 464 | int8_t DFRobot_BMI160::checkInvalidSettg( struct bmi160Dev *dev) 465 | { 466 | int8_t rslt; 467 | uint8_t data = 0; 468 | 469 | // read the error reg 470 | rslt = DFRobot_BMI160::getRegs(BMI160_ERROR_REG_ADDR, &data, 1, dev); 471 | 472 | data = data >> 1; 473 | data = data & BMI160_ERR_REG_MASK; 474 | if (data == 1) 475 | rslt = BMI160_E_ACCEL_ODR_BW_INVALID; 476 | else if (data == 2) 477 | rslt = BMI160_E_GYRO_ODR_BW_INVALID; 478 | else if (data == 3) 479 | rslt = BMI160_E_LWP_PRE_FLTR_INT_INVALID; 480 | else if (data == 7) 481 | rslt = BMI160_E_LWP_PRE_FLTR_INVALID; 482 | 483 | return rslt; 484 | } 485 | 486 | int8_t DFRobot_BMI160::getSensorData(uint8_t type, int16_t* data) 487 | { 488 | int8_t rslt=BMI160_OK; 489 | if (type==onlyAccel){ 490 | rslt = getSensorData(BMI160_ACCEL_SEL, Oaccel, NULL, Obmi160); 491 | if(rslt == BMI160_OK){ 492 | data[0]=Ogyro->x; 493 | data[1]=Ogyro->y; 494 | data[2]=Ogyro->z; 495 | } 496 | }else if(type==onlyGyro){ 497 | rslt = getSensorData(BMI160_GYRO_SEL, NULL, Ogyro, Obmi160); 498 | if(rslt == BMI160_OK){ 499 | data[0]=Oaccel->x; 500 | data[1]=Oaccel->y; 501 | data[2]=Oaccel->z; 502 | } 503 | }else if(type==bothAccelGyro){ 504 | rslt = DFRobot_BMI160::getSensorData((BMI160_ACCEL_SEL | BMI160_GYRO_SEL),Oaccel, Ogyro, Obmi160); 505 | if(rslt == BMI160_OK){ 506 | data[0]=Ogyro->x; 507 | data[1]=Ogyro->y; 508 | data[2]=Ogyro->z; 509 | data[3]=Oaccel->x; 510 | data[4]=Oaccel->y; 511 | data[5]=Oaccel->z; 512 | } 513 | }else{ 514 | rslt = BMI160_ERR_CHOOSE; 515 | } 516 | 517 | return rslt; 518 | } 519 | 520 | int8_t DFRobot_BMI160::getAccelData( int16_t* data) 521 | { 522 | int8_t rslt=BMI160_OK; 523 | rslt = getSensorData(BMI160_ACCEL_SEL, Oaccel, NULL, Obmi160); 524 | if(rslt == BMI160_OK){ 525 | data[0]=Oaccel->x; 526 | data[1]=Oaccel->y; 527 | data[2]=Oaccel->z; 528 | } 529 | return rslt; 530 | } 531 | 532 | int8_t DFRobot_BMI160::getAccelData( int16_t* data, uint32_t* timestamp) 533 | { 534 | int8_t rslt=BMI160_OK; 535 | rslt = getSensorData((BMI160_ACCEL_SEL | BMI160_TIME_SEL), Oaccel, NULL, Obmi160); 536 | if(rslt == BMI160_OK){ 537 | data[0]=Oaccel->x; 538 | data[1]=Oaccel->y; 539 | data[2]=Oaccel->z; 540 | *timestamp=Oaccel->sensortime; 541 | } 542 | return rslt; 543 | } 544 | 545 | int8_t DFRobot_BMI160::getGyroData( int16_t* data) 546 | { 547 | int rslt = BMI160_OK; 548 | rslt = getSensorData(BMI160_GYRO_SEL, NULL, Ogyro, Obmi160); 549 | if(rslt == BMI160_OK){ 550 | data[0]=Ogyro->x; 551 | data[1]=Ogyro->y; 552 | data[2]=Ogyro->z; 553 | } 554 | return rslt; 555 | } 556 | 557 | int8_t DFRobot_BMI160::getGyroData( int16_t* data, uint32_t* timestamp) 558 | { 559 | int rslt = BMI160_OK; 560 | rslt = getSensorData((BMI160_GYRO_SEL | BMI160_TIME_SEL), NULL, Ogyro, Obmi160); 561 | if(rslt == BMI160_OK){ 562 | data[0]=Ogyro->x; 563 | data[1]=Ogyro->y; 564 | data[2]=Ogyro->z; 565 | *timestamp=Ogyro->sensortime; 566 | } 567 | return rslt; 568 | } 569 | 570 | int8_t DFRobot_BMI160::getAccelGyroData( int16_t* data) 571 | { 572 | int8_t rslt = BMI160_OK; 573 | rslt = getSensorData((BMI160_ACCEL_SEL | BMI160_GYRO_SEL),Oaccel, Ogyro, Obmi160); 574 | if(rslt == BMI160_OK){ 575 | data[0]=Ogyro->x; 576 | data[1]=Ogyro->y; 577 | data[2]=Ogyro->z; 578 | data[3]=Oaccel->x; 579 | data[4]=Oaccel->y; 580 | data[5]=Oaccel->z; 581 | } 582 | return rslt; 583 | } 584 | 585 | int8_t DFRobot_BMI160::getAccelGyroData( int16_t* data, uint32_t* timestamp) 586 | { 587 | int8_t rslt = BMI160_OK; 588 | rslt = getSensorData((BMI160_ACCEL_SEL | BMI160_GYRO_SEL | BMI160_TIME_SEL),Oaccel, Ogyro, Obmi160); 589 | if(rslt == BMI160_OK){ 590 | data[0]=Ogyro->x; 591 | data[1]=Ogyro->y; 592 | data[2]=Ogyro->z; 593 | data[3]=Oaccel->x; 594 | data[4]=Oaccel->y; 595 | data[5]=Oaccel->z; 596 | timestamp[0]=Oaccel->sensortime; 597 | timestamp[1]=Ogyro->sensortime; 598 | } 599 | return rslt; 600 | } 601 | 602 | 603 | 604 | int8_t DFRobot_BMI160::getSensorData(uint8_t select_sensor, struct bmi160SensorData *accel, struct bmi160SensorData *gyro,struct bmi160Dev *dev) 605 | { 606 | int8_t rslt = BMI160_OK; 607 | uint8_t time_sel; 608 | uint8_t sen_sel; 609 | uint8_t len = 0; 610 | 611 | /*Extract the sensor and time select information*/ 612 | sen_sel = select_sensor & BMI160_SEN_SEL_MASK; 613 | time_sel = ((sen_sel & BMI160_TIME_SEL) >> 2); 614 | sen_sel = sen_sel & (BMI160_ACCEL_SEL | BMI160_GYRO_SEL); 615 | if (time_sel == 1) 616 | len = 3; 617 | 618 | /* Null-pointer check */ 619 | if (dev != NULL) { 620 | switch (sen_sel) { 621 | case eBmi160AccelOnly: 622 | /* Null-pointer check */ 623 | if (accel == NULL) 624 | rslt = BMI160_E_NULL_PTR; 625 | else 626 | rslt = DFRobot_BMI160::getAccelData(len, accel, dev); 627 | break; 628 | case eBmi160GyroOnly: 629 | /* Null-pointer check */ 630 | if (gyro == NULL) 631 | rslt = BMI160_E_NULL_PTR; 632 | else 633 | rslt = DFRobot_BMI160::getGyroData(len, gyro, dev); 634 | break; 635 | case eBmi160BothAccelAndGyro: 636 | /* Null-pointer check */ 637 | if ((gyro == NULL) || (accel == NULL)) 638 | rslt = BMI160_E_NULL_PTR; 639 | else 640 | rslt = DFRobot_BMI160::getAccelGyroData(len, accel, gyro, dev); 641 | break; 642 | default: 643 | rslt = BMI160_E_INVALID_INPUT; 644 | break; 645 | } 646 | } else { 647 | rslt = BMI160_E_NULL_PTR; 648 | } 649 | 650 | return rslt; 651 | } 652 | 653 | int8_t DFRobot_BMI160::getAccelData(uint8_t len, struct bmi160SensorData *accel, struct bmi160Dev *dev) 654 | { 655 | int8_t rslt; 656 | uint8_t idx = 0; 657 | uint8_t data_array[9] = {0}; 658 | uint8_t time_0 = 0; 659 | uint16_t time_1 = 0; 660 | uint32_t time_2 = 0; 661 | uint8_t lsb; 662 | uint8_t msb; 663 | float msblsb; 664 | 665 | rslt = DFRobot_BMI160::getRegs(BMI160_ACCEL_DATA_ADDR, data_array, 6 + len, dev); 666 | 667 | if (rslt == BMI160_OK){ 668 | lsb = data_array[idx++]; 669 | msb = data_array[idx++]; 670 | msblsb = (int16_t)((msb << 8) | lsb); 671 | accel->x = msblsb; /* Data in X axis */ 672 | lsb = data_array[idx++]; 673 | msb = data_array[idx++]; 674 | msblsb = (int16_t)((msb << 8) | lsb); 675 | accel->y = msblsb; /* Data in X axis */ 676 | lsb = data_array[idx++]; 677 | msb = data_array[idx++]; 678 | msblsb = (int16_t)((msb << 8) | lsb); 679 | accel->z = msblsb; /* Data in X axis */ 680 | 681 | if (len == 3){ 682 | time_0 = data_array[idx++]; 683 | time_1 = (uint16_t)(data_array[idx++] << 8); 684 | time_2 = (uint32_t)(data_array[idx++] << 16); 685 | accel->sensortime = (uint32_t)(time_2 | time_1 | time_0); 686 | } 687 | }else{ 688 | rslt = BMI160_E_COM_FAIL; 689 | } 690 | return rslt; 691 | } 692 | 693 | int8_t DFRobot_BMI160::getGyroData(uint8_t len, struct bmi160SensorData *gyro, struct bmi160Dev *dev) 694 | { 695 | int8_t rslt; 696 | uint8_t idx = 0; 697 | uint8_t data_array[15] = {0}; 698 | uint8_t time_0 = 0; 699 | uint16_t time_1 = 0; 700 | uint32_t time_2 = 0; 701 | uint8_t lsb; 702 | uint8_t msb; 703 | float msblsb; 704 | if (len == 0) { 705 | /* read gyro data only */ 706 | rslt = DFRobot_BMI160::getRegs(BMI160_GYRO_DATA_ADDR, data_array, 6, dev); 707 | if (rslt == BMI160_OK) { 708 | /* Gyro Data */ 709 | lsb = data_array[idx++]; 710 | msb = data_array[idx++]; 711 | msblsb = (int16_t)((msb << 8) | lsb); 712 | gyro->x = msblsb; /* Data in X axis */ 713 | 714 | lsb = data_array[idx++]; 715 | msb = data_array[idx++]; 716 | msblsb = (int16_t)((msb << 8) | lsb); 717 | gyro->y = msblsb; /* Data in Y axis */ 718 | 719 | lsb = data_array[idx++]; 720 | msb = data_array[idx++]; 721 | msblsb = (int16_t)((msb << 8) | lsb); 722 | gyro->z = msblsb; /* Data in Z axis */ 723 | } else { 724 | rslt = BMI160_E_COM_FAIL; 725 | } 726 | } else { 727 | /* read gyro sensor data along with time */ 728 | rslt = DFRobot_BMI160::getRegs(BMI160_GYRO_DATA_ADDR, data_array, 12 + len, dev); 729 | if (rslt == BMI160_OK) { 730 | /* Gyro Data */ 731 | lsb = data_array[idx++]; 732 | msb = data_array[idx++]; 733 | msblsb = (int16_t)((msb << 8) | lsb); 734 | gyro->x = msblsb; /* gyro X axis data */ 735 | 736 | lsb = data_array[idx++]; 737 | msb = data_array[idx++]; 738 | msblsb = (int16_t)((msb << 8) | lsb); 739 | gyro->y = msblsb; /* gyro Y axis data */ 740 | 741 | lsb = data_array[idx++]; 742 | msb = data_array[idx++]; 743 | msblsb = (int16_t)((msb << 8) | lsb); 744 | gyro->z = msblsb; /* gyro Z axis data */ 745 | 746 | idx = idx + 6; 747 | time_0 = data_array[idx++]; 748 | time_1 = (uint16_t)(data_array[idx++] << 8); 749 | time_2 = (uint32_t)(data_array[idx++] << 16); 750 | gyro->sensortime = (uint32_t)(time_2 | time_1 | time_0); 751 | 752 | } else { 753 | rslt = BMI160_E_COM_FAIL; 754 | } 755 | } 756 | 757 | return rslt; 758 | } 759 | 760 | int8_t DFRobot_BMI160::getAccelGyroData(uint8_t len, struct bmi160SensorData *accel, struct bmi160SensorData *gyro, struct bmi160Dev *dev) 761 | { 762 | int8_t rslt; 763 | uint8_t idx = 0; 764 | uint8_t data_array[15] = {0}; 765 | uint8_t time_0 = 0; 766 | uint16_t time_1 = 0; 767 | uint32_t time_2 = 0; 768 | uint8_t lsb; 769 | uint8_t msb; 770 | int16_t msblsb; 771 | 772 | /* read both accel and gyro sensor data 773 | * along with time if requested */ 774 | rslt = DFRobot_BMI160::getRegs(BMI160_GYRO_DATA_ADDR, data_array, 12 + len, dev); 775 | if (rslt == BMI160_OK) { 776 | /* Gyro Data */ 777 | lsb = data_array[idx++]; 778 | msb = data_array[idx++]; 779 | msblsb = (int16_t)((msb << 8) | lsb); 780 | gyro->x = msblsb; /* gyro X axis data */ 781 | 782 | lsb = data_array[idx++]; 783 | msb = data_array[idx++]; 784 | msblsb = (int16_t)((msb << 8) | lsb); 785 | gyro->y = msblsb; /* gyro Y axis data */ 786 | 787 | lsb = data_array[idx++]; 788 | msb = data_array[idx++]; 789 | msblsb = (int16_t)((msb << 8) | lsb); 790 | gyro->z = msblsb; /* gyro Z axis data */ 791 | 792 | /* Accel Data */ 793 | lsb = data_array[idx++]; 794 | msb = data_array[idx++]; 795 | msblsb = (int16_t)((msb << 8) | lsb); 796 | accel->x = (int16_t)msblsb; /* accel X axis data */ 797 | 798 | lsb = data_array[idx++]; 799 | msb = data_array[idx++]; 800 | msblsb = (int16_t)((msb << 8) | lsb); 801 | accel->y = (int16_t)msblsb; /* accel Y axis data */ 802 | 803 | lsb = data_array[idx++]; 804 | msb = data_array[idx++]; 805 | msblsb = (int16_t)((msb << 8) | lsb); 806 | accel->z = (int16_t)msblsb; /* accel Z axis data */ 807 | 808 | if (len == 3) { 809 | time_0 = data_array[idx++]; 810 | time_1 = (uint16_t)(data_array[idx++] << 8); 811 | time_2 = (uint32_t)(data_array[idx++] << 16); 812 | accel->sensortime = (uint32_t)(time_2 | time_1 | time_0); 813 | gyro->sensortime = (uint32_t)(time_2 | time_1 | time_0); 814 | } else { 815 | accel->sensortime = 0; 816 | gyro->sensortime = 0; 817 | ; 818 | } 819 | } else { 820 | rslt = BMI160_E_COM_FAIL; 821 | } 822 | 823 | return rslt; 824 | } 825 | 826 | int8_t DFRobot_BMI160::getRegs(uint8_t reg_addr, uint8_t *data, uint16_t len, struct bmi160Dev *dev) 827 | { 828 | 829 | int8_t rslt = BMI160_OK; 830 | //Null-pointer check 831 | if (dev == NULL) { 832 | rslt = BMI160_E_NULL_PTR; 833 | } else { 834 | //Configuring reg_addr for SPI Interface 835 | if (dev->interface == BMI160_SPI_INTF){ 836 | reg_addr = (reg_addr | BMI160_SPI_RD_MASK); 837 | rslt = DFRobot_BMI160::SPIGetRegs(dev, reg_addr, data, len); 838 | }else{ 839 | rslt = DFRobot_BMI160::I2cGetRegs(dev, reg_addr, data, len); 840 | } 841 | delay(1); 842 | if (rslt != BMI160_OK){ 843 | rslt = BMI160_E_COM_FAIL; 844 | } 845 | } 846 | 847 | return rslt; 848 | } 849 | 850 | int8_t DFRobot_BMI160::I2cGetRegs(struct bmi160Dev *dev, uint8_t reg_addr, uint8_t *data, uint16_t len) 851 | { 852 | Wire.beginTransmission(dev->id); 853 | Wire.write(reg_addr); 854 | Wire.endTransmission(true); 855 | delay(10); 856 | Wire.requestFrom(dev->id,len); 857 | 858 | for(int i = 0; i < len; i++){ 859 | data[i]=Wire.read(); 860 | delay(1); 861 | } 862 | return BMI160_OK; 863 | } 864 | 865 | int8_t DFRobot_BMI160::setRegs(uint8_t reg_addr, uint8_t *data, uint16_t len, struct bmi160Dev *dev) 866 | { 867 | int8_t rslt = BMI160_OK; 868 | uint8_t count = 0; 869 | //Null-pointer check 870 | if (dev == NULL) { 871 | rslt = BMI160_E_NULL_PTR; 872 | } else { 873 | //Configuring reg_addr for SPI Interface 874 | if (dev->interface == BMI160_SPI_INTF){ 875 | reg_addr = (reg_addr & BMI160_SPI_WR_MASK); 876 | rslt = DFRobot_BMI160::SPISetRegs(dev,reg_addr,data,len); 877 | }else{ 878 | rslt = DFRobot_BMI160::I2cSetRegs(dev,reg_addr,data,len); 879 | } 880 | delay(1); 881 | 882 | if (rslt != BMI160_OK) 883 | rslt = BMI160_E_COM_FAIL; 884 | } 885 | 886 | return rslt; 887 | } 888 | 889 | int8_t DFRobot_BMI160::I2cSetRegs(struct bmi160Dev *dev, uint8_t reg_addr, uint8_t *data, uint16_t len) 890 | { 891 | if ((dev->prevAccelCfg.power == BMI160_ACCEL_NORMAL_MODE)||(dev->prevGyroCfg.power == BMI160_GYRO_NORMAL_MODE)){ 892 | Wire.beginTransmission(dev->id); 893 | Wire.write(reg_addr); 894 | for(int i = 0; i < len; i++){ 895 | Wire.write(data[i]); 896 | delay(1); 897 | } 898 | Wire.endTransmission(true); 899 | }else{ 900 | for(int i = 0; i < len; i++){ 901 | Wire.beginTransmission(dev->id); 902 | Wire.write(reg_addr); 903 | Wire.write(data[i]); 904 | 905 | Wire.endTransmission(true); 906 | delay(1); 907 | } 908 | } 909 | return BMI160_OK; 910 | } 911 | 912 | int8_t DFRobot_BMI160::SPIGetRegs(struct bmi160Dev *dev, uint8_t reg_addr, uint8_t *data, uint16_t len) 913 | { 914 | digitalWrite(10,LOW); 915 | //SPI.transfer(0x6B); 916 | //SPI.transfer(0x10); 917 | uint8_t buff[10]={0}; 918 | for(int i = 0; i < 10; i++){ 919 | buff[i] = SPI.transfer(0x00); 920 | } 921 | 922 | digitalWrite(10,HIGH); 923 | return BMI160_OK; 924 | } 925 | int8_t DFRobot_BMI160::SPISetRegs(struct bmi160Dev *dev, uint8_t reg_addr, uint8_t *data, uint16_t len) 926 | { 927 | return BMI160_OK; 928 | } 929 | 930 | int8_t DFRobot_BMI160::setInt(int intNum) 931 | { 932 | return setInt(Obmi160,intNum); 933 | } 934 | 935 | int8_t DFRobot_BMI160::setInt(struct bmi160Dev *dev, int intNum) 936 | { 937 | int8_t rslt=BMI160_OK; 938 | if (dev == NULL){ 939 | rslt = BMI160_E_NULL_PTR; 940 | } 941 | struct bmi160IntSettg intConfig; 942 | if (intNum == 1){ 943 | intConfig.intChannel = BMI160_INT_CHANNEL_1; 944 | }else if(intNum == 2){ 945 | intConfig.intChannel = BMI160_INT_CHANNEL_2; 946 | }else{ 947 | return BMI160_E_NULL_PTR; 948 | } 949 | 950 | /* Select the Interrupt type */ 951 | intConfig.intType = BMI160_STEP_DETECT_INT;// Choosing Step Detector interrupt 952 | /* Select the interrupt channel/pin settings */ 953 | intConfig.intPinSettg.outputEn = BMI160_ENABLE;// Enabling interrupt pins to act as output pin 954 | intConfig.intPinSettg.outputMode = BMI160_DISABLE;// Choosing push-pull mode for interrupt pin 955 | intConfig.intPinSettg.outputType = BMI160_ENABLE;// Choosing active High output 956 | intConfig.intPinSettg.edgeCtrl = BMI160_ENABLE;// Choosing edge triggered output 957 | intConfig.intPinSettg.inputEn = BMI160_DISABLE;// Disabling interrupt pin to act as input 958 | intConfig.intPinSettg.latchDur =BMI160_LATCH_DUR_NONE;// non-latched output 959 | 960 | /* Select the Step Detector interrupt parameters, Kindly use the recommended settings for step detector */ 961 | intConfig.intTypeCfg.accStepDetectInt.stepDetectorMode = BMI160_STEP_DETECT_NORMAL; 962 | intConfig.intTypeCfg.accStepDetectInt.stepDetectorEn = BMI160_ENABLE;// 1-enable, 0-disable the step detector 963 | rslt = DFRobot_BMI160::setIntConfig(&intConfig, dev); 964 | return rslt; 965 | } 966 | 967 | int8_t DFRobot_BMI160::setIntConfig(struct bmi160IntSettg *intConfig, struct bmi160Dev *dev) 968 | { 969 | int8_t rslt = BMI160_OK; 970 | switch (intConfig->intType) { 971 | case BMI160_ACC_ANY_MOTION_INT: 972 | /*Any-motion interrupt*/ 973 | //rslt = set_accel_any_motion_int(intConfig, dev); 974 | break; 975 | case BMI160_ACC_SIG_MOTION_INT: 976 | /* Significant motion interrupt */ 977 | //rslt = set_accel_sig_motion_int(intConfig, dev); 978 | break; 979 | case BMI160_ACC_SLOW_NO_MOTION_INT: 980 | /* Slow or no motion interrupt */ 981 | //rslt = set_accel_no_motion_int(intConfig, dev); 982 | break; 983 | case BMI160_ACC_DOUBLE_TAP_INT: 984 | case BMI160_ACC_SINGLE_TAP_INT: 985 | /* Double tap and single tap Interrupt */ 986 | //rslt = set_accel_tap_int(intConfig, dev); 987 | break; 988 | case BMI160_STEP_DETECT_INT: 989 | /* Step detector interrupt */ 990 | rslt = setAccelStepDetectInt(intConfig, dev); 991 | break; 992 | case BMI160_ACC_ORIENT_INT: 993 | /* Orientation interrupt */ 994 | //rslt = set_accel_orientation_int(intConfig, dev); 995 | break; 996 | case BMI160_ACC_FLAT_INT: 997 | /* Flat detection interrupt */ 998 | //rslt = set_accel_flat_detect_int(intConfig, dev); 999 | break; 1000 | case BMI160_ACC_LOW_G_INT: 1001 | /* Low-g interrupt */ 1002 | //rslt = set_accel_low_g_int(intConfig, dev); 1003 | break; 1004 | case BMI160_ACC_HIGH_G_INT: 1005 | /* High-g interrupt */ 1006 | //rslt = set_accel_high_g_int(intConfig, dev); 1007 | break; 1008 | case BMI160_ACC_GYRO_DATA_RDY_INT: 1009 | /* Data ready interrupt */ 1010 | //rslt = set_accel_gyro_data_ready_int(intConfig, dev); 1011 | break; 1012 | case BMI160_ACC_GYRO_FIFO_FULL_INT: 1013 | /* Fifo full interrupt */ 1014 | //rslt = set_fifo_full_int(intConfig, dev); 1015 | break; 1016 | case BMI160_ACC_GYRO_FIFO_WATERMARK_INT: 1017 | /* Fifo water-mark interrupt */ 1018 | //rslt = set_fifo_watermark_int(intConfig, dev); 1019 | break; 1020 | default: 1021 | break; 1022 | } 1023 | return rslt; 1024 | } 1025 | 1026 | int8_t DFRobot_BMI160::setAccelStepDetectInt(struct bmi160IntSettg *intConfig, struct bmi160Dev *dev) 1027 | { 1028 | int8_t rslt = BMI160_OK; 1029 | 1030 | /* Null-pointer check */ 1031 | if (dev == NULL){ 1032 | rslt = BMI160_E_NULL_PTR; 1033 | } 1034 | if ((rslt != BMI160_OK) || (intConfig == NULL)) { 1035 | rslt = BMI160_E_NULL_PTR; 1036 | } else { 1037 | /* updating the interrupt structure to local structure */ 1038 | struct bmi160AccStepDetectIntCfg *stepDetectIntCfg = 1039 | &(intConfig->intTypeCfg.accStepDetectInt); 1040 | 1041 | rslt = enableStepDetectInt(stepDetectIntCfg, dev); 1042 | if (rslt == BMI160_OK) { 1043 | /* Configure Interrupt pins */ 1044 | rslt = setIntrPinConfig(intConfig, dev); 1045 | if (rslt == BMI160_OK) { 1046 | rslt = mapFeatureInterrupt(intConfig, dev); 1047 | if (rslt == BMI160_OK){ 1048 | rslt = configStepDetect(stepDetectIntCfg, dev); 1049 | } 1050 | } 1051 | } 1052 | } 1053 | return rslt; 1054 | } 1055 | 1056 | int8_t DFRobot_BMI160::enableStepDetectInt(struct bmi160AccStepDetectIntCfg *stepDetectIntCfg, struct bmi160Dev *dev) 1057 | { 1058 | int8_t rslt; 1059 | uint8_t data = 0; 1060 | uint8_t temp = 0; 1061 | 1062 | /* Enable data ready interrupt in Int Enable 2 register */ 1063 | rslt = getRegs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev); 1064 | if (rslt == BMI160_OK) { 1065 | temp = data & ~BMI160_STEP_DETECT_INT_EN_MASK; 1066 | data = temp | ((stepDetectIntCfg->stepDetectorEn << 3) & BMI160_STEP_DETECT_INT_EN_MASK); 1067 | /* Writing data to INT ENABLE 2 Address */ 1068 | rslt = setRegs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev); 1069 | } 1070 | return rslt; 1071 | } 1072 | 1073 | int8_t DFRobot_BMI160::setIntrPinConfig(struct bmi160IntSettg *intConfig, struct bmi160Dev *dev) 1074 | { 1075 | int8_t rslt; 1076 | 1077 | /* configure the behavioural settings of interrupt pin */ 1078 | rslt = configIntOutCtrl(intConfig, dev); 1079 | if (rslt == BMI160_OK) 1080 | rslt = configIntLatch(intConfig, dev); 1081 | 1082 | return rslt; 1083 | } 1084 | 1085 | int8_t DFRobot_BMI160::configIntOutCtrl(struct bmi160IntSettg *intConfig, struct bmi160Dev *dev) 1086 | { 1087 | int8_t rslt; 1088 | uint8_t temp = 0; 1089 | uint8_t data = 0; 1090 | 1091 | /* Configuration of output interrupt signals on pins INT1 and INT2 are 1092 | * done in BMI160_INT_OUT_CTRL_ADDR register*/ 1093 | rslt = getRegs(BMI160_INT_OUT_CTRL_ADDR, &data, 1, dev); 1094 | 1095 | if (rslt == BMI160_OK) { 1096 | /* updating the interrupt pin structure to local structure */ 1097 | const struct bmi160IntPinSettg *intr_pin_sett = &(intConfig->intPinSettg); 1098 | 1099 | /* Configuring channel 1 */ 1100 | if (intConfig->intChannel == BMI160_INT_CHANNEL_1) { 1101 | 1102 | /* Output enable */ 1103 | temp = data & ~BMI160_INT1_OUTPUT_EN_MASK; 1104 | data = temp | ((intr_pin_sett->outputEn << 3) & BMI160_INT1_OUTPUT_EN_MASK); 1105 | 1106 | /* Output mode */ 1107 | temp = data & ~BMI160_INT1_OUTPUT_MODE_MASK; 1108 | data = temp | ((intr_pin_sett->outputMode << 2) & BMI160_INT1_OUTPUT_MODE_MASK); 1109 | 1110 | /* Output type */ 1111 | temp = data & ~BMI160_INT1_OUTPUT_TYPE_MASK; 1112 | data = temp | ((intr_pin_sett->outputType << 1) & BMI160_INT1_OUTPUT_TYPE_MASK); 1113 | 1114 | /* edge control */ 1115 | temp = data & ~BMI160_INT1_EDGE_CTRL_MASK; 1116 | data = temp | ((intr_pin_sett->edgeCtrl) & BMI160_INT1_EDGE_CTRL_MASK); 1117 | 1118 | } else { 1119 | /* Configuring channel 2 */ 1120 | /* Output enable */ 1121 | temp = data & ~BMI160_INT2_OUTPUT_EN_MASK; 1122 | data = temp | ((intr_pin_sett->outputEn << 7) & BMI160_INT2_OUTPUT_EN_MASK); 1123 | 1124 | /* Output mode */ 1125 | temp = data & ~BMI160_INT2_OUTPUT_MODE_MASK; 1126 | data = temp | ((intr_pin_sett->outputMode << 6) & BMI160_INT2_OUTPUT_MODE_MASK); 1127 | 1128 | /* Output type */ 1129 | temp = data & ~BMI160_INT2_OUTPUT_TYPE_MASK; 1130 | data = temp | ((intr_pin_sett->outputType << 5) & BMI160_INT2_OUTPUT_TYPE_MASK); 1131 | 1132 | /* edge control */ 1133 | temp = data & ~BMI160_INT2_EDGE_CTRL_MASK; 1134 | data = temp | ((intr_pin_sett->edgeCtrl << 4) & BMI160_INT2_EDGE_CTRL_MASK); 1135 | } 1136 | 1137 | rslt = setRegs(BMI160_INT_OUT_CTRL_ADDR, &data, 1, dev); 1138 | } 1139 | 1140 | return rslt; 1141 | } 1142 | 1143 | int8_t DFRobot_BMI160::configIntLatch(struct bmi160IntSettg *intConfig, struct bmi160Dev *dev) 1144 | { 1145 | int8_t rslt; 1146 | uint8_t temp = 0; 1147 | uint8_t data = 0; 1148 | 1149 | /* Configuration of latch on pins INT1 and INT2 are done in 1150 | * BMI160_INT_LATCH_ADDR register*/ 1151 | rslt = getRegs(BMI160_INT_LATCH_ADDR, &data, 1, dev); 1152 | 1153 | if (rslt == BMI160_OK) { 1154 | /* updating the interrupt pin structure to local structure */ 1155 | const struct bmi160IntPinSettg *intr_pin_sett = &(intConfig->intPinSettg); 1156 | 1157 | if (intConfig->intChannel == BMI160_INT_CHANNEL_1) { 1158 | /* Configuring channel 1 */ 1159 | /* Input enable */ 1160 | temp = data & ~BMI160_INT1_INPUT_EN_MASK; 1161 | data = temp | ((intr_pin_sett->inputEn << 4) & BMI160_INT1_INPUT_EN_MASK); 1162 | } else { 1163 | /* Configuring channel 2 */ 1164 | /* Input enable */ 1165 | temp = data & ~BMI160_INT2_INPUT_EN_MASK; 1166 | data = temp | ((intr_pin_sett->inputEn << 5) & BMI160_INT2_INPUT_EN_MASK); 1167 | } 1168 | 1169 | /* In case of latch interrupt,update the latch duration */ 1170 | /* Latching holds the interrupt for the amount of latch 1171 | * duration time */ 1172 | temp = data & ~BMI160_INT_LATCH_MASK; 1173 | data = temp | (intr_pin_sett->latchDur & BMI160_INT_LATCH_MASK); 1174 | 1175 | /* OUT_CTRL_INT and LATCH_INT address lie consecutively, 1176 | * hence writing data to respective registers at one go */ 1177 | rslt = setRegs(BMI160_INT_LATCH_ADDR, &data, 1, dev); 1178 | } 1179 | return rslt; 1180 | } 1181 | 1182 | int8_t DFRobot_BMI160::mapFeatureInterrupt(struct bmi160IntSettg *intConfig, struct bmi160Dev *dev) 1183 | { 1184 | int8_t rslt; 1185 | uint8_t data[3] = {0, 0, 0}; 1186 | uint8_t temp[3] = {0, 0, 0}; 1187 | 1188 | rslt = getRegs(BMI160_INT_MAP_0_ADDR, data, 3, dev); 1189 | 1190 | if (rslt == BMI160_OK) { 1191 | temp[0] = data[0] & ~int_mask_lookup_table[intConfig->intType]; 1192 | temp[2] = data[2] & ~int_mask_lookup_table[intConfig->intType]; 1193 | 1194 | switch (intConfig->intChannel) { 1195 | case BMI160_INT_CHANNEL_NONE: 1196 | data[0] = temp[0]; 1197 | data[2] = temp[2]; 1198 | break; 1199 | case BMI160_INT_CHANNEL_1: 1200 | data[0] = temp[0] | int_mask_lookup_table[intConfig->intType]; 1201 | data[2] = temp[2]; 1202 | break; 1203 | case BMI160_INT_CHANNEL_2: 1204 | data[2] = temp[2] | int_mask_lookup_table[intConfig->intType]; 1205 | data[0] = temp[0]; 1206 | break; 1207 | case BMI160_INT_CHANNEL_BOTH: 1208 | data[0] = temp[0] | int_mask_lookup_table[intConfig->intType]; 1209 | data[2] = temp[2] | int_mask_lookup_table[intConfig->intType]; 1210 | break; 1211 | default: 1212 | rslt = BMI160_E_OUT_OF_RANGE; 1213 | } 1214 | if (rslt == BMI160_OK) 1215 | rslt = setRegs(BMI160_INT_MAP_0_ADDR, data, 3, dev); 1216 | } 1217 | 1218 | return rslt; 1219 | } 1220 | 1221 | int8_t DFRobot_BMI160::configStepDetect(struct bmi160AccStepDetectIntCfg *stepDetectIntCfg, struct bmi160Dev *dev) 1222 | { 1223 | int8_t rslt; 1224 | uint8_t temp = 0; 1225 | uint8_t data_array[2] = {0}; 1226 | 1227 | 1228 | if (stepDetectIntCfg->stepDetectorMode == BMI160_STEP_DETECT_NORMAL) { 1229 | /* Normal mode setting */ 1230 | data_array[0] = 0x15; 1231 | data_array[1] = 0x03; 1232 | } else if (stepDetectIntCfg->stepDetectorMode == BMI160_STEP_DETECT_SENSITIVE) { 1233 | /* Sensitive mode setting */ 1234 | data_array[0] = 0x2D; 1235 | data_array[1] = 0x00; 1236 | } else if (stepDetectIntCfg->stepDetectorMode == BMI160_STEP_DETECT_ROBUST) { 1237 | /* Robust mode setting */ 1238 | data_array[0] = 0x1D; 1239 | data_array[1] = 0x07; 1240 | } else if (stepDetectIntCfg->stepDetectorMode == BMI160_STEP_DETECT_USER_DEFINE) { 1241 | /* Non recommended User defined setting */ 1242 | /* Configuring STEP_CONFIG register */ 1243 | rslt = getRegs(BMI160_INT_STEP_CONFIG_0_ADDR, &data_array[0], 2, dev); 1244 | 1245 | if (rslt == BMI160_OK) { 1246 | temp = data_array[0] & ~BMI160_STEP_DETECT_MIN_THRES_MASK; 1247 | /* Adding minThreshold */ 1248 | data_array[0] = temp | ((stepDetectIntCfg->minThreshold << 3) 1249 | & BMI160_STEP_DETECT_MIN_THRES_MASK); 1250 | 1251 | temp = data_array[0] & ~BMI160_STEP_DETECT_STEPTIME_MIN_MASK; 1252 | /* Adding steptimeMin */ 1253 | data_array[0] = temp | ((stepDetectIntCfg->steptimeMin) 1254 | & BMI160_STEP_DETECT_STEPTIME_MIN_MASK); 1255 | 1256 | temp = data_array[1] & ~BMI160_STEP_MIN_BUF_MASK; 1257 | /* Adding steptimeMin */ 1258 | data_array[1] = temp | ((stepDetectIntCfg->stepMinBuf) & BMI160_STEP_MIN_BUF_MASK); 1259 | 1260 | } 1261 | } 1262 | 1263 | /* Write data to STEP_CONFIG register */ 1264 | rslt = setRegs(BMI160_INT_STEP_CONFIG_0_ADDR, data_array, 2, dev); 1265 | 1266 | return rslt; 1267 | } 1268 | 1269 | int8_t DFRobot_BMI160::setStepPowerMode(uint8_t model) 1270 | { 1271 | return DFRobot_BMI160::setStepPowerMode(model,Obmi160); 1272 | } 1273 | 1274 | int8_t DFRobot_BMI160::setStepPowerMode(uint8_t model,struct bmi160Dev *dev) 1275 | { 1276 | int8_t rslt = BMI160_OK; 1277 | if (model == stepNormalPowerMode){ 1278 | dev->accelCfg.odr=BMI160_ACCEL_ODR_1600HZ; 1279 | dev->accelCfg.power = BMI160_ACCEL_NORMAL_MODE; 1280 | dev->gyroCfg.odr = BMI160_GYRO_ODR_3200HZ; 1281 | dev->gyroCfg.power = BMI160_GYRO_NORMAL_MODE; 1282 | }else if(model == stepLowPowerMode){ 1283 | dev->accelCfg.odr=BMI160_ACCEL_ODR_50HZ; 1284 | dev->accelCfg.power = BMI160_ACCEL_LOWPOWER_MODE; 1285 | dev->gyroCfg.odr = BMI160_GYRO_ODR_50HZ; 1286 | dev->gyroCfg.power = BMI160_GYRO_SUSPEND_MODE; 1287 | }else{ 1288 | dev->accelCfg.odr=BMI160_ACCEL_ODR_1600HZ; 1289 | dev->accelCfg.power = BMI160_ACCEL_NORMAL_MODE; 1290 | dev->gyroCfg.odr = BMI160_GYRO_ODR_3200HZ; 1291 | dev->gyroCfg.power = BMI160_GYRO_NORMAL_MODE; 1292 | } 1293 | dev->accelCfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4; 1294 | dev->accelCfg.range = BMI160_ACCEL_RANGE_2G; 1295 | dev->gyroCfg.range = BMI160_GYRO_RANGE_2000_DPS; 1296 | dev->gyroCfg.bw = BMI160_GYRO_BW_NORMAL_MODE; 1297 | 1298 | rslt = DFRobot_BMI160::setAccelConf(dev); 1299 | if (rslt == BMI160_OK) { 1300 | rslt = DFRobot_BMI160::setGyroConf(dev); 1301 | if (rslt == BMI160_OK) { 1302 | /* write power mode for accel and gyro */ 1303 | rslt = DFRobot_BMI160::setPowerMode(dev); 1304 | if (rslt == BMI160_OK) 1305 | rslt = DFRobot_BMI160::checkInvalidSettg(dev); 1306 | } 1307 | } 1308 | 1309 | return rslt; 1310 | } 1311 | 1312 | int8_t DFRobot_BMI160::setStepCounter() 1313 | { 1314 | uint8_t step_enable = 1;//enable the step counter 1315 | return DFRobot_BMI160::setStepCounter(step_enable,Obmi160); 1316 | } 1317 | 1318 | int8_t DFRobot_BMI160::setStepCounter(uint8_t step_cnt_enable, struct bmi160Dev *dev) 1319 | { 1320 | int8_t rslt = BMI160_OK; 1321 | uint8_t data = 0; 1322 | 1323 | /* Null-pointer check */ 1324 | if (dev == NULL){ 1325 | rslt = BMI160_E_NULL_PTR; 1326 | } 1327 | 1328 | if (rslt != BMI160_OK) { 1329 | rslt = BMI160_E_NULL_PTR; 1330 | } else { 1331 | rslt = getRegs(BMI160_INT_STEP_CONFIG_1_ADDR, &data, 1, dev); 1332 | if (rslt == BMI160_OK) { 1333 | if (step_cnt_enable == BMI160_ENABLE){ 1334 | data |= (uint8_t)(step_cnt_enable << 3); 1335 | }else{ 1336 | data &= ~BMI160_STEP_COUNT_EN_BIT_MASK; 1337 | } 1338 | rslt = setRegs(BMI160_INT_STEP_CONFIG_1_ADDR, &data, 1, dev); 1339 | } 1340 | } 1341 | 1342 | return rslt; 1343 | } 1344 | 1345 | int8_t DFRobot_BMI160::readStepCounter(uint16_t *stepVal) 1346 | { 1347 | return readStepCounter(stepVal,Obmi160); 1348 | } 1349 | 1350 | int8_t DFRobot_BMI160::readStepCounter(uint16_t *stepVal, struct bmi160Dev *dev) 1351 | { 1352 | int8_t rslt = BMI160_OK; 1353 | uint8_t data[2] = {0, 0}; 1354 | uint16_t msb = 0; 1355 | uint8_t lsb = 0; 1356 | 1357 | /* Null-pointer check */ 1358 | if (dev == NULL){ 1359 | rslt = BMI160_E_NULL_PTR; 1360 | } 1361 | 1362 | if (rslt != BMI160_OK) { 1363 | rslt = BMI160_E_NULL_PTR; 1364 | } else { 1365 | rslt = getRegs(BMI160_INT_STEP_CNT_0_ADDR, data, 2, dev); 1366 | if (rslt == BMI160_OK) { 1367 | lsb = data[0]; 1368 | msb = data[1] << 8; 1369 | *stepVal = msb | lsb; 1370 | } 1371 | } 1372 | 1373 | return rslt; 1374 | } 1375 | 1376 | 1377 | -------------------------------------------------------------------------------- /DFRobot_BMI160.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file DFRobot_BMI160.h 3 | * @brief Define the basic structure of class DFRobot_BMI160 4 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 5 | * @license The MIT License (MIT) 6 | * @author DFRobot_haoJ(hao.jiang@dfrobot.com) 7 | * @version V1.0 8 | * @date 2017-12-01 9 | * @url https://github.com/DFRobot/DFRobot_BMI160 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #define LITTLE_ENDIAN 1 17 | 18 | /** Mask definitions */ 19 | #define BMI160_ACCEL_BW_MASK UINT8_C(0x70) 20 | #define BMI160_ACCEL_ODR_MASK UINT8_C(0x0F) 21 | #define BMI160_ACCEL_UNDERSAMPLING_MASK UINT8_C(0x80) 22 | #define BMI160_ACCEL_RANGE_MASK UINT8_C(0x0F) 23 | #define BMI160_GYRO_BW_MASK UINT8_C(0x30) 24 | #define BMI160_GYRO_ODR_MASK UINT8_C(0x0F) 25 | #define BMI160_GYRO_RANGE_MSK UINT8_C(0x07) 26 | 27 | /** Mask definitions for INT_EN registers */ 28 | #define BMI160_ANY_MOTION_X_INT_EN_MASK UINT8_C(0x01) 29 | #define BMI160_HIGH_G_X_INT_EN_MASK UINT8_C(0x01) 30 | #define BMI160_NO_MOTION_X_INT_EN_MASK UINT8_C(0x01) 31 | #define BMI160_ANY_MOTION_Y_INT_EN_MASK UINT8_C(0x02) 32 | #define BMI160_HIGH_G_Y_INT_EN_MASK UINT8_C(0x02) 33 | #define BMI160_NO_MOTION_Y_INT_EN_MASK UINT8_C(0x02) 34 | #define BMI160_ANY_MOTION_Z_INT_EN_MASK UINT8_C(0x04) 35 | #define BMI160_HIGH_G_Z_INT_EN_MASK UINT8_C(0x04) 36 | #define BMI160_NO_MOTION_Z_INT_EN_MASK UINT8_C(0x04) 37 | #define BMI160_SIG_MOTION_INT_EN_MASK UINT8_C(0x07) 38 | #define BMI160_ANY_MOTION_ALL_INT_EN_MASK UINT8_C(0x07) 39 | #define BMI160_STEP_DETECT_INT_EN_MASK UINT8_C(0x08) 40 | #define BMI160_DOUBLE_TAP_INT_EN_MASK UINT8_C(0x10) 41 | #define BMI160_SINGLE_TAP_INT_EN_MASK UINT8_C(0x20) 42 | #define BMI160_FIFO_FULL_INT_EN_MASK UINT8_C(0x20) 43 | #define BMI160_ORIENT_INT_EN_MASK UINT8_C(0x40) 44 | #define BMI160_FIFO_WATERMARK_INT_EN_MASK UINT8_C(0x40) 45 | #define BMI160_LOW_G_INT_EN_MASK UINT8_C(0x08) 46 | #define BMI160_STEP_DETECT_EN_MASK UINT8_C(0x08) 47 | #define BMI160_FLAT_INT_EN_MASK UINT8_C(0x80) 48 | #define BMI160_DATA_RDY_INT_EN_MASK UINT8_C(0x10) 49 | 50 | /** Mask definitions for INT_OUT_CTRL register */ 51 | #define BMI160_INT1_EDGE_CTRL_MASK UINT8_C(0x01) 52 | #define BMI160_INT1_OUTPUT_MODE_MASK UINT8_C(0x04) 53 | #define BMI160_INT1_OUTPUT_TYPE_MASK UINT8_C(0x02) 54 | #define BMI160_INT1_OUTPUT_EN_MASK UINT8_C(0x08) 55 | #define BMI160_INT2_EDGE_CTRL_MASK UINT8_C(0x10) 56 | #define BMI160_INT2_OUTPUT_MODE_MASK UINT8_C(0x40) 57 | #define BMI160_INT2_OUTPUT_TYPE_MASK UINT8_C(0x20) 58 | #define BMI160_INT2_OUTPUT_EN_MASK UINT8_C(0x80) 59 | 60 | /** Mask definitions for INT_LATCH register */ 61 | #define BMI160_INT1_INPUT_EN_MASK UINT8_C(0x10) 62 | #define BMI160_INT2_INPUT_EN_MASK UINT8_C(0x20) 63 | #define BMI160_INT_LATCH_MASK UINT8_C(0x0F) 64 | 65 | /** Mask definitions for INT_MAP register */ 66 | #define BMI160_INT1_LOW_G_MASK UINT8_C(0x01) 67 | #define BMI160_INT1_HIGH_G_MASK UINT8_C(0x02) 68 | #define BMI160_INT1_SLOPE_MASK UINT8_C(0x04) 69 | #define BMI160_INT1_NO_MOTION_MASK UINT8_C(0x08) 70 | #define BMI160_INT1_DOUBLE_TAP_MASK UINT8_C(0x10) 71 | #define BMI160_INT1_SINGLE_TAP_MASK UINT8_C(0x20) 72 | #define BMI160_INT1_FIFO_FULL_MASK UINT8_C(0x20) 73 | #define BMI160_INT1_FIFO_WM_MASK UINT8_C(0x40) 74 | #define BMI160_INT1_ORIENT_MASK UINT8_C(0x40) 75 | #define BMI160_INT1_FLAT_MASK UINT8_C(0x80) 76 | #define BMI160_INT1_DATA_READY_MASK UINT8_C(0x80) 77 | #define BMI160_INT2_LOW_G_MASK UINT8_C(0x01) 78 | #define BMI160_INT1_LOW_STEP_DETECT_MASK UINT8_C(0x01) 79 | #define BMI160_INT2_LOW_STEP_DETECT_MASK UINT8_C(0x01) 80 | #define BMI160_INT2_HIGH_G_MASK UINT8_C(0x02) 81 | #define BMI160_INT2_FIFO_FULL_MASK UINT8_C(0x02) 82 | #define BMI160_INT2_FIFO_WM_MASK UINT8_C(0x04) 83 | #define BMI160_INT2_SLOPE_MASK UINT8_C(0x04) 84 | #define BMI160_INT2_DATA_READY_MASK UINT8_C(0x08) 85 | #define BMI160_INT2_NO_MOTION_MASK UINT8_C(0x08) 86 | #define BMI160_INT2_DOUBLE_TAP_MASK UINT8_C(0x10) 87 | #define BMI160_INT2_SINGLE_TAP_MASK UINT8_C(0x20) 88 | #define BMI160_INT2_ORIENT_MASK UINT8_C(0x40) 89 | #define BMI160_INT2_FLAT_MASK UINT8_C(0x80) 90 | 91 | /** Mask definitions for INT_DATA register */ 92 | #define BMI160_TAP_SRC_INT_MASK UINT8_C(0x08) 93 | #define BMI160_LOW_HIGH_SRC_INT_MASK UINT8_C(0x80) 94 | #define BMI160_MOTION_SRC_INT_MASK UINT8_C(0x80) 95 | 96 | /** Mask definitions for INT_MOTION register */ 97 | #define BMI160_SLOPE_INT_DUR_MASK UINT8_C(0x03) 98 | #define BMI160_NO_MOTION_INT_DUR_MASK UINT8_C(0xFC) 99 | #define BMI160_NO_MOTION_SEL_BIT_MASK UINT8_C(0x01) 100 | 101 | /** Mask definitions for INT_TAP register */ 102 | #define BMI160_TAP_DUR_MASK UINT8_C(0x07) 103 | #define BMI160_TAP_SHOCK_DUR_MASK UINT8_C(0x40) 104 | #define BMI160_TAP_QUIET_DUR_MASK UINT8_C(0x80) 105 | #define BMI160_TAP_THRES_MASK UINT8_C(0x1F) 106 | 107 | /** Mask definitions for INT_FLAT register */ 108 | #define BMI160_FLAT_THRES_MASK UINT8_C(0x3F) 109 | #define BMI160_FLAT_HOLD_TIME_MASK UINT8_C(0x30) 110 | #define BMI160_FLAT_HYST_MASK UINT8_C(0x07) 111 | 112 | /** Mask definitions for INT_LOWHIGH register */ 113 | #define BMI160_LOW_G_HYST_MASK UINT8_C(0x03) 114 | #define BMI160_LOW_G_LOW_MODE_MASK UINT8_C(0x04) 115 | #define BMI160_HIGH_G_HYST_MASK UINT8_C(0xC0) 116 | 117 | /** Mask definitions for INT_SIG_MOTION register */ 118 | #define BMI160_SIG_MOTION_SEL_MASK UINT8_C(0x02) 119 | #define BMI160_SIG_MOTION_SKIP_MASK UINT8_C(0x0C) 120 | #define BMI160_SIG_MOTION_PROOF_MASK UINT8_C(0x30) 121 | 122 | /** Mask definitions for INT_ORIENT register */ 123 | #define BMI160_ORIENT_MODE_MASK UINT8_C(0x03) 124 | #define BMI160_ORIENT_BLOCK_MASK UINT8_C(0x0C) 125 | #define BMI160_ORIENT_HYST_MASK UINT8_C(0xF0) 126 | #define BMI160_ORIENT_THETA_MASK UINT8_C(0x3F) 127 | #define BMI160_ORIENT_UD_ENABLE UINT8_C(0x40) 128 | #define BMI160_AXES_EN_MASK UINT8_C(0x80) 129 | 130 | /** Mask definitions for FIFO_CONFIG register */ 131 | #define BMI160_FIFO_GYRO UINT8_C(0x80) 132 | #define BMI160_FIFO_ACCEL UINT8_C(0x40) 133 | #define BMI160_FIFO_AUX UINT8_C(0x20) 134 | #define BMI160_FIFO_TAG_INT1 UINT8_C(0x08) 135 | #define BMI160_FIFO_TAG_INT2 UINT8_C(0x04) 136 | #define BMI160_FIFO_TIME UINT8_C(0x02) 137 | #define BMI160_FIFO_HEADER UINT8_C(0x10) 138 | #define BMI160_FIFO_CONFIG_1_MASK UINT8_C(0xFE) 139 | 140 | 141 | /** Mask definitions for STEP_CONF register */ 142 | #define BMI160_STEP_COUNT_EN_BIT_MASK UINT8_C(0x08) 143 | #define BMI160_STEP_DETECT_MIN_THRES_MASK UINT8_C(0x18) 144 | #define BMI160_STEP_DETECT_STEPTIME_MIN_MASK UINT8_C(0x07) 145 | #define BMI160_STEP_MIN_BUF_MASK UINT8_C(0x07) 146 | 147 | /** Mask definition for FIFO Header Data Tag */ 148 | #define BMI160_FIFO_TAG_INTR_MASK UINT8_C(0xFC) 149 | 150 | /** Fifo byte counter mask definitions */ 151 | #define BMI160_FIFO_BYTE_COUNTER_MASK UINT8_C(0x07) 152 | 153 | /** Enable/disable bit value */ 154 | #define BMI160_ENABLE UINT8_C(0x01) 155 | #define BMI160_DISABLE UINT8_C(0x00) 156 | 157 | /** Latch Duration */ 158 | #define BMI160_LATCH_DUR_NONE UINT8_C(0x00) 159 | #define BMI160_LATCH_DUR_312_5_MICRO_SEC UINT8_C(0x01) 160 | #define BMI160_LATCH_DUR_625_MICRO_SEC UINT8_C(0x02) 161 | #define BMI160_LATCH_DUR_1_25_MILLI_SEC UINT8_C(0x03) 162 | #define BMI160_LATCH_DUR_2_5_MILLI_SEC UINT8_C(0x04) 163 | #define BMI160_LATCH_DUR_5_MILLI_SEC UINT8_C(0x05) 164 | #define BMI160_LATCH_DUR_10_MILLI_SEC UINT8_C(0x06) 165 | #define BMI160_LATCH_DUR_20_MILLI_SEC UINT8_C(0x07) 166 | #define BMI160_LATCH_DUR_40_MILLI_SEC UINT8_C(0x08) 167 | #define BMI160_LATCH_DUR_80_MILLI_SEC UINT8_C(0x09) 168 | #define BMI160_LATCH_DUR_160_MILLI_SEC UINT8_C(0x0A) 169 | #define BMI160_LATCH_DUR_320_MILLI_SEC UINT8_C(0x0B) 170 | #define BMI160_LATCH_DUR_640_MILLI_SEC UINT8_C(0x0C) 171 | #define BMI160_LATCH_DUR_1_28_SEC UINT8_C(0x0D) 172 | #define BMI160_LATCH_DUR_2_56_SEC UINT8_C(0x0E) 173 | #define BMI160_LATCHED UINT8_C(0x0F) 174 | 175 | /** BMI160 Register map */ 176 | #define BMI160_CHIP_ID_ADDR UINT8_C(0x00) 177 | #define BMI160_ERROR_REG_ADDR UINT8_C(0x02) 178 | #define BMI160_AUX_DATA_ADDR UINT8_C(0x04) 179 | #define BMI160_GYRO_DATA_ADDR UINT8_C(0x0C) 180 | #define BMI160_ACCEL_DATA_ADDR UINT8_C(0x12) 181 | #define BMI160_STATUS_ADDR UINT8_C(0x1B) 182 | #define BMI160_INT_STATUS_ADDR UINT8_C(0x1C) 183 | #define BMI160_FIFO_LENGTH_ADDR UINT8_C(0x22) 184 | #define BMI160_FIFO_DATA_ADDR UINT8_C(0x24) 185 | #define BMI160_ACCEL_CONFIG_ADDR UINT8_C(0x40) 186 | #define BMI160_ACCEL_RANGE_ADDR UINT8_C(0x41) 187 | #define BMI160_GYRO_CONFIG_ADDR UINT8_C(0x42) 188 | #define BMI160_GYRO_RANGE_ADDR UINT8_C(0x43) 189 | #define BMI160_AUX_ODR_ADDR UINT8_C(0x44) 190 | #define BMI160_FIFO_DOWN_ADDR UINT8_C(0x45) 191 | #define BMI160_FIFO_CONFIG_0_ADDR UINT8_C(0x46) 192 | #define BMI160_FIFO_CONFIG_1_ADDR UINT8_C(0x47) 193 | #define BMI160_AUX_IF_0_ADDR UINT8_C(0x4B) 194 | #define BMI160_AUX_IF_1_ADDR UINT8_C(0x4C) 195 | #define BMI160_AUX_IF_2_ADDR UINT8_C(0x4D) 196 | #define BMI160_AUX_IF_3_ADDR UINT8_C(0x4E) 197 | #define BMI160_AUX_IF_4_ADDR UINT8_C(0x4F) 198 | #define BMI160_INT_ENABLE_0_ADDR UINT8_C(0x50) 199 | #define BMI160_INT_ENABLE_1_ADDR UINT8_C(0x51) 200 | #define BMI160_INT_ENABLE_2_ADDR UINT8_C(0x52) 201 | #define BMI160_INT_OUT_CTRL_ADDR UINT8_C(0x53) 202 | #define BMI160_INT_LATCH_ADDR UINT8_C(0x54) 203 | #define BMI160_INT_MAP_0_ADDR UINT8_C(0x55) 204 | #define BMI160_INT_MAP_1_ADDR UINT8_C(0x56) 205 | #define BMI160_INT_MAP_2_ADDR UINT8_C(0x57) 206 | #define BMI160_INT_DATA_0_ADDR UINT8_C(0x58) 207 | #define BMI160_INT_DATA_1_ADDR UINT8_C(0x59) 208 | #define BMI160_INT_LOWHIGH_0_ADDR UINT8_C(0x5A) 209 | #define BMI160_INT_LOWHIGH_1_ADDR UINT8_C(0x5B) 210 | #define BMI160_INT_LOWHIGH_2_ADDR UINT8_C(0x5C) 211 | #define BMI160_INT_LOWHIGH_3_ADDR UINT8_C(0x5D) 212 | #define BMI160_INT_LOWHIGH_4_ADDR UINT8_C(0x5E) 213 | #define BMI160_INT_MOTION_0_ADDR UINT8_C(0x5F) 214 | #define BMI160_INT_MOTION_1_ADDR UINT8_C(0x60) 215 | #define BMI160_INT_MOTION_2_ADDR UINT8_C(0x61) 216 | #define BMI160_INT_MOTION_3_ADDR UINT8_C(0x62) 217 | #define BMI160_INT_TAP_0_ADDR UINT8_C(0x63) 218 | #define BMI160_INT_TAP_1_ADDR UINT8_C(0x64) 219 | #define BMI160_INT_ORIENT_0_ADDR UINT8_C(0x65) 220 | #define BMI160_INT_ORIENT_1_ADDR UINT8_C(0x66) 221 | #define BMI160_INT_FLAT_0_ADDR UINT8_C(0x67) 222 | #define BMI160_INT_FLAT_1_ADDR UINT8_C(0x68) 223 | #define BMI160_FOC_CONF_ADDR UINT8_C(0x69) 224 | #define BMI160_CONF_ADDR UINT8_C(0x6A) 225 | 226 | #define BMI160_IF_CONF_ADDR UINT8_C(0x6B) 227 | #define BMI160_SELF_TEST_ADDR UINT8_C(0x6D) 228 | #define BMI160_OFFSET_ADDR UINT8_C(0x71) 229 | #define BMI160_OFFSET_CONF_ADDR UINT8_C(0x77) 230 | #define BMI160_INT_STEP_CNT_0_ADDR UINT8_C(0x78) 231 | #define BMI160_INT_STEP_CONFIG_0_ADDR UINT8_C(0x7A) 232 | #define BMI160_INT_STEP_CONFIG_1_ADDR UINT8_C(0x7B) 233 | #define BMI160_COMMAND_REG_ADDR UINT8_C(0x7E) 234 | #define BMI160_SPI_COMM_TEST_ADDR UINT8_C(0x7F) 235 | #define BMI160_INTL_PULLUP_CONF_ADDR UINT8_C(0x85) 236 | 237 | /** Error code definitions */ 238 | #define BMI160_OK INT8_C(0) 239 | #define BMI160_E_NULL_PTR INT8_C(-1) 240 | #define BMI160_E_COM_FAIL INT8_C(-2) 241 | #define BMI160_E_DEV_NOT_FOUND INT8_C(-3) 242 | #define BMI160_E_OUT_OF_RANGE INT8_C(-4) 243 | #define BMI160_E_INVALID_INPUT INT8_C(-5) 244 | #define BMI160_E_ACCEL_ODR_BW_INVALID INT8_C(-6) 245 | #define BMI160_E_GYRO_ODR_BW_INVALID INT8_C(-7) 246 | #define BMI160_E_LWP_PRE_FLTR_INT_INVALID INT8_C(-8) 247 | #define BMI160_E_LWP_PRE_FLTR_INVALID INT8_C(-9) 248 | #define BMI160_E_AUX_NOT_FOUND INT8_C(-10) 249 | #define BMI160_FOC_FAILURE INT8_C(-11) 250 | #define BMI160_ERR_CHOOSE INT8_C(-12) 251 | 252 | /** name API warning codes */ 253 | #define BMI160_W_GYRO_SELF_TEST_FAIL INT8_C(1) 254 | #define BMI160_W_ACCEl_SELF_TEST_FAIL INT8_C(2) 255 | 256 | /** BMI160 unique chip identifier */ 257 | #define BMI160_CHIP_ID UINT8_C(0xD1) 258 | 259 | /** Soft reset command */ 260 | #define BMI160_SOFT_RESET_CMD UINT8_C(0xb6) 261 | #define BMI160_SOFT_RESET_DELAY_MS UINT8_C(15) 262 | /** Start FOC command */ 263 | #define BMI160_START_FOC_CMD UINT8_C(0x03) 264 | /** NVM backup enabling command */ 265 | #define BMI160_NVM_BACKUP_EN UINT8_C(0xA0) 266 | 267 | /* Delay in ms settings */ 268 | #define BMI160_ACCEL_DELAY_MS UINT8_C(5) 269 | #define BMI160_GYRO_DELAY_MS UINT8_C(81) 270 | #define BMI160_ONE_MS_DELAY UINT8_C(1) 271 | #define BMI160_AUX_COM_DELAY UINT8_C(10) 272 | #define BMI160_GYRO_SELF_TEST_DELAY UINT8_C(20) 273 | #define BMI160_ACCEL_SELF_TEST_DELAY UINT8_C(50) 274 | 275 | /** Self test configurations */ 276 | #define BMI160_ACCEL_SELF_TEST_CONFIG UINT8_C(0x2C) 277 | #define BMI160_ACCEL_SELF_TEST_POSITIVE_EN UINT8_C(0x0D) 278 | #define BMI160_ACCEL_SELF_TEST_NEGATIVE_EN UINT8_C(0x09) 279 | #define BMI160_ACCEL_SELF_TEST_LIMIT UINT16_C(8192) 280 | 281 | /** Power mode settings */ 282 | /* Accel power mode */ 283 | #define BMI160_ACCEL_NORMAL_MODE UINT8_C(0x11) 284 | #define BMI160_ACCEL_LOWPOWER_MODE UINT8_C(0x12) 285 | #define BMI160_ACCEL_SUSPEND_MODE UINT8_C(0x10) 286 | 287 | /* Gyro power mode */ 288 | #define BMI160_GYRO_SUSPEND_MODE UINT8_C(0x14) 289 | #define BMI160_GYRO_NORMAL_MODE UINT8_C(0x15) 290 | #define BMI160_GYRO_FASTSTARTUP_MODE UINT8_C(0x17) 291 | 292 | /* Aux power mode */ 293 | #define BMI160_AUX_SUSPEND_MODE UINT8_C(0x18) 294 | #define BMI160_AUX_NORMAL_MODE UINT8_C(0x19) 295 | #define BMI160_AUX_LOWPOWER_MODE UINT8_C(0x1A) 296 | 297 | /** Range settings */ 298 | /* Accel Range */ 299 | #define BMI160_ACCEL_RANGE_2G UINT8_C(0x03) 300 | #define BMI160_ACCEL_RANGE_4G UINT8_C(0x05) 301 | #define BMI160_ACCEL_RANGE_8G UINT8_C(0x08) 302 | #define BMI160_ACCEL_RANGE_16G UINT8_C(0x0C) 303 | 304 | /* Gyro Range */ 305 | #define BMI160_GYRO_RANGE_2000_DPS UINT8_C(0x00) 306 | #define BMI160_GYRO_RANGE_1000_DPS UINT8_C(0x01) 307 | #define BMI160_GYRO_RANGE_500_DPS UINT8_C(0x02) 308 | #define BMI160_GYRO_RANGE_250_DPS UINT8_C(0x03) 309 | #define BMI160_GYRO_RANGE_125_DPS UINT8_C(0x04) 310 | 311 | /** Bandwidth settings */ 312 | /* Accel Bandwidth */ 313 | #define BMI160_ACCEL_BW_OSR4_AVG1 UINT8_C(0x00) 314 | #define BMI160_ACCEL_BW_OSR2_AVG2 UINT8_C(0x01) 315 | #define BMI160_ACCEL_BW_NORMAL_AVG4 UINT8_C(0x02) 316 | #define BMI160_ACCEL_BW_RES_AVG8 UINT8_C(0x03) 317 | #define BMI160_ACCEL_BW_RES_AVG16 UINT8_C(0x04) 318 | #define BMI160_ACCEL_BW_RES_AVG32 UINT8_C(0x05) 319 | #define BMI160_ACCEL_BW_RES_AVG64 UINT8_C(0x06) 320 | #define BMI160_ACCEL_BW_RES_AVG128 UINT8_C(0x07) 321 | 322 | #define BMI160_GYRO_BW_OSR4_MODE UINT8_C(0x00) 323 | #define BMI160_GYRO_BW_OSR2_MODE UINT8_C(0x01) 324 | #define BMI160_GYRO_BW_NORMAL_MODE UINT8_C(0x02) 325 | 326 | /* Output Data Rate settings */ 327 | /* Accel Output data rate */ 328 | #define BMI160_ACCEL_ODR_RESERVED UINT8_C(0x00) 329 | #define BMI160_ACCEL_ODR_0_78HZ UINT8_C(0x01) 330 | #define BMI160_ACCEL_ODR_1_56HZ UINT8_C(0x02) 331 | #define BMI160_ACCEL_ODR_3_12HZ UINT8_C(0x03) 332 | #define BMI160_ACCEL_ODR_6_25HZ UINT8_C(0x04) 333 | #define BMI160_ACCEL_ODR_12_5HZ UINT8_C(0x05) 334 | #define BMI160_ACCEL_ODR_25HZ UINT8_C(0x06) 335 | #define BMI160_ACCEL_ODR_50HZ UINT8_C(0x07) 336 | #define BMI160_ACCEL_ODR_100HZ UINT8_C(0x08) 337 | #define BMI160_ACCEL_ODR_200HZ UINT8_C(0x09) 338 | #define BMI160_ACCEL_ODR_400HZ UINT8_C(0x0A) 339 | #define BMI160_ACCEL_ODR_800HZ UINT8_C(0x0B) 340 | #define BMI160_ACCEL_ODR_1600HZ UINT8_C(0x0C) 341 | #define BMI160_ACCEL_ODR_RESERVED0 UINT8_C(0x0D) 342 | #define BMI160_ACCEL_ODR_RESERVED1 UINT8_C(0x0E) 343 | #define BMI160_ACCEL_ODR_RESERVED2 UINT8_C(0x0F) 344 | 345 | /* Gyro Output data rate */ 346 | #define BMI160_GYRO_ODR_RESERVED UINT8_C(0x00) 347 | #define BMI160_GYRO_ODR_25HZ UINT8_C(0x06) 348 | #define BMI160_GYRO_ODR_50HZ UINT8_C(0x07) 349 | #define BMI160_GYRO_ODR_100HZ UINT8_C(0x08) 350 | #define BMI160_GYRO_ODR_200HZ UINT8_C(0x09) 351 | #define BMI160_GYRO_ODR_400HZ UINT8_C(0x0A) 352 | #define BMI160_GYRO_ODR_800HZ UINT8_C(0x0B) 353 | #define BMI160_GYRO_ODR_1600HZ UINT8_C(0x0C) 354 | #define BMI160_GYRO_ODR_3200HZ UINT8_C(0x0D) 355 | 356 | /* Auxiliary sensor Output data rate */ 357 | #define BMI160_AUX_ODR_RESERVED UINT8_C(0x00) 358 | #define BMI160_AUX_ODR_0_78HZ UINT8_C(0x01) 359 | #define BMI160_AUX_ODR_1_56HZ UINT8_C(0x02) 360 | #define BMI160_AUX_ODR_3_12HZ UINT8_C(0x03) 361 | #define BMI160_AUX_ODR_6_25HZ UINT8_C(0x04) 362 | #define BMI160_AUX_ODR_12_5HZ UINT8_C(0x05) 363 | #define BMI160_AUX_ODR_25HZ UINT8_C(0x06) 364 | #define BMI160_AUX_ODR_50HZ UINT8_C(0x07) 365 | #define BMI160_AUX_ODR_100HZ UINT8_C(0x08) 366 | #define BMI160_AUX_ODR_200HZ UINT8_C(0x09) 367 | #define BMI160_AUX_ODR_400HZ UINT8_C(0x0A) 368 | #define BMI160_AUX_ODR_800HZ UINT8_C(0x0B) 369 | 370 | /* Maximum limits definition */ 371 | #define BMI160_ACCEL_ODR_MAX UINT8_C(15) 372 | #define BMI160_ACCEL_BW_MAX UINT8_C(2) 373 | #define BMI160_ACCEL_RANGE_MAX UINT8_C(12) 374 | #define BMI160_GYRO_ODR_MAX UINT8_C(13) 375 | #define BMI160_GYRO_BW_MAX UINT8_C(2) 376 | #define BMI160_GYRO_RANGE_MAX UINT8_C(4) 377 | 378 | /** FIFO_CONFIG Definitions */ 379 | #define BMI160_FIFO_TIME_ENABLE UINT8_C(0x02) 380 | #define BMI160_FIFO_TAG_INT2_ENABLE UINT8_C(0x04) 381 | #define BMI160_FIFO_TAG_INT1_ENABLE UINT8_C(0x08) 382 | #define BMI160_FIFO_HEAD_ENABLE UINT8_C(0x10) 383 | #define BMI160_FIFO_M_ENABLE UINT8_C(0x20) 384 | #define BMI160_FIFO_A_ENABLE UINT8_C(0x40) 385 | #define BMI160_FIFO_M_A_ENABLE UINT8_C(0x60) 386 | #define BMI160_FIFO_G_ENABLE UINT8_C(0x80) 387 | #define BMI160_FIFO_M_G_ENABLE UINT8_C(0xA0) 388 | #define BMI160_FIFO_G_A_ENABLE UINT8_C(0xC0) 389 | #define BMI160_FIFO_M_G_A_ENABLE UINT8_C(0xE0) 390 | 391 | 392 | /* Accel, gyro and aux. sensor length and also their combined 393 | * length definitions in FIFO */ 394 | #define BMI160_FIFO_G_LENGTH UINT8_C(6) 395 | #define BMI160_FIFO_A_LENGTH UINT8_C(6) 396 | #define BMI160_FIFO_M_LENGTH UINT8_C(8) 397 | #define BMI160_FIFO_GA_LENGTH UINT8_C(12) 398 | #define BMI160_FIFO_MA_LENGTH UINT8_C(14) 399 | #define BMI160_FIFO_MG_LENGTH UINT8_C(14) 400 | #define BMI160_FIFO_MGA_LENGTH UINT8_C(20) 401 | 402 | 403 | /** FIFO Header Data definitions */ 404 | #define BMI160_FIFO_HEAD_SKIP_FRAME UINT8_C(0x40) 405 | #define BMI160_FIFO_HEAD_SENSOR_TIME UINT8_C(0x44) 406 | #define BMI160_FIFO_HEAD_INPUT_CONFIG UINT8_C(0x48) 407 | #define BMI160_FIFO_HEAD_OVER_READ UINT8_C(0x80) 408 | #define BMI160_FIFO_HEAD_A UINT8_C(0x84) 409 | #define BMI160_FIFO_HEAD_G UINT8_C(0x88) 410 | #define BMI160_FIFO_HEAD_G_A UINT8_C(0x8C) 411 | #define BMI160_FIFO_HEAD_M UINT8_C(0x90) 412 | #define BMI160_FIFO_HEAD_M_A UINT8_C(0x94) 413 | #define BMI160_FIFO_HEAD_M_G UINT8_C(0x98) 414 | #define BMI160_FIFO_HEAD_M_G_A UINT8_C(0x9C) 415 | 416 | 417 | /** FIFO sensor time length definitions */ 418 | #define BMI160_SENSOR_TIME_LENGTH UINT8_C(3) 419 | 420 | 421 | /** FIFO DOWN selection */ 422 | /* Accel fifo down-sampling values*/ 423 | #define BMI160_ACCEL_FIFO_DOWN_ZERO UINT8_C(0x00) 424 | #define BMI160_ACCEL_FIFO_DOWN_ONE UINT8_C(0x10) 425 | #define BMI160_ACCEL_FIFO_DOWN_TWO UINT8_C(0x20) 426 | #define BMI160_ACCEL_FIFO_DOWN_THREE UINT8_C(0x30) 427 | #define BMI160_ACCEL_FIFO_DOWN_FOUR UINT8_C(0x40) 428 | #define BMI160_ACCEL_FIFO_DOWN_FIVE UINT8_C(0x50) 429 | #define BMI160_ACCEL_FIFO_DOWN_SIX UINT8_C(0x60) 430 | #define BMI160_ACCEL_FIFO_DOWN_SEVEN UINT8_C(0x70) 431 | 432 | /* Gyro fifo down-smapling values*/ 433 | #define BMI160_GYRO_FIFO_DOWN_ZERO UINT8_C(0x00) 434 | #define BMI160_GYRO_FIFO_DOWN_ONE UINT8_C(0x01) 435 | #define BMI160_GYRO_FIFO_DOWN_TWO UINT8_C(0x02) 436 | #define BMI160_GYRO_FIFO_DOWN_THREE UINT8_C(0x03) 437 | #define BMI160_GYRO_FIFO_DOWN_FOUR UINT8_C(0x04) 438 | #define BMI160_GYRO_FIFO_DOWN_FIVE UINT8_C(0x05) 439 | #define BMI160_GYRO_FIFO_DOWN_SIX UINT8_C(0x06) 440 | #define BMI160_GYRO_FIFO_DOWN_SEVEN UINT8_C(0x07) 441 | 442 | /* Accel Fifo filter enable*/ 443 | #define BMI160_ACCEL_FIFO_FILT_EN UINT8_C(0x80) 444 | 445 | /* Gyro Fifo filter enable*/ 446 | #define BMI160_GYRO_FIFO_FILT_EN UINT8_C(0x08) 447 | 448 | /** Definitions to check validity of FIFO frames */ 449 | #define FIFO_CONFIG_MSB_CHECK UINT8_C(0x80) 450 | #define FIFO_CONFIG_LSB_CHECK UINT8_C(0x00) 451 | 452 | /*! BMI160 accel FOC configurations */ 453 | #define BMI160_FOC_ACCEL_DISABLED UINT8_C(0x00) 454 | #define BMI160_FOC_ACCEL_POSITIVE_G UINT8_C(0x01) 455 | #define BMI160_FOC_ACCEL_NEGATIVE_G UINT8_C(0x02) 456 | #define BMI160_FOC_ACCEL_0G UINT8_C(0x03) 457 | 458 | /** Array Parameter DefinItions */ 459 | #define BMI160_SENSOR_TIME_LSB_BYTE UINT8_C(0) 460 | #define BMI160_SENSOR_TIME_XLSB_BYTE UINT8_C(1) 461 | #define BMI160_SENSOR_TIME_MSB_BYTE UINT8_C(2) 462 | 463 | 464 | /** Interface settings */ 465 | #define BMI160_SPI_INTF UINT8_C(1) 466 | #define BMI160_I2C_INTF UINT8_C(0) 467 | #define BMI160_SPI_RD_MASK UINT8_C(0x80) 468 | #define BMI160_SPI_WR_MASK UINT8_C(0x7F) 469 | 470 | /* Sensor & time select definition*/ 471 | #define BMI160_ACCEL_SEL UINT8_C(0x01) 472 | #define BMI160_GYRO_SEL UINT8_C(0x02) 473 | #define BMI160_TIME_SEL UINT8_C(0x04) 474 | 475 | /* Sensor select mask*/ 476 | #define BMI160_SEN_SEL_MASK UINT8_C(0x07) 477 | 478 | /* Error code mask */ 479 | #define BMI160_ERR_REG_MASK UINT8_C(0x0F) 480 | 481 | /* BMI160 I2C address */ 482 | #define BMI160_I2C_ADDR UINT8_C(0x68) 483 | 484 | /* BMI160 secondary IF address */ 485 | #define BMI160_AUX_BMM150_I2C_ADDR UINT8_C(0x10) 486 | 487 | /** BMI160 Length definitions */ 488 | #define BMI160_ONE UINT8_C(1) 489 | #define BMI160_TWO UINT8_C(2) 490 | #define BMI160_THREE UINT8_C(3) 491 | #define BMI160_FOUR UINT8_C(4) 492 | #define BMI160_FIVE UINT8_C(5) 493 | 494 | /** BMI160 fifo level Margin */ 495 | #define BMI160_FIFO_LEVEL_MARGIN UINT8_C(16) 496 | 497 | /** BMI160 fifo flush Command */ 498 | #define BMI160_FIFO_FLUSH_VALUE UINT8_C(0xB0) 499 | 500 | /** BMI160 offset values for xyz axes of accel */ 501 | #define BMI160_ACCEL_MIN_OFFSET INT8_C(-128) 502 | #define BMI160_ACCEL_MAX_OFFSET INT8_C(127) 503 | 504 | /** BMI160 offset values for xyz axes of gyro */ 505 | #define BMI160_GYRO_MIN_OFFSET INT16_C(-512) 506 | #define BMI160_GYRO_MAX_OFFSET INT16_C(511) 507 | 508 | /** BMI160 fifo full interrupt position and mask */ 509 | #define BMI160_FIFO_FULL_INT_POS UINT8_C(5) 510 | #define BMI160_FIFO_FULL_INT_MSK UINT8_C(0x20) 511 | #define BMI160_FIFO_WTM_INT_POS UINT8_C(6) 512 | #define BMI160_FIFO_WTM_INT_MSK UINT8_C(0x40) 513 | 514 | #define BMI160_FIFO_FULL_INT_PIN1_POS UINT8_C(5) 515 | #define BMI160_FIFO_FULL_INT_PIN1_MSK UINT8_C(0x20) 516 | #define BMI160_FIFO_FULL_INT_PIN2_POS UINT8_C(1) 517 | #define BMI160_FIFO_FULL_INT_PIN2_MSK UINT8_C(0x02) 518 | 519 | #define BMI160_FIFO_WTM_INT_PIN1_POS UINT8_C(6) 520 | #define BMI160_FIFO_WTM_INT_PIN1_MSK UINT8_C(0x40) 521 | #define BMI160_FIFO_WTM_INT_PIN2_POS UINT8_C(2) 522 | #define BMI160_FIFO_WTM_INT_PIN2_MSK UINT8_C(0x04) 523 | 524 | #define BMI160_MANUAL_MODE_EN_POS UINT8_C(7) 525 | #define BMI160_MANUAL_MODE_EN_MSK UINT8_C(0x80) 526 | #define BMI160_AUX_READ_BURST_POS UINT8_C(0) 527 | #define BMI160_AUX_READ_BURST_MSK UINT8_C(0x03) 528 | 529 | #define BMI160_GYRO_SELF_TEST_POS UINT8_C(4) 530 | #define BMI160_GYRO_SELF_TEST_MSK UINT8_C(0x10) 531 | #define BMI160_GYRO_SELF_TEST_STATUS_POS UINT8_C(1) 532 | #define BMI160_GYRO_SELF_TEST_STATUS_MSK UINT8_C(0x02) 533 | 534 | #define BMI160_GYRO_FOC_EN_POS UINT8_C(6) 535 | #define BMI160_GYRO_FOC_EN_MSK UINT8_C(0x40) 536 | 537 | #define BMI160_ACCEL_FOC_X_CONF_POS UINT8_C(4) 538 | #define BMI160_ACCEL_FOC_X_CONF_MSK UINT8_C(0x30) 539 | 540 | #define BMI160_ACCEL_FOC_Y_CONF_POS UINT8_C(2) 541 | #define BMI160_ACCEL_FOC_Y_CONF_MSK UINT8_C(0x0C) 542 | 543 | #define BMI160_ACCEL_FOC_Z_CONF_MSK UINT8_C(0x03) 544 | 545 | #define BMI160_FOC_STATUS_POS UINT8_C(3) 546 | #define BMI160_FOC_STATUS_MSK UINT8_C(0x08) 547 | 548 | #define BMI160_GYRO_OFFSET_X_MSK UINT8_C(0x03) 549 | 550 | #define BMI160_GYRO_OFFSET_Y_POS UINT8_C(2) 551 | #define BMI160_GYRO_OFFSET_Y_MSK UINT8_C(0x0C) 552 | 553 | #define BMI160_GYRO_OFFSET_Z_POS UINT8_C(4) 554 | #define BMI160_GYRO_OFFSET_Z_MSK UINT8_C(0x30) 555 | 556 | #define BMI160_GYRO_OFFSET_EN_POS UINT8_C(7) 557 | #define BMI160_GYRO_OFFSET_EN_MSK UINT8_C(0x80) 558 | 559 | #define BMI160_ACCEL_OFFSET_EN_POS UINT8_C(6) 560 | #define BMI160_ACCEL_OFFSET_EN_MSK UINT8_C(0x40) 561 | 562 | 563 | #define BMI160_GYRO_OFFSET_POS UINT16_C(8) 564 | #define BMI160_GYRO_OFFSET_MSK UINT16_C(0x0300) 565 | 566 | #define BMI160_NVM_UPDATE_POS UINT8_C(1) 567 | #define BMI160_NVM_UPDATE_MSK UINT8_C(0x02) 568 | 569 | #define BMI160_NVM_STATUS_POS UINT8_C(4) 570 | #define BMI160_NVM_STATUS_MSK UINT8_C(0x10) 571 | 572 | /* BIT SLICE GET AND SET FUNCTIONS */ 573 | #define BMI160_GET_BITS(regvar, bitname)\ 574 | ((regvar & bitname##_MSK) >> bitname##_POS) 575 | #define BMI160_SET_BITS(regvar, bitname, val)\ 576 | ((regvar & ~bitname##_MSK) | \ 577 | ((val<> 8) 591 | 592 | /** 593 | * @struct bmi160FifoFrame 594 | * @brief This structure holds the information for usage of FIFO by the user. 595 | */ 596 | struct bmi160FifoFrame { 597 | uint8_t *data; /**< Data buffer of user defined length is to be mapped here */ 598 | uint16_t length; /**< While calling the API "bmi160_get_fifo_data" , length stores number of bytes in FIFO to be read (specified by user as input) and after execution of the API ,number of FIFO data bytes available is provided as an output to user*/ 599 | uint8_t fifoTimeEnable; /**< FIFO time enable */ 600 | uint8_t fifoHeaderEnable; /**< Enabling of the FIFO header to stream in header mode */ 601 | uint8_t fifoDataEnable; /**< Streaming of the Accelerometer, Gyroscope sensor data or both in FIFO */ 602 | uint16_t accelByteStartIdx;/**< Will be equal to length when no more frames are there to parse */ 603 | uint16_t gyroByteStartIdx; /**< Will be equal to length when no more frames are there to parse */ 604 | uint16_t auxByteStartIdx; /**< Will be equal to length when no more frames are there to parse */ 605 | uint32_t sensorTime; /**< Value of FIFO sensor time time */ 606 | uint8_t skippedFrameCount; /**< Value of Skipped frame counts */ 607 | }; 608 | 609 | /** 610 | * @enum eBmi160AnySigMotionActiveInterruptState 611 | * @brief bmi160 active state of any & sig motion interrupt. 612 | */ 613 | enum eBmi160AnySigMotionActiveInterruptState { 614 | eBmi160BothAnySigMotionDisabled = -1, /**< Both any & sig motion are disabled */ 615 | eBmi160AnyMotionEnabled, /**< Any-motion selected */ 616 | eBmi160SigMotionEnabled /**< Sig-motion selected */ 617 | }; 618 | 619 | /** 620 | * @enum eBmi160SelectSensor 621 | * @brief bmi160 sensor select structure 622 | */ 623 | enum eBmi160SelectSensor { 624 | eBmi160AccelOnly = 1, 625 | eBmi160GyroOnly, 626 | eBmi160BothAccelAndGyro 627 | }; 628 | 629 | /** 630 | * @struct bmi160Cfg 631 | * @brief bmi160 sensor configuration structure 632 | */ 633 | struct bmi160Cfg { 634 | uint8_t power; /**< power mode */ 635 | uint8_t odr; /**< output data rate */ 636 | uint8_t range; /**< range */ 637 | uint8_t bw; /**< bandwidth */ 638 | }; 639 | 640 | /** 641 | * @brief Aux sensor configuration structure 642 | */ 643 | struct bmi160AuxCfg { 644 | uint8_t auxSensorEnable : 1; /**< Aux sensor, 1 - enable 0 - disable */ 645 | uint8_t manualEnable : 1; /**< Aux manual/auto mode status */ 646 | uint8_t auxRdBurstLen : 2; /**< Aux read burst length */ 647 | uint8_t auxOdr :4; /**< output data rate */ 648 | uint8_t auxI2cAddr; /**< i2c addr of auxiliary sensor */ 649 | }; 650 | 651 | /* type definitions */ 652 | typedef int8_t (*bmi160ComFptrT)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t len); 653 | typedef void (*bmi160DelayFptrT)(uint32_t period); 654 | 655 | struct bmi160Dev { 656 | uint8_t chipId; /**< Chip Id */ 657 | uint8_t id; /**< Device Id */ 658 | uint8_t interface;/**< 0 - I2C , 1 - SPI Interface */ 659 | enum eBmi160AnySigMotionActiveInterruptState any_sig_sel;/**< Hold active interrupts status for any and sig motion 0 - Any-motion enable, 1 - Sig-motion enable, -1 neither any-motion nor sig-motion selected */ 660 | struct bmi160Cfg accelCfg; /**< Structure to configure Accel sensor */ 661 | struct bmi160Cfg prevAccelCfg;/**< Structure to hold previous/old accel config parameters.This is used at driver level to prevent overwriting of samedata, hence user does not change it in the code */ 662 | struct bmi160Cfg gyroCfg; /**< Structure to configure Gyro sensor */ 663 | struct bmi160Cfg prevGyroCfg; /**< Structure to hold previous/old gyro config parameters.This is used at driver level to prevent overwriting of same data, hence user does not change it in the code */ 664 | struct bmi160AuxCfg auxCfg; /**< Structure to configure the auxiliary sensor */ 665 | struct bmi160AuxCfg prevAuxCfg;/**< Structure to hold previous/old aux config parameters.This is used at driver level to prevent overwriting of samedata, hence user does not change it in the code */ 666 | struct bmi160FifoFrame *fifo; /**< FIFO related configurations */ 667 | bmi160ComFptrT read; /**< Read function pointer */ 668 | bmi160ComFptrT write; /**< Write function pointer */ 669 | bmi160DelayFptrT delayMs; /**< Delay function pointer */ 670 | }; 671 | 672 | /** 673 | * @brief bmi160 sensor data structure which comprises of accel data 674 | */ 675 | struct bmi160SensorData { 676 | int16_t x; /**< X-axis sensor data */ 677 | int16_t y; /**< Y-axis sensor data */ 678 | int16_t z; /**< Z-axis sensor data */ 679 | uint32_t sensortime; /**< sensor time */ 680 | }; 681 | 682 | enum bmi160IntChannel { 683 | BMI160_INT_CHANNEL_NONE, /**< Un-map both channels */ 684 | BMI160_INT_CHANNEL_1, /**< interrupt Channel 1 */ 685 | BMI160_INT_CHANNEL_2, /**< interrupt Channel 2 */ 686 | BMI160_INT_CHANNEL_BOTH /**< Map both channels */ 687 | }; 688 | 689 | enum bmi160IntTypes { 690 | BMI160_ACC_ANY_MOTION_INT, /**< Slope/Any-motion interrupt */ 691 | BMI160_ACC_SIG_MOTION_INT, /**< Significant motion interrupt */ 692 | BMI160_STEP_DETECT_INT, /**< Step detector interrupt */ 693 | BMI160_ACC_DOUBLE_TAP_INT, /**< double tap interrupt */ 694 | BMI160_ACC_SINGLE_TAP_INT, /**< single tap interrupt */ 695 | BMI160_ACC_ORIENT_INT, /**< orientation interrupt */ 696 | BMI160_ACC_FLAT_INT, /**< flat interrupt */ 697 | BMI160_ACC_HIGH_G_INT, /**< high-g interrupt */ 698 | BMI160_ACC_LOW_G_INT, /**< low-g interrupt */ 699 | BMI160_ACC_SLOW_NO_MOTION_INT, /**< slow/no-motion interrupt */ 700 | BMI160_ACC_GYRO_DATA_RDY_INT, /**< data ready interrupt */ 701 | BMI160_ACC_GYRO_FIFO_FULL_INT, /**< fifo full interrupt */ 702 | BMI160_ACC_GYRO_FIFO_WATERMARK_INT /**< fifo watermark interrupt */ 703 | }; 704 | 705 | struct bmi160IntPinSettg { 706 | #if LITTLE_ENDIAN == 1 707 | 708 | uint16_t outputEn :1; /**< To enable either INT1 or INT2 pin as output. 0- output disabled ,1- output enabled */ 709 | uint16_t outputMode :1; /**< 0 - push-pull 1- open drain,only valid if outputEn is set 1 */ 710 | uint16_t outputType :1; /**< 0 - active low , 1 - active high level. if outputEn is 1,this applies to interrupts,else PMU_trigger */ 711 | uint16_t edgeCtrl :1; /**< 0 - level trigger , 1 - edge trigger */ 712 | uint16_t inputEn :1; /**< To enable either INT1 or INT2 pin as input. 0 - input disabled ,1 - input enabled */ 713 | uint16_t latchDur :4; /**< latch duration*/ 714 | #elif BIG_ENDIAN == 1 715 | uint16_t latchDur : 4; /**< latch duration*/ 716 | uint16_t inputEn : 1; /**< Latched,non-latched or temporary interrupt modes */ 717 | uint16_t edgeCtrl : 1; /**< 1 - edge trigger, 0 - level trigger */ 718 | uint16_t outputType : 1;/**< 0 - active low , 1 - active high level. if outputEn is 1,this applies to interrupts,else PMU_trigger */ 719 | uint16_t outputMode : 1;/**< 0 - push-pull , 1 - open drain,only valid if outputEn is set 1 */ 720 | uint16_t outputEn : 1; /**< To enable either INT1 or INT2 pin as output. 0 - output disabled , 1 - output enabled */ 721 | #endif 722 | }; 723 | 724 | struct bmi160AccTapIntCfg { 725 | #if LITTLE_ENDIAN == 1 726 | uint16_t tapThr :5; /**< tap threshold */ 727 | uint16_t tapShock :1; /**< tap shock */ 728 | uint16_t tapQuiet :1; /**< tap quiet */ 729 | uint16_t tapDur :3; /**< tap duration */ 730 | uint16_t tapDataSrc :1; /**< data source 0- filter & 1 pre-filter*/ 731 | uint16_t tapEn :1; /**< tap enable, 1 - enable, 0 - disable */ 732 | #elif BIG_ENDIAN == 1 733 | uint16_t tapEn :1; /**< tap enable, 1 - enable, 0 - disable */ 734 | uint16_t tapDataSrc :1;/**< data source 0- filter & 1 pre-filter*/ 735 | uint16_t tapDur : 3; /**< tap duration */ 736 | uint16_t tapQuiet : 1; /**< tap quiet */ 737 | uint16_t tapShock : 1; /**< tap shock */ 738 | uint16_t tapThr : 5; /**< tap threshold */ 739 | #endif 740 | }; 741 | 742 | struct bmi160AccAnyMotIntCfg { 743 | #if LITTLE_ENDIAN == 1 744 | uint8_t anymotionEn :1; /**< 1 any-motion enable, 0 - any-motion disable */ 745 | uint8_t anymotionX :1; /**< slope interrupt x, 1 - enable, 0 - disable */ 746 | uint8_t anymotionY :1; /**< slope interrupt y, 1 - enable, 0 - disable */ 747 | uint8_t anymotionZ :1; /**< slope interrupt z, 1 - enable, 0 - disable */ 748 | uint8_t anymotionDur :2; /**< slope duration */ 749 | uint8_t anymotionDataSrc :1;/**< data source 0- filter & 1 pre-filter*/ 750 | uint8_t anymotionThr; /**< slope threshold */ 751 | #elif BIG_ENDIAN == 1 752 | 753 | uint8_t anymotionThr; /**< slope threshold */ 754 | uint8_t anymotionDataSrc :1;/**< data source 0- filter & 1 pre-filter*/ 755 | uint8_t anymotionDur : 2; /**< slope duration */ 756 | uint8_t anymotionZ : 1; /**< slope interrupt z, 1 - enable, 0 - disable */ 757 | uint8_t anymotionY : 1; /**< slope interrupt y, 1 - enable, 0 - disable */ 758 | uint8_t anymotionX : 1; /**< slope interrupt x, 1 - enable, 0 - disable */ 759 | uint8_t anymotionEn :1; /**< 1 any-motion enable, 0 - any-motion disable */ 760 | #endif 761 | }; 762 | 763 | struct bmi160AccSigMotIntCfg { 764 | #if LITTLE_ENDIAN == 1 765 | uint8_t sigMotSkip :2; /**< skip time of sig-motion interrupt */ 766 | uint8_t sigMotProof :2; /**< proof time of sig-motion interrupt */ 767 | uint8_t sigDataSrc :1; /**< data source 0- filter & 1 pre-filter*/ 768 | uint8_t sigEn :1; /**< 1 - enable sig, 0 - disable sig & enable anymotion */ 769 | uint8_t sigMotThres; /**< sig-motion threshold */ 770 | #elif BIG_ENDIAN == 1 771 | 772 | uint8_t sigMotThres; /**< sig-motion threshold */ 773 | uint8_t sigEn :1; /**< 1 - enable sig, 0 - disable sig & enable anymotion */ 774 | uint8_t sigDataSrc :1; /**< data source 0- filter & 1 pre-filter*/ 775 | uint8_t sigMotProof : 2;/**< proof time of sig-motion interrupt */ 776 | uint8_t sigMotSkip : 2; /**< skip time of sig-motion interrupt */ 777 | #endif 778 | }; 779 | 780 | struct bmi160AccStepDetectIntCfg { 781 | #if LITTLE_ENDIAN == 1 782 | uint16_t stepDetectorEn :1; /**< 1- step detector enable, 0- step detector disable */ 783 | uint16_t minThreshold :2; /**< minimum threshold */ 784 | uint16_t steptimeMin :3; /**< minimal detectable step time */ 785 | uint16_t stepDetectorMode :2;/**< enable step counter mode setting */ 786 | uint16_t stepMinBuf :3; /**< minimum step buffer size*/ 787 | #elif BIG_ENDIAN == 1 788 | uint16_t stepMinBuf :3; /**< minimum step buffer size*/ 789 | uint16_t stepDetectorMode : 2;/**< enable step counter mode setting */ 790 | uint16_t steptimeMin : 3; /**< minimal detectable step time */ 791 | uint16_t minThreshold : 2; /**< minimum threshold */ 792 | uint16_t stepDetectorEn :1; /**< 1- step detector enable, 0- step detector disable */ 793 | #endif 794 | }; 795 | 796 | struct bmi160AccNoMotionIntCfg { 797 | #if LITTLE_ENDIAN == 1 798 | uint16_t noMotionX :1; /**< no motion interrupt x */ 799 | uint16_t noMotionY :1; /**< no motion interrupt y */ 800 | uint16_t noMotionZ :1; /**< no motion interrupt z */ 801 | uint16_t noMotionDur :6;/**< no motion duration */ 802 | uint16_t noMotionSel :1;/**< no motion sel , 1 - enable no-motion ,0- enable slow-motion */ 803 | uint16_t noMotionSrc :1;/**< data source 0- filter & 1 pre-filter*/ 804 | uint8_t noMotionThres; /**< no motion threshold */ 805 | #elif BIG_ENDIAN == 1 806 | uint8_t noMotionThres; /**< no motion threshold */ 807 | uint16_t noMotionSrc :1; /**< data source 0- filter & 1 pre-filter*/ 808 | uint16_t noMotionSel : 1;/**< no motion sel , 1 - enable no-motion ,0- enable slow-motion */ 809 | uint16_t noMotionDur : 6;/**< no motion duration */ 810 | uint16_t noMotionZ :1; /**< no motion interrupt z */ 811 | uint16_t noMotionY :1; /**< no motion interrupt y */ 812 | uint16_t noMotionX :1; /**< no motion interrupt x */ 813 | #endif 814 | }; 815 | 816 | struct bmi160AccOrientIntCfg { 817 | #if LITTLE_ENDIAN == 1 818 | uint16_t orientMode :2; /**< thresholds for switching between the different orientations */ 819 | uint16_t orientBlocking :2;/**< blocking_mode */ 820 | uint16_t orientHyst :4; /**< Orientation interrupt hysteresis */ 821 | uint16_t orientTheta :6; /**< Orientation interrupt theta */ 822 | uint16_t orientUdEn :1; /**< Enable/disable Orientation interrupt */ 823 | uint16_t axesEx :1; /**< exchange x- and z-axis in algorithm ,0 - z, 1 - x */ 824 | uint8_t orientEn :1; /**< 1 - orient enable, 0 - orient disable */ 825 | #elif BIG_ENDIAN == 1 826 | uint8_t orientEn :1; /**< 1 - orient enable, 0 - orient disable */ 827 | uint16_t axesEx : 1; /**< exchange x- and z-axis in algorithm ,0 - z, 1 - x */ 828 | uint16_t orientUdEn : 1; /**< Enable/disable Orientation interrupt */ 829 | uint16_t orientTheta : 6; /**< Orientation interrupt theta */ 830 | uint16_t orientHyst : 4; /**< Orientation interrupt hysteresis */ 831 | uint16_t orientBlocking : 2;/**< blocking_mode */ 832 | uint16_t orientMode : 2; /**< thresholds for switching between the different orientations */ 833 | #endif 834 | }; 835 | 836 | struct bmi160AccFlatDetectIntCfg { 837 | #if LITTLE_ENDIAN == 1 838 | 839 | uint16_t flatTheta :6; /**< flat threshold */ 840 | uint16_t flatHy :3; /**< flat interrupt hysteresis */ 841 | uint16_t flatHoldTime :2; /**< delay time for which the flat value must remain stable for the flat interrupt to be generated */ 842 | uint16_t flatEn :1; /**< 1 - flat enable, 0 - flat disable */ 843 | #elif BIG_ENDIAN == 1 844 | uint16_t flatEn :1; /**< 1 - flat enable, 0 - flat disable */ 845 | uint16_t flatHoldTime : 2; /**< delay time for which the flat value must remain stable for the flat interrupt to be generated */ 846 | uint16_t flatHy : 3; /**< flat interrupt hysteresis */ 847 | uint16_t flatTheta : 6; /**< flat threshold */ 848 | #endif 849 | }; 850 | 851 | struct bmi160AccLowGIntCfg { 852 | #if LITTLE_ENDIAN == 1 853 | uint8_t lowDur; /**< low-g interrupt trigger delay */ 854 | uint8_t lowThres; /**< low-g interrupt trigger threshold */ 855 | uint8_t lowHyst :2; /**< hysteresis of low-g interrupt */ 856 | uint8_t lowMode :1; /**< 0 - single-axis mode ,1 - axis-summing mode */ 857 | uint8_t lowDataSrc :1;/**< data source 0- filter & 1 pre-filter */ 858 | uint8_t lowEn :1; /**< 1 - enable low-g, 0 - disable low-g */ 859 | #elif BIG_ENDIAN == 1 860 | uint8_t lowEn :1; /**< 1 - enable low-g, 0 - disable low-g */ 861 | uint8_t lowDataSrc :1;/**< data source 0- filter & 1 pre-filter */ 862 | uint8_t lowMode : 1; /**< 0 - single-axis mode ,1 - axis-summing mode */ 863 | uint8_t lowHyst : 2; /**< hysteresis of low-g interrupt */ 864 | uint8_t lowThres; /**< low-g interrupt trigger threshold */ 865 | uint8_t lowDur; /**< low-g interrupt trigger delay */ 866 | #endif 867 | }; 868 | 869 | struct bmi160AccHighGIntCfg { 870 | #if LITTLE_ENDIAN == 1 871 | 872 | uint8_t high_g_x :1; /**< High-g interrupt x, 1 - enable, 0 - disable */ 873 | uint8_t high_g_y :1; /**< High-g interrupt y, 1 - enable, 0 - disable */ 874 | uint8_t high_g_z :1; /**< High-g interrupt z, 1 - enable, 0 - disable */ 875 | uint8_t highHy :2; /**< High-g hysteresis */ 876 | uint8_t highDataSrc :1; /**< data source 0- filter & 1 pre-filter */ 877 | uint8_t highThres; /**< High-g threshold */ 878 | uint8_t highDur; /**< High-g duration */ 879 | #elif BIG_ENDIAN == 1 880 | uint8_t highDur; /**< High-g duration */ 881 | uint8_t highThres; /**< High-g threshold */ 882 | uint8_t highDataSrc :1;/**< data source 0- filter & 1 pre-filter */ 883 | uint8_t highHy : 2; /**< High-g hysteresis */ 884 | uint8_t high_g_z : 1; /**< High-g interrupt z, 1 - enable, 0 - disable */ 885 | uint8_t high_g_y : 1; /**< High-g interrupt y, 1 - enable, 0 - disable */ 886 | uint8_t high_g_x : 1; /**< High-g interrupt x, 1 - enable, 0 - disable */ 887 | #endif 888 | }; 889 | 890 | union bmi160IntTypeCfg { 891 | struct bmi160AccTapIntCfg accTapInt; /**< Tap interrupt structure */ 892 | struct bmi160AccAnyMotIntCfg accAnyMotionInt; /**< Slope interrupt structure */ 893 | struct bmi160AccSigMotIntCfg accSigMotionInt; /**< Significant motion interrupt structure */ 894 | struct bmi160AccStepDetectIntCfg accStepDetectInt; /**< Step detector interrupt structure */ 895 | struct bmi160AccNoMotionIntCfg accNoMotionInt; /**< No motion interrupt structure */ 896 | struct bmi160AccOrientIntCfg accOrientInt; /**< Orientation interrupt structure */ 897 | struct bmi160AccFlatDetectIntCfg accFlatInt; /**< Flat interrupt structure */ 898 | struct bmi160AccLowGIntCfg accLowGInt; /**< Low-g interrupt structure */ 899 | struct bmi160AccHighGIntCfg accHighGInt; /**< High-g interrupt structure */ 900 | }; 901 | 902 | struct bmi160IntSettg { 903 | enum bmi160IntChannel intChannel; /**< Interrupt channel */ 904 | enum bmi160IntTypes intType; /**< Select Interrupt */ 905 | struct bmi160IntPinSettg intPinSettg;/**< Structure configuring Interrupt pins */ 906 | union bmi160IntTypeCfg intTypeCfg; /**< Union configures required interrupt */ 907 | uint8_t fifoFullIntEn :1; /**< FIFO FULL INT 1-enable, 0-disable */ 908 | uint8_t fifoWTMIntEn :1; /**< FIFO WTM INT 1-enable, 0-disable */ 909 | }; 910 | 911 | enum bmi160StepDetectMode { 912 | BMI160_STEP_DETECT_NORMAL, 913 | BMI160_STEP_DETECT_SENSITIVE, 914 | BMI160_STEP_DETECT_ROBUST, 915 | BMI160_STEP_DETECT_USER_DEFINE /**< Non recommended User defined setting */ 916 | }; 917 | 918 | class DFRobot_BMI160{ 919 | public: 920 | DFRobot_BMI160(); 921 | 922 | /** 923 | * @fn I2cInit 924 | * @brief set the i2c addr and init the i2c. 925 | * @param i2c_addr bmi160 i2c addr 926 | * @n 0x68: connect SDIO pin of the BMI160 to GND which means the default I2C address 927 | * @n 0x69: set I2C address by parameter 928 | * @return BMI160_OK(0) means success 929 | */ 930 | int8_t I2cInit(int8_t i2c_addr = BMI160_I2C_ADDR); 931 | 932 | /** 933 | * @fn getSensorData 934 | * @brief select mode and save returned data to parameter data. 935 | * @param type three type 936 | * @n onlyAccel : only get the accel data 937 | * @n onlyGyro : only get the gyro data 938 | * @n bothAccelGyro: get boath accel and gyro data 939 | * @param data save returned data to parameter data 940 | * @return BMI160_OK(0) means succse 941 | */ 942 | int8_t getSensorData(uint8_t type,int16_t* data); 943 | 944 | /** 945 | * @fn getAccelData 946 | * @brief get the accel data 947 | * @param data pointer to store the accel data 948 | * @return BMI160_OK(0) means succse 949 | */ 950 | int8_t getAccelData(int16_t* data); 951 | 952 | /** 953 | * @fn getAccelData 954 | * @brief get the accel data 955 | * @param data pointer to store the accel data 956 | * @param timestamp pointer to store the timestamp for accel 957 | * @return BMI160_OK(0) means succse 958 | */ 959 | int8_t getAccelData(int16_t* data, uint32_t* timestamp); 960 | 961 | /** 962 | * @fn getGyroData 963 | * @brief get the gyro data 964 | * @param data pointer to store the gyro data 965 | * @return BMI160_OK(0) means succse 966 | */ 967 | int8_t getGyroData(int16_t* data); 968 | 969 | /** 970 | * @fn getGyroData 971 | * @brief get the gyro data 972 | * @param data pointer to store the gyro data 973 | * @param timestamp pointer to store the timestamp for gryo 974 | * @return BMI160_OK(0) means succse 975 | */ 976 | int8_t getGyroData(int16_t* data, uint32_t* timestamp); 977 | 978 | /** 979 | * @fn getAccelGyroData 980 | * @brief get the accel and gyro data 981 | * @param data pointer to store the accel and gyro data 982 | * @return BMI160_OK(0) means succse 983 | */ 984 | int8_t getAccelGyroData(int16_t* data); 985 | 986 | /** 987 | * @fn getAccelGyroData 988 | * @brief get the accel and gyro data 989 | * @param data pointer to store the accel and gyro data 990 | * @param timestamp pointer to store the timestamp for accel and gyro 991 | * @return BMI160_OK(0) means succse 992 | */ 993 | int8_t getAccelGyroData(int16_t* data, uint32_t* timestamp); 994 | 995 | /** 996 | * @fn softReset 997 | * @brief reset bmi160 hardware 998 | * @return BMI160_OK(0) means success 999 | */ 1000 | int8_t softReset(); 1001 | 1002 | /** 1003 | * @fn setInt 1004 | * @brief set interrupt number and choosing step detector interrupt 1005 | * @param intNum choose int1 or int2 1006 | * @return BMI160_OK(0) means succse 1007 | */ 1008 | int8_t setInt(int intNum); 1009 | 1010 | /** 1011 | * @fn setStepCounter 1012 | * @brief enable the step counter 1013 | * @return BMI160_OK(0) means succse 1014 | */ 1015 | int8_t setStepCounter(); 1016 | 1017 | /** 1018 | * @fn readStepCounter 1019 | * @brief read the step counter from bmi160 1020 | * @param stepVal pointer to store the step 1021 | * @return BMI160_OK(0) measn succse 1022 | */ 1023 | int8_t readStepCounter(uint16_t *stepVal); 1024 | /** 1025 | * @fn setStepPowerMode 1026 | * @brief set the step power model 1027 | * @param model type of model 1028 | * @return BMI160_OK(0) measn succse 1029 | */ 1030 | int8_t setStepPowerMode(uint8_t model); 1031 | 1032 | 1033 | uint8_t onlyAccel=1; 1034 | uint8_t onlyGyro=2; 1035 | uint8_t bothAccelGyro=3; 1036 | uint8_t stepNormalPowerMode=0; 1037 | uint8_t stepLowPowerMode=1; 1038 | 1039 | private: 1040 | int8_t I2cInit(struct bmi160Dev *dev); 1041 | int8_t SPIInit(); 1042 | int8_t SPIInit(struct bmi160Dev *dev); 1043 | 1044 | int8_t softReset(struct bmi160Dev *dev); 1045 | void defaultParamSettg(struct bmi160Dev *dev); 1046 | 1047 | int8_t setSensConf(); 1048 | int8_t setSensConf(struct bmi160Dev *dev); 1049 | 1050 | int8_t setAccelConf(struct bmi160Dev *dev); 1051 | int8_t checkAccelConfig(uint8_t *data, struct bmi160Dev *dev); 1052 | int8_t processAccelOdr(uint8_t *data, struct bmi160Dev *dev); 1053 | int8_t processAccelBw(uint8_t *data, struct bmi160Dev *dev); 1054 | int8_t processAccelRange(uint8_t *data, struct bmi160Dev *dev); 1055 | 1056 | int8_t setGyroConf(struct bmi160Dev *dev); 1057 | int8_t checkGyroConfig(uint8_t *data, struct bmi160Dev *dev); 1058 | int8_t processGyroOdr(uint8_t *data, struct bmi160Dev *dev); 1059 | int8_t processGyroBw(uint8_t *data, struct bmi160Dev *dev); 1060 | int8_t processGyroRange(uint8_t *data, struct bmi160Dev *dev); 1061 | 1062 | int8_t setPowerMode(struct bmi160Dev *dev); 1063 | int8_t setAccelPwr(struct bmi160Dev *dev); 1064 | int8_t processUnderSampling(uint8_t *data, struct bmi160Dev *dev); 1065 | int8_t setGyroPwr(struct bmi160Dev *dev); 1066 | 1067 | int8_t checkInvalidSettg( struct bmi160Dev *dev); 1068 | 1069 | int8_t getSensorData(uint8_t select_sensor, struct bmi160SensorData *accel, struct bmi160SensorData *gyro,struct bmi160Dev *dev); 1070 | int8_t getAccelData(uint8_t len, struct bmi160SensorData *accel, struct bmi160Dev *dev); 1071 | int8_t getGyroData(uint8_t len, struct bmi160SensorData *gyro, struct bmi160Dev *dev); 1072 | int8_t getAccelGyroData(uint8_t len, struct bmi160SensorData *accel, struct bmi160SensorData *gyro, struct bmi160Dev *dev); 1073 | 1074 | int8_t getRegs(uint8_t reg_addr, uint8_t * data, uint16_t len, struct bmi160Dev *dev); 1075 | int8_t setRegs(uint8_t reg_addr, uint8_t * data, uint16_t len, struct bmi160Dev *dev); 1076 | 1077 | int8_t I2cGetRegs(struct bmi160Dev *dev, uint8_t reg_addr, uint8_t *data, uint16_t len); 1078 | int8_t I2cSetRegs(struct bmi160Dev *dev, uint8_t reg_addr, uint8_t *data, uint16_t len); 1079 | 1080 | int8_t SPIGetRegs(struct bmi160Dev *dev, uint8_t reg_addr, uint8_t *data, uint16_t len); 1081 | int8_t SPISetRegs(struct bmi160Dev *dev, uint8_t reg_addr, uint8_t *data, uint16_t len); 1082 | 1083 | 1084 | int8_t setInt(struct bmi160Dev *dev, int intNum); 1085 | int8_t setIntConfig(struct bmi160IntSettg *intConfig, struct bmi160Dev *dev); 1086 | int8_t setAccelStepDetectInt(struct bmi160IntSettg *intConfig, struct bmi160Dev *dev); 1087 | int8_t enableStepDetectInt(struct bmi160AccStepDetectIntCfg *stepDetectIntCfg, struct bmi160Dev *dev); 1088 | int8_t setIntrPinConfig(struct bmi160IntSettg *intConfig, struct bmi160Dev *dev); 1089 | int8_t configIntOutCtrl(struct bmi160IntSettg *intConfig, struct bmi160Dev *dev); 1090 | int8_t configIntLatch(struct bmi160IntSettg *intConfig, struct bmi160Dev *dev); 1091 | int8_t mapFeatureInterrupt(struct bmi160IntSettg *intConfig, struct bmi160Dev *dev); 1092 | int8_t configStepDetect(struct bmi160AccStepDetectIntCfg *stepDetectIntCfg, struct bmi160Dev *dev); 1093 | 1094 | int8_t setStepCounter(uint8_t step_cnt_enable, struct bmi160Dev *dev); 1095 | int8_t setStepPowerMode(uint8_t model,struct bmi160Dev *dev); 1096 | int8_t readStepCounter(uint16_t *stepVal, struct bmi160Dev *dev); 1097 | 1098 | 1099 | struct bmi160Dev* Obmi160; 1100 | struct bmi160SensorData* Oaccel; 1101 | struct bmi160SensorData* Ogyro; 1102 | }; 1103 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2010 DFRobot Co.Ltd 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DFRobot_BMI160 2 | 3 | * [中文](./README_CN.md) 4 | 5 | The BMI160 is a highly integrated, low power inertial measurement unit (IMU) that provides precise acceleration and angular rate (gyroscopic) measurement.
6 | The BMI160 contains 16 bit digtial,triaxial accelerometer and 16 bit digital, triaxial gyroscope.
7 | This example is for BMI160 sensor and it oprated via Arduino I2C.
8 | 9 | ![产品效果图](./resources/images/SEN0250.png) 10 | 11 | ## Product Link([https://www.dfrobot.com/product-1716.html](https://www.dfrobot.com/product-1716.html)) 12 | SKU: SEN0250 13 | 14 | ## Table of Contents 15 | 16 | * [Summary](#summary) 17 | * [Installation](#installation) 18 | * [Methods](#methods) 19 | * [Compatibility](#compatibility) 20 | * [History](#history) 21 | * [Credits](#credits) 22 | 23 | ## Summary 24 | 25 | Provide an Arduino library to control the bmi160 to get accel, gyro and step counter, via I2C communication. 26 | 27 | ## Installation 28 | 29 | To use this library, first download the library file, paste it into the \Arduino\libraries directory, then open the examples folder and run the demo in the folder. 30 | 31 | ## Methods 32 | 33 | ```C++ 34 | 35 | /** 36 | * @fn I2cInit 37 | * @brief set the i2c addr and init the i2c. 38 | * @param i2c_addr bmi160 i2c addr 39 | * @n 0x68: connect SDIO pin of the BMI160 to GND which means the default I2C address 40 | * @n 0x69: set I2C address by parameter 41 | * @return BMI160_OK(0) means success 42 | */ 43 | int8_t I2cInit(int8_t i2c_addr = BMI160_I2C_ADDR); 44 | 45 | /** 46 | * @fn getSensorData 47 | * @brief select mode and save returned data to parameter data. 48 | * @param type three type 49 | * @n onlyAccel : only get the accel data 50 | * @n onlyGyro : only get the gyro data 51 | * @n bothAccelGyro: get boath accel and gyro data 52 | * @param data save returned data to parameter data 53 | * @return BMI160_OK(0) means succse 54 | */ 55 | int8_t getSensorData(uint8_t type,int16_t* data); 56 | 57 | /** 58 | * @fn getAccelData 59 | * @brief get the accel data 60 | * @param data pointer to store the accel data 61 | * @return BMI160_OK(0) means succse 62 | */ 63 | int8_t getAccelData(int16_t* data); 64 | 65 | /** 66 | * @fn getGyroData 67 | * @brief get the gyro data 68 | * @param data pointer to store the gyro data 69 | * @return BMI160_OK(0) means succse 70 | */ 71 | int8_t getGyroData(int16_t* data); 72 | 73 | /** 74 | * @fn getAccelGyroData 75 | * @brief get the accel and gyro data 76 | * @param data pointer to store the accel and gyro data 77 | * @return BMI160_OK(0) means succse 78 | */ 79 | int8_t getAccelGyroData(int16_t* data); 80 | 81 | /** 82 | * @fn softReset 83 | * @brief reset bmi160 hardware 84 | * @return BMI160_OK(0) means success 85 | */ 86 | int8_t softReset(); 87 | 88 | /** 89 | * @fn setInt 90 | * @brief set interrupt number and choosing step detector interrupt 91 | * @param intNum choose int1 or int2 92 | * @return BMI160_OK(0) means succse 93 | */ 94 | int8_t setInt(int intNum); 95 | 96 | /** 97 | * @fn setStepCounter 98 | * @brief enable the step counter 99 | * @return BMI160_OK(0) means succse 100 | */ 101 | int8_t setStepCounter(); 102 | 103 | /** 104 | * @fn readStepCounter 105 | * @brief read the step counter from bmi160 106 | * @param stepVal pointer to store the step 107 | * @return BMI160_OK(0) measn succse 108 | */ 109 | int8_t readStepCounter(uint16_t *stepVal); 110 | /** 111 | * @fn setStepPowerMode 112 | * @brief set the step power model 113 | * @param model type of model 114 | * @return BMI160_OK(0) measn succse 115 | */ 116 | int8_t setStepPowerMode(uint8_t model); 117 | 118 | ``` 119 | 120 | ## Compatibility 121 | 122 | MCU | Work Well | Work Wrong | Untested | Remarks 123 | ------------------ | :----------: | :----------: | :---------: | ----- 124 | FireBeetle-ESP32 | √ | | | 125 | FireBeetle-ESP8266 | √ | | | 126 | Arduino uno | √ | | | 127 | 128 | 129 | ## History 130 | 131 | - 2017-12-01 - Version 1.0.0 released. 132 | 133 | 134 | ## Credits 135 | 136 | Written by DFRobot_haoJ(hao.jiang@dfrobot.com), 2017. (Welcome to our [website](https://www.dfrobot.com/)) 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | # DFRobot_BMI160 2 | 3 | * [English Version](./README.md) 4 | 5 | BMI160 是一种高度集成的低功耗惯性测量单元 (IMU),可提供精确的加速度和角速率(陀螺仪)测量。
6 | BMI160 包含 16 位数字三轴加速度计和 16 位数字三轴陀螺仪。
7 | 此示例适用于 BMI160 传感器,它通过 Arduino I2C 进行操作。
8 | 9 | ![产品效果图](./resources/images/SEN0250.png) 10 | 11 | 12 | ## 产品链接([https://www.dfrobot.com.cn/goods-1693.html](https://www.dfrobot.com.cn/goods-1693.html)) 13 | SKU: SEN0250 14 | 15 | ## 目录 16 | 17 | * [概述](#概述) 18 | * [库安装](#库安装) 19 | * [方法](#方法) 20 | * [兼容性](#兼容性) 21 | * [历史](#历史) 22 | * [创作者](#创作者) 23 | 24 | ## 概述 25 | 提供 Arduino 库,通过 I2C 通信控制 bmi160 获取 加速度、陀螺仪和计步器数据。
26 | 27 | ## 库安装 28 | 29 | 使用此库前,请首先下载库文件,将其粘贴到\Arduino\libraries目录中,然后打开examples文件夹并在该文件夹中运行演示。 30 | 31 | ## 方法 32 | 33 | ```C++ 34 | /** 35 | * @fn I2cInit 36 | * @brief 设置I2C地址,并初始化 37 | * @param i2c_addr bmi160 I2C地址 38 | * @n 0x68: 传感器SDIO拉低时,IIC地址为0x68 39 | * @n 0x69: 传感器SDIO引脚拉高时,IIC地址为0x69 40 | * @return BMI160_OK(0) 返回成功 41 | */ 42 | int8_t I2cInit(int8_t i2c_addr = BMI160_I2C_ADDR); 43 | 44 | /** 45 | * @brief 设置获取数据的类型,并保存获取的数据 46 | * @param type 3种类型 47 | * @n onlyAccel : 只获取加速度数据 48 | * @n onlyGyro : 只获取陀螺仪数据 49 | * @n bothAccelGyro: 既获取加速度数据,又获取陀螺仪数据 50 | * @param data 指向保存获取的数据的缓存 51 | * @return BMI160_OK(0) 获取成功 52 | */ 53 | int8_t getSensorData(uint8_t type,int16_t* data); 54 | 55 | /** 56 | * @fn getAccelData 57 | * @brief 获取加速度数据 58 | * @param data 指向存储加速度数据的缓存的指针 59 | * @return BMI160_OK(0) 获取成功 60 | */ 61 | int8_t getAccelData(int16_t* data); 62 | 63 | /** 64 | * @fn getGyroData 65 | * @brief 获取陀螺仪数据 66 | * @param data 指向存储陀螺仪数据缓存的指针 67 | * @return BMI160_OK(0) 获取成功 68 | */ 69 | int8_t getGyroData(int16_t* data); 70 | 71 | /** 72 | * @fn getAccelGyroData 73 | * @brief 获取加速度陀螺仪数据 74 | * @param data 指向存储加速度陀螺仪数据缓存的指针 75 | * @return BMI160_OK(0) 获取成功 76 | */ 77 | int8_t getAccelGyroData(int16_t* data); 78 | 79 | /** 80 | * @fn softReset 81 | * @brief 软件复位BMI160传感器 82 | * @return BMI160_OK(0) 复位成功 83 | */ 84 | int8_t softReset(); 85 | 86 | /** 87 | * @fn setInt 88 | * @brief 设置中断引脚 89 | * @param intNum 选择中断引脚号 90 | * @return BMI160_OK(0) 设置成功 91 | */ 92 | int8_t setInt(int intNum); 93 | 94 | /** 95 | * @fn setStepCounter 96 | * @brief 使能计步 97 | * @return BMI160_OK(0) 成功 98 | */ 99 | int8_t setStepCounter(); 100 | 101 | /** 102 | * @fn readStepCounter 103 | * @brief 读取计步数据 104 | * @param stepVal 指向存储计步数据缓存的指针 105 | * @return BMI160_OK(0) 读取成功 106 | */ 107 | int8_t readStepCounter(uint16_t *stepVal); 108 | /** 109 | * @fn setStepPowerMode 110 | * @brief 设置步进功率模型 111 | * @param model 模型类型 112 | * @return BMI160_OK(0) 设置成功 113 | */ 114 | int8_t setStepPowerMode(uint8_t model); 115 | ``` 116 | 117 | ## 兼容性 118 | 119 | MCU | Work Well | Work Wrong | Untested | Remarks 120 | ------------------ | :----------: | :----------: | :---------: | ----- 121 | FireBeetle-ESP32 | √ | | | 122 | FireBeetle-ESP8266 | √ | | | 123 | Arduino uno | √ | | | 124 | 125 | ## 历史 126 | 127 | - 2017-12-01 - 1.0.0 版本 128 | 129 | ## 创作者 130 | 131 | Written by DFRobot_haoJ(hao.jiang@dfrobot.com), 2017. (Welcome to our [website](https://www.dfrobot.com/)) 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /examples/accelGyro/accelGyro.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file accelGyro.ino 3 | * @brief I2C addr: 4 | * @n 0x68: connect SDIO pin of the BMI160 to GND which means the default I2C address 5 | * @n 0x69: set I2C address by parameter 6 | * @n Through the example, you can get the sensor data by using getSensorData: 7 | * @n get acell by paremeter onlyAccel; 8 | * @n get gyro by paremeter onlyGyro; 9 | * @n get both acell and gyro by paremeter bothAccelGyro. 10 | * @n With the rotation of the sensor, data changes are visible. 11 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 12 | * @license The MIT License (MIT) 13 | * @author DFRobot_haoJ(hao.jiang@dfrobot.com) 14 | * @version V1.0 15 | * @date 2017-12-01 16 | * @url https://github.com/DFRobot/DFRobot_BMI160 17 | */ 18 | 19 | #include 20 | 21 | DFRobot_BMI160 bmi160; 22 | const int8_t i2c_addr = 0x69; 23 | void setup(){ 24 | Serial.begin(115200); 25 | delay(100); 26 | 27 | //init the hardware bmin160 28 | if (bmi160.softReset() != BMI160_OK){ 29 | Serial.println("reset false"); 30 | while(1); 31 | } 32 | 33 | //set and init the bmi160 i2c address 34 | if (bmi160.I2cInit(i2c_addr) != BMI160_OK){ 35 | Serial.println("init false"); 36 | while(1); 37 | } 38 | } 39 | 40 | void loop(){ 41 | int i = 0; 42 | int rslt; 43 | int16_t accelGyro[6]={0}; 44 | 45 | //get both accel and gyro data from bmi160 46 | //parameter accelGyro is the pointer to store the data 47 | rslt = bmi160.getAccelGyroData(accelGyro); 48 | if(rslt == 0){ 49 | for(i=0;i<6;i++){ 50 | if (i<3){ 51 | //the first three are gyro data 52 | Serial.print(accelGyro[i]*3.14/180.0);Serial.print("\t"); 53 | }else{ 54 | //the following three data are accel data 55 | Serial.print(accelGyro[i]/16384.0);Serial.print("\t"); 56 | } 57 | } 58 | Serial.println(); 59 | }else{ 60 | Serial.println("err"); 61 | } 62 | delay(100); 63 | /* 64 | * //only read accel data from bmi160 65 | * int16_t onlyAccel[3]={0}; 66 | * bmi160.getAccelData(onlyAccel); 67 | */ 68 | 69 | /* 70 | * ////only read gyro data from bmi160 71 | * int16_t onlyGyro[3]={0}; 72 | * bmi160.getGyroData(onlyGyro); 73 | */ 74 | } 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /examples/stepCounterLowPower/stepCounterLowPower.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file stepCounterLowPower.ino 3 | * @brief I2C addr: 4 | * @n 0x68: connect SDIO pin of the BMI160 to GND which means the default I2C address 5 | * @n 0x69: set I2C address by parameter 6 | * @n Through the example, you can get the sensor data which means step counter. Set step counter power mode by setStepPowerMode(stepNormalPowerMode means normal 7 | * @n model, stepLowPowerMode means low power model). Upload interrupt number by setInt (choose int1 or int2) data from int1 and int2 read in readStepCounter 8 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 9 | * @license The MIT License (MIT) 10 | * @author DFRobot_haoJ(hao.jiang@dfrobot.com) 11 | * @version V1.0 12 | * @date 2017-12-01 13 | * @url https://github.com/DFRobot/DFRobot_BMI160 14 | */ 15 | 16 | #include 17 | 18 | DFRobot_BMI160 bmi160; 19 | const int8_t i2c_addr = 0x69; 20 | bool readStep = false; 21 | 22 | #if defined ARDUINO_AVR_UNO || defined ARDUINO_AVR_MEGA2560 || defined ARDUINO_AVR_PRO 23 | //interrupt number of uno and mega2560 is 0 24 | int pbIn = 2; 25 | #elif ARDUINO_AVR_LEONARDO 26 | //interrupt number of uno and leonardo is 0 27 | int pbIn = 3; 28 | #else 29 | int pbIn = 13; 30 | #endif 31 | /*the bmi160 have two interrput interfaces*/ 32 | int int1 = 1; 33 | int int2 = 2; 34 | 35 | void stepChange() 36 | { 37 | //once the step conter is changed, the value can be read 38 | readStep = true; 39 | } 40 | 41 | void setup(){ 42 | Serial.begin(115200); 43 | delay(100); 44 | 45 | //set and init the bmi160 i2c address 46 | while (bmi160.I2cInit(i2c_addr) != BMI160_OK){ 47 | Serial.println("i2c init fail"); 48 | delay(1000); 49 | } 50 | 51 | //set interrput number to int1 or int2 52 | if (bmi160.setInt(int2) != BMI160_OK){ 53 | Serial.println("set interrput fail"); 54 | while(1); 55 | } 56 | 57 | //set the bmi160 mode to step counter 58 | if (bmi160.setStepCounter() != BMI160_OK){ 59 | Serial.println("set step fail"); 60 | while(1); 61 | } 62 | 63 | //set the bmi160 power model, contains:stepNormalPowerMode,stepLowPowerMode 64 | if (bmi160.setStepPowerMode(bmi160.stepLowPowerMode) != BMI160_OK){ 65 | Serial.println("set setStepPowerMode fail"); 66 | while(1); 67 | } 68 | 69 | #if defined ARDUINO_AVR_UNO || defined ARDUINO_AVR_MEGA2560 || defined ARDUINO_AVR_LEONARDO || defined ARDUINO_AVR_PRO 70 | //set the pin in the board to connect to int1 or int2 of bmi160 71 | attachInterrupt(digitalPinToInterrupt(pbIn), stepChange, FALLING); 72 | #else 73 | attachInterrupt(pbIn, stepChange, FALLING); 74 | #endif 75 | 76 | Serial.println(pbIn); 77 | } 78 | 79 | void loop(){ 80 | if (readStep){ 81 | uint16_t stepCounter = 0; 82 | //read step counter from hardware bmi160 83 | if (bmi160.readStepCounter(&stepCounter)==BMI160_OK){ 84 | Serial.print("step counter = ");Serial.println(stepCounter); 85 | } 86 | readStep = false; 87 | } 88 | } 89 | 90 | 91 | -------------------------------------------------------------------------------- /examples/stepCounterNormal/stepCounterNormal.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file stepCounterNormal.ino 3 | * @brief I2C addr: 4 | * @n 0x68: connect SDIO pin of the BMI160 to GND which means the default I2C address 5 | * @n 0x69: set I2C address by parameter 6 | * @n Through the example, you can get the sensor data which means step counter. Set step counter power mode by setStepPowerMode(stepNormalPowerMode means normal 7 | * @n mode, stepLowPowerMode means low power model) upload interrupt number by setInt (choose int1 or int2) data from int1 and int2 read in readStepCounter 8 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 9 | * @license The MIT License (MIT) 10 | * @author DFRobot_haoJ(hao.jiang@dfrobot.com) 11 | * @version V1.0 12 | * @date 2017-12-01 13 | * @url https://github.com/DFRobot/DFRobot_BMI160 14 | */ 15 | 16 | #include 17 | 18 | DFRobot_BMI160 bmi160; 19 | const int8_t i2c_addr = 0x69; 20 | bool readStep = false; 21 | 22 | #if defined ARDUINO_AVR_UNO || defined ARDUINO_AVR_MEGA2560 || defined ARDUINO_AVR_PRO 23 | //interrupt number of uno and mega2560 is 0 24 | int pbIn = 2; 25 | #elif ARDUINO_AVR_LEONARDO 26 | //interrupt number of uno and leonardo is 0 27 | int pbIn = 3; 28 | #else 29 | int pbIn = 13; 30 | #endif 31 | /*the bmi160 have two interrput interfaces*/ 32 | int int1 = 1; 33 | int int2 = 2; 34 | 35 | void stepChange() 36 | { 37 | //once the step conter is changed, the value can be read 38 | readStep = true; 39 | } 40 | 41 | void setup(){ 42 | Serial.begin(115200); 43 | delay(100); 44 | 45 | //set and init the bmi160 i2c address 46 | while (bmi160.I2cInit(i2c_addr) != BMI160_OK){ 47 | Serial.println("i2c init fail"); 48 | delay(1000); 49 | } 50 | 51 | //set interrput number to int1 or int2 52 | if (bmi160.setInt(int2) != BMI160_OK){ 53 | Serial.println("set interrput fail"); 54 | while(1); 55 | } 56 | 57 | //set the bmi160 mode to step counter 58 | if (bmi160.setStepCounter() != BMI160_OK){ 59 | Serial.println("set step fail"); 60 | while(1); 61 | } 62 | 63 | //set the bmi160 power model, contains:stepNormalPowerMode,stepLowPowerMode 64 | if (bmi160.setStepPowerMode(bmi160.stepNormalPowerMode) != BMI160_OK){ 65 | Serial.println("set setStepPowerMode fail"); 66 | while(1); 67 | } 68 | 69 | #if defined ARDUINO_AVR_UNO || defined ARDUINO_AVR_MEGA2560 || defined ARDUINO_AVR_LEONARDO || defined ARDUINO_AVR_PRO 70 | //set the pin in the board to connect to int1 or int2 of bmi160 71 | attachInterrupt(digitalPinToInterrupt(pbIn), stepChange, FALLING); 72 | #else 73 | attachInterrupt(pbIn, stepChange, FALLING); 74 | #endif 75 | 76 | Serial.println(pbIn); 77 | } 78 | 79 | void loop(){ 80 | if (readStep){ 81 | uint16_t stepCounter = 0; 82 | //read step counter from hardware bmi160 83 | if (bmi160.readStepCounter(&stepCounter)==BMI160_OK){ 84 | Serial.print("step counter = ");Serial.println(stepCounter); 85 | } 86 | readStep = false; 87 | } 88 | } 89 | 90 | 91 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring DFRobot_BMI160 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | DFRobot_BMI160 KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | I2cInit KEYWORD2 16 | getSensorData KEYWORD2 17 | softReset KEYWORD2 18 | setInt KEYWORD2 19 | setStepCounter KEYWORD2 20 | readStepCounter KEYWORD2 21 | setStepPowerMode KEYWORD2 22 | onlyAccel KEYWORD2 23 | onlyGyro KEYWORD2 24 | bothAccelGyro KEYWORD2 25 | stepNormalPowerMode KEYWORD2 26 | stepLowPowerMode KEYWORD2 27 | getAccelData KEYWORD2 28 | getGyroData KEYWORD2 29 | getAccelGyroData KEYWORD2 30 | 31 | 32 | ####################################### 33 | # Constants (LITERAL1) 34 | ####################################### 35 | 36 | BMI160_OK LITERAL1 37 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=DFRobot_BMI160 2 | version=1.0.0 3 | author=DFRobot 4 | maintainer=Arya DFRobot_haoJ 5 | sentence=DFRobot Standard library(SKU:SEN0250). 6 | paragraph=This is a 6-axis sensor library. 7 | category=Sensors 8 | url=https://github.com/DFRobot/DFRobot_BMI160 9 | architectures=* 10 | -------------------------------------------------------------------------------- /python/raspberrypi/DFRobot_BMI160.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | ''' 4 | @file DFRobot_BMI160.py 5 | @brief The BMI160 6-axis inertial motion sensor integrates accelerometer and gyroscope into one, and uses I2C communication. 6 | @n Features: 7 | @n 1. Accelerometer scale options: ±2g/±4g/±8g/±16g 8 | @n 2. Gyroscope scale options: ±125°/s, ±250°/s, ±500°/s, ±1000°/s, ±2000°/s 9 | @n 3. Accelerometer zero drift: ±40mg 10 | @n 4. Gyroscope zero drift: ±10°/s 11 | @n 5. I2C address is controlled by SDO: 12 | @n BMI160_IIC_ADDR_SDO_H or 0x69: SDO turns to high level (SDO default to be high) 13 | @n BMI160_IIC_ADDR_SDO_L or 0x68:SDO turns to low level 14 | @n 15 | @n Hardware conneted table in IIC 16 | @n -------------------------------------------------------------------------- 17 | @n Sensor | raspberry pi | 18 | @n -------------------------------------------------------------------------- 19 | @n + | 3V3/VCC | 20 | @n - | GND | 21 | @n C | connected to scl of MCU's IIC | 22 | @n D | connected to sda of MCU's IIC | 23 | @n INT1 | connected to the external interrupt IO pin of MCU | 24 | @n INT2 | connected to the external interrupt IO pin of MCU | 25 | @n SDO | connected to the IO pin of MCU or connected to GND or VCC | 26 | @n -------------------------------------------------------------------------- 27 | @ 28 | @Copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 29 | @licence The MIT License (MIT) 30 | @author [Arya](xue.peng@dfrobot.com) 31 | @version V1.0 32 | @date 2021-06-10 33 | @url from https://github.com/DFRobot/DFRobot_BMI160 34 | ''' 35 | import sys 36 | import smbus 37 | import time 38 | import RPi.GPIO as GPIO 39 | import spidev 40 | import numpy as np 41 | 42 | BMI160_IIC_ADDR_SDO_H = 0x69 43 | BMI160_IIC_ADDR_SDO_L = 0x68 44 | 45 | ''' Mask definitions ''' 46 | BMI160_ACCEL_BW_MASK = 0x70 47 | BMI160_ACCEL_ODR_MASK = 0x0F 48 | BMI160_ACCEL_UNDERSAMPLING_MASK = 0x80 49 | BMI160_ACCEL_RANGE_MASK = 0x0F 50 | BMI160_GYRO_BW_MASK = 0x30 51 | BMI160_GYRO_ODR_MASK = 0x0F 52 | BMI160_GYRO_RANGE_MSK = 0x07 53 | 54 | BMI160_ERR_REG_MASK = 0x0F 55 | 56 | ''' BMI160 Register map ''' 57 | BMI160_CHIP_ID_ADDR = 0x00 58 | BMI160_ERROR_REG_ADDR = 0x02 59 | BMI160_AUX_DATA_ADDR = 0x04 60 | BMI160_GYRO_DATA_ADDR = 0x0C 61 | BMI160_ACCEL_DATA_ADDR = 0x12 62 | BMI160_STATUS_ADDR = 0x1B 63 | BMI160_INT_STATUS_ADDR = 0x1C 64 | BMI160_FIFO_LENGTH_ADDR = 0x22 65 | BMI160_FIFO_DATA_ADDR = 0x24 66 | BMI160_ACCEL_CONFIG_ADDR = 0x40 67 | BMI160_ACCEL_RANGE_ADDR = 0x41 68 | BMI160_GYRO_CONFIG_ADDR = 0x42 69 | BMI160_GYRO_RANGE_ADDR = 0x43 70 | BMI160_AUX_ODR_ADDR = 0x44 71 | BMI160_FIFO_DOWN_ADDR = 0x45 72 | BMI160_FIFO_CONFIG_0_ADDR = 0x46 73 | BMI160_FIFO_CONFIG_1_ADDR = 0x47 74 | BMI160_AUX_IF_0_ADDR = 0x4B 75 | BMI160_AUX_IF_1_ADDR = 0x4C 76 | BMI160_AUX_IF_2_ADDR = 0x4D 77 | BMI160_AUX_IF_3_ADDR = 0x4E 78 | BMI160_AUX_IF_4_ADDR = 0x4F 79 | BMI160_INT_ENABLE_0_ADDR = 0x50 80 | BMI160_INT_ENABLE_1_ADDR = 0x51 81 | BMI160_INT_ENABLE_2_ADDR = 0x52 82 | BMI160_INT_OUT_CTRL_ADDR = 0x53 83 | BMI160_INT_LATCH_ADDR = 0x54 84 | BMI160_INT_MAP_0_ADDR = 0x55 85 | BMI160_INT_MAP_1_ADDR = 0x56 86 | BMI160_INT_MAP_2_ADDR = 0x57 87 | BMI160_INT_DATA_0_ADDR = 0x58 88 | BMI160_INT_DATA_1_ADDR = 0x59 89 | BMI160_INT_LOWHIGH_0_ADDR = 0x5A 90 | BMI160_INT_LOWHIGH_1_ADDR = 0x5B 91 | BMI160_INT_LOWHIGH_2_ADDR = 0x5C 92 | BMI160_INT_LOWHIGH_3_ADDR = 0x5D 93 | BMI160_INT_LOWHIGH_4_ADDR = 0x5E 94 | BMI160_INT_MOTION_0_ADDR = 0x5F 95 | BMI160_INT_MOTION_1_ADDR = 0x60 96 | BMI160_INT_MOTION_2_ADDR = 0x61 97 | BMI160_INT_MOTION_3_ADDR = 0x62 98 | BMI160_INT_TAP_0_ADDR = 0x63 99 | BMI160_INT_TAP_1_ADDR = 0x64 100 | BMI160_INT_ORIENT_0_ADDR = 0x65 101 | BMI160_INT_ORIENT_1_ADDR = 0x66 102 | BMI160_INT_FLAT_0_ADDR = 0x67 103 | BMI160_INT_FLAT_1_ADDR = 0x68 104 | BMI160_FOC_CONF_ADDR = 0x69 105 | BMI160_CONF_ADDR = 0x6A 106 | BMI160_IF_CONF_ADDR = 0x6B 107 | BMI160_SELF_TEST_ADDR = 0x6D 108 | BMI160_OFFSET_ADDR = 0x71 109 | BMI160_OFFSET_CONF_ADDR = 0x77 110 | BMI160_INT_STEP_CNT_0_ADDR = 0x78 111 | BMI160_INT_STEP_CONFIG_0_ADDR = 0x7A 112 | BMI160_INT_STEP_CONFIG_1_ADDR = 0x7B 113 | BMI160_COMMAND_REG_ADDR = 0x7E 114 | BMI160_SPI_COMM_TEST_ADDR = 0x7F 115 | BMI160_INTL_PULLUP_CONF_ADDR = 0x85 116 | 117 | ''' Maximum limits definition ''' 118 | BMI160_ACCEL_ODR_MAX = 15 119 | BMI160_ACCEL_BW_MAX = 2 120 | BMI160_ACCEL_RANGE_MAX = 12 121 | BMI160_GYRO_ODR_MAX = 13 122 | BMI160_GYRO_BW_MAX = 2 123 | BMI160_GYRO_RANGE_MAX = 4 124 | 125 | ''' Delay in ms settings ''' 126 | BMI160_ACCEL_DELAY_MS = 0.005 127 | BMI160_GYRO_DELAY_MS = 0.081 128 | BMI160_ONE_MS_DELAY = 0.001 129 | BMI160_AUX_COM_DELAY = 0.01 130 | BMI160_GYRO_SELF_TEST_DELAY = 0.02 131 | BMI160_ACCEL_SELF_TEST_DELAY = 0.05 132 | 133 | ''' Soft reset command ''' 134 | BMI160_SOFT_RESET_CMD = 0xb6 135 | BMI160_SOFT_RESET_DELAY_MS = 0.015 136 | BMI160_COMMAND_REG_ADDR = 0x7E 137 | 138 | '''BMI160 unique chip identifier ''' 139 | BMI160_CHIP_ID = 0xD1 140 | 141 | ''' Bandwidth settings ''' 142 | ''' Accel Bandwidth ''' 143 | BMI160_ACCEL_BW_OSR4_AVG1 = 0x00 144 | BMI160_ACCEL_BW_OSR2_AVG2 = 0x01 145 | BMI160_ACCEL_BW_NORMAL_AVG4 = 0x02 146 | BMI160_ACCEL_BW_RES_AVG8 = 0x03 147 | BMI160_ACCEL_BW_RES_AVG16 = 0x04 148 | BMI160_ACCEL_BW_RES_AVG32 = 0x05 149 | BMI160_ACCEL_BW_RES_AVG64 = 0x06 150 | BMI160_ACCEL_BW_RES_AVG128 = 0x07 151 | 152 | BMI160_GYRO_BW_OSR4_MODE = 0x00 153 | BMI160_GYRO_BW_OSR2_MODE = 0x01 154 | BMI160_GYRO_BW_NORMAL_MODE = 0x02 155 | 156 | ''' Output Data Rate settings ''' 157 | ''' Accel Output data rate ''' 158 | BMI160_ACCEL_ODR_RESERVED = 0x00 159 | BMI160_ACCEL_ODR_0_78HZ = 0x01 160 | BMI160_ACCEL_ODR_1_56HZ = 0x02 161 | BMI160_ACCEL_ODR_3_12HZ = 0x03 162 | BMI160_ACCEL_ODR_6_25HZ = 0x04 163 | BMI160_ACCEL_ODR_12_5HZ = 0x05 164 | BMI160_ACCEL_ODR_25HZ = 0x06 165 | BMI160_ACCEL_ODR_50HZ = 0x07 166 | BMI160_ACCEL_ODR_100HZ = 0x08 167 | BMI160_ACCEL_ODR_200HZ = 0x09 168 | BMI160_ACCEL_ODR_400HZ = 0x0A 169 | BMI160_ACCEL_ODR_800HZ = 0x0B 170 | BMI160_ACCEL_ODR_1600HZ = 0x0C 171 | BMI160_ACCEL_ODR_RESERVED0 = 0x0D 172 | BMI160_ACCEL_ODR_RESERVED1 = 0x0E 173 | BMI160_ACCEL_ODR_RESERVED2 = 0x0F 174 | 175 | ''' Gyro Output data rate ''' 176 | BMI160_GYRO_ODR_RESERVED = 0x00 177 | BMI160_GYRO_ODR_25HZ = 0x06 178 | BMI160_GYRO_ODR_50HZ = 0x07 179 | BMI160_GYRO_ODR_100HZ = 0x08 180 | BMI160_GYRO_ODR_200HZ = 0x09 181 | BMI160_GYRO_ODR_400HZ = 0x0A 182 | BMI160_GYRO_ODR_800HZ = 0x0B 183 | BMI160_GYRO_ODR_1600HZ = 0x0C 184 | BMI160_GYRO_ODR_3200HZ = 0x0D 185 | 186 | ''' Power mode settings ''' 187 | ''' Accel power mode ''' 188 | BMI160_ACCEL_NORMAL_MODE = 0x11 189 | BMI160_ACCEL_LOWPOWER_MODE = 0x12 190 | BMI160_ACCEL_SUSPEND_MODE = 0x10 191 | 192 | ''' Gyro power mode ''' 193 | BMI160_GYRO_SUSPEND_MODE = 0x14 194 | BMI160_GYRO_NORMAL_MODE = 0x15 195 | BMI160_GYRO_FASTSTARTUP_MODE = 0x17 196 | 197 | ''' Range settings ''' 198 | ''' Accel Range ''' 199 | BMI160_ACCEL_RANGE_2G = 0x03 200 | BMI160_ACCEL_RANGE_4G = 0x05 201 | BMI160_ACCEL_RANGE_8G = 0x08 202 | BMI160_ACCEL_RANGE_16G = 0x0C 203 | 204 | ''' Gyro Range ''' 205 | BMI160_GYRO_RANGE_2000_DPS = 0x00 206 | BMI160_GYRO_RANGE_1000_DPS = 0x01 207 | BMI160_GYRO_RANGE_500_DPS = 0x02 208 | BMI160_GYRO_RANGE_250_DPS = 0x03 209 | BMI160_GYRO_RANGE_125_DPS = 0x04 210 | 211 | ''' Error code definitions ''' 212 | BMI160_OK = 0 213 | BMI160_E_NULL_PTR = -1 214 | BMI160_E_COM_FAIL = -2 215 | BMI160_E_DEV_NOT_FOUND = -3 216 | BMI160_E_OUT_OF_RANGE = -4 217 | BMI160_E_INVALID_INPUT = -5 218 | BMI160_E_ACCEL_ODR_BW_INVALID = -6 219 | BMI160_E_GYRO_ODR_BW_INVALID = -7 220 | BMI160_E_LWP_PRE_FLTR_INT_INVALID = -8 221 | BMI160_E_LWP_PRE_FLTR_INVALID = -9 222 | BMI160_E_AUX_NOT_FOUND = -10 223 | BMI160_FOC_FAILURE = -11 224 | BMI160_ERR_CHOOSE = -12 225 | 226 | '''bmi160 active state of any & sig motion interrupt.''' 227 | '''enum bmi160_any_sig_motion_active_interrupt_state''' 228 | eBMI160_BOTH_ANY_SIG_MOTION_DISABLE = -1 229 | eBMI160_ANY_MOTION_ENABLE = 0 230 | eBMI160_SIG_MOTION_ENABLE = 1 231 | 232 | ''' Sensor & time select definition''' 233 | BMI160_ACCEL_SEL = 0x01 234 | BMI160_GYRO_SEL = 0x02 235 | BMI160_TIME_SEL = 0x04 236 | 237 | ''' Sensor select mask''' 238 | BMI160_SEN_SEL_MASK = 0x07 239 | 240 | eBMI160_ACCEL_ONLY = 1 241 | eBMI160_GYRO_ONLY = 2 242 | eBMI160_BOTH_ACCEL_AND_GYRO = 3 243 | 244 | BMI160_RAW_DATA_LENGTH = 15 245 | 246 | BMI160_INT_CHANNEL_NONE = 0 247 | BMI160_INT_CHANNEL_1 = 1 248 | BMI160_INT_CHANNEL_2 = 2 249 | BMI160_INT_CHANNEL_BOTH = 3 250 | 251 | BMI160_ACC_ANY_MOTION_INT = 0 252 | BMI160_ACC_SIG_MOTION_INT = 1 253 | BMI160_STEP_DETECT_INT = 2 254 | BMI160_ACC_DOUBLE_TAP_INT = 3 255 | BMI160_ACC_SINGLE_TAP_INT = 4 256 | BMI160_ACC_ORIENT_INT = 5 257 | BMI160_ACC_FLAT_INT = 6 258 | BMI160_ACC_HIGH_G_INT = 7 259 | BMI160_ACC_LOW_G_INT = 8 260 | BMI160_ACC_SLOW_NO_MOTION_INT = 9 261 | BMI160_ACC_GYRO_DATA_RDY_INT = 10 262 | BMI160_ACC_GYRO_FIFO_FULL_INT = 11 263 | BMI160_ACC_GYRO_FIFO_WATERMARK_INT = 12 264 | 265 | ''' Enable/disable bit value ''' 266 | BMI160_ENABLE = 0x01 267 | BMI160_DISABLE = 0x00 268 | 269 | ''' Latch Duration ''' 270 | BMI160_LATCH_DUR_NONE = 0x00 271 | BMI160_LATCH_DUR_312_5_MICRO_SEC = 0x01 272 | BMI160_LATCH_DUR_625_MICRO_SEC = 0x02 273 | BMI160_LATCH_DUR_1_25_MILLI_SEC = 0x03 274 | BMI160_LATCH_DUR_2_5_MILLI_SEC = 0x04 275 | BMI160_LATCH_DUR_5_MILLI_SEC = 0x05 276 | BMI160_LATCH_DUR_10_MILLI_SEC = 0x06 277 | BMI160_LATCH_DUR_20_MILLI_SEC = 0x07 278 | BMI160_LATCH_DUR_40_MILLI_SEC = 0x08 279 | BMI160_LATCH_DUR_80_MILLI_SEC = 0x09 280 | BMI160_LATCH_DUR_160_MILLI_SEC = 0x0A 281 | BMI160_LATCH_DUR_320_MILLI_SEC = 0x0B 282 | BMI160_LATCH_DUR_640_MILLI_SEC = 0x0C 283 | BMI160_LATCH_DUR_1_28_SEC = 0x0D 284 | BMI160_LATCH_DUR_2_56_SEC = 0x0E 285 | BMI160_LATCHED = 0x0F 286 | 287 | BMI160_STEP_DETECT_NORMAL = 0 288 | BMI160_STEP_DETECT_SENSITIVE = 1 289 | BMI160_STEP_DETECT_ROBUST = 2 290 | BMI160_STEP_DETECT_USER_DEFINE = 3 291 | 292 | class DFRobot_BMI160: 293 | _dev_accel_cfg_bw = BMI160_ACCEL_BW_NORMAL_AVG4 294 | _dev_accel_cfg_odr = BMI160_ACCEL_ODR_100HZ 295 | _dev_accel_cfg_power = BMI160_ACCEL_SUSPEND_MODE 296 | _dev_accel_cfg_range = BMI160_ACCEL_RANGE_2G 297 | _dev_gyro_cfg_bw = BMI160_GYRO_BW_NORMAL_MODE 298 | _dev_gyro_cfg_odr = BMI160_GYRO_ODR_100HZ 299 | _dev_gyro_cfg_power = BMI160_GYRO_SUSPEND_MODE 300 | _dev_gyro_cfg_range = BMI160_GYRO_RANGE_2000_DPS 301 | 302 | _dev_pre_accel_cfg_bw = _dev_accel_cfg_bw 303 | _dev_pre_accel_cfg_odr = _dev_accel_cfg_odr 304 | _dev_pre_accel_cfg_power = _dev_accel_cfg_power 305 | _dev_pre_accel_cfg_range = _dev_accel_cfg_range 306 | _dev_pre_gyro_cfg_bw = _dev_gyro_cfg_bw 307 | _dev_pre_gyro_cfg_odr = _dev_gyro_cfg_odr 308 | _dev_pre_gyro_cfg_power = _dev_gyro_cfg_power 309 | _dev_pre_gyro_cfg_range = _dev_gyro_cfg_range 310 | 311 | _dev_any_sig_sel = eBMI160_ANY_MOTION_ENABLE 312 | _dev_chip_id = BMI160_CHIP_ID 313 | 314 | _raw_data = [0]*BMI160_RAW_DATA_LENGTH 315 | _update = 0 316 | 317 | _gyro_x = 0 318 | _gyro_y = 0 319 | _gyro_z = 0 320 | _accel_x = 0 321 | _accel_y = 0 322 | _accel_z = 0 323 | _accel_sensor_time = 0 324 | _gyro_sensor_time = 0 325 | 326 | step_normal_power_mode = 0 327 | step_lower_power_mode = 1 328 | 329 | '''Enum status mode''' 330 | eSTATUS_OK = 0 #Normal status, no error 331 | eSTATUS_ERR = 1 #Error status 332 | eSTATUS_ERR_DEV_NOT_DETECTED = 2 #Device not detected 333 | eSTATUS_ERR_PARAM = 3 #Parameter error 334 | 335 | def __init__(self): 336 | GPIO.setmode(GPIO.BCM) 337 | GPIO.setwarnings(False) 338 | 339 | def begin(self, mode = 0): 340 | ''' 341 | @brief Initialize sensor 342 | @return Error code: 343 | BMI160_OK or 0 : init succeeded, no error 344 | BMI160_E_NULL_PTR or -1 : the parameters is empty 345 | BMI160_E_COM_FAIL or -2 : interaction failed 346 | BMI160_E_DEV_NOT_FOUND or -3 : device not connected 347 | BMI160_E_OUT_OF_RANGE or -4 : out of sensor range 348 | BMI160_E_INVALID_INPUT or -5 : invalid input 349 | BMI160_E_ACCEL_ODR_BW_INVALID or -6 : accelerometer data output rate is invalid 350 | BMI160_E_GYRO_ODR_BW_INVALID or -7 : gyroscope data output rate is invalid 351 | BMI160_E_LWP_PRE_FLTR_INT_INVALID or -8 : low-power interrupt filter is invalid 352 | BMI160_E_LWP_PRE_FLTR_INVALID or -9 : low-power filter is invalid 353 | BMI160_FOC_FAILURE or -11: crystal oscillator failed 354 | ''' 355 | if self.soft_reset() != BMI160_OK: 356 | print("soft reset failed") 357 | return -1 358 | rslt = self._get_regs(BMI160_CHIP_ID_ADDR, 1) 359 | if rslt[0] == BMI160_OK and rslt[1] == BMI160_CHIP_ID: 360 | self._dev_any_sig_sel = eBMI160_ANY_MOTION_ENABLE 361 | self._dev_chip_id = rslt[1] 362 | rslt = self.soft_reset() 363 | if rslt == BMI160_OK: 364 | rslt == self._set_sens_conf() 365 | 366 | else: 367 | rslt = BMI160_E_DEV_NOT_FOUND 368 | return rslt 369 | 370 | def set_int(self, intNum): 371 | ''' 372 | @brief Configure interrupt pin 373 | @param intNum: The INT pin of sensor, INT1 or INT2: 374 | @n 1 : The INT1 pin of sensor 375 | @n 2 : The INT2 pin of sensor 376 | @return Error code: 377 | BMI160_OK or 0 : Config succeeded 378 | others value : Config failed 379 | ''' 380 | if intNum == 1: 381 | self._write_bytes(0x52, [8,0x0B,0,1,0,0]) 382 | self._write_bytes(0x7A, [0x15,3]) 383 | elif intNum == 2: 384 | self._write_bytes(0x52, [8,0xB0,0,0,0,1]) 385 | self._write_bytes(0x7A, [0x15,3]) 386 | else: 387 | return BMI160_E_NULL_PTR 388 | return BMI160_OK 389 | 390 | def set_step_power_mode(self, model): 391 | ''' 392 | @brief Set pedometer power mode 393 | @param model: Power mode type 394 | @n step_normal_power_mode: Count step in normal power mode 395 | @n step_lower_power_mode : Count step in low power mode 396 | @return Error code: 397 | BMI160_OK or 0 : setting succeeded 398 | others value : setting failed 399 | ''' 400 | if model == self.step_normal_power_mode: 401 | _dev_accel_cfg_odr = BMI160_ACCEL_ODR_1600HZ 402 | _dev_accel_cfg_power = BMI160_ACCEL_NORMAL_MODE 403 | _dev_gyro_cfg_odr = BMI160_GYRO_ODR_3200HZ 404 | _dev_gyro_cfg_power = BMI160_GYRO_NORMAL_MODE 405 | elif model == self.step_lower_power_mode: 406 | _dev_accel_cfg_odr = BMI160_ACCEL_ODR_50HZ 407 | _dev_accel_cfg_power = BMI160_ACCEL_LOWPOWER_MODE 408 | _dev_gyro_cfg_odr = BMI160_GYRO_ODR_50HZ 409 | _dev_gyro_cfg_power = BMI160_GYRO_SUSPEND_MODE 410 | else: 411 | _dev_accel_cfg_odr = BMI160_ACCEL_ODR_1600HZ 412 | _dev_accel_cfg_power = BMI160_ACCEL_NORMAL_MODE 413 | _dev_gyro_cfg_odr = BMI160_GYRO_ODR_3200HZ 414 | _dev_gyro_cfg_power = BMI160_GYRO_NORMAL_MODE 415 | _dev_accel_cfg_bw = BMI160_ACCEL_BW_NORMAL_AVG4 416 | _dev_accel_cfg_range = BMI160_ACCEL_RANGE_2G 417 | _dev_gyro_cfg_bw = BMI160_GYRO_BW_NORMAL_MODE 418 | _dev_gyro_cfg_range = BMI160_GYRO_RANGE_2000_DPS 419 | 420 | 421 | rslt = self._set_accel_conf() 422 | if rslt == BMI160_OK: 423 | rslt = self._set_gyro_conf() 424 | if rslt == BMI160_OK: 425 | rslt = self._set_power_mode() 426 | if rslt == BMI160_OK: 427 | rslt = self._check_invalid_settg() 428 | return rslt 429 | 430 | def soft_reset(self): 431 | ''' 432 | @brief Soft reset 433 | @param model: Power mode type 434 | @n step_normal_power_mode: Count step in normal power mode 435 | @n step_lower_power_mode : Count step in low power mode 436 | @return Error code: 437 | @n BMI160_OK or 0 : Soft reset succeeded 438 | @n others value : Soft reset failed 439 | ''' 440 | rslt = self._set_regs(BMI160_COMMAND_REG_ADDR, [BMI160_SOFT_RESET_CMD]) 441 | time.sleep(BMI160_SOFT_RESET_DELAY_MS) 442 | if rslt == BMI160_OK: 443 | self._default_param_settg() 444 | return rslt 445 | 446 | def get_sensor_data(self): 447 | ''' 448 | @brief Get sensor data, including data of gyroscope, accelerometer, etc. 449 | @return Return data of dictionary type, the format is as follows: 450 | @n {'accel':{'x':0, 'y':0, 'z':0}, 'gyro':{'x':0, 'y':0, 'z':0}} 451 | @n Note: it's raw data, process it to get the correct data: 452 | @n Gyroscope: gyroscope data of each axis *3.14/180.0, after calculation, unit is rad/s 453 | @n Accelerometer: accelerometer data of each axis //16384.0, after calculation, unit is g 454 | ''' 455 | sensor = {'accel':{'x':0, 'y':0, 'z':0}, 'gyro':{'x':0, 'y':0, 'z':0}} 456 | rslt = self._get_raw_data() 457 | self._update = 0 458 | if rslt == BMI160_OK: 459 | sensor['accel']['x'] = self._accel_x 460 | sensor['accel']['y'] = self._accel_y 461 | sensor['accel']['z'] = self._accel_z 462 | sensor['gyro']['x'] = self._gyro_x 463 | sensor['gyro']['y'] = self._gyro_y 464 | sensor['gyro']['z'] = self._gyro_z 465 | return sensor 466 | 467 | def get_accel_data(self): 468 | ''' 469 | @brief Get accelerometer data 470 | @return Return data of dictionary type, the format is as follows: 471 | @n {'accel':{'x':0, 'y':0, 'z':0}} 472 | @n Note: it's raw data, process it to get the correct data: 473 | @n Accelerometer: accelerometer data of each axis//16384.0, after calculation, unit is g 474 | ''' 475 | sensor = {'accel':{'x':0, 'y':0, 'z':0}} 476 | if self._update & 0x01 != 0x01: 477 | rslt = self._get_raw_data() 478 | sensor['accel']['x'] = self._accel_x 479 | sensor['accel']['y'] = self._accel_y 480 | sensor['accel']['z'] = self._accel_z 481 | self._update &= 0xFE 482 | return sensor 483 | 484 | def get_gyro_data(self): 485 | ''' 486 | @brief Get gyroscope data 487 | @return Return data of dictionary type, the format is as follows: 488 | @n {'gyro':{'x':0, 'y':0, 'z':0}} 489 | @n Note: it's raw data, process it to get the correct data: 490 | @n Gyroscope: gyroscope data of each axis *3.14/180.0, after calculation, unit is rad/s 491 | ''' 492 | sensor = {'gyro':{'x':0, 'y':0, 'z':0}} 493 | if self._update & 0x02 != 0x02: 494 | rslt = self._get_raw_data() 495 | sensor['gyro']['x'] = self._gyro_x 496 | sensor['gyro']['y'] = self._gyro_y 497 | sensor['gyro']['z'] = self._gyro_z 498 | self._update &= 0xFD 499 | return sensor 500 | 501 | def set_step_counter(self): 502 | ''' 503 | @brief Set step count 504 | @return Error code: 505 | @n BMI160_OK or 0 : Setting succeeded 506 | @n others value : Setting failed 507 | ''' 508 | rslt = self._get_regs(BMI160_INT_STEP_CONFIG_1_ADDR, 1) 509 | if rslt[0] == BMI160_OK: 510 | rslt[1] |= ((1 << 3) & 0xFF) 511 | rslt = self._set_regs(BMI160_INT_STEP_CONFIG_1_ADDR, [rslt[1]]) 512 | else: 513 | rslt = rslt[0] 514 | return rslt 515 | 516 | def read_step_counter(self): 517 | ''' 518 | @brief Read step count data 519 | @return Data of dictionary type, the format is error code + current step count data: 520 | @n {'error':0, 'step':0} 521 | @n Note: when 'error' value is BMI160_OK, it means that 'step' is valid data, otherwise it is invalid data. 522 | ''' 523 | val = {'error':0, 'step':0} 524 | rslt = self._get_regs(BMI160_INT_STEP_CNT_0_ADDR, 2) 525 | if rslt[0] == BMI160_OK: 526 | lsb = rslt[1] 527 | msb = (rslt[2] << 8) 528 | val['step'] = msb | lsb 529 | val['error'] = rslt[0] 530 | return val 531 | 532 | def _get_raw_data(self): 533 | self._raw_data = [0]*BMI160_RAW_DATA_LENGTH 534 | rslt = self._get_regs(BMI160_GYRO_DATA_ADDR, BMI160_RAW_DATA_LENGTH) 535 | self._update = 0x03 536 | idex = 1 537 | _gyro_x = 0 538 | _gyro_y = 0 539 | _gyro_z = 0 540 | _accel_x = 0 541 | _accel_y = 0 542 | _accel_z = 0 543 | _accel_sensor_time = 0 544 | _gyro_sensor_time = 0 545 | if rslt[0] == BMI160_OK: 546 | lsb = rslt[idex] 547 | msb = rslt[idex+1] 548 | self._gyro_x = np.int16((msb)*256 + lsb) 549 | idex += 2 550 | 551 | lsb = rslt[idex] 552 | msb = rslt[idex+1] 553 | self._gyro_y = np.int16((msb)*256 + lsb) 554 | idex += 2 555 | 556 | lsb = rslt[idex] 557 | msb = rslt[idex+1] 558 | self._gyro_z = np.int16((msb)*256 + lsb) 559 | idex += 2 560 | 561 | lsb = rslt[idex] 562 | msb = rslt[idex+1] 563 | self._accel_x = np.int16((msb)*256 + lsb) 564 | idex += 2 565 | 566 | lsb = rslt[idex] 567 | msb = rslt[idex+1] 568 | self._accel_y = np.int16((msb)*256 + lsb) 569 | idex += 2 570 | 571 | lsb = rslt[idex] 572 | msb = rslt[idex+1] 573 | self._accel_z = np.int16((msb)*256 + lsb) 574 | idex += 2 575 | 576 | time_0 = rslt[idex] 577 | time_1 = rslt[idex+1] << 8 578 | time_2 = rslt[idex+2] << 16 579 | 580 | self._accel_sensor_time = time_2|time_1|time_0 581 | self._gyro_sensor_time = time_2|time_1|time_0 582 | return BMI160_OK 583 | return BMI160_E_COM_FAIL 584 | 585 | def _set_regs(self, reg, dataList): 586 | rslt = BMI160_OK 587 | count = 0 588 | rslt = self._write_bytes(reg, dataList) 589 | time.sleep(0.001) 590 | if rslt == len(dataList): 591 | return BMI160_OK 592 | else: 593 | return BMI160_E_COM_FAIL 594 | 595 | def _get_regs(self, reg, length): 596 | rslt = self._read_bytes(reg,length) 597 | time.sleep(0.001) 598 | if len(rslt) != length: 599 | rslt.insert(0, BMI160_E_COM_FAIL) 600 | else: 601 | rslt.insert(0, BMI160_OK) 602 | return rslt 603 | 604 | def _update_reg_bit_value(self, reg_value, bit, offset, value): 605 | reg_value &= ((~(offset << bit)) & 0xFF) 606 | reg_value |= (value << bit) 607 | return reg_value & 0xFF 608 | 609 | def _get_reg_bit_value(self, reg_value, bit, offset): 610 | reg_value >>= bit 611 | reg_value &= offset 612 | return reg_value & 0xFF 613 | 614 | def _default_param_settg(self): 615 | self._dev_accel_cfg_bw = BMI160_ACCEL_BW_NORMAL_AVG4 616 | self._dev_accel_cfg_odr = BMI160_ACCEL_ODR_100HZ 617 | self._dev_accel_cfg_power = BMI160_ACCEL_SUSPEND_MODE 618 | self._dev_accel_cfg_range = BMI160_ACCEL_RANGE_2G 619 | self._dev_gyro_cfg_bw = BMI160_GYRO_BW_NORMAL_MODE 620 | self._dev_gyro_cfg_odr = BMI160_GYRO_ODR_100HZ 621 | self._dev_gyro_cfg_power = BMI160_GYRO_SUSPEND_MODE 622 | self._dev_gyro_cfg_range = BMI160_GYRO_RANGE_2000_DPS 623 | 624 | self._dev_pre_accel_cfg_bw = self._dev_accel_cfg_bw 625 | self._dev_pre_accel_cfg_odr = self._dev_accel_cfg_odr 626 | self._dev_pre_accel_cfg_power = self._dev_accel_cfg_power 627 | self._dev_pre_accel_cfg_range = self._dev_accel_cfg_range 628 | self._dev_pre_gyro_cfg_bw = self._dev_gyro_cfg_bw 629 | self._dev_pre_gyro_cfg_odr = self._dev_gyro_cfg_odr 630 | self._dev_pre_gyro_cfg_power = self._dev_gyro_cfg_power 631 | self._dev_pre_gyro_cfg_range = self._dev_gyro_cfg_range 632 | 633 | def _set_sens_conf(self): 634 | self._dev_accel_cfg_odr = BMI160_ACCEL_ODR_1600HZ 635 | self._dev_accel_cfg_range = BMI160_ACCEL_RANGE_2G 636 | self._dev_accel_cfg_bw = BMI160_ACCEL_BW_NORMAL_AVG4 637 | 638 | self._dev_accel_cfg_power = BMI160_ACCEL_NORMAL_MODE 639 | 640 | self._dev_gyro_cfg_odr = BMI160_GYRO_ODR_3200HZ 641 | self._dev_gyro_cfg_range = BMI160_GYRO_RANGE_2000_DPS 642 | self._dev_gyro_cfg_bw = BMI160_GYRO_BW_NORMAL_MODE 643 | 644 | self._dev_gyro_cfg_power = BMI160_GYRO_NORMAL_MODE 645 | 646 | rslt = self._set_accel_conf() 647 | if rslt == BMI160_OK: 648 | rslt = self._set_gyro_conf() 649 | if rslt == BMI160_OK: 650 | rslt = self._set_power_mode() 651 | if rslt == BMI160_OK: 652 | rslt = self._check_invalid_settg() 653 | return rslt 654 | 655 | 656 | def _set_accel_conf(self): 657 | rslt = self._check_accel_config() 658 | if rslt[0] == BMI160_OK: 659 | rslt1 = self._set_regs(BMI160_ACCEL_CONFIG_ADDR, [rslt[1]]) 660 | if rslt1 == BMI160_OK: 661 | self._dev_pre_accel_cfg_bw = self._dev_accel_cfg_bw 662 | self._dev_pre_accel_cfg_odr = self._dev_accel_cfg_odr 663 | time.sleep(BMI160_ONE_MS_DELAY) 664 | rslt1 = self._set_regs(BMI160_ACCEL_RANGE_ADDR, [rslt[2]]) 665 | if rslt1 == BMI160_OK: 666 | self._dev_pre_accel_cfg_range = self._dev_accel_cfg_range 667 | else: 668 | rslt1 = rslt[0] 669 | return rslt1 670 | 671 | def _set_gyro_conf(self): 672 | value = [0]*2 673 | rslt = self._check_gyro_config() 674 | if rslt[0] == BMI160_OK: 675 | value[0] = rslt[1] 676 | value[1] = rslt[2] 677 | rslt = self._set_regs(BMI160_GYRO_CONFIG_ADDR, [value[0]]) 678 | if rslt == BMI160_OK: 679 | self._dev_pre_gyro_cfg_bw = self._dev_gyro_cfg_bw 680 | self._dev_pre_gyro_cfg_odr = self._dev_gyro_cfg_odr 681 | time.sleep(BMI160_ONE_MS_DELAY) 682 | rslt = self._set_regs(BMI160_GYRO_RANGE_ADDR, [value[1]]) 683 | if rslt == BMI160_OK: 684 | self._dev_pre_gyro_cfg_range = self._dev_gyro_cfg_range 685 | else: 686 | rslt = rslt[0] 687 | return rslt 688 | 689 | def _set_power_mode(self): 690 | rslt = self._set_accel_pwr() 691 | if rslt == BMI160_OK: 692 | rslt = self._set_gyro_pwr() 693 | return rslt 694 | 695 | def _set_accel_pwr(self): 696 | rslt = BMI160_OK 697 | if (self._dev_accel_cfg_power >= BMI160_ACCEL_SUSPEND_MODE) and (self._dev_accel_cfg_power <= BMI160_ACCEL_LOWPOWER_MODE): 698 | if self._dev_accel_cfg_power != self._dev_pre_accel_cfg_power: 699 | rslt = self._process_under_sampling() 700 | if rslt == BMI160_OK: 701 | rslt = self._set_regs(BMI160_COMMAND_REG_ADDR, [self._dev_accel_cfg_power]) 702 | if self._dev_pre_accel_cfg_power == BMI160_ACCEL_SUSPEND_MODE: 703 | time.sleep(BMI160_ACCEL_DELAY_MS) 704 | self._dev_pre_accel_cfg_power = self._dev_accel_cfg_power 705 | return BMI160_OK 706 | return rslt 707 | 708 | def _process_under_sampling(self): 709 | value = 0 710 | rslt = self._get_regs(BMI160_ACCEL_CONFIG_ADDR, 1) 711 | if rslt[0] == BMI160_OK: 712 | value = rslt[1] 713 | if self._dev_accel_cfg_power == BMI160_ACCEL_LOWPOWER_MODE: 714 | temp = (value & (~BMI160_ACCEL_UNDERSAMPLING_MASK))&0xff 715 | value = (temp | ((1 << 7) & BMI160_ACCEL_UNDERSAMPLING_MASK))&0xff 716 | rslt = self._set_regs(BMI160_ACCEL_CONFIG_ADDR, [value]) 717 | if rslt == BMI160_OK: 718 | rslt = self._set_regs(BMI160_INT_DATA_0_ADDR, [0]) 719 | return rslt 720 | else: 721 | if value & BMI160_ACCEL_UNDERSAMPLING_MASK: 722 | temp = (value & (~BMI160_ACCEL_UNDERSAMPLING_MASK)) & 0xFF 723 | value = temp 724 | rslt = self._set_regs(BMI160_ACCEL_CONFIG_ADDR, [value]) 725 | return rslt 726 | rslt = rslt[0] 727 | return rslt 728 | 729 | def _set_gyro_pwr(self): 730 | rslt = BMI160_OK 731 | if self._dev_gyro_cfg_power == BMI160_GYRO_SUSPEND_MODE or self._dev_gyro_cfg_power == BMI160_GYRO_NORMAL_MODE or self._dev_gyro_cfg_power == BMI160_GYRO_FASTSTARTUP_MODE: 732 | if self._dev_gyro_cfg_power != self._dev_pre_gyro_cfg_power: 733 | rslt = self._set_regs(BMI160_COMMAND_REG_ADDR, [self._dev_gyro_cfg_power]) 734 | if self._dev_pre_gyro_cfg_power == BMI160_GYRO_SUSPEND_MODE: 735 | time.sleep(BMI160_GYRO_DELAY_MS) 736 | elif self._dev_pre_gyro_cfg_power == BMI160_GYRO_FASTSTARTUP_MODE and self._dev_gyro_cfg_power == BMI160_GYRO_NORMAL_MODE: 737 | time.sleep(0.01) 738 | self._dev_pre_gyro_cfg_power = self._dev_gyro_cfg_power 739 | return BMI160_OK 740 | 741 | return rslt 742 | 743 | def _check_invalid_settg(self): 744 | value = 0 745 | rslt = self._get_regs(BMI160_ERROR_REG_ADDR, 1) 746 | if len(rslt) == 2: 747 | value = rslt[1] 748 | value = (value >> 1)&0xff 749 | value = value & BMI160_ERR_REG_MASK 750 | rslt = rslt[0] 751 | if value == 1: 752 | rslt = BMI160_E_ACCEL_ODR_BW_INVALID 753 | elif value == 2: 754 | rslt = BMI160_E_GYRO_ODR_BW_INVALID 755 | elif value == 3: 756 | rslt = BMI160_E_LWP_PRE_FLTR_INT_INVALID 757 | elif value == 7: 758 | rslt = BMI160_E_LWP_PRE_FLTR_INVALID 759 | return rslt 760 | 761 | def _check_gyro_config(self): 762 | value = [0]*3 763 | rslt = self._get_regs(BMI160_GYRO_CONFIG_ADDR, 2) 764 | if rslt[0] == BMI160_OK: 765 | value[1] = rslt[1] 766 | value[2] = rslt[2] 767 | rslt = self._process_gyro_odr(value[1]) 768 | if rslt[0] == BMI160_OK: 769 | value[1] = rslt[1] 770 | rslt = self._process_gyro_bw(value[1]) 771 | if rslt[0] == BMI160_OK: 772 | rslt = self._process_gyro_range(value[2]) 773 | if rslt[0] == BMI160_OK: 774 | value[2] = rslt[1] 775 | value[0] = rslt[0] 776 | return value 777 | 778 | def _process_gyro_odr(self, data): 779 | rslt = [0]*2 780 | rslt[1] = data 781 | if self._dev_gyro_cfg_odr <= BMI160_GYRO_ODR_MAX: 782 | if self._dev_gyro_cfg_odr != self._dev_pre_gyro_cfg_odr: 783 | odr = self._dev_gyro_cfg_odr & 0xFF 784 | temp = (data & (~BMI160_GYRO_ODR_MASK)) & 0xff 785 | rslt[1] = temp | (odr & BMI160_GYRO_ODR_MASK) 786 | rslt[0] = BMI160_OK 787 | else: 788 | rslt[0] = BMI160_E_OUT_OF_RANGE 789 | return rslt 790 | 791 | def _process_gyro_bw(self, data): 792 | rslt = [0]*2 793 | rslt[1] = data 794 | if self._dev_gyro_cfg_bw <= BMI160_GYRO_BW_MAX: 795 | #if self._dev_gyro_cfg_bw != self._dev_pre_gyro_cfg_bw: 796 | bw = self._dev_gyro_cfg_bw & 0xFF 797 | temp = (data & (~BMI160_GYRO_BW_MASK)) & 0xff 798 | rslt[1] = (temp | ( (bw << 4) & BMI160_GYRO_BW_MASK))&0xff 799 | rslt[0] = BMI160_OK 800 | else: 801 | rslt[0] = BMI160_E_OUT_OF_RANGE 802 | return rslt 803 | 804 | def _process_gyro_range(self, data): 805 | rslt = [0]*2 806 | rslt[1] = data 807 | if self._dev_gyro_cfg_range <= BMI160_ACCEL_RANGE_MAX: 808 | if self._dev_gyro_cfg_range != self._dev_pre_gyro_cfg_range: 809 | range = self._dev_gyro_cfg_range & 0xFF 810 | temp = (data & (~BMI160_GYRO_RANGE_MSK)) & 0xff 811 | rslt[1] = (temp | ( range & BMI160_GYRO_RANGE_MSK))&0xff 812 | rslt[0] = BMI160_OK 813 | else: 814 | rslt[0] = BMI160_E_OUT_OF_RANGE 815 | return rslt 816 | 817 | def _check_accel_config(self): 818 | value = [0]*3 819 | rslt = self._get_regs(BMI160_ACCEL_CONFIG_ADDR, 2) 820 | if rslt[0] == BMI160_OK: 821 | value[1] = rslt[1] 822 | value[2] = rslt[2] 823 | rslt = self._process_accel_odr(value[1]) 824 | if rslt[0] == BMI160_OK: 825 | value[1] = rslt[1] 826 | rslt = self._process_accel_bw(value[1]) 827 | if rslt[0] == BMI160_OK: 828 | rslt = self._process_accel_range(value[2]) 829 | if rslt[0] == BMI160_OK: 830 | value[2] = rslt[1] 831 | value[0] = rslt[0] 832 | return value 833 | def _process_accel_odr(self, data): 834 | rslt = [0]*2 835 | rslt[1] = data 836 | if self._dev_accel_cfg_odr <= BMI160_ACCEL_ODR_MAX: 837 | if self._dev_accel_cfg_odr != self._dev_pre_accel_cfg_odr: 838 | odr = self._dev_accel_cfg_odr & 0xFF 839 | temp = (data & (~BMI160_ACCEL_ODR_MASK)) & 0xff 840 | rslt[1] = temp | (odr & BMI160_ACCEL_ODR_MASK) 841 | rslt[0] = BMI160_OK 842 | else: 843 | rslt[0] = BMI160_E_OUT_OF_RANGE 844 | return rslt 845 | 846 | def _process_accel_bw(self, data): 847 | rslt = [0]*2 848 | rslt[1] = data 849 | if self._dev_accel_cfg_bw <= BMI160_ACCEL_BW_MAX: 850 | if self._dev_accel_cfg_bw != self._dev_pre_accel_cfg_bw: 851 | bw = self._dev_accel_cfg_bw & 0xFF 852 | temp = (data & (~BMI160_ACCEL_BW_MASK)) & 0xff 853 | rslt[1] = (temp | ( (bw << 4) & BMI160_ACCEL_BW_MASK))&0xff 854 | rslt[0] = BMI160_OK 855 | else: 856 | rslt[0] = BMI160_E_OUT_OF_RANGE 857 | return rslt 858 | 859 | def _process_accel_range(self,data): 860 | rslt = [0]*2 861 | rslt[1] = data 862 | if self._dev_accel_cfg_range <= BMI160_ACCEL_RANGE_MAX: 863 | if self._dev_accel_cfg_range != self._dev_pre_accel_cfg_range: 864 | range = self._dev_accel_cfg_range & 0xFF 865 | temp = (data & (~BMI160_ACCEL_RANGE_MASK)) & 0xff 866 | rslt[1] = (temp | ( range & BMI160_ACCEL_RANGE_MASK))&0xff 867 | rslt[0] = BMI160_OK 868 | else: 869 | rslt[0] = BMI160_E_OUT_OF_RANGE 870 | return rslt 871 | 872 | def _write_bytes(self, reg, buf): 873 | pass 874 | 875 | def _read_bytes(self, reg, length): 876 | pass 877 | 878 | class DFRobot_BMI160_IIC(DFRobot_BMI160): 879 | def __init__(self,addr = BMI160_IIC_ADDR_SDO_H): 880 | ''' 881 | @brief The constructor of the BMI160 sensor using IIC communication. 882 | @param addr: 7-bit IIC address, controlled by SDO pin. 883 | @n BMI160_IIC_ADDR_SDO_H or 0x69: SDO pull high.(default) 884 | @n BMI160_IIC_ADDR_SDO_L or 0x68: SDO pull down. 885 | ''' 886 | self._addr = addr 887 | self._bus = smbus.SMBus(1) 888 | DFRobot_BMI160.__init__(self) 889 | 890 | 891 | def _write_bytes(self, reg, buf): 892 | try: 893 | self._bus.write_i2c_block_data(self._addr, reg, buf) 894 | return len(buf) 895 | except: 896 | return 0 897 | 898 | def _read_bytes(self, reg, length): 899 | try: 900 | rslt = self._bus.read_i2c_block_data(self._addr, reg, length) 901 | return rslt 902 | except: 903 | return [0]*length 904 | 905 | 906 | -------------------------------------------------------------------------------- /python/raspberrypi/README.md: -------------------------------------------------------------------------------- 1 | # DFRobot_BMI160 2 | 3 | * [中文](./README_CN.md) 4 | 5 | The BMI160 is a highly integrated, low power inertial measurement unit (IMU) that provides precise acceleration and angular rate (gyroscopic) measurement.
6 | The BMI160 contains 16 bit digtial,triaxial accelerometer and 16 bit digital, triaxial gyroscope.
7 | This example is for BMI160 sensor and it oprated via Arduino I2C.
8 | 9 | ![产品效果图](../../resources/images/SEN0250.png) 10 | 11 | ## Product Link([https://www.dfrobot.com/product-1716.html](https://www.dfrobot.com/product-1716.html)) 12 | SKU: SEN0250 13 | 14 | ## Table of Contents 15 | 16 | * [Summary](#summary) 17 | * [Connected](#connected) 18 | * [Installation](#installation) 19 | * [Methods](#methods) 20 | * [Compatibility](#compatibility) 21 | * [History](#history) 22 | * [Credits](#credits) 23 | 24 | ## Summary 25 | This is a 6-axis MEMS sensor BMI160 library. It can only support IIC communication.
26 | It can detect accelerometer, gyroscope, and onboard temperature.
27 | 28 | ## Connected 29 | 30 | 31 | 32 | | Sensor | raspberry pi | 33 | |------------ |:---------------------------------------------------------:| 34 | | + | 3V3/VCC | 35 | | - | GND | 36 | | C | connected to scl of MCU's IIC | 37 | | D | connected to sda of MCU's IIC | 38 | | INT1 | connected to the external interrupt IO pin of MCU | 39 | | INT2 | connected to the external interrupt IO pin of MCU | 40 | | SDO | connected to the IO pin of MCU or connected to GND or VCC | 41 | 42 | ## Installation 43 | 1. To use this library, first download the library file
44 | ```python 45 | sudo git clone https://github.com/DFRobot/DFRobot_BMI160 46 | ``` 47 | 2. Open and run the routine. To execute a routine demo_x.py, enter python demo_x.py in the command line. For example, to execute the demo_sleep.py routine, you need to enter :
48 | 49 | ```python 50 | python demo_sleep.py 51 | or 52 | python2 demo_sleep.py 53 | or 54 | python3 demo_sleep.py 55 | ``` 56 | 57 | 58 | ## Methods 59 | 60 | ```python 61 | ''' 62 | @brief The constructor of the BMI160 sensor using IIC communication. 63 | @param addr: 7-bit IIC address, controlled by SDO pin. 64 | @n BMI160_IIC_ADDR_SDO_H or 0x69: SDO pull high.(default) 65 | @n BMI160_IIC_ADDR_SDO_L or 0x68: SDO pull down. 66 | ''' 67 | class DFRobot_BMI160_IIC(DFRobot_BMI160): 68 | def __init__(self,addr = BMI160_IIC_ADDR_SDO_H): 69 | 70 | ''' 71 | @brief Initialize sensor 72 | @return Error code: 73 | BMI160_OK or 0 : init succeeded, no error 74 | BMI160_E_NULL_PTR or -1 : the parameters is empty 75 | BMI160_E_COM_FAIL or -2 : interaction failed 76 | BMI160_E_DEV_NOT_FOUND or -3 : device is not connected 77 | BMI160_E_OUT_OF_RANGE or -4 : range is out of sensor range 78 | BMI160_E_INVALID_INPUT or -5 : invalid input 79 | BMI160_E_ACCEL_ODR_BW_INVALID or -6 : accelerometer data output rate is invalid 80 | BMI160_E_GYRO_ODR_BW_INVALID or -7 : gyroscope data output rate is invalid 81 | BMI160_E_LWP_PRE_FLTR_INT_INVALID or -8 : low-power interrupt filter is invalid 82 | BMI160_E_LWP_PRE_FLTR_INVALID or -9 : low-power filter is invalid 83 | BMI160_FOC_FAILURE or -11: crystal oscillator failed 84 | ''' 85 | def begin(self, mode = 0): 86 | 87 | ''' 88 | @brief Configure interrupt pin 89 | @param intNum: The INT pin of sensor, INT1 or INT2: 90 | @n 1 : The INT1 pin of sensor 91 | @n 2 : The INT2 pin of sensor 92 | @return Error code: 93 | BMI160_OK or 0 : config succeeded 94 | others value : config failed 95 | ''' 96 | def set_int(self, intNum): 97 | 98 | ''' 99 | @brief Set pedometer power mode 100 | @param model: Power mode type 101 | @n step_normal_power_mode: Count step in normal power mode 102 | @n step_lower_power_mode : Count step in low power mode 103 | @return Error code: 104 | BMI160_OK or 0 : setting succeeded 105 | others value : setting failed 106 | ''' 107 | def set_step_power_mode(self, model): 108 | 109 | ''' 110 | @brief Soft reset, after reset 111 | @param model: Power mode type 112 | @n step_normal_power_mode: Count step in normal power mode 113 | @n step_lower_power_mode : Count step in low power mode 114 | @return Error code: 115 | @n BMI160_OK or 0 : soft reset succeeded 116 | @n others value : soft reset failed 117 | ''' 118 | def soft_reset(self): 119 | 120 | ''' 121 | @brief Get sensor data, including data of gyroscope, accelerometer, etc. 122 | @return Return data of dictionary type, the format is as follows: 123 | @n {'accel':{'x':0, 'y':0, 'z':0}, 'gyro':{'x':0, 'y':0, 'z':0}} 124 | @n Note: it's the raw data, process it to get the correct data: 125 | @n Gyroscope: gyroscope data per axis need *3.14/180.0, after calculation, unit is rad/s 126 | @n Accelerometer: accelerometer data per axis required //16384.0, after calculation, unit is g 127 | ''' 128 | def get_sensor_data(self): 129 | 130 | ''' 131 | @brief Get accelerometer data 132 | @return Return data of dictionary type, the format is as follows: 133 | @n {'accel':{'x':0, 'y':0, 'z':0}} 134 | @n Note: it's the raw data, process it to get the correct data: 135 | @n Accelerometer: accelerometer data per axis required //16384.0, after calculation, unit is g 136 | ''' 137 | def get_accel_data(self): 138 | 139 | ''' 140 | @brief Get gyroscope data 141 | @return Return data of dictionary type, the format is as follows: 142 | @n {'gyro':{'x':0, 'y':0, 'z':0}} 143 | @n Note: it's the raw data, process it to get the correct data: 144 | @n Gyroscope: gyroscope data per axis required *3.14/180.0, after calculation, unit is rad/s 145 | ''' 146 | def get_gyro_data(self): 147 | 148 | ''' 149 | @brief Set step count 150 | @return Error code: 151 | @n BMI160_OK or 0 : Setting succeeded 152 | @n others value : Setting failed 153 | ''' 154 | def set_step_counter(self): 155 | 156 | ''' 157 | @brief Read step count data 158 | @return Data of dictionary type, the format is error code + current step count data: 159 | @n {'error':0, 'step':0} 160 | @n Note: when 'error' value is BMI160_OK, it means that 'step' is valid data, otherwise it is invalid data. 161 | ''' 162 | def read_step_counter(self): 163 | ``` 164 | 165 | ## Compatibility 166 | 167 | | MCU | Work Well | Work Wrong | Untested | Remarks | 168 | | ------------ | :--: | :----: | :----: | :--: | 169 | | RaspberryPi2 | | | √ | | 170 | | RaspberryPi3 | | | √ | | 171 | | RaspberryPi4 | √ | | | | 172 | 173 | * Python Version 174 | 175 | | Python | Work Well | Work Wrong | Untested | Remarks | 176 | | ------- | :--: | :----: | :----: | ---- | 177 | | Python2 | √ | | | | 178 | | Python3 | √ | | | | 179 | 180 | ## History 181 | 182 | - 2021-06-11 - Version 1.0.0 released.s 183 | 184 | ## Credits 185 | 186 | Written by Arya(xue.peng@dfrobot.com), 2021. (Welcome to our [website](https://www.dfrobot.com/)) 187 | 188 | 189 | 190 | 191 | 192 | -------------------------------------------------------------------------------- /python/raspberrypi/README_CN.md: -------------------------------------------------------------------------------- 1 | # DFRobot_BMI160 2 | 3 | * [English Version](./README.md) 4 | 5 | BMI160 是一种高度集成的低功耗惯性测量单元 (IMU),可提供精确的加速度和角速率(陀螺仪)测量。
6 | BMI160 包含 16 位数字三轴加速度计和 16 位数字三轴陀螺仪。
7 | 此示例适用于 BMI160 传感器,它通过 Arduino I2C 进行操作。
8 | 9 | ![产品效果图](../../resources/images/SEN0250.png) 10 | 11 | 12 | ## 产品链接([https://www.dfrobot.com.cn/goods-1693.html](https://www.dfrobot.com.cn/goods-1693.html)) 13 | SKU: SEN0250 14 | 15 | ## 目录 16 | 17 | * [概述](#概述) 18 | * [连接](#连接) 19 | * [库安装](#库安装) 20 | * [方法](#方法) 21 | * [兼容性](#兼容性) 22 | * [历史](#历史) 23 | * [创作者](#创作者) 24 | 25 | ## 概述 26 | 27 | 提供 Arduino 库,通过 I2C 通信控制 bmi160 获取 加速度、陀螺仪和计步器数据。
28 | 29 | ## 连接 30 | 31 | | Sensor | raspberry pi | 32 | | ------------ | :--: | 33 | | + | 3V3 or VCC | 34 | | - | GND | 35 | | C | 连接到树莓派的scl引脚 | 36 | | D | 连接到树莓派的sda引脚 | 37 | | INT1 | 连接到树莓派的外部中断引脚 | 38 | | INT2 | 连接到树莓派的外部中断引脚 | 39 | | SDO | 连接到树莓派的IO引脚或连接到VCC或GND | 40 | 41 | 42 | ## 库安装 43 | 1. 下载库至树莓派,要使用这个库,首先要将库下载到Raspberry Pi,命令下载方法如下:
44 | ```python 45 | sudo git clone https://github.com/DFRobot/DFRobot_BMI160 46 | ``` 47 | 2. 打开并运行例程,要执行一个例程demo_x.py,请在命令行中输入python demo_x.py。例如,要执行 demo_sleep.py例程,你需要输入:
48 | 49 | ```python 50 | python demo_sleep.py 51 | 或 52 | python2 demo_sleep.py 53 | 或 54 | python3 demo_sleep.py 55 | ``` 56 | 57 | ## 方法 58 | 59 | ```python 60 | ''' 61 | @brief 使用 IIC 通信的 BMI160 传感器的构造函数。 62 | @param addr: 7位IIC地址,通过SDO引脚控制 63 | @n BMI160_IIC_ADDR_SDO_H or 0x69: SDO引脚拉高 64 | @n BMI160_IIC_ADDR_SDO_L or 0x68: SDO引脚拉低 65 | ''' 66 | class DFRobot_BMI160_IIC(DFRobot_BMI160): 67 | def __init__(self,addr = BMI160_IIC_ADDR_SDO_H): 68 | 69 | ''' 70 | @brief 初始化传感器 71 | @return 错误代码: 72 | BMI160_OK or 0 : 初始化成功,无错误 73 | BMI160_E_NULL_PTR or -1 : 参数为空 74 | BMI160_E_COM_FAIL or -2 : 交互失败 75 | BMI160_E_DEV_NOT_FOUND or -3 : 设备未连接 76 | BMI160_E_OUT_OF_RANGE or -4 : 量程超出传感器范围 77 | BMI160_E_INVALID_INPUT or -5 : 无效的输入 78 | BMI160_E_ACCEL_ODR_BW_INVALID or -6 : 加速度数据输出速率无效 79 | BMI160_E_GYRO_ODR_BW_INVALID or -7 : 陀螺仪数据输出速率无效 80 | BMI160_E_LWP_PRE_FLTR_INT_INVALID or -8 : 低功耗中断滤波器无效 81 | BMI160_E_LWP_PRE_FLTR_INVALID or -9 : 低功耗滤波器无效 82 | BMI160_FOC_FAILURE or -11: 晶振失败 83 | ''' 84 | def begin(self, mode = 0): 85 | 86 | ''' 87 | @brief 配置中断引脚 88 | @param intNum: 传感器的INT引脚,INT1或INT2: 89 | @n 1 : 传感器的INT1引脚 90 | @n 2 : 传感器的INT2引脚 91 | @return 错误代码: 92 | BMI160_OK or 0 : 配置成功 93 | others value : 配置失败 94 | ''' 95 | def set_int(self, intNum): 96 | 97 | ''' 98 | @brief 设置计步模式 99 | @param model: 模式类型 100 | @n step_normal_power_mode: 普通模式下计步 101 | @n step_lower_power_mode : 低功耗模式下计步 102 | @return 错误代码: 103 | BMI160_OK or 0 : 设置成功 104 | others value : 设置失败 105 | ''' 106 | def set_step_power_mode(self, model): 107 | 108 | ''' 109 | @brief 软件复位 110 | @param model: 模式类型 111 | @n step_normal_power_mode: 普通模式下计步 112 | @n step_lower_power_mode : 低功耗模式下计步 113 | @return 错误代码: 114 | @n BMI160_OK or 0 : 软件复位成功 115 | @n others value : 软件复位失败 116 | ''' 117 | def soft_reset(self): 118 | 119 | ''' 120 | @brief 获取传感器数据,包括陀螺仪和加速度等数据 121 | @return 返回字典类型的数据,格式如下: 122 | @n {'accel':{'x':0, 'y':0, 'z':0}, 'gyro':{'x':0, 'y':0, 'z':0}} 123 | @n 注意,这是原始数据,得到正确数据还需要处理: 124 | @n 陀螺仪: 陀螺仪的每轴数据需要*3.14/180.0,计算后,单位rad/s 125 | @n 加速度: 加速度的每轴数据需要//16384.0, 计算后,单位g 126 | ''' 127 | def get_sensor_data(self): 128 | 129 | ''' 130 | @brief 获取加速度数据 131 | @return 返回字典类型的数据,格式如下: 132 | @n {'accel':{'x':0, 'y':0, 'z':0}} 133 | @n 注意,这是原始数据,得到正确数据还需要处理: 134 | @n 加速度: 加速度的每轴数据需要//16384.0, 计算后,单位g 135 | ''' 136 | def get_accel_data(self): 137 | 138 | ''' 139 | @brief 获取陀螺仪数据 140 | @return 返回字典类型的数据,格式如下: 141 | @n {'gyro':{'x':0, 'y':0, 'z':0}} 142 | @n 注意,这是原始数据,得到正确数据还需要处理: 143 | @n 陀螺仪: 陀螺仪的每轴数据需要*3.14/180.0,计算后,单位rad/s 144 | ''' 145 | def get_gyro_data(self): 146 | 147 | ''' 148 | @brief 设置计步计数 149 | @return 错误代码: 150 | @n BMI160_OK or 0 : 设置成功 151 | @n others value : 设置失败 152 | ''' 153 | def set_step_counter(self): 154 | 155 | ''' 156 | @brief 读取计步计数数据 157 | @return 字典类型数据, 格式为错误代码+当前的计步数据: 158 | @n {'error':0, 'step':0} 159 | @n 注意: 当'error'的值为BMI160_OK时,表示'step'为有效数据,否则为无效数据 160 | ''' 161 | def read_step_counter(self): 162 | 163 | ``` 164 | 165 | ## 兼容性 166 | 167 | | 主板 | 通过 | 未通过 | 未测试 | 备注 | 168 | | ------------ | :--: | :----: | :----: | :--: | 169 | | RaspberryPi2 | | | √ | | 170 | | RaspberryPi3 | | | √ | | 171 | | RaspberryPi4 | √ | | | | 172 | 173 | * Python 版本 174 | 175 | | Python | 通过 | 未通过 | 未测试 | 备注 | 176 | | ------- | :--: | :----: | :----: | ---- | 177 | | Python2 | √ | | | | 178 | | Python3 | √ | | | | 179 | 180 | ## 历史 181 | 182 | - 2021/06/01 - 1.0.0 版本 183 | 184 | ## 创作者 185 | 186 | Written by Arya(xue.peng@dfrobot.com), 2021. (Welcome to our [website](https://www.dfrobot.com/)) 187 | 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /python/raspberrypi/examples/demo_get_accel_gyro.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | ''' 4 | @file demo_get_accel_gyro.py 5 | @brief Get BMI160 6-axis sensor data including gyroscope, accelerometer, etc. 6 | @n ---------------------------------------------------------------------------------------- 7 | @n Sensor | raspberry pi | 8 | @n ----------------------------------------------------------------------------------------- 9 | @n + | 3V3/VCC | 3V3/VCC | 10 | @n - | GND | GND | 11 | @n C | connected to scl of MCU's IIC | SCL/3(BCM) | 12 | @n D | connected to sda of MCU's IIC | SDA/2(BCM) | 13 | @n INT1 | connected to the external interrupt IO pin of MCU | floating | 14 | @n INT2 | connected to the external interrupt IO pin of MCU | floating | 15 | @n SDO | connected to the IO pin of MCU or connected to GND or VCC | floating | 16 | @n ---------------------------------------------------------------------------------------- 17 | 18 | @Copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 19 | @licence The MIT License (MIT) 20 | @author [Arya](xue.peng@dfrobot.com) 21 | @version V1.0 22 | @date 2021-06-11 23 | @url from https://github.com/DFRobot/DFRobot_BME280 24 | ''' 25 | 26 | import sys 27 | import os 28 | import time 29 | 30 | sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) 31 | from DFRobot_BMI160 import * 32 | 33 | ''' 34 | @brief The constructor of the BMI160 sensor using IIC communication. 35 | @param addr: 7-bit IIC address, controlled by SDO pin. 36 | @n BMI160_IIC_ADDR_SDO_H or 0x69: SDO pull high.(default) 37 | @n BMI160_IIC_ADDR_SDO_L or 0x68: SDO pull down. 38 | ''' 39 | bmi = DFRobot_BMI160_IIC(addr = BMI160_IIC_ADDR_SDO_H) 40 | 41 | if __name__ == "__main__": 42 | ''' 43 | @brief Initialize sensor 44 | @return Error code: 45 | BMI160_OK or 0 : init succeeded, no error 46 | BMI160_E_NULL_PTR or -1 : the parameters is empty 47 | BMI160_E_COM_FAIL or -2 : interaction failed 48 | BMI160_E_DEV_NOT_FOUND or -3 : device not connected 49 | BMI160_E_OUT_OF_RANGE or -4 : out of sensor range 50 | BMI160_E_INVALID_INPUT or -5 : invalid input 51 | BMI160_E_ACCEL_ODR_BW_INVALID or -6 : accelerometer data output rate is invalid 52 | BMI160_E_GYRO_ODR_BW_INVALID or -7 : gyroscope data output rate is invalid 53 | BMI160_E_LWP_PRE_FLTR_INT_INVALID or -8 : low-power interrupt filter is invalid 54 | BMI160_E_LWP_PRE_FLTR_INVALID or -9 : low-power filter is invalid 55 | BMI160_FOC_FAILURE or -11: crystal oscillator failed 56 | ''' 57 | while bmi.begin() != BMI160_OK: 58 | print("Initialization 6-axis sensor failed.") 59 | time.sleep(1) 60 | print("Initialization 6-axis sensor sucess.") 61 | 62 | 63 | while True: 64 | ''' 65 | @brief Get sensor data, including data of gyroscope, accelerometer, etc. 66 | @return Return data of dictionary type, the format is as follows: 67 | @n {'accel':{'x':0, 'y':0, 'z':0}, 'gyro':{'x':0, 'y':0, 'z':0}} 68 | @n Note: it's raw data, process it to get the correct data: 69 | @n Gyroscope: each axis of gyroscope data *3.14/180.0, after calculation, unit is rad/s 70 | @n Accelerometer: each axis of accelerometer data//16384.0, after calculation, unit is g 71 | ''' 72 | data = bmi.get_sensor_data() 73 | print("gyro : x: %.3f rad/s, y: %.3f rad/s, z: %.3f rad/s"%(data['gyro']['x']*3.14/180.0, data['gyro']['y']*3.14/180.0, data['gyro']['z']*3.14/180.0)) 74 | print("accel : x: %.3f g , y: %.3f g , z: %.3f g "%(data['accel']['x']/16384.0, data['accel']['y']/16384.0, data['accel']['z']/16384.0)) 75 | print("\n") 76 | time.sleep(0.1) 77 | -------------------------------------------------------------------------------- /python/raspberrypi/examples/demo_step_counter_low_power.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | ''' 4 | @file demo_step_counter_low_power.py 5 | @brief Through the example, you can get the sensor data which means step counter. 6 | @n Set step counter power mode by setStepPowerMode(stepNormalPowerMode means normal mode, stepLowPowerMode means low power mode) 7 | @n Upload interrupt number by set_int (choose int1 or int2) 8 | @n data from int1 and int2 read in readStepCounter 9 | 10 | @n Hardware conneted table in IIC 11 | @n Hardware conneted table in IIC 12 | @n ---------------------------------------------------------------------------------------- 13 | @n Sensor | raspberry pi | 14 | @n ----------------------------------------------------------------------------------------- 15 | @n + | 3V3/VCC | 3V3/VCC | 16 | @n - | GND | GND | 17 | @n C | connected to scl of MCU's IIC | SCL/3(BCM) | 18 | @n D | connected to sda of MCU's IIC | SDA/2(BCM) | 19 | @n INT1 | connected to the external interrupt IO pin of MCU | 22(BCM) | 20 | @n INT2 | connected to the external interrupt IO pin of MCU | floating | 21 | @n SDO | connected to the IO pin of MCU or connected to GND or VCC | floating | 22 | @n ---------------------------------------------------------------------------------------- 23 | 24 | @Copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 25 | @licence The MIT License (MIT) 26 | @author [Arya](xue.peng@dfrobot.com) 27 | @version V1.0 28 | @date 2021-06-10 29 | @url from https://github.com/DFRobot/DFRobot_BMI160 30 | ''' 31 | 32 | import sys 33 | import os 34 | import time 35 | import RPi.GPIO as GPIO 36 | 37 | GPIO.setmode(GPIO.BCM) 38 | GPIO.setwarnings(False) 39 | 40 | sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) 41 | from DFRobot_BMI160 import * 42 | 43 | ''' 44 | @brief The constructor of the BMI160 sensor using IIC communication. 45 | @param addr: 7-bit IIC address, controlled by SDO pin. 46 | @n BMI160_IIC_ADDR_SDO_H or 0x69: SDO pull high.(default) 47 | @n BMI160_IIC_ADDR_SDO_L or 0x68: SDO pull down. 48 | ''' 49 | bmi = DFRobot_BMI160_IIC(addr = BMI160_IIC_ADDR_SDO_H) 50 | 51 | read_step = False 52 | def step_change(channel): 53 | global read_step 54 | read_step = True #once the step conter is changed, the value can be read 55 | 56 | 57 | if __name__ == "__main__": 58 | ''' 59 | @brief Initialize sensor 60 | @return Error code: 61 | BMI160_OK or 0 : init succeeded, no error 62 | BMI160_E_NULL_PTR or -1 : the parameters is empty 63 | BMI160_E_COM_FAIL or -2 : interaction failed 64 | BMI160_E_DEV_NOT_FOUND or -3 : device not connected 65 | BMI160_E_OUT_OF_RANGE or -4 : out of sensor range 66 | BMI160_E_INVALID_INPUT or -5 : invalid input 67 | BMI160_E_ACCEL_ODR_BW_INVALID or -6 : accelerometer data output rate is invalid 68 | BMI160_E_GYRO_ODR_BW_INVALID or -7 : gyroscope data output rate is invalid 69 | BMI160_E_LWP_PRE_FLTR_INT_INVALID or -8 : low-power interrupt filter is invalid 70 | BMI160_E_LWP_PRE_FLTR_INVALID or -9 : low-power filter is invalid 71 | BMI160_FOC_FAILURE or -11: crystal oscillator failed 72 | ''' 73 | while bmi.begin() != BMI160_OK: 74 | print("Initialization 6-axis sensor failed.") 75 | time.sleep(1) 76 | print("Initialization 6-axis sensor sucess.") 77 | 78 | ''' 79 | @brief Configure interrupt pin 80 | @param intNum: The INT pin of sensor, INT1 or INT2: 81 | @n 1 : The INT1 pin of sensor 82 | @n 2 : The INT2 pin of sensor 83 | @return Error code: 84 | BMI160_OK or 0 : Config succeeded 85 | others value : Config failed 86 | ''' 87 | if bmi.set_int(1) != BMI160_OK: 88 | print("set interrput fail") 89 | 90 | ''' 91 | @brief Set step count 92 | @return Error code: 93 | @n BMI160_OK or 0 : setting succeeded 94 | @n others value : setting failed 95 | ''' 96 | if bmi.set_step_counter() != BMI160_OK: 97 | print("set step fail") 98 | 99 | ''' 100 | @brief Set pedometer power mode 101 | @param model: Power mode type 102 | @n step_normal_power_mode: Count step in normal power mode 103 | @n step_lower_power_mode : Count step in low power mode 104 | @return Error code: 105 | BMI160_OK or 0 : Setting succeeded 106 | others value : Setting failed 107 | ''' 108 | if bmi.set_step_power_mode(bmi.step_lower_power_mode) != BMI160_OK: 109 | print("set step_low_power_mode fail") 110 | GPIO.setup(22, GPIO.IN)#22: the exteral pin of raspberry pi which is connected to INT1 111 | GPIO.add_event_detect(22, GPIO.FALLING, step_change) 112 | 113 | while True: 114 | if read_step: 115 | ''' 116 | @brief Read step count data 117 | @return Data of dictionary type, the format is error code + current step count data: 118 | @n {'error':0, 'step':0} 119 | @n Note: when 'error' value is BMI160_OK, it means that 'step' is valid data, otherwise it is invalid data. 120 | ''' 121 | rslt = bmi.read_step_counter() 122 | if rslt['error'] == BMI160_OK: 123 | print("step counter = %d"%rslt['step']) 124 | read_step = False 125 | -------------------------------------------------------------------------------- /python/raspberrypi/examples/demo_step_counter_normal.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | ''' 4 | @file demo_step_counter_normalpy 5 | @brief Through the example, you can get the sensor data which means step counter. 6 | @n Set step counter power mode by setStepPowerMode(stepNormalPowerMode means normal model, stepLowPowerMode means low power model) 7 | @n Upload interrupt number by set_int (choose int1 or int2) 8 | @n data from int1 and int2 read in readStepCounter 9 | 10 | @n Hardware conneted table in IIC 11 | @n Hardware conneted table in IIC 12 | @n ---------------------------------------------------------------------------------------- 13 | @n Sensor | raspberry pi | 14 | @n ----------------------------------------------------------------------------------------- 15 | @n + | 3V3/VCC | 3V3/VCC | 16 | @n - | GND | GND | 17 | @n C | connected to scl of MCU's IIC | SCL/3(BCM) | 18 | @n D | connected to sda of MCU's IIC | SDA/2(BCM) | 19 | @n INT1 | connected to the external interrupt IO pin of MCU | floating | 20 | @n INT2 | connected to the external interrupt IO pin of MCU | 22(BCM) | 21 | @n SDO | connected to the IO pin of MCU or connected to GND or VCC | floating | 22 | @n ---------------------------------------------------------------------------------------- 23 | 24 | @Copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 25 | @licence The MIT License (MIT) 26 | @author [Arya](xue.peng@dfrobot.com) 27 | @version V1.0 28 | @date 2021-06-10 29 | @url from https://github.com/DFRobot/DFRobot_BMI160 30 | ''' 31 | 32 | import sys 33 | import os 34 | import time 35 | import RPi.GPIO as GPIO 36 | 37 | GPIO.setmode(GPIO.BCM) 38 | GPIO.setwarnings(False) 39 | 40 | sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) 41 | from DFRobot_BMI160 import * 42 | 43 | ''' 44 | @brief The constructor of the BMI160 sensor using IIC communication. 45 | @param addr: 7-bit IIC address, controlled by SDO pin. 46 | @n BMI160_IIC_ADDR_SDO_H or 0x69: SDO pull high.(default) 47 | @n BMI160_IIC_ADDR_SDO_L or 0x68: SDO pull down. 48 | ''' 49 | bmi = DFRobot_BMI160_IIC(addr = BMI160_IIC_ADDR_SDO_H) 50 | 51 | read_step = False 52 | def step_change(channel): 53 | global read_step 54 | read_step = True #once the step conter is changed, the value can be read 55 | 56 | 57 | if __name__ == "__main__": 58 | ''' 59 | @brief Initialize sensor 60 | @return Error code: 61 | BMI160_OK or 0 : init succeeded, no error 62 | BMI160_E_NULL_PTR or -1 : the parameters is empty 63 | BMI160_E_COM_FAIL or -2 : interaction failed 64 | BMI160_E_DEV_NOT_FOUND or -3 : device not connected 65 | BMI160_E_OUT_OF_RANGE or -4 : out of sensor range 66 | BMI160_E_INVALID_INPUT or -5 : invalid input 67 | BMI160_E_ACCEL_ODR_BW_INVALID or -6 : accelerometer data output rate is invalid 68 | BMI160_E_GYRO_ODR_BW_INVALID or -7 : gyroscope data output rate is invalid 69 | BMI160_E_LWP_PRE_FLTR_INT_INVALID or -8 : low-power interrupt filter is invalid 70 | BMI160_E_LWP_PRE_FLTR_INVALID or -9 : low-power filter is invalid 71 | BMI160_FOC_FAILURE or -11: crystal oscillator failed 72 | ''' 73 | while bmi.begin() != BMI160_OK: 74 | print("Initialization 6-axis sensor failed.") 75 | time.sleep(1) 76 | print("Initialization 6-axis sensor sucess.") 77 | 78 | ''' 79 | @brief Configure interrupt pin 80 | @param intNum: The INT pin of sensor, INT1 or INT2: 81 | @n 1 : The INT1 pin of sensor 82 | @n 2 : The INT2 pin of sensor 83 | @return Error code: 84 | BMI160_OK or 0 : Config succeeded 85 | others value : Config failed 86 | ''' 87 | if bmi.set_int(2) != BMI160_OK: 88 | print("set interrput fail") 89 | 90 | ''' 91 | @brief Set step count 92 | @return Error code: 93 | @n BMI160_OK or 0 : Setting succeeded 94 | @n others value : Setting failed 95 | ''' 96 | if bmi.set_step_counter() != BMI160_OK: 97 | print("set step fail") 98 | 99 | ''' 100 | @brief Set pedometer power mode 101 | @param model: Power mode type 102 | @n step_normal_power_mode: Count step in normal power mode 103 | @n step_lower_power_mode : Count step in low power mode 104 | @return Error code: 105 | BMI160_OK or 0 : setting succeeded 106 | others value : setting failed 107 | ''' 108 | if bmi.set_step_power_mode(bmi.step_normal_power_mode) != BMI160_OK: 109 | print("set step_normal_power_mode fail") 110 | GPIO.setup(22, GPIO.IN) #22: the exteral pin of raspberry pi which is connected to INT2 111 | GPIO.add_event_detect(22, GPIO.FALLING, step_change) 112 | 113 | while True: 114 | if read_step: 115 | ''' 116 | @brief Read step count data 117 | @return Data of dictionary type, the format is error code + current step count data: 118 | @n {'error':0, 'step':0} 119 | @n Note: when 'error' value is BMI160_OK, it means that 'step' is valid data, otherwise it is invalid data. 120 | ''' 121 | rslt = bmi.read_step_counter() 122 | if rslt['error'] == BMI160_OK: 123 | print("step counter = %d"%rslt['step']) 124 | read_step = False 125 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # DFRobot_BMI160 2 | 3 | * [中文](./README_CN.md) 4 | 5 | The BMI160 is a highly integrated, low power inertial measurement unit (IMU) that provides precise acceleration and angular rate (gyroscopic) measurement.
6 | The BMI160 contains 16 bit digtial,triaxial accelerometer and 16 bit digital, triaxial gyroscope.
7 | This example is for BMI160 sensor and it oprated via Arduino I2C.
8 | 9 | ![产品效果图](./resources/images/SEN0250.png) 10 | 11 | ## Product Link([https://www.dfrobot.com/product-1716.html](https://www.dfrobot.com/product-1716.html)) 12 | SKU: SEN0250 13 | 14 | ## Table of Contents 15 | 16 | * [Summary](#summary) 17 | * [Installation](#installation) 18 | * [Methods](#methods) 19 | * [Compatibility](#compatibility) 20 | * [History](#history) 21 | * [Credits](#credits) 22 | 23 | ## Summary 24 | 25 | Provide an Arduino library to control the bmi160 to get accel, gyro and step counter, via I2C communication. 26 | 27 | ## Installation 28 | 29 | To use this library, first download the library file, paste it into the \Arduino\libraries directory, then open the examples folder and run the demo in the folder. 30 | 31 | ## Methods 32 | 33 | ```C++ 34 | 35 | /** 36 | * @fn I2cInit 37 | * @brief set the i2c addr and init the i2c. 38 | * @param i2c_addr bmi160 i2c addr 39 | * @n 0x68: connect SDIO pin of the BMI160 to GND which means the default I2C address 40 | * @n 0x69: set I2C address by parameter 41 | * @return BMI160_OK(0) means success 42 | */ 43 | int8_t I2cInit(int8_t i2c_addr = BMI160_I2C_ADDR); 44 | 45 | /** 46 | * @fn getSensorData 47 | * @brief select mode and save returned data to parameter data. 48 | * @param type three type 49 | * @n onlyAccel : only get the accel data 50 | * @n onlyGyro : only get the gyro data 51 | * @n bothAccelGyro: get boath accel and gyro data 52 | * @param data save returned data to parameter data 53 | * @return BMI160_OK(0) means succse 54 | */ 55 | int8_t getSensorData(uint8_t type,int16_t* data); 56 | 57 | /** 58 | * @fn getAccelData 59 | * @brief get the accel data 60 | * @param data pointer to store the accel data 61 | * @return BMI160_OK(0) means succse 62 | */ 63 | int8_t getAccelData(int16_t* data); 64 | 65 | /** 66 | * @fn getGyroData 67 | * @brief get the gyro data 68 | * @param data pointer to store the gyro data 69 | * @return BMI160_OK(0) means succse 70 | */ 71 | int8_t getGyroData(int16_t* data); 72 | 73 | /** 74 | * @fn getAccelGyroData 75 | * @brief get the accel and gyro data 76 | * @param data pointer to store the accel and gyro data 77 | * @return BMI160_OK(0) means succse 78 | */ 79 | int8_t getAccelGyroData(int16_t* data); 80 | 81 | /** 82 | * @fn softReset 83 | * @brief reset bmi160 hardware 84 | * @return BMI160_OK(0) means success 85 | */ 86 | int8_t softReset(); 87 | 88 | /** 89 | * @fn setInt 90 | * @brief set interrupt number and choosing step detector interrupt 91 | * @param intNum choose int1 or int2 92 | * @return BMI160_OK(0) means succse 93 | */ 94 | int8_t setInt(int intNum); 95 | 96 | /** 97 | * @fn setStepCounter 98 | * @brief enable the step counter 99 | * @return BMI160_OK(0) means succse 100 | */ 101 | int8_t setStepCounter(); 102 | 103 | /** 104 | * @fn readStepCounter 105 | * @brief read the step counter from bmi160 106 | * @param stepVal pointer to store the step 107 | * @return BMI160_OK(0) measn succse 108 | */ 109 | int8_t readStepCounter(uint16_t *stepVal); 110 | /** 111 | * @fn setStepPowerMode 112 | * @brief set the step power model 113 | * @param model type of model 114 | * @return BMI160_OK(0) measn succse 115 | */ 116 | int8_t setStepPowerMode(uint8_t model); 117 | 118 | ``` 119 | 120 | ## Compatibility 121 | 122 | MCU | Work Well | Work Wrong | Untested | Remarks 123 | ------------------ | :----------: | :----------: | :---------: | ----- 124 | FireBeetle-ESP32 | √ | | | 125 | FireBeetle-ESP8266 | √ | | | 126 | Arduino uno | √ | | | 127 | 128 | 129 | ## History 130 | 131 | - 2017-12-01 - Version 1.0.0 released. 132 | 133 | 134 | ## Credits 135 | 136 | Written by DFRobot_haoJ(hao.jiang@dfrobot.com), 2017. (Welcome to our [website](https://www.dfrobot.com/)) 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /resources/images/SEN0250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DFRobot/DFRobot_BMI160/6abe9dc9ed817a806c1a143ff6adc92a2c4e9985/resources/images/SEN0250.png --------------------------------------------------------------------------------