Statistics
| Branch: | Revision:

adafruit_bno055 / Adafruit_BNO055.cpp @ f7556b0d

History | View | Annotate | Download (22.98 KB)

1
/*!
2
 * @file Adafruit_BNO055.cpp
3
 *
4
 *  @mainpage Adafruit BNO055 Orientation Sensor
5
 *
6
 *  @section intro_sec Introduction
7
 *
8
 *  This is a library for the BNO055 orientation sensor
9
 *
10
 *  Designed specifically to work with the Adafruit BNO055 Breakout.
11
 *
12
 *  Pick one up today in the adafruit shop!
13
 *  ------> https://www.adafruit.com/product/2472
14
 *
15
 *  These sensors use I2C to communicate, 2 pins are required to interface.
16
 *
17
 *  Adafruit invests time and resources providing this open source code,
18
 *  please support Adafruit andopen-source hardware by purchasing products
19
 *  from Adafruit!
20
 *
21
 *  @section author Author
22
 *
23
 *  K.Townsend (Adafruit Industries)
24
 *
25
 *  @section license License
26
 *
27
 *  MIT license, all text above must be included in any redistribution
28
 */
29

    
30
#include "Arduino.h"
31

    
32
#include <limits.h>
33
#include <math.h>
34

    
35
#include "Adafruit_BNO055.h"
36

    
37
/*!
38
 *  @brief  Instantiates a new Adafruit_BNO055 class
39
 */
40
Adafruit_BNO055::Adafruit_BNO055() {}
41

    
42
/*!
43
 *  @brief  Sets up the HW
44
 *  @param  mode
45
 *          mode values
46
 *           [OPERATION_MODE_CONFIG,
47
 *            OPERATION_MODE_ACCONLY,
48
 *            OPERATION_MODE_MAGONLY,
49
 *            OPERATION_MODE_GYRONLY,
50
 *            OPERATION_MODE_ACCMAG,
51
 *            OPERATION_MODE_ACCGYRO,
52
 *            OPERATION_MODE_MAGGYRO,
53
 *            OPERATION_MODE_AMG,
54
 *            OPERATION_MODE_IMUPLUS,
55
 *            OPERATION_MODE_COMPASS,
56
 *            OPERATION_MODE_M4G,
57
 *            OPERATION_MODE_NDOF_FMC_OFF,
58
 *            OPERATION_MODE_NDOF]
59
 *  @param  *theWire
60
 *          Wire object
61
 *  @return true if process is successful
62
 */
63
bool Adafruit_BNO055::begin() {
64
  _wire = &Wire;
65
#if defined(ARDUINO_SAMD_ZERO) && !(ARDUINO_SAMD_FEATHER_M0)
66
#error                                                                         \
67
    "On an arduino Zero, BNO055's ADR pin must be high. Fix that, then delete this line."
68
  _address = BNO055_ADDRESS_B;
69
#else
70
  _address = BNO055_ADDRESS_A;
71
#endif
72

    
73
  return init(OPERATION_MODE_NDOF);
74
}
75

    
76
/*!
77
 *  @brief  Sets up the HW
78
 *  @param  mode
79
 *          mode values
80
 *           [OPERATION_MODE_CONFIG,
81
 *            OPERATION_MODE_ACCONLY,
82
 *            OPERATION_MODE_MAGONLY,
83
 *            OPERATION_MODE_GYRONLY,
84
 *            OPERATION_MODE_ACCMAG,
85
 *            OPERATION_MODE_ACCGYRO,
86
 *            OPERATION_MODE_MAGGYRO,
87
 *            OPERATION_MODE_AMG,
88
 *            OPERATION_MODE_IMUPLUS,
89
 *            OPERATION_MODE_COMPASS,
90
 *            OPERATION_MODE_M4G,
91
 *            OPERATION_MODE_NDOF_FMC_OFF,
92
 *            OPERATION_MODE_NDOF]
93
 *  @param  *theWire
94
 *          Wire object
95
 *  @return true if process is successful
96
 */
