# Датчик BNO055 / I2C

BNO-055 - датчик, в котором есть свой модуль вычислений - 32-битное ядро ARM Cortex M0. Ядро получает данные акселерометра, гироскопа, магнитометра, производит расчеты и сохраняет результаты. Результаты в дальнейшем могут быть запрошены внешними устройствами. Ниже приведена внутренняя архитектура описываемого датчика и его взаимодействие с внешним процессором, информация взята из [документации](https://datasheetspdf.com/datasheet/BNO055.html) BOSH.

<figure><img src="https://3551773033-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBjLyfPc4FcQUfXFi5fQr%2Fuploads%2FszYj5Z8bfBTVxAfLpCQR%2Fimage.png?alt=media&#x26;token=6d62182f-fa19-4304-83c5-517618745b6a" alt=""><figcaption></figcaption></figure>

Для работы с IMU датчиком BNO055 необходимо скачать библиотеку Adafruit BNO055 через менеджер библиотек в Arduino IDE. Там же есть несколько примеров, которые работу библиотеки. Согласно документации BNO-055 может поддерживать три интерфейса обмена с внешними устройствами: I2C, HID-I2C, UART (Serial). Мы будем работать с I2C, не забудьте подключить библиотеку VBCoreG4\_arduino\_system и указать пины, к которым подключены SDA и SCL. Для этого в setup() добавим две строчки:

```arduino
Wire.setSDA(PB_7_ALT1);
Wire.setSCL(PC6);
```

В адресе I2C укажите 0x29. Ниже приведен один измененный для драйвера VBCoreG4 пример из библиотеки Adafruit BNO055

{% file src="<https://3551773033-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBjLyfPc4FcQUfXFi5fQr%2Fuploads%2Ffgx7aoe9s7ELhVXTTil5%2FBNO055_position_VB32G474.ino?alt=media&token=f9d8feb0-200a-4a15-919f-4a656195f310>" %}

```arduino
#include <VBCoreG4_arduino_system.h>
#include <Wire.h>

#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>

double xPos = 0, yPos = 0, headingVel = 0;
uint16_t BNO055_SAMPLERATE_DELAY_MS = 10; //how often to read data from the board
uint16_t PRINT_DELAY_MS = 500; // how often to print the data
uint16_t printCount = 0; //counter to avoid printing every 10MS sample

//velocity = accel*dt (dt in seconds)
//position = 0.5*accel*dt^2
double ACCEL_VEL_TRANSITION =  (double)(BNO055_SAMPLERATE_DELAY_MS) / 1000.0;
double ACCEL_POS_TRANSITION = 0.5 * ACCEL_VEL_TRANSITION * ACCEL_VEL_TRANSITION;
double DEG_2_RAD = 0.01745329251; //trig functions require radians, BNO055 outputs degrees

// Check I2C device address and correct line below (by default address is 0x29 or 0x28)
//                                   id, address
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x29);

void setup(void)
{
  Serial.begin(115200);
  Wire.setSDA(PB_7_ALT1);
  Wire.setSCL(PC6);
  Wire.begin();

  while (!Serial) delay(10);  // wait for serial port to open!
  
  if (!bno.begin())
  {
    Serial.print("No BNO055 detected");
    while (1);
  }


  delay(1000);
}

void loop(void)
{
  //
  unsigned long tStart = micros();
  sensors_event_t orientationData , linearAccelData;
  bno.getEvent(&orientationData, Adafruit_BNO055::VECTOR_EULER);
  //  bno.getEvent(&angVelData, Adafruit_BNO055::VECTOR_GYROSCOPE);
  bno.getEvent(&linearAccelData, Adafruit_BNO055::VECTOR_LINEARACCEL);

  xPos = xPos + ACCEL_POS_TRANSITION * linearAccelData.acceleration.x;
  yPos = yPos + ACCEL_POS_TRANSITION * linearAccelData.acceleration.y;

  // velocity of sensor in the direction it's facing
  headingVel = ACCEL_VEL_TRANSITION * linearAccelData.acceleration.x / cos(DEG_2_RAD * orientationData.orientation.x);

  if (printCount * BNO055_SAMPLERATE_DELAY_MS >= PRINT_DELAY_MS) {
    //enough iterations have passed that we can print the latest data
    Serial.print("Heading: ");
    Serial.println(orientationData.orientation.x);
    Serial.print("Position: ");
    Serial.print(xPos);
    Serial.print(" , ");
    Serial.println(yPos);
    Serial.print("Speed: ");
    Serial.println(headingVel);
    Serial.println("-------");

    printCount = 0;
  }
  else {
    printCount = printCount + 1;
  }



  while ((micros() - tStart) < (BNO055_SAMPLERATE_DELAY_MS * 1000))
  {
    //poll until the next sample is ready
  }
}

void printEvent(sensors_event_t* event) {
  Serial.println();
  Serial.print(event->type);
  double x = -1000000, y = -1000000 , z = -1000000; //dumb values, easy to spot problem
  if (event->type == SENSOR_TYPE_ACCELEROMETER) {
    x = event->acceleration.x;
    y = event->acceleration.y;
    z = event->acceleration.z;
  }
  else if (event->type == SENSOR_TYPE_ORIENTATION) {
    x = event->orientation.x;
    y = event->orientation.y;
    z = event->orientation.z;
  }
  else if (event->type == SENSOR_TYPE_MAGNETIC_FIELD) {
    x = event->magnetic.x;
    y = event->magnetic.y;
    z = event->magnetic.z;
  }
  else if ((event->type == SENSOR_TYPE_GYROSCOPE) || (event->type == SENSOR_TYPE_ROTATION_VECTOR)) {
    x = event->gyro.x;
    y = event->gyro.y;
    z = event->gyro.z;
  }

  Serial.print(": x= ");
  Serial.print(x);
  Serial.print(" | y= ");
  Serial.print(y);
  Serial.print(" | z= ");
  Serial.println(z);
}

```
