ESP32 Micromod + BNO086 IMU = how to connect INT and RST

Hi,

I successfully connected a BNO086 IMU with Qwiic to a Micromod board with ESP32, but unlike with the ThingsPlus I used before, I have no idea how/where to connect the 2 additional connections recommended in the IMU hookup guide for A4/INT and A5/RST.

The micromod board seems to not have such pinouts A4/INT and A5/RST, or am I missing something?

When I use:
if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended)
instead of
if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false)

I regularly get wrong readings, which makes the values delivered by the IMU useless. I assume those wrong readings are because of INT and RST are not connected. When I switch to the ThingsPlus I get smooth readings, but unfortunately I also need PoE-Ethernet, which now works fine with Micromod Board but not with the ThingsPlus setup.

Thanks,
Michael

Do you use RX1 and TXO already on the side of the single mainboard ? If not RX1 is GPIO16 or RX1, TXO is GPIO17 or TX1 with an ESP32 MM processor. Give it try…

1 Like

Thank you for your reply,

both are unused.

I am sorry for asking simple questions but this is beyond my experience:

You mean I could just use RX1 and TXO? Don’t they do something different than INT (Interrupt) and RST (Reset)?

What pins to I have to use then in the sketch?

Currently I use those from the example:
//#define BNO08X_INT A4
//#define BNO08X_RST A5

And then I just solder INT to RX1 and RST to TXO?


if you connect INT to RX1 and RST to TXO, then define

#define BNO08X_INT RX1
#define BNO08X_RST TX1

see what happens

Hi @paulvha

I did as you suggested, but unfortunately it does not work.

I have wired
RXI to INT
TXO to RST

And declared
#define BNO08X_INT RX1
#define BNO08X_RST TX1

When calling

Wire.begin();
delay(1000);
if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false)
{
 Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing...");
 while (1)
 ;
}

I first get message “I2C address found” followed by the “BNO08x not detected” message.

When using just myIMU.begin(BNO08X_ADDR, Wire) or just myIMU.begin() the IMU is detected but gives wrong readings.

Changing #define BNO08X_ADDR 0x4B to #define BNO08X_ADDR 0x4A does not help either.
Also switching from one to the other Qwiic connectors does not help.

Would you have another suggestion for me?

(I also tested with and without any other component or Micromod board attached, with the same result)

Maybe this helps? In the examples, the comment says

// For the most reliable interaction with the SHTP bus, we need
// to use hardware reset control, and to monitor the H_INT pin.
// The H_INT pin will go low when its okay to talk on the SHTP bus.
// Note, these can be other GPIO if you like.
// Define as -1 to disable these features.
#define BNO08X_INT  A4
//#define BNO08X_INT  -1
#define BNO08X_RST  A5
//#define BNO08X_RST  -1

I suspect timing… with reset.. disable the reset for now:

#define BNO08X_INT RX1
#define BNO08X_RST -1

Wire.begin();
delay(1000);
if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false)
{
 Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing...");
 while (1)
 ;
}

see what happens..

Unfortunately it does not work either.

What I’ve tried and results:

myIMU.begin(BNO08X_ADDR, Wire, TX1, RX1)
//or
myIMU.begin(BNO08X_ADDR, Wire, RX1, TX1)

//or
#define BNO08X_INT RX1
#define BNO08X_RST -1

//or
#define BNO08X_INT -1
#define BNO08X_RST RX1

//with
myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST)

→ E (1546) i2c.master: I2C hardware timeout detected
→ E (1546) i2c.master: probe device timeout. Please check if xfer_timeout_ms and pull-ups are correctly set up

#define BNO08X_INT TX1
#define BNO08X_RST -1
myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST)

→ I2C address found
→ BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing…

#define BNO08X_INT -1
#define BNO08X_RST TX1

