FXAS21000 stops working

cancel
Showing results for 
Search instead for 
Did you mean: 

FXAS21000 stops working

Jump to solution
788 Views
alex323qp
Contributor III

Hi guys, I'm working with the FXAS21000 and after following the bare metal example project I was able to get some readings out of the device. The problem, however, is that after a few readings (<5) the device stops working. I noticed that the interrupt pin remains low. Since I'm using INT2 as an external interrupt to know when to read the registers, my code just stops working. If I ignore the interrupt pin and just read the OUT_X_MSB register, I do get the correct readings.

I understand that just reading the 6 data bytes starting at OUT_X_MSB should reset the interrupt flag (Datasheet: "Reading the INT_SRC_FLAG register does not reset any event-flag source bits; they are reset by reading the appropriate event source register"), but that doesn't seem to be the case. The datasheet also states that "...The content of this register (0x0B) is reset upon a transition from Standby to Active or from Ready to Active modes", so I decided to switch from "active" to "ready" mode before reading and back to "active" after reading the contents of the registers, this seems to fix the issue but is not ideal since I need 3 operations just to read the data.

#define FXAS21000_DR_SHIFT2(x) (x << 2)
#define FXAS21000_REG1_DR_MSK 0x1C

void FXAS21000::init(){
    writeRegister(FXAS21000_CTRL_REG1, FXAS21000_REG1_SFT_RST); // Factory default
    wait(1_ms);
    // Enter in standby mode
    uint8_t reg = getRegister(FXAS21000_CTRL_REG1);
    writeRegister(FXAS21000_CTRL_REG1, reg & ~FXAS21000_REG1_STANDBY);
    // Set the Full scale mode at 800dps
    // High pass filter disabled
    writeRegister(FXAS21000_CTRL_REG0, 0x01);
    // Enable data ready interrupts
    writeRegister(FXAS21000_CTRL_REG2, (1 << 2));
    // Set a low sampling rate to start with (Mode_25Hz)
    reg = getRegister(FXAS21000_CTRL_REG1) & ~FXAS21000_REG1_DR_MSK;
    writeRegister(FXAS21000_CTRL_REG1, reg | (FXAS21000_REG1_DR_MSK & FXAS21000_DR_SHIFT2(3)));
    // Back to active mode
    reg = getRegister(FXAS21000_CTRL_REG1) & ~FXAS21000_REG1_STANDBY;
    int r = writeRegister(FXAS21000_CTRL_REG1, reg | FXAS21000_REG1_ACTIVE);
}

int FXAS21000::read(int16_t * t){
    uint8_t d[7];
    int r = read( FXAS21000_STATUS, d, 7);
    if(r <= 0){
        return r;
    }

    t[0] = ((d[1] * 256) + ((unsigned short) d[2]));
    t[1] = ((d[3] * 256) + ((unsigned short) d[4]));
    t[2] = ((d[5] * 256) + ((unsigned short) d[6]));
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Has anybody encountered a similar issue? any help would be really appreciated!

Thanks, 

A.

Labels (2)
0 Kudos
1 Solution
410 Views
alex323qp
Contributor III

It's been over a year and I had completely forgotten about this post. I'm replying now so the info might help others.

The problem turned out to be a race condition; in the IRQ routine, I was setting a flag to indicate the gyro had data and then in the main loop I checked that flag to determine if I should read new data or not and if so, read the data and reset the flag back to 0. The problem as you would imagine at this point is that right between the time the i2c transaction to read the axes finished and the time I was resetting the flag back to 0, another IRQ would occur, so I was basically ignoring the last interrupt signal, which explained why the interrupt pin remained low.

There are a couple of workarounds for this, but I think I ended up leaving everything as it was but then in the main loop, double checked if the IRQ pin was low even though the flag was false (no interrupt present), this avoided having to pull the pin status on every loop cycle but rather, only in those scenarios when it was obvious an error occurred (flag indicates no new data but interrupt pin was low).

Hope this helps someone.

Cheers!

A.

View solution in original post

0 Kudos
3 Replies
411 Views
alex323qp
Contributor III

It's been over a year and I had completely forgotten about this post. I'm replying now so the info might help others.

The problem turned out to be a race condition; in the IRQ routine, I was setting a flag to indicate the gyro had data and then in the main loop I checked that flag to determine if I should read new data or not and if so, read the data and reset the flag back to 0. The problem as you would imagine at this point is that right between the time the i2c transaction to read the axes finished and the time I was resetting the flag back to 0, another IRQ would occur, so I was basically ignoring the last interrupt signal, which explained why the interrupt pin remained low.

There are a couple of workarounds for this, but I think I ended up leaving everything as it was but then in the main loop, double checked if the IRQ pin was low even though the flag was false (no interrupt present), this avoided having to pull the pin status on every loop cycle but rather, only in those scenarios when it was obvious an error occurred (flag indicates no new data but interrupt pin was low).

Hope this helps someone.

Cheers!

A.

0 Kudos
410 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Alexander,

Do you have a logic analyzer or an oscilloscope to know what is going on on the bus? Without it, it might be hard to debug.

 

You are right that the SRC_DRDY flag is cleared and consequently the INTx pin deasserted by reading all the X, Y, Z output data registers (0x01 – 0x06). It is also necessary to acknowledge an IRQ in your ISR usually by writing a logic 1 to a specific bit of your MCU. Without doing it, the interrupt flag on your MCU will remain active and then you are not able to receive any further interrupts from the FXAS21000.

 

Hope it helps.   

Best regards,

Tomas

0 Kudos
410 Views
alex323qp
Contributor III

Hi Tomas, thank you for your reply. 

Yes, I do have a logic analyzer but unfortunately, the device is in an assembled board and I don't have easy access to the bus. I know the INT2 pin remains low because I can read the logic level of the pin from the MCU and indicates LOW (after the readings stop coming up).

I'm aware of the ISR's reset bit; I have another sensor on the same board (and many other boards) using the same IRQ handling routines working just fine. In addition, if that was the case, just changing the active modes of the gyro should not have "fixed" the issue. This tells me it is something silly I'm doing in the configuration of the registers of the FXAS21000.

I mentioned in the original post that the device works ok for up to ~5 readings (seems random) and then stops working, which makes me wonder if there is a FIFO buffer that I should be clearing out after a certain number of readings?

Thanks,

A.

0 Kudos