ShellAddicted / BNO055ESP32

C++ Interface for the Bosch-Sensortec's BNO055 compatible with Espressif's ESP32 SoC running esp-idf.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

interrupt example not working

josephpal opened this issue · comments

Hi,

currently I try to get your example of enabling interrupts working. I am wondering about to correct wiring. To which pin of the ESP32 do i have to route the INT pin of the BNO055, because if i define e.g. GPIO_NUM_16, your example seems not working.

	/* setup I²C */
	i2c_config_t conf;
	conf.mode = I2C_MODE_MASTER;
	conf.sda_io_num = GPIO_NUM_21;
	conf.scl_io_num = GPIO_NUM_22;
	conf.sda_pullup_en = GPIO_PULLUP_DISABLE;
	conf.scl_pullup_en = GPIO_PULLUP_DISABLE;
	conf.master.clk_speed = 1000000;
	i2c_param_config(I2C_NUM_0, &conf);
	i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0);
	i2c_set_timeout(I2C_NUM_0, 56000);

	/* BNO055 I2C Addr can be 0x28 or 0x29 (depends on your hardware) */
	ESP_LOGD(TAG, "start BNO055 I2C init");  // DEBUG
	bno = new BNO055((i2c_port_t) I2C_NUM_0, 0x29, GPIO_NUM_MAX, GPIO_NUM_16);

        ....

	/* setup sensor */
	try {
		/* BNO055 is in CONFIG_MODE until it is changed */
		bno->begin();
		bno->enableExternalCrystal();

		bno->setPwrModeNormal();
		bno->setAccelAnyMotionInterrupt(2, 2, true, true, true);  // configure the interrupt, see datasheet for more details.
		bno->setAccelNoMotionInterrupt(0, 0, true, true, true);
		bno->enableAccelAnyMotionInterrupt(true);  // you can disable it with disableAccelAnyMotionInterrupt();
		bno->enableAccelNoMotionInterrupt(true);
		bno->setOprModeNdof();

		ESP_LOGI(TAG, "Setup Done.");
	} catch (BNO055BaseException &ex) {
		ESP_LOGE(TAG, "Setup Failed, Error: %s", ex.what());
		return;
	} catch (std::exception &ex) {
		ESP_LOGE(TAG, "Setup Failed, Error: %s", ex.what());
		return;
	}

	int16_t sw = bno->getSWRevision();
	uint8_t bl_rev = bno->getBootloaderRevision();
	ESP_LOGI(TAG, "SW rev: %d, bootloader rev: %u", sw, bl_rev);

        ....

I am using the BNO055 Shuttle Board and my connection is the following:

/*
 * PS1 -> GND (LOW) -> Enables I²C protocol
 * SCL -> SCL (Default: GPIO_NUM_22)
 * SDA -> SDA (Default: GPIO_NUM_21)
 * INT  -> GPIO_NUM_16
*/

Hi, I've just tested the code and I can't replicate your problem, everything works as expcted.
I've used BNO055 bno((i2c_port_t)I2C_NUM_0, 0x28, GPIO_NUM_MAX, GPIO_NUM_16);
Anyway I suggest to use a less valuable pin like GPIO_NUM_35 for interrupts.

