BNO055 per esp32, esp8266 e Arduino: giroscopio ad alta velocità e interrupt per ogni movimento – 6
In questo articolo, esploreremo l’utilizzo del sensore BNO055 con ESP32, ESP8266 e Arduino per ottenere un giroscopio ad alta frequenza e qualsiasi interruzione di movimento. Il BNO055 è un sensore versatile che combina un accelerometro, un magnetometro e un giroscopio in un unico modulo, rendendolo una scelta ideale per i progetti che richiedono un tracciamento accurato dell’orientamento.
Inizieremo discutendo i principi di base del sensore BNO055 e le sue diverse modalità di funzionamento. Poi, ti mostreremo come connettere il BNO055 alla tua scheda ESP32, ESP8266 o Arduino e leggere i dati da esso. Successivamente, approfondiremo la modalità di alta frequenza del giroscopio, che consente al sensore di emettere dati a una velocità molto più elevata rispetto alla modalità standard. Infine, ti mostreremo come utilizzare qualsiasi interruzione di movimento per rilevare cambiamenti improvvisi di orientamento e attivare un’azione nel tuo codice.
Architettura
Ho preso questa immagine dal datasheet per ricordare che questo sensore aveva tre sensori e un microcontrollore con software di fusione per gestire i dati e fornirti una posizione assoluta.
Pinout BNO055
Ci sono molte versioni di moduli di questi sensori, ho scelto il più piccolo e economico.
Qui il modulo Aliexpress
Tutti questi moduli avevano le stesse funzionalità, ma per abilitarli, è necessario eseguire diverse operazioni.
Questo è il clone che uso:
Ecco invece quello di Adafruit:
Il sensore supporta un livello di logica a 3,3 V, ma il modulo può essere alimentato a 5 V.
Interrupt di alta velocità giroscopio
Questo interrupt è basato sul confronto dei dati di velocità angolare rispetto a una soglia di alta velocità per la rilevazione di shock o altri eventi ad alta velocità angolare.
Parametri | Valore |
---|---|
Selezione asse | Asse X |
Asse Y | |
Asse Z | |
Impostazioni filtro ad alta frequenza | Filtrato |
Non filtrato | |
Impostazioni interruzione asse X | Soglia |
Durata | |
Isteresi | |
Impostazioni interruzione asse Y | Soglia |
Durata | |
Isteresi | |
Impostazioni interruzione asse Z | Soglia |
Durata | |
Isteresi |
L’interruzione ad alta frequenza è abilitata (disabilitata) per asse. La soglia ad alta frequenza è impostata attraverso i bit di soglia. L’isteresi può essere selezionata impostando i bit.
L’interruzione ad alta frequenza viene generata se il valore assoluto della velocità angolare di almeno uno degli assi abilitati (relazione “o”) è superiore alla soglia per almeno il tempo definito dal registro. L’interruzione viene ripristinata se il valore assoluto della velocità angolare di tutti gli assi abilitati (relazione “e”) è inferiore alla soglia meno l’isteresi. Il bit di stato dell’interruzione viene memorizzato. La relazione tra il contenuto e il ritardo effettivo della generazione dell’interruzione è ritardo [ms] = [+ 1] * 2,5 ms. Pertanto, i possibili tempi di ritardo variano da 2,5 ms a 640 ms.
Quindi uno sketch di esempio deve essere in modalità NORMAL e devi abilitare l’interruzione ad alta velocità del giroscopio e il pin di interruzione con questo comando.
// Attiva la frequenza di campionamento elevata dell'accelerazione e la maschera dei bit per il pin INT
bno055_set_int_gyro_highrate(1);
bno055_set_intmsk_gyro_highrate(1); // per abilitare il pin INT
Puoi abilitare il filtro (disabilitato per impostazione predefinita).
bno055_set_gyro_highrate_filter(0);
E impostare il valore corretto per la soglia, la durata e l’isteresi con questi comandi.
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);
E ricorda che tutti gli assi sono disabilitati per impostazione predefinita, quindi devi abilitarli.
// Abilita gli assi
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);
Per evitare lo stato INT HIGH, imposto il reset al registro.
// resetta tutti i segnali INT precedenti
bno055_set_reset_int(1);
Quindi lo sketch completo diventa:
/**
* 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);
}
Il risultato nel serial output sarà
---- 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
Interruzione di qualsiasi movimento del giroscopio
La rilevazione del movimento (slope) utilizza la pendenza tra i segnali di velocità angolare successivi per rilevare i cambiamenti di movimento. Un’interruzione viene generata quando la pendenza (valore assoluto della differenza di velocità angolare) supera una soglia preimpostata. Viene cancellata non appena la pendenza scende al di sotto della soglia.
Parametri | Valore |
---|---|
Selezione asse | Asse X |
Asse Y | |
Asse Z | |
Impostazioni filtro di qualsiasi movimento | Filtrato |
Non filtrato | |
Impostazioni interruzione | Soglia |
Campioni di pendenza | |
Durata di attivazione |
La soglia può essere definita. La differenza di tempo tra i segnali di velocità angolare successivi dipende dal tasso di aggiornamento selezionato (fs).
1 LSB = 1 °/s nel range 2000°/s 1 LSB = 0,5°/s nel range 1000°/s 1 LSB = 0,25°/s nel range 500°/s
…
Puoi impostare una soglia con questo comando.
bno055_set_gyro_anymotion_threshold(4);
Per sopprimere falsi trigger, l’interruzione viene generata (cancellata) solo se un certo numero di punti dati di pendenza consecutivi è maggiore (minore) della soglia di pendenza. Possono essere impostati i bit Campioni di pendenza.
Puoi impostare la pendenza con questo comando.
bno055_set_gyro_anymotion_slope_samples(2);
La rilevazione del movimento può essere abilitata (disabilitata) separatamente per ciascun asse. I criteri per la rilevazione del movimento sono soddisfatti, e l’interruzione di movimento (Any-Motion) viene generata se la pendenza di uno qualsiasi degli assi abilitati supera la soglia impostata in modo consecutivo. Non appena le pendenze di tutti gli assi abilitati scendono o rimangono al di sotto di questa soglia per un insieme di tempi consecutivi, l’interruzione viene cancellata a meno che il segnale di interruzione sia bloccato.
Per impostare il numero di campioni, devi usare questo comando.
bno055_set_gyro_anymotion_awake_duration(2);
La durata di attivazione (Awake Duration) imposta il numero di campioni. 0=8 campioni, 1=16 campioni, 2=32 campioni, 3=64 campioni
Lo stato dell’interruzione è memorizzato in bit nel registro. L’interruzione Any-motion fornisce informazioni aggiuntive sulla pendenza rilevata.
L’interruzione di movimento viene attivata se [Slope Samples + 1]*4 punti dati consecutivi sono sopra la soglia di interruzione di movimento definita.
Puoi filtrare la banda passante con questo comando.
bno055_set_gyro_anymotion_filter(0);
Per attivare l’interruzione (sul registro) e il pin INT, devi abilitare l’interruzione e impostare la maschera di bit di interruzione, rispettivamente.
// Attiva il rilevamento di qualsiasi movimento (anymotion) del giroscopio e la maschera del bit per il pin INT
bno055_set_int_gyro_anymotion(1);
bno055_set_intmsk_gyro_anymotion(1); // per abilitare il pin INT
Ecco qui lo sketch completo.
/**
* 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
Quando muovo il bno055, genera un’interruzione, ma per ottenere un’altra interruzione, devo interrompere tutte le operazioni per 3 secondi, poi mi muovo di nuovo, generando un’altra interruzione.
Grazie
- BNO055 accelerometro, giroscopio, magnetometro con la semplice libreria Adafruit
- BNO055 per esp32, esp8266 e Arduino: cablaggio e libreria Bosch avanzata
- BNO055 per esp32, esp8266 e Arduino: caratteristiche, configurazione e rimappatura assi
- BNO055: modalità di alimentazione, accelerometro e interrupt di movimento
- BNO055 per esp32, esp8266 e Arduino: abilitare il pin INT e High G Interrupt dell’accelerometro
- BNO055 per esp32, esp8266 e Arduino: giroscopio ad alta velocità e interrupt per ogni movimento