//or
#define BNO08X_INT -1
#define BNO08X_RST -1
  • IMU is found, but with wrong readings (I assume because INT is not used)
  • only works if I disconnect power inbetween this attempt and the others described above. If I upload a sketch with e.g. TX1/-1 and get “I2C hardware timeout detected” and after that upload -1/TX1 I get the same “I2C hardware timeout detected”. Only if I do a power cycle (not reset button) the IMU is found. (Which leads me to the conclusion that the RESET signal is mandatory, I will try connecting the mainboards’ RST to RST on the IMU maybe that helps for this issue, but that does not solve the problem with INT)

Maybe the answer lies somewhere in the block headline " Multiplexed Primary UART" in the mainboards’ hookup guide (where RX1 and TX0 are mentioned), but I am not experienced enough to understand/know what to do with it..

Update
(unsuccessful) I disabled Serial.begin as I read that using RX/TX for Interrupt does not work along with using Serial connection.
(unsuccessful) I swapped connections (IMU Int to TX0 and IMU Rst to RX1) as I read that TX0 is for Transmit, and it sounds plausible to me that the Interrupt signal is transmitted from the ESP32 to the IMU, not the other way around? But result is the same.
(unsuccessful) I have connected IMU RST to Mainboard RST, did not change anything.

Update #2
Quote from the IMU hookup guide, maybe this leads somewhere?

  • RST — The reset signal pin is an input pin and it is active low. Pull it low to reset the IC. You can find this on both sides of the board.
  • INT — The interrupt pin is an output pin and active low. When BNO080 is ready for communication, it will pull this pin low.

If I understand this right

  • the RST pin could be connected to the RST on the mainboard just for the Reset Signal?
  • the INT pin is indeed a signal from the IMU to the mainboard that tells the ESP32 when the IMU is ready (so INT goes to RX as you have suggested from the beginning on)

There is also a section in the hookup guide for UART communication mentioning TXO and RXI but I am unsure what to make out of this, or if this leads into the right direction?

Does the pins_arduino.h file help for the used ESP32 / Micromod?

#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
static const uint8_t TX = 1;
static const uint8_t RX = 3;
#define TX1 17
#define RX1 16
static const uint8_t SDA = 21;
static const uint8_t SCL = 22;
static const uint8_t I2C_INT = 4;
#define WIRE1_PIN_DEFINED 1 // See Wire.cpp at bool TwoWire::initPins(int sdaPin, int sclPin)
static const uint8_t SDA1 = 26;
static const uint8_t SCL1 = 25;
static const uint8_t SS = 5;
static const uint8_t MOSI = 23;
static const uint8_t MISO = 19;
static const uint8_t SCK = 18;
static const uint8_t A0 = 34;
static const uint8_t A1 = 35;
static const uint8_t BATT_VIN = 39;
static const uint8_t PWM0 = 13;
static const uint8_t PWM1 = 12;
static const uint8_t D0 = 14;
static const uint8_t D1 = 27;
static const uint8_t G0 = 15;
static const uint8_t G1 = 25;
static const uint8_t G2 = 26;
static const uint8_t G3 = 17;
static const uint8_t G4 = 16;
static const uint8_t G5 = 32;
static const uint8_t G6 = 33;
static const uint8_t AUD_OUT = 17;
static const uint8_t AUD_IN = 16;
static const uint8_t AUD_LRCLK = 25;
static const uint8_t AUD_BCLK = 26;
static const uint8_t T0 = 4;
static const uint8_t T1 = 0;
static const uint8_t T2 = 2;
static const uint8_t T3 = 15;
static const uint8_t T4 = 13;
static const uint8_t T5 = 12;
static const uint8_t T6 = 14;
static const uint8_t T7 = 27;
static const uint8_t T8 = 33;
static const uint8_t T9 = 32;
static const uint8_t DAC1 = 25;
static const uint8_t DAC2 = 26;
static const uint8_t LED_BUILTIN = 2;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN
#endif /* Pins_Arduino_h */

I read here, that the IMU send its Interrupt signal to the ESP32 A4 which is an analog input.

The RX1 is a digital input and cannot read analog value directly to be used as interrupt.