I (3174) BNO055ESP32Example: Self-Test Results: MCU: 1, GYR:1, MAG:1, ACC: 1
I (3184) BNO055ESP32Example: Euler: X: 0.0 Y: 0.0 Z: 0.0 || Calibration SYS: 0 GYRO: 0 ACC:0 MAG:0
I (3294) BNO055ESP32Example: Euler: X: 0.0 Y: 0.8 Z: -0.8 || Calibration SYS: 0 GYRO: 0 ACC:0 MAG:0
I (3394) BNO055ESP32Example: Euler: X: 0.1 Y: 0.8 Z: -0.8 || Calibration SYS: 0 GYRO: 0 ACC:0 MAG:0
<*Shaked the BNO0555*>
I (3494) BNO055ESP32Example: AccelAnyMotion Interrupt received.
I (3494) BNO055ESP32Example: Euler: X: 1.4 Y: 0.7 Z: -0.7 || Calibration SYS: 0 GYRO: 0 ACC:0 MAG:0
I (3594) BNO055ESP32Example: Euler: X: 6.1 Y: 0.6 Z: -0.4 || Calibration SYS: 0 GYRO: 0 ACC:0 MAG:0
I (3694) BNO055ESP32Example: Euler: X: 3.8 Y: 0.5 Z: -0.9 || Calibration SYS: 0 GYRO: 0 ACC:0 MAG:0
I (3794) BNO055ESP32Example: AccelAnyMotion Interrupt received.
I (3794) BNO055ESP32Example: Euler: X: 5.2 Y: 0.6 Z: -0.7 || Calibration SYS: 0 GYRO: 0 ACC:0 MAG:0
I (3894) BNO055ESP32Example: Euler: X: 5.1 Y: 0.8 Z: -3.1 || Calibration SYS: 0 GYRO: 0 ACC:0 MAG:0
I (3994) BNO055ESP32Example: Euler: X: 5.6 Y: 0.6 Z: -0.9 || Calibration SYS: 0 GYRO: 0 ACC:0 MAG:0
I (4094) BNO055ESP32Example: AccelAnyMotion Interrupt received.
I (4094) BNO055ESP32Example: Euler: X: 3.9 Y: 0.9 Z: -1.1 || Calibration SYS: 0 GYRO: 0 ACC:0 MAG:0
I (4194) BNO055ESP32Example: Euler: X: 3.9 Y: 0.9 Z: -1.1 || Calibration SYS: 0 GYRO: 0 ACC:0 MAG:0
I (4294) BNO055ESP32Example: Euler: X: 3.9 Y: 0.9 Z: -1.1 || Calibration SYS: 0 GYRO: 0 ACC:0 MAG:0
<*Stopped shaking*>
<.........>
I (8294) BNO055ESP32Example: accelNoSlowMotion Interrupt received.
I (8294) BNO055ESP32Example: Euler: X: 3.9 Y: 0.9 Z: -1.1 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
I (8394) BNO055ESP32Example: Euler: X: 3.9 Y: 0.9 Z: -1.1 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
I (8494) BNO055ESP32Example: Euler: X: 3.9 Y: 0.9 Z: -1.1 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0

please provide more details.

Thanks for your quick response. It looks like i had some issues with my wiring, now your example is working. Here is my full code:

#include "Arduino.h"
#include "libs/BNO055ESP32/src/BNO055ESP32.h"