97
bool Adafruit_BNO055::begin(adafruit_bno055_opmode_t mode, uint8_t address,
98
                            TwoWire *theWire) {
99
  _wire = theWire;
100
  _address = address;
101

    
102
  return init(mode);
103
}
104

    
105
bool Adafruit_BNO055::init(adafruit_bno055_opmode_t mode) {
106
  /* Enable I2C */
107
  _wire->begin();
108

    
109
  /* BNO055 clock stretches for 500us or more! */
110
#ifdef ESP8266
111
  /* Allow for 1000us of clock stretching */
112
<<<<<<< HEAD
113
  _wire->setClockStretchLimit(1000);
114
=======
115
  Wire.setClockStretchLimit(1000);
116
>>>>>>> 75f03d2e1fd440e7febc0de8c47a52bab09c51b0
117
#endif
118

    
119
  /* Make sure we have the right device */
120
  uint8_t id = read8(BNO055_CHIP_ID_ADDR);
121
  if (id != BNO055_ID) {
122
    /* hold on for boot */
123
    delay(1000);
124
    id = read8(BNO055_CHIP_ID_ADDR);
125
    if (id != BNO055_ID) {
126
      /* still not? ok bail */
127
      return false;
128
    }
129
  }
130

    
131
  /* Switch to config mode (just in case since this is the default) */
132
  setMode(OPERATION_MODE_CONFIG);
133

    
134
  /* Reset */
135
  write8(BNO055_SYS_TRIGGER_ADDR, 0x20);
136
  while (read8(BNO055_CHIP_ID_ADDR) != BNO055_ID) {
137
    delay(10);
138
  }
139
  delay(50);
140

    
141
  /* Set to normal power mode */
142
  write8(BNO055_PWR_MODE_ADDR, POWER_MODE_NORMAL);
143
  delay(10);
144

    
145
  write8(BNO055_PAGE_ID_ADDR, 0);
146

    
147
  /* Set the output units
148
     uint8_t unitsel = (0 << 7) | // Orientation = Android
149
                       (0 << 4) | // Temperature = Celsius
150
                       (0 << 2) | // Euler = Degrees
151
                       (1 << 1) | // Gyro = Rads
152
                       (0 << 0);  // Accelerometer = m/s^2
153
     write8(BNO055_UNIT_SEL_ADDR, unitsel);
154
   */
155

    
156
  /* Configure axis mapping (see section 3.4) */
157
  write8(BNO055_SYS_TRIGGER_ADDR, 0x0);
158
  delay(10);
159
  /* Set the requested operating mode (see section 3.3) */
160
  setMode(mode);
161
  delay(20);
162

    
163
  return true;
164
}
165

    
166
/*!
167
 *  @brief  Puts the chip in the specified operating mode
168
 *  @param  mode
169
 *          mode values
170
 *           [OPERATION_MODE_CONFIG,
171
 *            OPERATION_MODE_ACCONLY,
172
 *            OPERATION_MODE_MAGONLY,
173
 *            OPERATION_MODE_GYRONLY,
174
 *            OPERATION_MODE_ACCMAG,
175
 *            OPERATION_MODE_ACCGYRO,
176
 *            OPERATION_MODE_MAGGYRO,
177
 *            OPERATION_MODE_AMG,
178
 *            OPERATION_MODE_IMUPLUS,
179
 *            OPERATION_MODE_COMPASS,
180
 *            OPERATION_MODE_M4G,
181
 *            OPERATION_MODE_NDOF_FMC_OFF,
182
 *            OPERATION_MODE_NDOF]
183
 */
184
void Adafruit_BNO055::setMode(adafruit_bno055_opmode_t mode) {
185
  _mode = mode;
186
  write8(BNO055_OPR_MODE_ADDR, _mode);
187
  delay(30);
188
}
189

    
190
/*!
191
 *  @brief  Changes the chip's axis remap
192
 *  @param  remapcode
193
 *          remap code possible values
194
 *          [REMAP_CONFIG_P0
195
 *           REMAP_CONFIG_P1 (default)
196
 *           REMAP_CONFIG_P2
197
 *           REMAP_CONFIG_P3
198
 *           REMAP_CONFIG_P4
199
 *           REMAP_CONFIG_P5
200
 *           REMAP_CONFIG_P6
201
 *           REMAP_CONFIG_P7]
202
 */
203
void Adafruit_BNO055::setAxisRemap(
204
    adafruit_bno055_axis_remap_config_t remapcode) {
205
  adafruit_bno055_opmode_t modeback = _mode;
206

    
207
  setMode(OPERATION_MODE_CONFIG);
208
  delay(25);
209
  write8(BNO055_AXIS_MAP_CONFIG_ADDR, remapcode);
210
  delay(10);
211
  /* Set the requested operating mode (see section 3.3) */
212
  setMode(modeback);
213
  delay(20);
214
}
215

    
216
/*!
217
 *  @brief  Changes the chip's axis signs
218
 *  @param  remapsign
219
 *          remap sign possible values
220
 *          [REMAP_SIGN_P0
221
 *           REMAP_SIGN_P1 (default)
222
 *           REMAP_SIGN_P2
223
 *           REMAP_SIGN_P3
224
 *           REMAP_SIGN_P4
225
 *           REMAP_SIGN_P5
226
 *           REMAP_SIGN_P6
227
 *           REMAP_SIGN_P7]
228
 */
