BNO055 for esp32, esp8266, and Arduino: Gyroscope High Rate and Any Motion Interrupt – 6

Spread the love

In this article, we will explore using the BNO055 sensor with ESP32, ESP8266, and Arduino to achieve a gyroscope high rate and any motion interrupt. The BNO055 is a versatile sensor that combines an accelerometer, magnetometer, and gyroscope in one module, making it an ideal choice for projects that require accurate orientation tracking.

BNO055 for esp32, esp8266, and Arduino: Gyroscope High Rate and Any Motion Interrupt
BNO055 for esp32, esp8266, and Arduino: Gyroscope High Rate and Any Motion Interrupt

We will start by discussing the basic principles of the BNO055 sensor and its different modes of operation. Then, we will show you how to connect the BNO055 to your ESP32, ESP8266, or Arduino board and read data from it. Next, we will dive into the gyroscope high rate mode, which allows the sensor to output data at a much faster rate than the standard mode. Finally, we will show you how to use any motion interrupt to detect sudden changes in orientation and trigger an action in your code.

Architecture

I got this image from a datasheet to remember that this sensor had three sensors and a microcontroller with fusion software to manage data and give you an absolute position.

Architecture of bno055
Architecture of bno055

BNO055 pinouts

There are many module versions of these sensors, I choose the smallest and cheap.

Here the module Aliexpress

All these modules had the same features, but to enable them, you must do different operations.

This is the clone I use:

BNO055 pinout mischianti
BNO055 pinout mischianti

And here is the Adafruit one:

Adafruit bno055 pinout specs
Adafruit bno055 pinout specs

The sensor support a 3.3v logic level, but the module can be powered by 5v.

Gyroscope High Rate Interrupt

This interrupt is based on the comparison of angular rate data against a high-rate threshold for the detection of shock or other high-angular rate events.

ParamsValue
Axis selectionX-axis
 Y-axis
 Z-axis
High Rate Filter settingsFiltered
 Unfiltered
Interrupt Settings X- axisThreshold
 Duration
 Hysteresis
Interrupt Settings Y- axisThreshold
 Duration
 Hysteresis
Interrupt Settings X- axisThreshold
 Duration
 Hysteresis

The high-rate interrupt is enabled (disabled) per axis. The high-rate threshold is set through the Threshold bits. Hysteresis can be selected by setting the bits.

Gyroscope High Rate Interrupt principle chart
Gyroscope High Rate Interrupt principle chart

The high-rate interrupt is generated if the absolute value of the angular rate of at least one of the enabled axes (´or´ relation) is higher than the threshold for at least the time defined by the register. The interrupt is reset if the absolute value of the angular rate of all enabled axes (´and´ relation) is lower than the threshold minus the hysteresis. In the bit in the interrupt status is stored. The relation between the content and the actual delay of the interrupt generation is delay [ms] = [+ 1] * 2.5 ms. Therefore, possible delay times range from 2.5 ms to 640ms.

So a sample sketch must be in NORMAL mode, and you must enable the gyroscope high-rate interrupt and interrupt pin with this command.

  // Activate acceleration highrate and bit mask fot INT pin
  bno055_set_int_gyro_highrate(1);
  bno055_set_intmsk_gyro_highrate(1); // to enable INT pin

You can enable the filter (disable it by default).

  bno055_set_gyro_highrate_filter(0);

And set the correct value for threshold, duration, and hysteresis with these commands.

  bno055_set_gyro_highrate_x_threshold(1);
  bno055_set_gyro_highrate_x_duration(25);
  bno055_set_gyro_highrate_x_hysteresis(0);
  bno055_set_gyro_highrate_y_threshold(1);
  bno055_set_gyro_highrate_y_duration(25);
  bno055_set_gyro_highrate_y_hysteresis(0);
  bno055_set_gyro_highrate_z_threshold(1);
  bno055_set_gyro_highrate_z_duration(25);
  bno055_set_gyro_highrate_z_hysteresis(0);

And remember that all axes were disabled by default, so you must enable them.

  // Enable axes
  bno055_set_accel_high_g_axis_enable(BNO055_GYRO_HR_X_AXIS, 1);
  bno055_set_accel_high_g_axis_enable(BNO055_GYRO_HR_Y_AXIS, 1);
  bno055_set_accel_high_g_axis_enable(BNO055_GYRO_HR_Z_AXIS, 1);

To prevent INT status HIGH, I set reset to register.

  // reset all previous int signal
  bno055_set_reset_int(1);

So the complete sketch becomes.