void setup() {
	// Setup I²C
	i2c_config_t conf;
	conf.mode = I2C_MODE_MASTER;
	conf.sda_io_num = GPIO_NUM_21;
	conf.scl_io_num = GPIO_NUM_22;
	conf.sda_pullup_en = GPIO_PULLUP_DISABLE;
	conf.scl_pullup_en = GPIO_PULLUP_DISABLE;
	conf.master.clk_speed = 1000000;
	i2c_param_config(I2C_NUM_0, &conf);
	i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0);
	i2c_set_timeout(I2C_NUM_0, 65000);

	//to use i²C leave the following line active
	BNO055 bno((i2c_port_t) I2C_NUM_0, 0x29, GPIO_NUM_25, GPIO_NUM_5);

	try {
		bno.begin();  // BNO055 is in CONFIG_MODE until it is changed
		bno.enableExternalCrystal();
		// bno.setSensorOffsets(storedOffsets);
		// bno.setAxisRemap(BNO055_REMAP_CONFIG_P1, BNO055_REMAP_SIGN_P1); // see datasheet, section 3.4
		/* you can specify a PoWeRMode using:
		 - setPwrModeNormal(); (Default on startup)
		 - setPwrModeLowPower();
		 - setPwrModeSuspend(); (while suspended bno055 must remain in CONFIG_MODE)
		 */
		bno.setAccelAnyMotionInterrupt(2, 2, true, true, true); // configure the interrupt, see datasheet for more details.
		bno.setAccelNoMotionInterrupt(0, 0, true, true, true);
		bno.enableAccelAnyMotionInterrupt(true); // you can disable it with disableAccelAnyMotionInterrupt();
		bno.enableAccelNoMotionInterrupt(true);
		bno.setOprModeNdof();
		ESP_LOGI(TAG, "Setup Done.");
	} catch (BNO055BaseException &ex) { // see BNO055ESP32.h for more details about exceptions
		ESP_LOGE(TAG, "Setup Failed, Error: %s", ex.what());
		return;
	} catch (std::exception &ex) {
		ESP_LOGE(TAG, "Setup Failed, Error: %s", ex.what());
		return;
	}

	try {
		int8_t temperature = bno.getTemp();
		ESP_LOGI(TAG, "TEMP: %d°C", temperature);

		int16_t sw = bno.getSWRevision();
		uint8_t bl_rev = bno.getBootloaderRevision();
		ESP_LOGI(TAG, "SW rev: %d, bootloader rev: %u", sw, bl_rev);

		bno055_self_test_result_t res = bno.getSelfTestResult();
		ESP_LOGI(TAG, "Self-Test Results: MCU: %u, GYR:%u, MAG:%u, ACC: %u",
				res.mcuState, res.gyrState, res.magState, res.accState);
	} catch (BNO055BaseException &ex) { // see BNO055ESP32.h for more details about exceptions
		ESP_LOGE(TAG, "Something bad happened: %s", ex.what());
		return;
	} catch (std::exception &ex) {
		ESP_LOGE(TAG, "Something bad happened: %s", ex.what());
		return;
	}

	while (1) {
		try {
			if (bno.interruptFlag == true) {
				// See bno055_interrupts_status_t for more details.
				bno055_interrupts_status_t ist = bno.getInterruptsStatus();
				// remember that multiple interrupts can be triggered at the same time. so you shouldn't use 'else if'
				if (ist.accelAnyMotion == 1) {
					ESP_LOGI(TAG, "AccelAnyMotion Interrupt received.");
				}
				if (ist.accelNoSlowMotion == 1) {
					ESP_LOGI(TAG, "accelNoSlowMotion Interrupt received.");
				}
				bno.clearInterruptPin();  // don't forget to place this.
			}
			// Calibration 3 = fully calibrated, 0 = not calibrated
			bno055_calibration_t cal = bno.getCalibration();
			bno055_vector_t v = bno.getVectorEuler();
			ESP_LOGI(TAG,
					"Euler: X: %.1f Y: %.1f Z: %.1f || Calibration SYS: %u GYRO: %u ACC:%u MAG:%u",
					v.x, v.y, v.z, cal.sys, cal.gyro, cal.accel, cal.mag);
		} catch (BNO055BaseException &ex) {
			ESP_LOGE(TAG, "Something bad happened: %s", ex.what());
			return;
		} catch (std::exception &ex) {
			ESP_LOGE(TAG, "Something bad happened: %s", ex.what());
		}
		vTaskDelay(100 / portTICK_PERIOD_MS); // in fusion mode max output rate is 100hz (actual rate: 100ms (10hz))
	}
}

void loop() {

}

The console output is also similar to the one you have posted. The only problem i have right now is that after some time it looks like the I2C communication isn't working anymore, and this problem occurs repeatedly.