229
void Adafruit_BNO055::setAxisSign(adafruit_bno055_axis_remap_sign_t remapsign) {
230
  adafruit_bno055_opmode_t modeback = _mode;
231

    
232
  setMode(OPERATION_MODE_CONFIG);
233
  delay(25);
234
  write8(BNO055_AXIS_MAP_SIGN_ADDR, remapsign);
235
  delay(10);
236
  /* Set the requested operating mode (see section 3.3) */
237
  setMode(modeback);
238
  delay(20);
239
}
240

    
241
/*!
242
 *  @brief  Use the external 32.768KHz crystal
243
 *  @param  usextal
244
 *          use external crystal boolean
245
 */
246
void Adafruit_BNO055::setExtCrystalUse(boolean usextal) {
247
  adafruit_bno055_opmode_t modeback = _mode;
248

    
249
  /* Switch to config mode (just in case since this is the default) */
250
  setMode(OPERATION_MODE_CONFIG);
251
  delay(25);
252
  write8(BNO055_PAGE_ID_ADDR, 0);
253
  if (usextal) {
254
    write8(BNO055_SYS_TRIGGER_ADDR, 0x80);
255
  } else {
256
    write8(BNO055_SYS_TRIGGER_ADDR, 0x00);
257
  }
258
  delay(10);
259
  /* Set the requested operating mode (see section 3.3) */
260
  setMode(modeback);
261
  delay(20);
262
}
263

    
264
/*!
265
 *   @brief  Gets the latest system status info
266
 *   @param  system_status
267
 *           system status info
268
 *   @param  self_test_result
269
 *           self test result
270
 *   @param  system_error
271
 *           system error info
272
 */
273
void Adafruit_BNO055::getSystemStatus(uint8_t *system_status,
274
                                      uint8_t *self_test_result,
275
                                      uint8_t *system_error) {
276
  write8(BNO055_PAGE_ID_ADDR, 0);
277

    
278
  /* System Status (see section 4.3.58)
279
     0 = Idle
280
     1 = System Error
281
     2 = Initializing Peripherals
282
     3 = System Iniitalization
283
     4 = Executing Self-Test
284
     5 = Sensor fusio algorithm running
285
     6 = System running without fusion algorithms
286
   */
287

    
288
  if (system_status != 0)
289
    *system_status = read8(BNO055_SYS_STAT_ADDR);
290

    
291
  /* Self Test Results
292
     1 = test passed, 0 = test failed
293

294
     Bit 0 = Accelerometer self test
295
     Bit 1 = Magnetometer self test
296
     Bit 2 = Gyroscope self test
297
     Bit 3 = MCU self test
298

299
     0x0F = all good!
300
   */
301

    
302
  if (self_test_result != 0)
303
    *self_test_result = read8(BNO055_SELFTEST_RESULT_ADDR);
304

    
305
  /* System Error (see section 4.3.59)
306
     0 = No error
307
     1 = Peripheral initialization error
308
     2 = System initialization error
309
     3 = Self test result failed
310
     4 = Register map value out of range
311
     5 = Register map address out of range
312
     6 = Register map write error
313
     7 = BNO low power mode not available for selected operat ion mode
314
     8 = Accelerometer power mode not available
315
     9 = Fusion algorithm configuration error
316
     A = Sensor configuration error
317
   */
318

    
319
  if (system_error != 0)
320
    *system_error = read8(BNO055_SYS_ERR_ADDR);
321

    
322
  delay(200);
323
}
324

    
325
/*!
326
 *  @brief  Gets the chip revision numbers
327
 *  @param  info
328
 *          revision info
329
 */
