1. Introduction

The sensor BNO055 is an excellent MEMS IMU and Arduino has a Shield to manage the sensor. https://www.bosch-sensortec.com/bst/products/all_products/bno055

image

2. NAxesMotion API

  • void resetSensor(unsigned int address);

  • void setOperationMode(byte operationMode);

  • void setPowerMode(byte powerMode);

  • void updateAccel(void);

  • void updateMag(void);

  • void updateGyro(void);

  • void updateQuat(void);

  • void updateEuler(void);

  • void updateLinearAccel(void);

  • void updateGravAccel(void);

  • void updateCalibStatus(void);

  • void writeAccelConfig(uint8_t range, uint8_t bandwidth, uint8_t powerMode);

  • void updateAccelConfig(void);

  • void accelInterrupts(bool xStatus, bool yStatus, bool zStatus);

  • void resetInterrupt(void);

  • void enableAnyMotion(uint8_t threshold, uint8_t duration);

  • void disableAnyMotion(void);

  • void enableSlowNoMotion(uint8_t threshold, uint8_t duration, bool motion);

  • void disableSlowNoMotion(void);

  • void setUpdateMode(bool updateMode);

  • float readAccelX(void);

  • float readAccelY(void);

  • float readAccelZ(void);

  • float readGyroX(void);

  • float readGyroY(void);

  • float readGyroZ(void);

  • float readMagX(void);

  • float readMagY(void);

  • float readMagZ(void);

  • int16_t readQuatW(void);

  • int16_t readQuatX(void);

  • int16_t readQuatY(void);

  • int16_t readQuatZ(void);

  • float readEulerHeading(void);

  • float readEulerRoll(void);

  • float readEulerPitch(void);

  • float readLinearAccelX(void);

  • float readLinearAccelY(void);

  • float readLinearAccelZ(void);

  • float readGravAccelX(void);

  • float readGravAccelY(void);

  • float readGravAccelZ(void);

  • uint8_t readAccelCalibStatus(void);

  • uint8_t readGyroCalibStatus(void);

  • uint8_t readMagCalibStatus(void);

  • uint8_t readSystemCalibStatus(void);

  • uint8_t readAccelRange(void);

  • uint8_t readAccelBandwidth(void);

  • uint8_t readAccelPowerMode(void);

3. Arduino Sketch

#include "NAxisMotion.h"
#include <Wire.h>

NAxisMotion mySensor;
unsigned long lastStreamTime = 0;
const int streamPeriod = 20;          //To stream at 50Hz without using additional timers (time period(ms) =1000/frequency(Hz))
bool updateSensorData = true;         //Flag to update the sensor data. Default is true to perform the first read before the first stream

void setup() //This code is executed once
{
  //Peripheral Initialization
  Serial.begin(115200);           //Initialize the Serial Port to view information on the Serial Monitor
  I2C.begin();                    //Initialize I2C communication to the let the library communicate with the sensor.

  //Sensor Initialization
  mySensor.initSensor();          //The I2C Address can be changed here inside this function in the library
  mySensor.setOperationMode(OPERATION_MODE_NDOF);   //Can be configured to other operation modes as desired
  mySensor.setUpdateMode(MANUAL);  //The default is AUTO. Changing to MANUAL requires calling the relevant update functions prior to calling the read functions
  //Setting to MANUAL requires fewer reads to the sensor
}

void loop()
{
  if (updateSensorData)  //Keep the updating of data as a separate task
  {
    mySensor.updateEuler();
    mySensor.updateLinearAccel();
    mySensor.updateMag();
    mySensor.updateGyro();
    mySensor.updateCalibStatus();  //Update the Calibration Status
    updateSensorData = false;
  }

  if ((millis() - lastStreamTime) >= streamPeriod)
  {
    lastStreamTime = millis();

    //Euler

    //Serial.print(" H: ");
    Serial.print(mySensor.readEulerHeading());
    Serial.print(", ");

    //Serial.print(" R: ");
    Serial.print(mySensor.readEulerRoll());
    Serial.print(",");

    //Serial.print(" P: ");
    Serial.print(mySensor.readEulerPitch());
    Serial.print(", ");

    //Acceleration

    //Serial.print(" AccelX: ");
    Serial.print(mySensor.readLinearAccelX());
    Serial.print(", ");

    //Serial.print(" AccelY: ");
    Serial.print(mySensor.readLinearAccelY());
    Serial.print(", ");

    //Serial.print(" AccelZ: ");
    Serial.print(mySensor.readLinearAccelZ());
    Serial.print(", ");

    //Magnetometer

    //Serial.print(" MagX: ");
    Serial.print(mySensor.readMagX());
    Serial.print(", ");

    //Serial.print(" MagY: ");
    Serial.print(mySensor.readMagY());
    Serial.print(", ");

    //Serial.print(" MagZ: ");
    Serial.print(mySensor.readMagZ());
    Serial.print(", ");

    //Gyroscope

    //Serial.print(" GyroX: ");
    Serial.print(mySensor.readGyroX());
    Serial.print(", ");

    //Serial.print(" GyroY: ");
    Serial.print(mySensor.readGyroY());
    Serial.print(", ");

    //Serial.print(" GyroZ: ");
    Serial.print(mySensor.readGyroZ());
    Serial.print(", ");

    Serial.println();

    updateSensorData = true;
  }
}

4. How to use the sensor

package examples;

import ev3dev.actuators.Sound;
import ev3dev.arduino.sensors.bn055.BNO055;
import ev3dev.arduino.sensors.bn055.BNO055Listener;
import ev3dev.arduino.sensors.bn055.model.BNO055Response;
import ev3dev.arduino.sensors.bn055.model.Euler;
import ev3dev.sensors.Battery;
import ev3dev.sensors.Button;
import lombok.extern.slf4j.Slf4j;

public @Slf4j class BNO055TurnTest {

	public static void main(String[] args) throws Exception {

		final String port = "/dev/ttyACM0";
		final BNO055 bno055 = new BNO055(port);
		bno055.init();

		log.debug("{}", Battery.getInstance().getVoltage());

		bno055.addListener(new BNO055Listener() {

			@Override
			public void dataReceived(final BNO055Response response) {

				if(response.getEuler() != null){

					final Euler euler = response.getEuler();

					log.debug("Heading: {}", euler.getHeading());

					if( (euler.getHeading() > 90.0f) &&
						(euler.getHeading() <= 100.00f)) {

						//Sound.getInstance().beep();
						log.info("REACHED");
					}
				}
			}

		});

		Button.waitForAnyPress();
		log.debug("{}", Battery.getInstance().getVoltage());
		bno055.close();
		log.info("Closing connection with Arduino");

	}
}