/**
 * bno055 simple interrupt management
 * enable register interrupt and pin 15
 * for high-rate gyroscope
 * bit mask for interrupt pin on high-rate gyroscope
 *
 * by Renzo Mischianti <www.mischianti.org>
 *
 * https://mischianti.org/
 */

#include "BNO055_support.h"		//Contains the bridge code between the API and Arduino
#include <Wire.h>

//The device address is set to BNO055_I2C_ADDR2 in this example. You can change this in the BNO055.h file in the code segment shown below.
// /* bno055 I2C Address */
// #define BNO055_I2C_ADDR1                0x28
// #define BNO055_I2C_ADDR2                0x29
// #define BNO055_I2C_ADDR                 BNO055_I2C_ADDR2

//Pin assignments as tested on the Arduino Due.
//Vdd,Vddio : 3.3V
//GND : GND
//SDA/SCL : SDA/SCL
//PSO/PS1 : GND/GND (I2C mode)

//This structure contains the details of the BNO055 device that is connected. (Updated after initialization)
struct bno055_t myBNO;
struct bno055_euler myEulerData; //Structure to hold the Euler data

unsigned long lastTime = 0;

/* Set the delay between fresh samples */
#define BNO055_SAMPLERATE_DELAY_MS (1000)

#define INTERRUPT_PIN 15

void getIntInterruptEnabled();
void getIntInterruptBitMaskEnabled();
void getInterruptStatusEnabled(bool synthetic = false);
void printGyroHighrateParameters();

bool somethingHappened = false;
void IRAM_ATTR interruptCallback() {
	somethingHappened = true;
}

void setup() //This code is executed once
{
  //Initialize I2C communication
  Wire.begin();

  //Initialization of the BNO055
  BNO_Init(&myBNO); //Assigning the structure to hold information about the device
//  bno055_set_reset_sys(1);

  delay(1500);

  bno055_set_powermode(POWER_MODE_NORMAL);

  // disable nomotion and anymotion
  bno055_set_int_accel_anymotion(0);
  bno055_set_int_accel_nomotion(0);

  // Activate INT pin with bitmask
  bno055_set_intmsk_accel_nomotion(0);
  bno055_set_intmsk_accel_anymotion(0);

  // Deactivate acceleration high-g and bit mask fot INT pin
  bno055_set_int_accel_high_g(0);
  bno055_set_intmsk_accel_high_g(0);

  // Activate gyro highrate and bit mask fot INT pin
  bno055_set_int_gyro_highrate(1);
  bno055_set_intmsk_gyro_highrate(1); // to enable INT pin

  // Set default parameter (you can remove these)
  bno055_set_gyro_highrate_filter(0);
  bno055_set_gyro_highrate_x_threshold(1);
  bno055_set_gyro_highrate_x_duration(25);
  bno055_set_gyro_highrate_x_hysteresis(0);
  bno055_set_gyro_highrate_y_threshold(1);
  bno055_set_gyro_highrate_y_duration(25);
  bno055_set_gyro_highrate_y_hysteresis(0);
  bno055_set_gyro_highrate_z_threshold(1);
  bno055_set_gyro_highrate_z_duration(25);
  bno055_set_gyro_highrate_z_hysteresis(0);

  // Enable axes
  bno055_set_gyro_highrate_axis_enable(BNO055_GYRO_HR_X_AXIS, 1);
  bno055_set_gyro_highrate_axis_enable(BNO055_GYRO_HR_Y_AXIS, 1);
  bno055_set_gyro_highrate_axis_enable(BNO055_GYRO_HR_Z_AXIS, 1);

  // reset all previous int signal
  bno055_set_reset_int(1);

  //Configuration to NDoF mode
  bno055_set_operation_mode(OPERATION_MODE_NDOF);

  delay(1);

  //Initialize the Serial Port to view information on the Serial Monitor
  Serial.begin(115200);

  pinMode(INTERRUPT_PIN, INPUT);
  attachInterrupt(INTERRUPT_PIN, interruptCallback, RISING);

  delay(1000);
  getIntInterruptEnabled();
  getIntInterruptBitMaskEnabled();
  printGyroHighrateParameters();
}

bool suspended = false;
bool reactivated = false;