330
void Adafruit_BNO055::getRevInfo(adafruit_bno055_rev_info_t *info) {
331
  uint8_t a, b;
332

    
333
  memset(info, 0, sizeof(adafruit_bno055_rev_info_t));
334

    
335
  /* Check the accelerometer revision */
336
  info->accel_rev = read8(BNO055_ACCEL_REV_ID_ADDR);
337

    
338
  /* Check the magnetometer revision */
339
  info->mag_rev = read8(BNO055_MAG_REV_ID_ADDR);
340

    
341
  /* Check the gyroscope revision */
342
  info->gyro_rev = read8(BNO055_GYRO_REV_ID_ADDR);
343

    
344
  /* Check the SW revision */
345
  info->bl_rev = read8(BNO055_BL_REV_ID_ADDR);
346

    
347
  a = read8(BNO055_SW_REV_ID_LSB_ADDR);
348
  b = read8(BNO055_SW_REV_ID_MSB_ADDR);
349
  info->sw_rev = (((uint16_t)b) << 8) | ((uint16_t)a);
350
}
351

    
352
/*!
353
 *  @brief  Gets current calibration state.  Each value should be a uint8_t
354
 *          pointer and it will be set to 0 if not calibrated and 3 if
355
 *          fully calibrated.
356
 *          See section 34.3.54
357
 *  @param  sys
358
 *          Current system calibration status, depends on status of all sensors,
359
 * read-only
360
 *  @param  gyro
361
 *          Current calibration status of Gyroscope, read-only
362
 *  @param  accel
363
 *          Current calibration status of Accelerometer, read-only
364
 *  @param  mag
365
 *          Current calibration status of Magnetometer, read-only
366
 */
367
void Adafruit_BNO055::getCalibration(uint8_t *sys, uint8_t *gyro,
368
                                     uint8_t *accel, uint8_t *mag) {
369
  uint8_t calData = read8(BNO055_CALIB_STAT_ADDR);
370
  if (sys != NULL) {
371
    *sys = (calData >> 6) & 0x03;
372
  }
373
  if (gyro != NULL) {
374
    *gyro = (calData >> 4) & 0x03;
375
  }
376
  if (accel != NULL) {
377
    *accel = (calData >> 2) & 0x03;
378
  }
379
  if (mag != NULL) {
380
    *mag = calData & 0x03;
381
  }
382
}
383

    
384
/*!
385
 *  @brief  Gets the temperature in degrees celsius
386
 *  @return temperature in degrees celsius
387
 */
388
int8_t Adafruit_BNO055::getTemp() {
389
  int8_t temp = (int8_t)(read8(BNO055_TEMP_ADDR));
390
  return temp;
391
}
392

    
393
/*!
394
 *  @brief   Gets a vector reading from the specified source
395
 *  @param   vector_type
396
 *           possible vector type values
397
 *           [VECTOR_ACCELEROMETER
398
 *            VECTOR_MAGNETOMETER
399
 *            VECTOR_GYROSCOPE
400
 *            VECTOR_EULER
401
 *            VECTOR_LINEARACCEL
402
 *            VECTOR_GRAVITY]
403
 *  @return  vector from specified source
404
 */
405
imu::Vector<3> Adafruit_BNO055::getVector(adafruit_vector_type_t vector_type) {
406
  imu::Vector<3> xyz;
407
  uint8_t buffer[6];
408
  memset(buffer, 0, 6);
409

    
410
  int16_t x, y, z;
411
  x = y = z = 0;
412

    
413
  /* Read vector data (6 bytes) */
414
  readLen((adafruit_bno055_reg_t)vector_type, buffer, 6);
415

    
416
  x = ((int16_t)buffer[0]) | (((int16_t)buffer[1]) << 8);
417
  y = ((int16_t)buffer[2]) | (((int16_t)buffer[3]) << 8);
418
  z = ((int16_t)buffer[4]) | (((int16_t)buffer[5]) << 8);
419

    
420
  /*!
421
   * Convert the value to an appropriate range (section 3.6.4)
422
   * and assign the value to the Vector type
423
   */
424
  switch (vector_type) {
425
  case VECTOR_MAGNETOMETER:
426
    /* 1uT = 16 LSB */
427
    xyz[0] = ((double)x) / 16.0;
428
    xyz[1] = ((double)y) / 16.0;
429
    xyz[2] = ((double)z) / 16.0;
430
    break;
431
  case VECTOR_GYROSCOPE:
432
    /* 1dps = 16 LSB */
433
    xyz[0] = ((double)x) / 16.0;
434
    xyz[1] = ((double)y) / 16.0;
435
    xyz[2] = ((double)z) / 16.0;
436
    break;
437
  case VECTOR_EULER:
438
    /* 1 degree = 16 LSB */
439
    xyz[0] = ((double)x) / 16.0;
440
    xyz[1] = ((double)y) / 16.0;
441
    xyz[2] = ((double)z) / 16.0;
442
    break;
443
  case VECTOR_ACCELEROMETER:
444
  case VECTOR_LINEARACCEL:
445
  case VECTOR_GRAVITY:
446
    /* 1m/s^2 = 100 LSB */
447
    xyz[0] = ((double)x) / 100.0;
448
    xyz[1] = ((double)y) / 100.0;
449
    xyz[2] = ((double)z) / 100.0;
450
    break;
451
  }
452

    
453
  return xyz;
454
}
455

    
456
/*!
457
 *  @brief  Gets a quaternion reading from the specified source
458
 *  @return quaternion reading
459
 */