Is that correct and doesn’t that mean that I cannot use the TX1 as suggested here?

The function that wait for interrupt is using digitalread(). So it does not need to be Analog

static bool hal_wait_for_int(void) {
  for (int i = 0; i < 500; i++) {
    if (!digitalRead(_int_pin))
      return true;
    // Serial.print(".");
    delay(1);
  }
  // Serial.println("Timed out!");
  hal_hardwareReset();

  return false;
}

I used that pins_arduino.h to get RX1 and TX1 information

If I understand this right

    the RST pin could be connected to the RST on the mainboard just for the Reset Signal?
    the INT pin is indeed a signal from the IMU to the mainboard that tells the ESP32 when the IMU is ready (so INT goes to RX as you have suggested from the beginning on)

There is also a section in the hookup guide for UART communication mentioning TXO and RXI but I am unsure what to make out of this, or if this leads into the right direction?

The RX and TXO are pins that could be used form Serial1 from the ESP32. But they are also normal GPIO pins. Hence they should be able to be used for RST and INT-pin. I need to look in the library code to understand why it does not.

Else.. do not use the INT and RST (both set to -1). In the loop() of the example, change delay(10); to delay(1000). See whether that makes a change.

  • “I need to look in the library code..” yes please if you could do that, as I am a bit lost on what to do next..
  • “do not use INT and RST (set to -1)” => problem is, if I do that (use -1) I occasionally get wrong readings. I assume because in the moment when new values are requested from IMU the IMU is not ready and sends garbage (don’t know how to test this assumption though). If I increase delay, wrong readings become less but still happen. Also, I need very fast readings (at least 30/s) to have smooth rotation, delays are not an option.

Wrong readings look like this (the lines with a negative value that does not change much even if I rotate the IMU):

13:25:25.809 -> 140.91
13:25:26.810 -> 140.89
13:25:27.806 -> -179.22
13:25:28.806 -> -179.22
13:25:29.812 -> 140.92
13:25:30.835 -> 140.92
13:25:31.800 -> 134.82
13:25:32.846 -> 108.63
13:25:33.852 -> -179.99
13:25:34.811 -> 91.24
13:25:35.804 -> 84.02
13:25:36.836 -> 84.02
13:25:37.801 -> 84.46

Other thoughts, maybe helpful?

  • call pinMode(BNO08X_INT, INPUT); (did not change anything though)
  • call Wire.begin(BNO08X_INT,BNO08X_RST); (did not change anything too though)

Wire.setClock(10000);
I found out that setting the clock speed to 10.000 or lower will prevent wrong readings, but unfortunately with this I will get max. 10 readings/second which is too little. I need at least 30 (better 60). When setting to 20.000+ I get wrong readings again (although very little). Default seems to be 100.000 and max. is 400.000 (the higher the clock speed is, the more wrong readings pop up).

Also I found out that connecting the RST to the Mainboard does work and is required. Without connecting it, the IMU will most of the time be not properly detected when rebooting/flashing. Only power cycle would then allow the IMU to be detected properly again. Maybe this is another hint figuring out why INT RX1 does not work..

as gpio test,
connect RX1 and TX1 with a wire. nothing else
copy/ compile the following sketc.
if TX1 is set high, RX1 should read that as well.

void setup() {
  Serial.begin(115200);
  
  while(!Serial) delay(10); // Wait for Serial to become available.
 
  Serial.println();
  Serial.println("Test RX1/ TX1 pins ESP32");
  
  // set RX1 pin
  Serial.print("RX1 input :");
  Serial.println(RX1);
  pinMode(RX1, INPUT_PULLUP);
  
  // Set TX1 pin
  Serial.print("TX1 output :");
  Serial.println(TX1);
  pinMode(TX1, OUTPUT);
}

void loop() {
  SetTX1(HIGH);
  DisplayRX1();

  SetTX1(LOW);
  DisplayRX1();

  Serial.println();
  
  delay(1000);
}