void loop() //This code is looped forever
{
  if ((millis() - lastTime) >= BNO055_SAMPLERATE_DELAY_MS) //To stream at 10Hz without using additional timers
  {
    lastTime = millis();

    bno055_read_euler_hrp(&myEulerData);			//Update Euler data into the structure

    Serial.print(millis()/1000); Serial.print("Secs - ");

    /* The WebSerial 3D Model Viewer expects data as heading, pitch, roll */
    Serial.print(F("Orientation: "));
    Serial.print(360-(float(myEulerData.h) / 16.00));
    Serial.print(F(", "));
    Serial.print(360-(float(myEulerData.p) / 16.00));
    Serial.print(F(", "));
    Serial.print(360-(float(myEulerData.r) / 16.00));
    Serial.print(F("   -    "));

	getInterruptStatusEnabled(true);
  }
  if (somethingHappened) {
	    Serial.println("---------------");
	    getInterruptStatusEnabled();
	    Serial.println("---------------");

	    bno055_set_reset_int(1);

	    somethingHappened = false;
  }

}

/*
 * Print the interrupt enabled
 */
void getIntInterruptEnabled() {
	unsigned char gyro_am = 0;
	unsigned char gyro_hr = 0;
	unsigned char accel_hg = 0;
	unsigned char accel_am = 0;
	unsigned char accel_nm = 0;

	bno055_get_int_gyro_anymotion(&gyro_am);
	bno055_get_int_gyro_highrate(&gyro_hr);
	bno055_get_int_accel_high_g(&accel_hg);
	bno055_get_int_accel_anymotion(&accel_am);
	bno055_get_int_accel_nomotion(&accel_nm);

	Serial.println( "---- Interrupt enabled ----" );
	Serial.print( "Gyro Any Motion  " );
	Serial.println( gyro_am );
	Serial.print( "Gyro High Rate   " );
	Serial.println( gyro_hr );
	Serial.print( "Accel High G     " );
	Serial.println( accel_hg );
	Serial.print( "Accel Any Motion " );
	Serial.println( accel_am );
	Serial.print( "Accel No Motion  " );
	Serial.println( accel_nm );
	Serial.println( "---------------------------" );

}

/*
 * Print the interrupt to send on interrupt pin
 */
void getIntInterruptBitMaskEnabled() {
	unsigned char gyro_am = 0;
	unsigned char gyro_hr = 0;
	unsigned char accel_hg = 0;
	unsigned char accel_am = 0;
	unsigned char accel_nm = 0;

	bno055_get_intmsk_gyro_anymotion(&gyro_am);
	bno055_get_intmsk_gyro_highrate(&gyro_hr);
	bno055_get_intmsk_accel_high_g(&accel_hg);
	bno055_get_intmsk_accel_anymotion(&accel_am);
	bno055_get_intmsk_accel_nomotion(&accel_nm);

	Serial.println( "---- Interrupt bitmask ----" );
	Serial.print( "Gyro Any Motion  " );
	Serial.println( gyro_am );
	Serial.print( "Gyro High Rate   " );
	Serial.println( gyro_hr );
	Serial.print( "Accel High G     " );
	Serial.println( accel_hg );
	Serial.print( "Accel Any Motion " );
	Serial.println( accel_am );
	Serial.print( "Accel No Motion  " );
	Serial.println( accel_nm );
	Serial.println( "---------------------------" );
}

/*
 * Print the interrupt status
 */
void getInterruptStatusEnabled(bool synthetic) {

	// 37 	INT_STA 	0x00	ACC_NM	ACC_AM	ACC_HIGH_G	GYR_DRDY	GYR_HIGH_RATE	GYRO_AM	MAG_DRDY	ACC_BSX_DRDY

		#pragma pack(push, 1)
			struct StatusInterrupt {
				byte accel_bsx_drdy		: 1;
				byte mag_drdy			: 1;
				byte gyro_am			: 1;
				byte gyro_high_rate	  	: 1;
				byte gyro_drdy	  		: 1;
				byte accel_high_g 		: 1;
				byte accel_am	  		: 1;
				byte accel_nm	  		: 1;
			};
		#pragma pack(pop)

		StatusInterrupt registerByte = {0};
		// Read all tht INT_STA addr to get all interrupt status in one read
		// after the read the register is cleared
		BNO055_RETURN_FUNCTION_TYPE res = bno055_read_register(BNO055_INT_STA_ADDR, (unsigned char *)(®isterByte), 1);

		if (res == 0) {
			if (synthetic){
				Serial.print("Anm Aam Ahg Grd Ggr Gam Mrd Abr --> ");
				Serial.print( registerByte.accel_nm );
				Serial.print( registerByte.accel_am );
				Serial.print( registerByte.accel_high_g );
				Serial.print( registerByte.gyro_drdy );
				Serial.print( registerByte.gyro_high_rate );
				Serial.print( registerByte.gyro_am );
				Serial.print( registerByte.mag_drdy );
				Serial.println( registerByte.accel_bsx_drdy );
			}else{
				Serial.print( "Gyro Any Motion  " );
				Serial.println( registerByte.gyro_am );
				Serial.print( "Gyro High Rate   " );
				Serial.println( registerByte.gyro_high_rate );
				Serial.print( "Accel High G     " );
				Serial.println( registerByte.accel_high_g );
				Serial.print( "Accel Any Motion " );
				Serial.println( registerByte.accel_am );
				Serial.print( "Accel No Motion  " );
				Serial.println( registerByte.accel_nm );
			}
		} else {
			Serial.println("Error status!");
		}
	}