460
imu::Quaternion Adafruit_BNO055::getQuat() {
461
  uint8_t buffer[8];
462
  memset(buffer, 0, 8);
463

    
464
  int16_t x, y, z, w;
465
  x = y = z = w = 0;
466

    
467
  /* Read quat data (8 bytes) */
468
  readLen(BNO055_QUATERNION_DATA_W_LSB_ADDR, buffer, 8);
469
  w = (((uint16_t)buffer[1]) << 8) | ((uint16_t)buffer[0]);
470
  x = (((uint16_t)buffer[3]) << 8) | ((uint16_t)buffer[2]);
471
  y = (((uint16_t)buffer[5]) << 8) | ((uint16_t)buffer[4]);
472
  z = (((uint16_t)buffer[7]) << 8) | ((uint16_t)buffer[6]);
473

    
474
  /*!
475
   * Assign to Quaternion
476
   * See
477
   * http://ae-bst.resource.bosch.com/media/products/dokumente/bno055/BST_BNO055_DS000_12~1.pdf
478
   * 3.6.5.5 Orientation (Quaternion)
479
   */
480
  const double scale = (1.0 / (1 << 14));
481
  imu::Quaternion quat(scale * w, scale * x, scale * y, scale * z);
482
  return quat;
483
}
484

    
485
/*!
486
 *  @brief  Provides the sensor_t data for this sensor
487
 *  @param  sensor
488
 */
489
void Adafruit_BNO055::getSensor(sensor_t *sensor) {
490
  /* Clear the sensor_t object */
491
  memset(sensor, 0, sizeof(sensor_t));
492

    
493
  /* Insert the sensor name in the fixed length char array */
494
  strncpy(sensor->name, "BNO055", sizeof(sensor->name) - 1);
495
  sensor->name[sizeof(sensor->name) - 1] = 0;
496
  sensor->version = 1;
497
  sensor->sensor_id = _sensorID;
498
  sensor->type = SENSOR_TYPE_ORIENTATION;
499
  sensor->min_delay = 0;
500
  sensor->max_value = 0.0F;
501
  sensor->min_value = 0.0F;
502
  sensor->resolution = 0.01F;
503
}
504

    
505
/*!
506
 *  @brief  Reads the sensor and returns the data as a sensors_event_t
507
 *  @param  event
508
 *  @return always returns true
509
 */
510
bool Adafruit_BNO055::getEvent(sensors_event_t *event) {
511
  /* Clear the event */
512
  memset(event, 0, sizeof(sensors_event_t));
513

    
514
  event->version = sizeof(sensors_event_t);
515
  event->sensor_id = _sensorID;
516
  event->type = SENSOR_TYPE_ORIENTATION;
517
  event->timestamp = millis();
518

    
519
  /* Get a Euler angle sample for orientation */
520
  imu::Vector<3> euler = getVector(Adafruit_BNO055::VECTOR_EULER);
521
  event->orientation.x = euler.x();
522
  event->orientation.y = euler.y();
523
  event->orientation.z = euler.z();
524

    
525
  return true;
526
}
527

    
528
/*!
529
 *  @brief  Reads the sensor's offset registers into a byte array
530
 *  @param  calibData
531
 *  @return true if read is successful
532
 */
533
bool Adafruit_BNO055::getSensorOffsets(uint8_t *calibData) {
534
  if (isFullyCalibrated()) {
535
    adafruit_bno055_opmode_t lastMode = _mode;
536
    setMode(OPERATION_MODE_CONFIG);
537

    
538
    readLen(ACCEL_OFFSET_X_LSB_ADDR, calibData, NUM_BNO055_OFFSET_REGISTERS);
539

    
540
    setMode(lastMode);
541
    return true;
542
  }
543
  return false;
544
}
545

    
546
/*!
547
 *  @brief  Reads the sensor's offset registers into an offset struct
548
 *  @param  offsets_type
549
 *  @return true if read is successful
550
 */