void DisplayRX1()
{
  if (digitalRead(RX1))
    Serial.println("RX1 reads HIGH");
  else
    Serial.println("RX1 reads LOW");
}

void SetTX1(bool val)
{
  if(val) {
    digitalWrite(TX1, HIGH);
    Serial.println("TX1 is set HIGH");
  }
  else {
    digitalWrite(TX1, LOW);
    Serial.println("TX1 is set LOW");
  }
}

The result of your sketch is:
RX1 input :16
TX1 output :17

09:13:12.145 → TX1 is set HIGH
09:13:12.145 → RX1 reads HIGH
09:13:12.145 → TX1 is set LOW
09:13:12.145 → RX1 reads HIGH

I assume that the last line should read LOW instead of HIGH?

DELAY
I added delay(1000) between the 2 call blocks to make sure the reading is not because of no delay between setting high and low.

  SetTX1(HIGH);
  DisplayRX1();

  Serial.println();
  delay(1000);

  SetTX1(LOW);
  DisplayRX1();

  Serial.println();
  delay(1000);

But that did not change the result:
09:15:44.925 → TX1 is set HIGH
09:15:44.925 → RX1 reads HIGH
09:15:45.932 → TX1 is set LOW
09:15:45.932 → RX1 reads HIGH

PIN MODES
I tested all pin modes for RX1:
ANALOG
PULLUP
INPUT
INPUT_PULLDOWN
OPEN_DRAIN
OUTPUT_OPEN_DRAIN
=> result is always RX1 LOW (TX1 either HIGH or LOW)

TX1 only
Serial.println(digitalRead(TX1));
I printed the value of TX1 after changing from LOW to HIGH to test if that works, and TX1 changes OK from 0 to 1 and back.

RX1 only
When I set RX1 to be an output and change from LOW to HIGH, digitalRead returns LOW and HIGH for RX1:

//setup
pinMode(RX1, OUTPUT);
//loop
digitalWrite(RX1, HIGH);
//or
digitalWrite(RX1, LOW);
//and
Serial.println(digitalRead(RX1));

swap RX1 and TX1
I swapped RX1 to be output and TX1 input, in that case RX1 changes from LOW to HIGH but TX1 always is HIGH.

pinMode(RX1, OUTPUT);
pinMode(TX1, INPUT_PULLUP);

Do not setup pinModes
If I do not call pinMode for both pins, both digitalRead(RX1) and digitalRead(TX1) report 0, no matter if set TX1 to LOW or HIGH.

No Serial, TX
I removed Serial.begin() and changed TX1 to TX (as it reads TXO on the board), did not change anything.

So what does that mean?

Use the standard sketch as i sent you. But now connect SEL-pin to GND

Try again..

OK that works, RX1 now equals TX1.

cool. Keep SEL connected to GND

now back to the original issue with the BN0086. As we defined before using RX1 for INT and TX1 for RESET. Try that and let us know.

It works and readings are all good.

Many thanks!

Notes:
It does only work when RST is connected to TX0. In that case, upon boot/reset, several hardware timeout messages pop up, but then after around 2s the sensor starts to work and deliver values. When I connect RST to the mainboards RST, I only get hardware timeout messages but the sensor never delivers values.

I am not sure if it is needed but I added the pinMode calls from the “pin test sketch” to setup():

pinMode(RX1, INPUT_PULLUP);
pinMode(TX1, OUTPUT);

When I do that, digitalRead(RX1) returns 1 and digitalRead(TX1) returns 0.
When I don’t do that, digitalRead(RX1) returns 0 and digitalRead(TX1) returns 1.

Per default, the clock is set to 100.000 - I changed that to the max (400.000) and it still works fine.
Wire.setClock(400000);

1 Like

One more question: what does it imply that TX1 and RX1 are now used for the IMU?

I assume that means I cannot add any other hardware that would rely on serial connection, right?

But I can add other Qwiic devices? (Thats what I will do next, display, vibration, audio, led..)