void printGyroHighrateParameters(){
	  unsigned char gyro_hr_filter = 0;
	  bno055_get_gyro_highrate_filter(&gyro_hr_filter);
	  Serial.print("Gyro highrate filter: ");
	  Serial.println(gyro_hr_filter);

	  unsigned char gyro_hr_x_thres = 0;
	  bno055_get_gyro_highrate_x_threshold(&gyro_hr_x_thres);
	  Serial.print("Gyro highrate X threshold: ");
	  Serial.println(gyro_hr_x_thres);
	  unsigned char gyro_hr_x_dur = 0;
	  bno055_get_gyro_highrate_x_duration(&gyro_hr_x_dur);
	  Serial.print("Gyro highrate X duration: ");
	  Serial.println(gyro_hr_x_dur);
	  unsigned char gyro_hr_x_hys = 0;
	  bno055_get_gyro_highrate_x_hysteresis(&gyro_hr_x_hys);
	  Serial.print("Gyro highrate X hysteresis: ");
	  Serial.println(gyro_hr_x_hys);

	  unsigned char gyro_hr_y_thres = 0;
	  bno055_get_gyro_highrate_y_threshold(&gyro_hr_y_thres);
	  Serial.print("Gyro highrate Y threshold: ");
	  Serial.println(gyro_hr_y_thres);
	  unsigned char gyro_hr_y_dur = 0;
	  bno055_get_gyro_highrate_y_duration(&gyro_hr_y_dur);
	  Serial.print("Gyro highrate Y duration: ");
	  Serial.println(gyro_hr_y_dur);
	  unsigned char gyro_hr_y_hys = 0;
	  bno055_get_gyro_highrate_y_hysteresis(&gyro_hr_y_hys);
	  Serial.print("Gyro highrate Y hysteresis: ");
	  Serial.println(gyro_hr_y_hys);

	  unsigned char gyro_hr_z_thres = 0;
	  bno055_get_gyro_highrate_z_threshold(&gyro_hr_z_thres);
	  Serial.print("Gyro highrate Z threshold: ");
	  Serial.println(gyro_hr_z_thres);
	  unsigned char gyro_hr_z_dur = 0;
	  bno055_get_gyro_highrate_z_duration(&gyro_hr_z_dur);
	  Serial.print("Gyro highrate Z duration: ");
	  Serial.println(gyro_hr_z_dur);
	  unsigned char gyro_hr_z_hys = 0;
	  bno055_get_gyro_highrate_z_hysteresis(&gyro_hr_z_hys);
	  Serial.print("Gyro highrate Z hysteresis: ");
	  Serial.println(gyro_hr_z_hys);

	  unsigned char xEnabled = 0;
	  bno055_get_gyro_highrate_axis_enable(BNO055_GYRO_HR_X_AXIS, &xEnabled);
	  Serial.print("X axis high rate enabled: ");
	  Serial.println(xEnabled);

	  unsigned char yEnabled = 0;
	  bno055_get_gyro_highrate_axis_enable(BNO055_GYRO_HR_Y_AXIS, &yEnabled);
	  Serial.print("Y axis high rate enabled: ");
	  Serial.println(yEnabled);

	  unsigned char zEnabled = 0;
	  bno055_get_gyro_highrate_axis_enable(BNO055_GYRO_HR_Z_AXIS, &zEnabled);
	  Serial.print("Z axis high rate enabled: ");
	  Serial.println(zEnabled);

}

The result in serial output was this.