551
bool Adafruit_BNO055::getSensorOffsets(
552
    adafruit_bno055_offsets_t &offsets_type) {
553
  if (isFullyCalibrated()) {
554
    adafruit_bno055_opmode_t lastMode = _mode;
555
    setMode(OPERATION_MODE_CONFIG);
556
    delay(25);
557

    
558
    /* Accel offset range depends on the G-range:
559
       +/-2g  = +/- 2000 mg
560
       +/-4g  = +/- 4000 mg
561
       +/-8g  = +/- 8000 mg
562
       +/-1§g = +/- 16000 mg */
563
    offsets_type.accel_offset_x = (read8(ACCEL_OFFSET_X_MSB_ADDR) << 8) |
564
                                  (read8(ACCEL_OFFSET_X_LSB_ADDR));
565
    offsets_type.accel_offset_y = (read8(ACCEL_OFFSET_Y_MSB_ADDR) << 8) |
566
                                  (read8(ACCEL_OFFSET_Y_LSB_ADDR));
567
    offsets_type.accel_offset_z = (read8(ACCEL_OFFSET_Z_MSB_ADDR) << 8) |
568
                                  (read8(ACCEL_OFFSET_Z_LSB_ADDR));
569

    
570
    /* Magnetometer offset range = +/- 6400 LSB where 1uT = 16 LSB */
571
    offsets_type.mag_offset_x =
572
        (read8(MAG_OFFSET_X_MSB_ADDR) << 8) | (read8(MAG_OFFSET_X_LSB_ADDR));
573
    offsets_type.mag_offset_y =
574
        (read8(MAG_OFFSET_Y_MSB_ADDR) << 8) | (read8(MAG_OFFSET_Y_LSB_ADDR));
575
    offsets_type.mag_offset_z =
576
        (read8(MAG_OFFSET_Z_MSB_ADDR) << 8) | (read8(MAG_OFFSET_Z_LSB_ADDR));
577

    
578
    /* Gyro offset range depends on the DPS range:
579
      2000 dps = +/- 32000 LSB
580
      1000 dps = +/- 16000 LSB
581
       500 dps = +/- 8000 LSB
582
       250 dps = +/- 4000 LSB
583
       125 dps = +/- 2000 LSB
584
       ... where 1 DPS = 16 LSB */
585
    offsets_type.gyro_offset_x =
586
        (read8(GYRO_OFFSET_X_MSB_ADDR) << 8) | (read8(GYRO_OFFSET_X_LSB_ADDR));
587
    offsets_type.gyro_offset_y =
588
        (read8(GYRO_OFFSET_Y_MSB_ADDR) << 8) | (read8(GYRO_OFFSET_Y_LSB_ADDR));
589
    offsets_type.gyro_offset_z =
590
        (read8(GYRO_OFFSET_Z_MSB_ADDR) << 8) | (read8(GYRO_OFFSET_Z_LSB_ADDR));
591

    
592
    /* Accelerometer radius = +/- 1000 LSB */
593
    offsets_type.accel_radius =
594
        (read8(ACCEL_RADIUS_MSB_ADDR) << 8) | (read8(ACCEL_RADIUS_LSB_ADDR));
595

    
596
    /* Magnetometer radius = +/- 960 LSB */
597
    offsets_type.mag_radius =
598
        (read8(MAG_RADIUS_MSB_ADDR) << 8) | (read8(MAG_RADIUS_LSB_ADDR));
599

    
600
    setMode(lastMode);
601
    return true;
602
  }
603
  return false;
604
}
605

    
606
/*!
607
 *  @brief  Writes an array of calibration values to the sensor's offset
608
<<<<<<< HEAD
609
 * registers
610
=======
611
 *          registers
612
>>>>>>> 75f03d2e1fd440e7febc0de8c47a52bab09c51b0
613
 *  @param  calibData
614
 *          calibration data
615
 */
