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
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.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");
}
}