[I][esp32_BNO055ESP32_Interrupts.ino:35] setup(): Setup Done.
[I][esp32_BNO055ESP32_Interrupts.ino:46] setup(): TEMP: 24°C
[I][esp32_BNO055ESP32_Interrupts.ino:50] setup(): SW rev: 800, bootloader rev: 21
[I][esp32_BNO055ESP32_Interrupts.ino:54] setup(): Self-Test Results: MCU: 1, GYR:1, MAG:1, ACC: 1
...
[I][esp32_BNO055ESP32_Interrupts.ino:73] setup(): accelNoSlowMotion Interrupt received.
[I][esp32_BNO055ESP32_Interrupts.ino:82] setup(): Euler: X: 359.9 Y: 0.0 Z: 4.3 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
[I][esp32_BNO055ESP32_Interrupts.ino:70] setup(): AccelAnyMotion Interrupt received.
[I][esp32_BNO055ESP32_Interrupts.ino:82] setup(): Euler: X: 359.7 Y: 0.0 Z: 4.3 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
[I][esp32_BNO055ESP32_Interrupts.ino:82] setup(): Euler: X: 359.8 Y: -0.1 Z: 4.3 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
[I][esp32_BNO055ESP32_Interrupts.ino:82] setup(): Euler: X: 0.1 Y: -0.2 Z: 4.7 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
[I][esp32_BNO055ESP32_Interrupts.ino:82] setup(): Euler: X: 359.9 Y: -0.6 Z: 5.7 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
[I][esp32_BNO055ESP32_Interrupts.ino:70] setup(): AccelAnyMotion Interrupt received.
[I][esp32_BNO055ESP32_Interrupts.ino:82] setup(): Euler: X: 0.3 Y: -2.5 Z: 4.3 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
[I][esp32_BNO055ESP32_Interrupts.ino:82] setup(): Euler: X: 0.2 Y: -4.7 Z: 4.1 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
[I][esp32_BNO055ESP32_Interrupts.ino:82] setup(): Euler: X: 0.2 Y: -6.6 Z: 3.5 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
[I][esp32_BNO055ESP32_Interrupts.ino:82] setup(): Euler: X: 0.5 Y: -7.2 Z: 2.0 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
[I][esp32_BNO055ESP32_Interrupts.ino:82] setup(): Euler: X: 1.1 Y: -7.6 Z: 1.1 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
...
[I][esp32_BNO055ESP32_Interrupts.ino:82] setup(): Euler: X: 3.9 Y: 0.0 Z: 4.2 || Calibration SYS: 0 GYRO: 3 ACC:0 MAG:0
E (3347527) BNO055: (i2c RL) Error: -1
[E][esp32_BNO055ESP32_Interrupts.ino:84] setup(): Something bad happened: I2CError: Check your wiring.
E (3347539) BNO055: (i2c WL) Error: -1

My current setup consists of an ESP32 (ESP-WROOM-32), a BNO055 Shuttle Board (HF 1717) and I am using your library in combination with the Arduino Sloebber plugin inside Eclipse, so my espressif idf version should be 3.2 (arduino-esp32 version 1.0.4).

The wiring (BNO055 Shuffle Board to -> ESP32) is the following:

  • PS0 (PIN8) -> GND
  • PS1 (PIN9) -> GND
  • GND (PIN3) -> GND
  • VDD (PIN1) -> 3.3V
  • VDDIO (PIN2) ->3.3V
  • SCL (PIN18) -> GPIO_NUM_22 (with 820Ohm PULLUP)
  • SDA (PIN17) -> GPIO_NUM_21 (with 820Ohm PULLUP)
  • nReset (PIN19) -> GPIO_NUM_25
  • INT (PIN21) -> GPIO_NUM_5

grafik

I modified some parts of the I2C interface implementaion:

  • conf.sda_pullup_en = GPIO_PULLUP_DISABLE -> because i am using a PULLUP
  • conf.scl_pullup_en = GPIO_PULLUP_DISABLE
  • conf.master.clk_speed = 1000000 -> i experimented a little bit with increasing the clock speed
  • i2c_set_timeout(I2C_NUM_0, 65000) -> higher clock speed needs a higher timeout value

So i am wondering if this issue is related to a general problem with the I2C interface of the ESP32? Or is this caused by the old idf version i am using?

Hi, yes there are issues with I²C (even with the latest idf), that's why UART is suggested and I²C is reported as partially supported by this library (see the readme.md).

As far as I know there's no way to fix that.
In case you find a solution: any help is appreciated.

I noticed that with a large timeout like i2c_set_timeout(i2c_port, 1048575) (1048575 = 2**20 - 1 clock cycles at 80 MHz = approx. 13 ms) the communication seems to be working (tested for 3+ hours). Might this be a solution or do I just have to wait longer for a communication problem?