616
void Adafruit_BNO055::setSensorOffsets(const uint8_t *calibData) {
617
  adafruit_bno055_opmode_t lastMode = _mode;
618
  setMode(OPERATION_MODE_CONFIG);
619
  delay(25);
620

    
621
  /* Note: Configuration will take place only when user writes to the last
622
     byte of each config data pair (ex. ACCEL_OFFSET_Z_MSB_ADDR, etc.).
623
     Therefore the last byte must be written whenever the user wants to
624
     changes the configuration. */
625

    
626
  /* A writeLen() would make this much cleaner */
627
  write8(ACCEL_OFFSET_X_LSB_ADDR, calibData[0]);
628
  write8(ACCEL_OFFSET_X_MSB_ADDR, calibData[1]);
629
  write8(ACCEL_OFFSET_Y_LSB_ADDR, calibData[2]);
630
  write8(ACCEL_OFFSET_Y_MSB_ADDR, calibData[3]);
631
  write8(ACCEL_OFFSET_Z_LSB_ADDR, calibData[4]);
632
  write8(ACCEL_OFFSET_Z_MSB_ADDR, calibData[5]);
633

    
634
  write8(MAG_OFFSET_X_LSB_ADDR, calibData[6]);
635
  write8(MAG_OFFSET_X_MSB_ADDR, calibData[7]);
636
  write8(MAG_OFFSET_Y_LSB_ADDR, calibData[8]);
637
  write8(MAG_OFFSET_Y_MSB_ADDR, calibData[9]);
638
  write8(MAG_OFFSET_Z_LSB_ADDR, calibData[10]);
639
  write8(MAG_OFFSET_Z_MSB_ADDR, calibData[11]);
640

    
641
  write8(GYRO_OFFSET_X_LSB_ADDR, calibData[12]);
642
  write8(GYRO_OFFSET_X_MSB_ADDR, calibData[13]);
643
  write8(GYRO_OFFSET_Y_LSB_ADDR, calibData[14]);
644
  write8(GYRO_OFFSET_Y_MSB_ADDR, calibData[15]);
645
  write8(GYRO_OFFSET_Z_LSB_ADDR, calibData[16]);
646
  write8(GYRO_OFFSET_Z_MSB_ADDR, calibData[17]);
647

    
648
  write8(ACCEL_RADIUS_LSB_ADDR, calibData[18]);
649
  write8(ACCEL_RADIUS_MSB_ADDR, calibData[19]);
650

    
651
  write8(MAG_RADIUS_LSB_ADDR, calibData[20]);
652
  write8(MAG_RADIUS_MSB_ADDR, calibData[21]);
653

    
654
  setMode(lastMode);
655
}
656

    
657
/*!
658
 *  @brief  Writes to the sensor's offset registers from an offset struct
659
 *  @param  offsets_type
660
<<<<<<< HEAD
661
 *          accel_offset_x = acceleration offset x
662
 *          accel_offset_y = acceleration offset y
663
 *          accel_offset_z = acceleration offset z
664
 *
665
 *          mag_offset_x   = magnetometer offset x
666
 *          mag_offset_y   = magnetometer offset y
667
 *          mag_offset_z   = magnetometer offset z
668
 *
669
 *          gyro_offset_x  = gyroscrope offset x
670
 *          gyro_offset_y  = gyroscrope offset y
671
 *          gyro_offset_z  = gyroscrope offset z
672
 *
673
 *
674
=======
675
>>>>>>> 75f03d2e1fd440e7febc0de8c47a52bab09c51b0
676
 */