---- Interrupt enabled ----
Gyro Any Motion  0
Gyro High Rate   1
Accel High G     1
Accel Any Motion 0
Accel No Motion  0
---------------------------
---- Interrupt bitmask ----
Gyro Any Motion  0
Gyro High Rate   1
Accel High G     1
Accel Any Motion 0
Accel No Motion  0
---------------------------
Gyro highrate filter: 0
Gyro highrate X threshold: 1
Gyro highrate X duration: 25
Gyro highrate X hysteresis: 0
Gyro highrate Y threshold: 1
Gyro highrate Y duration: 25
Gyro highrate Y hysteresis: 0
Gyro highrate Z threshold: 1
Gyro highrate Z duration: 25
Gyro highrate Z hysteresis: 0
X axis high rate enabled: 1
Y axis high rate enabled: 1
Z axis high rate enabled: 1
2Secs - Orientation: 0.06, 363.87, 358.19   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
3Secs - Orientation: 0.06, 363.87, 358.19   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
4Secs - Orientation: 0.06, 363.87, 358.19   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
5Secs - Orientation: 0.06, 363.87, 358.19   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
6Secs - Orientation: 0.56, 364.69, 358.00   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
---------------
Gyro Any Motion  0
Gyro High Rate   1
Accel High G     0
Accel Any Motion 0
Accel No Motion  0
---------------
7Secs - Orientation: 2.44, 358.69, 332.50   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
---------------
Gyro Any Motion  0
Gyro High Rate   1
Accel High G     0
Accel Any Motion 0
Accel No Motion  0
---------------
8Secs - Orientation: 4.00, 360.31, 358.75   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
9Secs - Orientation: 4.56, 364.50, 359.50   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
---------------
Gyro Any Motion  0
Gyro High Rate   1
Accel High G     0
Accel Any Motion 0
Accel No Motion  0
---------------
10Secs - Orientation: 5.75, 364.56, 363.87   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
11Secs - Orientation: 6.75, 363.62, 363.56   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
12Secs - Orientation: 7.25, 363.56, 360.75   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
13Secs - Orientation: 7.31, 363.69, 359.69   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
14Secs - Orientation: 7.31, 363.69, 359.37   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
15Secs - Orientation: 7.31, 363.69, 359.37   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
16Secs - Orientation: 7.31, 363.69, 359.37   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
17Secs - Orientation: 7.31, 363.69, 359.37   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
18Secs - Orientation: 7.31, 363.69, 359.37   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
19Secs - Orientation: 7.31, 363.69, 359.37   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000

Gyroscope Any Motion Interrupt

Any-motion (slope) detection uses the slope between successive angular rate signals to detect changes in motion. An interrupt is generated when the slope (absolute value of angular rate difference) exceeds a preset threshold. It is cleared as soon as the slope falls below the threshold.

ParamsValue
Axis selectionX-axis
 Y-axis
 Z-axis
Any Motion Filter settingsFiltered
 Unfiltered
Interrupt SettingsThreshold
 Slope Samples
 Awake Duration

The threshold can be defined. The time difference between the successive angular rate signals depends on the selected update rate(fs).
1 LSB = 1 °/s in 2000°/s-range 1 LSB = 0.5°/s in 1000°/s-range 1 LSB = 0.25°/s in 500°/s -range

You can set a threshold with this command.

  bno055_set_gyro_anymotion_threshold(4);

In order to suppress false triggers, the interrupt is only generated (cleared) if a certain number of consecutive slope data points is larger (smaller) than the slope threshold. Can be set the Slope Samples bits.

You can set slope with this command.

  bno055_set_gyro_anymotion_slope_samples(2);

Any motion detection can be enabled (disabled) for each axis separately. The criteria for any-motion detection are fulfilled, and the Any-Motion interrupt is generated if the slope of any of the enabled axes exceeds the threshold set on consecutive times. As soon as the slopes of all enabled axes fall or stay below this threshold for a set of consecutive times, the interrupt is cleared unless the interrupt signal is latched.

To set the sample number, you must use this command.

  bno055_set_gyro_anymotion_awake_duration(2);

The Awake Duration set the samples number
0=8 samples, 1=16 samples, 2=32 samples, 3=64 samples

bno055 Gyroscope Any Motion Interrupt principle chart
bno055 Gyroscope Any Motion Interrupt principle chart

The interrupt status is stored in bit in the register. The Any-motion interrupt supplies additional information about the detected slope.

Any motion interrupt triggers if [Slope Samples + 1]*4 consecutive data points are above the any motion interrupt threshold defined.

You can filter the bandwidth with this command.

  bno055_set_gyro_anymotion_filter(0);

To activate the interrupt (on the register) and the INT pin, you must enable interrupt and set the interrupt bit-mask, respectively.

  // Activate gyro anymotion and bit mask fot INT pin
  bno055_set_int_gyro_anymotion(1);
  bno055_set_intmsk_gyro_anymotion(1); // to enable INT pin

And here is the complete sketch.

/**
 * bno055 simple interrupt management
 * enable register interrupt and pin 15
 * for anymotion for gyroscope
 * bit mask for interrupt pin on anymotion gyroscope
 *
 * by Renzo Mischianti <www.mischianti.org>
 *
 * https://mischianti.org/
 */

