ShellAddicted / BNO055ESP32

C++ Interface for the Bosch-Sensortec's BNO055 compatible with Espressif's ESP32 SoC running esp-idf.
MIT License
24 stars 9 forks source link

enableInterrupt() multiple interrupts routed to INT pin? #9

Closed josephpal closed 3 years ago

josephpal commented 3 years ago

Hi,

i want to configure the BNO055 for using its interrupts signals. My setup consists of one ESP32 connected to a BNO055 Shuttle board from Bosch.

On page 40 inside the datasheet of the BNO055 sensor, it is described how to enable specific interrupts by setting the corresponding bits inside the INT_EN (address: 0x10) register. In order to route an interrupt to the INT pin, it is neccessary to set the corresponding bit inside the INT_MSK register (address: 0xF0).

Those two register in your case are named (see BNO055ESP32.h):

typedef enum {
    ...
    BNO055_REG_INT_MSK = 0x0F,
    BNO055_REG_INT_EN = 0x10,
    ...
} bno055_reg_t;

What i understood from your implementation so far is that you set the corresponding bits inside the register BNO055_REG_INT_MSK with the content of tmp[0] and BNO055_REG_INT_EN with the content of tmp[1] right?

But if useInterruptPin is true, tmp[1] | flag will only add the corresponding bit inside the BNO055_REG_INT_EN register while tmp[0] |= flag will do the same for the BNO055_REG_INT_MSK, so in this case we would have multiple interrupts enabled and masked for being routed to the INT pin or did i missed something?

void BNO055::enableInterrupt(uint8_t flag, bool useInterruptPin) {
    uint8_t tmp[2];
    setPage(1);

    readLen(BNO055_REG_INT_MSK, tmp, 2); 
    tmp[0] |= flag;                                                   
    tmp[1] = (useInterruptPin == true) ?  (tmp[1] | flag) : (tmp[1] & ~flag);   <--  tmp[0] & flag ? 
    writeLen(BNO055_REG_INT_MSK, tmp, 2);
}

So in order to route only the last "activated" interrupt to the INT pin, tmp[1] | flag has to be changed to tmp[0] & flag?

ShellAddicted commented 3 years ago

Hi, it seems you're really confused. Let me try to clarify the code for you:

void BNO055::enableInterrupt(uint8_t flag, bool useInterruptPin) {
    uint8_t tmp[2];
    setPage(1);

// Step 1: read the current value of the registers, to avoid to overwrite already active interrupts (if any)
    readLen(BNO055_REG_INT_MSK, tmp, 2); 
// Registers `BNO055_REG_INT_MSK` and `BNO055_REG_INT_EN` are one next to the other (0x0F + 0x01 = 0x10)
// this means they can be both read with a single I²C read request instead of two
// Now tmp[0] contains the value of BNO055_REG_INT_MSK
// and tmp[1] contains the value of BNO055_REG_INT_EN

// Step 2: turn on the interrupt
    tmp[0] |= flag; // this is an OR operation, only bits that are changed from 0 to 1 in flag will change,
                    // enabling only the interrupt of interest, leaving the others untouched.

// Step 3: enabled/disable the usage of the INT pin for this specific interrupt depending on useInterruptPin
// (tmp[1] | flag) makes sure that the relevant bit is set (1)
// (tmp[1] & ~flag) makes sure that the relevant bit is not set (0)
    tmp[1] = (useInterruptPin == true) ?  (tmp[1] | flag) : (tmp[1] & ~flag);   

// Step 4: write back the updated values to both registers with a single I²C write request instead of two
    writeLen(BNO055_REG_INT_MSK, tmp, 2);
}

Now that's sorted out.

So in order to route only the last "activated" interrupt to the INT pin, tmp[1] | flag has to be changed to tmp[0] & flag?

I don't understand your statement, why do you think is a good idea to mix the values of two different registers? the AND operation would enable the pin for the current ('last') interrupt, and disable everything else but why would you want do that? interrupts and pin usage can be individually and independently enabled/disabled according to the application requirements.

josephpal commented 3 years ago

Hi, it seems you're really confused. Let me try to clarify the code for you:

void BNO055::enableInterrupt(uint8_t flag, bool useInterruptPin) {
    uint8_t tmp[2];
    setPage(1);

// Step 1: read the current value of the registers, to avoid to overwrite already active interrupts (if any)
    readLen(BNO055_REG_INT_MSK, tmp, 2); 
// Registers `BNO055_REG_INT_MSK` and `BNO055_REG_INT_EN` are one next to the other (0x0F + 0x01 = 0x10)
// this means they can be both read with a single I²C read request instead of two
// Now tmp[0] contains the value of BNO055_REG_INT_MSK
// and tmp[1] contains the value of BNO055_REG_INT_EN

// Step 2: turn on the interrupt
    tmp[0] |= flag; // this is an OR operation, only bits that are changed from 0 to 1 in flag will change,
                    // enabling only the interrupt of interest, leaving the others untouched.

// Step 3: enabled/disable the usage of the INT pin for this specific interrupt depending on useInterruptPin
// (tmp[1] | flag) makes sure that the relevant bit is set (1)
// (tmp[1] & ~flag) makes sure that the relevant bit is not set (0)
    tmp[1] = (useInterruptPin == true) ?  (tmp[1] | flag) : (tmp[1] & ~flag);   

// Step 4: write back the updated values to both registers with a single I²C write request instead of two
    writeLen(BNO055_REG_INT_MSK, tmp, 2);
}

Now that's sorted out.

So in order to route only the last "activated" interrupt to the INT pin, tmp[1] | flag has to be changed to tmp[0] & flag?

I don't understand your statement, why do you think is a good idea to mix the values of two different registers? the AND operation would enable the pin for the current ('last') interrupt, and disable everything else but why would you want do that? interrupts and pin usage can be individually and independently enabled/disabled according to the application requirements.

Hi,

thank you very much for your reply and the explanation of your code. Indeed i was confused ;) I didn't realize that it is possible to enable/handle multiple interrupts.

So in order to route only the last "activated" interrupt to the INT pin, tmp[1] | flag has to be changed to tmp[0] & flag?

Yeah, this was definitely wrong ;) I meant tmp[1] | flag has to be changed to tmp[1] & flag, but now everything is clear. I think the "issue" is solved now and can be closed.

Thanks