677
void Adafruit_BNO055::setSensorOffsets(
678
    const adafruit_bno055_offsets_t &offsets_type) {
679
  adafruit_bno055_opmode_t lastMode = _mode;
680
  setMode(OPERATION_MODE_CONFIG);
681
  delay(25);
682

    
683
  /* Note: Configuration will take place only when user writes to the last
684
     byte of each config data pair (ex. ACCEL_OFFSET_Z_MSB_ADDR, etc.).
685
     Therefore the last byte must be written whenever the user wants to
686
     changes the configuration. */
687

    
688
  write8(ACCEL_OFFSET_X_LSB_ADDR, (offsets_type.accel_offset_x) & 0x0FF);
689
  write8(ACCEL_OFFSET_X_MSB_ADDR, (offsets_type.accel_offset_x >> 8) & 0x0FF);
690
  write8(ACCEL_OFFSET_Y_LSB_ADDR, (offsets_type.accel_offset_y) & 0x0FF);
691
  write8(ACCEL_OFFSET_Y_MSB_ADDR, (offsets_type.accel_offset_y >> 8) & 0x0FF);
692
  write8(ACCEL_OFFSET_Z_LSB_ADDR, (offsets_type.accel_offset_z) & 0x0FF);
693
  write8(ACCEL_OFFSET_Z_MSB_ADDR, (offsets_type.accel_offset_z >> 8) & 0x0FF);
694

    
695
  write8(MAG_OFFSET_X_LSB_ADDR, (offsets_type.mag_offset_x) & 0x0FF);
696
  write8(MAG_OFFSET_X_MSB_ADDR, (offsets_type.mag_offset_x >> 8) & 0x0FF);
697
  write8(MAG_OFFSET_Y_LSB_ADDR, (offsets_type.mag_offset_y) & 0x0FF);
698
  write8(MAG_OFFSET_Y_MSB_ADDR, (offsets_type.mag_offset_y >> 8) & 0x0FF);
699
  write8(MAG_OFFSET_Z_LSB_ADDR, (offsets_type.mag_offset_z) & 0x0FF);
700
  write8(MAG_OFFSET_Z_MSB_ADDR, (offsets_type.mag_offset_z >> 8) & 0x0FF);
701

    
702
  write8(GYRO_OFFSET_X_LSB_ADDR, (offsets_type.gyro_offset_x) & 0x0FF);
703
  write8(GYRO_OFFSET_X_MSB_ADDR, (offsets_type.gyro_offset_x >> 8) & 0x0FF);
704
  write8(GYRO_OFFSET_Y_LSB_ADDR, (offsets_type.gyro_offset_y) & 0x0FF);
705
  write8(GYRO_OFFSET_Y_MSB_ADDR, (offsets_type.gyro_offset_y >> 8) & 0x0FF);
706
  write8(GYRO_OFFSET_Z_LSB_ADDR, (offsets_type.gyro_offset_z) & 0x0FF);
707
  write8(GYRO_OFFSET_Z_MSB_ADDR, (offsets_type.gyro_offset_z >> 8) & 0x0FF);
708

    
709
  write8(ACCEL_RADIUS_LSB_ADDR, (offsets_type.accel_radius) & 0x0FF);
710
  write8(ACCEL_RADIUS_MSB_ADDR, (offsets_type.accel_radius >> 8) & 0x0FF);
711

    
712
  write8(MAG_RADIUS_LSB_ADDR, (offsets_type.mag_radius) & 0x0FF);
713
  write8(MAG_RADIUS_MSB_ADDR, (offsets_type.mag_radius >> 8) & 0x0FF);
714

    
715
  setMode(lastMode);
716
}
717

    
718
/*!
719
 *  @brief  Checks of all cal status values are set to 3 (fully calibrated)
720
 *  @return status of calibration
721
 */
722
bool Adafruit_BNO055::isFullyCalibrated() {
723
  uint8_t system, gyro, accel, mag;
724
  getCalibration(&system, &gyro, &accel, &mag);
725
  if (system < 3 || gyro < 3 || accel < 3 || mag < 3)
726
    return false;
727
  return true;
728
}
729

    
730
/*!
731
 *  @brief  Writes an 8 bit value over I2C
732
 */
733
bool Adafruit_BNO055::write8(adafruit_bno055_reg_t reg, byte value) {
734
  _wire->beginTransmission(_address);
735
#if ARDUINO >= 100
736
  _wire->write((uint8_t)reg);
737
  _wire->write((uint8_t)value);
738
#else
739
  _wire->send(reg);
740
  _wire->send(value);
741
#endif
742
  _wire->endTransmission();
743

    
744
  /* ToDo: Check for error! */
745
  return true;
746
}
747

    
748
/*!
749
 *  @brief  Reads an 8 bit value over I2C
750
 */
751
byte Adafruit_BNO055::read8(adafruit_bno055_reg_t reg) {
752
  byte value = 0;
753

    
754
  _wire->beginTransmission(_address);
755
#if ARDUINO >= 100
756
  _wire->write((uint8_t)reg);
757
#else
758
  _wire->send(reg);
759
#endif
760
  _wire->endTransmission();
761
  _wire->requestFrom(_address, (byte)1);
762
#if ARDUINO >= 100
763
  value = _wire->read();
764
#else
765
  value = _wire->receive();
766
#endif
767

    
768
  return value;
769
}
770

    
771
/*!
772
 *  @brief  Reads the specified number of bytes over I2C
773
 */
774
bool Adafruit_BNO055::readLen(adafruit_bno055_reg_t reg, byte *buffer,
775
                              uint8_t len) {
776
  _wire->beginTransmission(_address);
777
#if ARDUINO >= 100
778
  _wire->write((uint8_t)reg);
779
#else
780
  _wire->send(reg);
781
#endif
782
  _wire->endTransmission();
783
  _wire->requestFrom(_address, (byte)len);
784

    
785
  for (uint8_t i = 0; i < len; i++) {
786
#if ARDUINO >= 100
787
    buffer[i] = _wire->read();
788
#else
789
    buffer[i] = _wire->receive();
790
#endif
791
  }
792

    
793
  /* ToDo: Check for errors! */
794
  return true;
795
}