#include "BNO055_support.h"		//Contains the bridge code between the API and Arduino
#include <Wire.h>

//The device address is set to BNO055_I2C_ADDR2 in this example. You can change this in the BNO055.h file in the code segment shown below.
// /* bno055 I2C Address */
// #define BNO055_I2C_ADDR1                0x28
// #define BNO055_I2C_ADDR2                0x29
// #define BNO055_I2C_ADDR                 BNO055_I2C_ADDR2

//Pin assignments as tested on the Arduino Due.
//Vdd,Vddio : 3.3V
//GND : GND
//SDA/SCL : SDA/SCL
//PSO/PS1 : GND/GND (I2C mode)

//This structure contains the details of the BNO055 device that is connected. (Updated after initialization)
struct bno055_t myBNO;
struct bno055_euler myEulerData; //Structure to hold the Euler data

unsigned long lastTime = 0;

/* Set the delay between fresh samples */
#define BNO055_SAMPLERATE_DELAY_MS (1000)

#define INTERRUPT_PIN 15

void getIntInterruptEnabled();
void getIntInterruptBitMaskEnabled();
void getInterruptStatusEnabled(bool synthetic = false);
void printGyroAnymotionParameters();

bool somethingHappened = false;
void IRAM_ATTR interruptCallback() {
	somethingHappened = true;
}

void setup() //This code is executed once
{
  //Initialize I2C communication
  Wire.begin();

  //Initialization of the BNO055
  BNO_Init(&myBNO); //Assigning the structure to hold information about the device
//  bno055_set_reset_sys(1);

  delay(1500);

  bno055_set_powermode(POWER_MODE_NORMAL);

  // disable nomotion and anymotion
  bno055_set_int_accel_anymotion(0);
  bno055_set_int_accel_nomotion(0);

  // Activate INT pin with bitmask
  bno055_set_intmsk_accel_nomotion(0);
  bno055_set_intmsk_accel_anymotion(0);

  // Deactivate acceleration high-g and bit mask fot INT pin
  bno055_set_int_accel_high_g(0);
  bno055_set_intmsk_accel_high_g(0);

  // Activate acceleration highrate and bit mask fot INT pin
  bno055_set_int_gyro_highrate(0);
  bno055_set_intmsk_gyro_highrate(0); // to enable INT pin

  // Activate gyro anymotion and bit mask fot INT pin
  bno055_set_int_gyro_anymotion(1);
  bno055_set_intmsk_gyro_anymotion(1); // to enable INT pin

  // Set default parameter (you can remove these)
  bno055_set_gyro_anymotion_filter(0);
  bno055_set_gyro_anymotion_slope_samples(2);
  bno055_set_gyro_anymotion_awake_duration(2);
  bno055_set_gyro_anymotion_threshold(4);

  // Enable axes
  bno055_set_gyro_anymotion_axis_enable(BNO055_GYRO_AM_X_AXIS, 1);
  bno055_set_gyro_anymotion_axis_enable(BNO055_GYRO_AM_Y_AXIS, 1);
  bno055_set_gyro_anymotion_axis_enable(BNO055_GYRO_AM_Y_AXIS, 1);

  // reset all previous int signal
  bno055_set_reset_int(1);

  //Configuration to NDoF mode
  bno055_set_operation_mode(OPERATION_MODE_NDOF);

  delay(1);

  //Initialize the Serial Port to view information on the Serial Monitor
  Serial.begin(115200);

  pinMode(INTERRUPT_PIN, INPUT);
  attachInterrupt(INTERRUPT_PIN, interruptCallback, RISING);

  delay(1000);
  getIntInterruptEnabled();
  getIntInterruptBitMaskEnabled();
  printGyroAnymotionParameters();
}

bool suspended = false;
bool reactivated = false;

void loop() //This code is looped forever
{
  if ((millis() - lastTime) >= BNO055_SAMPLERATE_DELAY_MS) //To stream at 10Hz without using additional timers
  {
    lastTime = millis();

    bno055_read_euler_hrp(&myEulerData);			//Update Euler data into the structure

    Serial.print(millis()/1000); Serial.print("Secs - ");

    /* The WebSerial 3D Model Viewer expects data as heading, pitch, roll */
    Serial.print(F("Orientation: "));
    Serial.print(360-(float(myEulerData.h) / 16.00));
    Serial.print(F(", "));
    Serial.print(360-(float(myEulerData.p) / 16.00));
    Serial.print(F(", "));
    Serial.print(360-(float(myEulerData.r) / 16.00));
    Serial.print(F("   -    "));

	getInterruptStatusEnabled(true);
  }
  if (somethingHappened) {
	    Serial.println("---------------");
	    getInterruptStatusEnabled();
	    Serial.println("---------------");

	    bno055_set_reset_int(1);

	    somethingHappened = false;
  }

}

/*
 * Print the interrupt enabled
 */
void getIntInterruptEnabled() {
	unsigned char gyro_am = 0;
	unsigned char gyro_hr = 0;
	unsigned char accel_hg = 0;
	unsigned char accel_am = 0;
	unsigned char accel_nm = 0;

	bno055_get_int_gyro_anymotion(&gyro_am);
	bno055_get_int_gyro_highrate(&gyro_hr);
	bno055_get_int_accel_high_g(&accel_hg);
	bno055_get_int_accel_anymotion(&accel_am);
	bno055_get_int_accel_nomotion(&accel_nm);

	Serial.println( "---- Interrupt enabled ----" );
	Serial.print( "Gyro Any Motion  " );
	Serial.println( gyro_am );
	Serial.print( "Gyro High Rate   " );
	Serial.println( gyro_hr );
	Serial.print( "Accel High G     " );
	Serial.println( accel_hg );
	Serial.print( "Accel Any Motion " );
	Serial.println( accel_am );
	Serial.print( "Accel No Motion  " );
	Serial.println( accel_nm );
	Serial.println( "---------------------------" );

}

/*
 * Print the interrupt to send on interrupt pin
 */
void getIntInterruptBitMaskEnabled() {
	unsigned char gyro_am = 0;
	unsigned char gyro_hr = 0;
	unsigned char accel_hg = 0;
	unsigned char accel_am = 0;
	unsigned char accel_nm = 0;

	bno055_get_intmsk_gyro_anymotion(&gyro_am);
	bno055_get_intmsk_gyro_highrate(&gyro_hr);
	bno055_get_intmsk_accel_high_g(&accel_hg);
	bno055_get_intmsk_accel_anymotion(&accel_am);
	bno055_get_intmsk_accel_nomotion(&accel_nm);

	Serial.println( "---- Interrupt bitmask ----" );
	Serial.print( "Gyro Any Motion  " );
	Serial.println( gyro_am );
	Serial.print( "Gyro High Rate   " );
	Serial.println( gyro_hr );
	Serial.print( "Accel High G     " );
	Serial.println( accel_hg );
	Serial.print( "Accel Any Motion " );
	Serial.println( accel_am );
	Serial.print( "Accel No Motion  " );
	Serial.println( accel_nm );
	Serial.println( "---------------------------" );
}

/*
 * Print the interrupt status
 */
void getInterruptStatusEnabled(bool synthetic) {

	// 37 	INT_STA 	0x00	ACC_NM	ACC_AM	ACC_HIGH_G	GYR_DRDY	GYR_HIGH_RATE	GYRO_AM	MAG_DRDY	ACC_BSX_DRDY

		#pragma pack(push, 1)
			struct StatusInterrupt {
				byte accel_bsx_drdy		: 1;
				byte mag_drdy			: 1;
				byte gyro_am			: 1;
				byte gyro_high_rate	  	: 1;
				byte gyro_drdy	  		: 1;
				byte accel_high_g 		: 1;
				byte accel_am	  		: 1;
				byte accel_nm	  		: 1;
			};
		#pragma pack(pop)

		StatusInterrupt registerByte = {0};
		// Read all tht INT_STA addr to get all interrupt status in one read
		// after the read the register is cleared
		BNO055_RETURN_FUNCTION_TYPE res = bno055_read_register(BNO055_INT_STA_ADDR, (unsigned char *)(®isterByte), 1);

		if (res == 0) {
			if (synthetic){
				Serial.print("Anm Aam Ahg Grd Ggr Gam Mrd Abr --> ");
				Serial.print( registerByte.accel_nm );
				Serial.print( registerByte.accel_am );
				Serial.print( registerByte.accel_high_g );
				Serial.print( registerByte.gyro_drdy );
				Serial.print( registerByte.gyro_high_rate );
				Serial.print( registerByte.gyro_am );
				Serial.print( registerByte.mag_drdy );
				Serial.println( registerByte.accel_bsx_drdy );
			}else{
				Serial.print( "Gyro Any Motion  " );
				Serial.println( registerByte.gyro_am );
				Serial.print( "Gyro High Rate   " );
				Serial.println( registerByte.gyro_high_rate );
				Serial.print( "Accel High G     " );
				Serial.println( registerByte.accel_high_g );
				Serial.print( "Accel Any Motion " );
				Serial.println( registerByte.accel_am );
				Serial.print( "Accel No Motion  " );
				Serial.println( registerByte.accel_nm );
			}
		} else {
			Serial.println("Error status!");
		}
	}


void printGyroAnymotionParameters(){
	  unsigned char gyro_am_filter = 0;
	  bno055_get_gyro_anymotion_filter(&gyro_am_filter);
	  Serial.print("Gyro anymotion filter: ");
	  Serial.println(gyro_am_filter);

	  unsigned char gyro_am_slp = 0;
	  bno055_get_gyro_anymotion_slope_samples(&gyro_am_slp);
	  Serial.print("Gyro anymotion slope: ");
	  Serial.println(gyro_am_slp);

	  unsigned char gyro_am_awk = 0;
	  bno055_get_gyro_anymotion_awake_duration(&gyro_am_awk);
	  Serial.print("Gyro anymotion awake duration: ");
	  Serial.println(gyro_am_awk);

	  unsigned char gyro_am_thres = 0;
	  bno055_get_gyro_anymotion_threshold(&gyro_am_thres);
	  Serial.print("Gyro anymotion threshold: ");
	  Serial.println(gyro_am_thres);


	  unsigned char xEnabled = 0;
	  bno055_get_accel_high_g_axis_enable(BNO055_GYRO_HR_X_AXIS, &xEnabled);
	  Serial.print("X axis high rate enabled: ");
	  Serial.println(xEnabled);

	  unsigned char yEnabled = 0;
	  bno055_get_accel_high_g_axis_enable(BNO055_GYRO_HR_Y_AXIS, &yEnabled);
	  Serial.print("Y axis high rate enabled: ");
	  Serial.println(yEnabled);

	  unsigned char zEnabled = 0;
	  bno055_get_accel_high_g_axis_enable(BNO055_GYRO_HR_Z_AXIS, &zEnabled);
	  Serial.print("Z axis high rate enabled: ");
	  Serial.println(zEnabled);

}

The result in serial output is this.

---- Interrupt enabled ----
Gyro Any Motion  1
Gyro High Rate   0
Accel High G     0
Accel Any Motion 0
Accel No Motion  0
---------------------------
---- Interrupt bitmask ----
Gyro Any Motion  1
Gyro High Rate   0
Accel High G     0
Accel Any Motion 0
Accel No Motion  0
---------------------------
Gyro anymotion filter: 0
Gyro anymotion slope: 2
Gyro anymotion awake duration: 2
Gyro anymotion threshold: 4
X axis high rate enabled: 1
Y axis high rate enabled: 1
Z axis high rate enabled: 1
2Secs - Orientation: 179.19, 363.75, 356.12   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
3Secs - Orientation: 179.19, 363.75, 356.12   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
---------------
Gyro Any Motion  1
Gyro High Rate   0
Accel High G     0
Accel Any Motion 0
Accel No Motion  0
---------------
4Secs - Orientation: 166.69, 336.87, 416.81   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
5Secs - Orientation: 176.81, 364.50, 350.69   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
6Secs - Orientation: 162.12, 378.19, 331.37   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
7Secs - Orientation: 174.81, 365.50, 352.75   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
8Secs - Orientation: 174.75, 364.37, 354.62   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
9Secs - Orientation: 174.75, 364.19, 355.00   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
10Secs - Orientation: 174.75, 364.19, 355.00   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
11Secs - Orientation: 174.75, 364.19, 355.00   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
---------------
Gyro Any Motion  1
Gyro High Rate   0
Accel High G     0
Accel Any Motion 0
Accel No Motion  0
---------------
12Secs - Orientation: 173.62, 358.81, 368.19   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
13Secs - Orientation: 177.25, 362.50, 358.06   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
14Secs - Orientation: 177.81, 363.94, 356.44   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000
15Secs - Orientation: 177.81, 363.87, 356.19   -    Anm Aam Ahg Grd Ggr Gam Mrd Abr --> 00000000

When I move the bno055, It generates an interrupt, but to get another interrupt, I must stop all operations for 3 seconds, then I move again, generating another interrupt.

Thanks

  1. BNO055 accelerometer, gyroscope, magnetometer with basic Adafruit library
  2. BNO055 for esp32, esp8266, and Arduino: wiring and advanced Bosch library
  3. BNO055 for esp32, esp8266, and Arduino: features, configuration, and axes remap
  4. BNO055: power modes, accelerometer, and motion interrupt
  5. BNO055 for esp32, esp8266, and Arduino: enable INT pin and accelerometer High G Interrupt
  6. BNO055 for esp32, esp8266, and Arduino: Gyroscope High Rate and Any Motion Interrupt

Spread the love

Leave a Reply

Your email address will not be published. Required fields are marked *