FXOS8700CQ interrupt and data reading is not stable

cancel
Showing results for 
Search instead for 
Did you mean: 

FXOS8700CQ interrupt and data reading is not stable

2,044 Views
tungdao
Contributor I

Hi, I followed the example on this article FXOS8700CQ - Bare metal example project  to write similar code to run with the TI CC3200. However I have experienced unstable interrupt and data reading. The interrupt (INT1) is not always available, regardless how hard I move the board around to change the acceleration and magnetic field. Also data reading hangs after a few ( 4 to 7) reads and then I would not be able to read the magnetic data at all, until I cycle power the sensor. So I have few problems I would need help with:

1. Is there a way to reset the sensor without cycling power?

2. Did I do anything wrong in setting up the sensor? (Code is at the end of this post)

3. My application is fairly simple: if there's a magnetic change in the environment, sends an interrupt signal to the MCU to read the magnetic data. Then wait until the magnetic signal is stabilize (i.e. no changes in magnetic within 10s) and activate interrupt listener again. What would be the best way to use the FXOS8700CQ for this application?

The current code I have on CC3200:

void I2C_Init() {

  I2C_Open(I2C_MASTER_MODE_STD);

 

  GPIO_IF_LedConfigure(LED1|LED2|LED3);

  Fxos8700cqInit();

}

static void Fxos8700cqInit (void) {

  WriteSingle(FXOS8700CQ_I2C_ADDRESS, FX_CTRL_REG2, 0x40); // Reset all registers to POR values

  MAP_UtilsDelay(16000); // ~1ms delay.

  WriteSingle(FXOS8700CQ_I2C_ADDRESS, FX_XYZ_DATA_CFG_REG, 0x00); // +/-2g range with 0.244mg/LSB

  WriteSingle(FXOS8700CQ_I2C_ADDRESS, FX_M_CTRL_REG1, 0x1F); // Hybrid mode (accelerometer + magnetometer), max OSR

  WriteSingle(FXOS8700CQ_I2C_ADDRESS, FX_M_CTRL_REG2, 0x20); // M_OUT_X_MSB register 0x33 follows the OUT_Z_LSB register 0x06 (used for burst read)

  WriteSingle(FXOS8700CQ_I2C_ADDRESS, FX_CTRL_REG2, 0x02);     // High Resolution mode

  WriteSingle(FXOS8700CQ_I2C_ADDRESS, FX_CTRL_REG3, 0x00); // Push-pull, active low interrupt

  WriteSingle(FXOS8700CQ_I2C_ADDRESS, FX_CTRL_REG4, 0x01); // Enable DRDY interrupt

  WriteSingle(FXOS8700CQ_I2C_ADDRESS, FX_CTRL_REG5, 0x01); // DRDY interrupt routed to INT1 - PTD4

  WriteSingle(FXOS8700CQ_I2C_ADDRESS, FX_CTRL_REG1, 0x35); // ODR = 3.125Hz, Reduced noise, Active mode

}

static void I2C_HandleDataReadyInterrupt()

{

  DisableGpioInterruptHandler(INT_TEST_SW3);     //disable INT1 interrupt handler

  GPIO_IF_LedToggle(MCU_RED_LED_GPIO);

  _dataReady = 1;

}

static void ResetDataInterrupt()

{

   _dataReady = 0;

  MAP_UtilsDelay(16000);

  InitGpioInterruptHandler(I2C_HandleDataReadyInterrupt, INT_TEST_SW3);     //set interrupt handler for INT1

}

int main(void)

{

  ResetDataInterrupt();

  while (1)

  {

  if (_dataReady) // Is a new set of data ready?

  {

  ReadMulti(FXOS8700CQ_I2C_ADDRESS, FX_OUT_X_MSB_REG, 12, AccelMagData); // Read data output registers 0x01-0x06 and 0x33 - 0x38

  // 14-bit accelerometer data

  Xout_Accel_14_bit = ((short) (AccelMagData[0] << 8 | AccelMagData[1])) >> 2; // Compute 14-bit X-axis acceleration output value

  Yout_Accel_14_bit = ((short) (AccelMagData[2] << 8 | AccelMagData[3])) >> 2; // Compute 14-bit Y-axis acceleration output value

  Zout_Accel_14_bit = ((short) (AccelMagData[4] << 8 | AccelMagData[5])) >> 2; // Compute 14-bit Z-axis acceleration output value

  // Accelerometer data converted to g's

  Xout_g = ((float) Xout_Accel_14_bit) / FX_SENSITIVITY_2G; // Compute X-axis output value in g's

  Yout_g = ((float) Yout_Accel_14_bit) / FX_SENSITIVITY_2G; // Compute Y-axis output value in g's

  Zout_g = ((float) Zout_Accel_14_bit) / FX_SENSITIVITY_2G; // Compute Z-axis output value in g's

  // 16-bit magnetometer data

  Xout_Mag_16_bit = (short) (AccelMagData[6] << 8 | AccelMagData[7]); // Compute 16-bit X-axis magnetic output value

  Yout_Mag_16_bit = (short) (AccelMagData[8] << 8 | AccelMagData[9]); // Compute 16-bit Y-axis magnetic output value

  Zout_Mag_16_bit = (short) (AccelMagData[10] << 8 | AccelMagData[11]); // Compute 16-bit Z-axis magnetic output value

  // Magnetometer data converted to microteslas

  Xout_uT = (float) (Xout_Mag_16_bit) / FX_SENSITIVITY_MAG; // Compute X-axis output magnetic value in uT

  Yout_uT = (float) (Yout_Mag_16_bit) / FX_SENSITIVITY_MAG; // Compute Y-axis output magnetic value in uT

  Zout_uT = (float) (Zout_Mag_16_bit) / FX_SENSITIVITY_MAG; // Compute Z-axis output magnetic value in uT

  Heading = atan2(Yout_uT, Xout_uT) * 180 / PI; // Compute Yaw angle

  printf("Mag(uT) - X:%f Y:%f Z:%f Heading:%f \n\r", Xout_uT, Yout_uT, Zout_uT, Heading);

  ResetDataInterrupt();

  }

  }

}

0 Kudos
3 Replies

712 Views
Joz
Contributor I

Hello!

How big is your yaw angle error?

0 Kudos

884 Views
aswins
NXP Employee
NXP Employee

Hi Tungdao,

                       Can you pls let me know what do you mean by 'INT1 is not always available'? Do you mean you dont see DRDY signal in INT1 at all or is it triggering occasionally?

To answer you other questions:

1. Is there a way to reset the sensor without cycling power?

            Yes you can use RST(pin 16) for hard reset or soft reset (CTRL_REG2 like you use in your program).

2. Did I do anything wrong in setting up the sensor? (Code is at the end of this post)

           

             May I know the reason as to why you have 1 ms delay in ResetDataInterrupt () function?

3. My application is fairly simple: if there's a magnetic change in the environment, sends an interrupt signal to the MCU to read the magnetic data. Then wait until the magnetic signal is stabilize (i.e. no changes in magnetic within 10s) and activate interrupt listener again. What would be the best way to use the FXOS8700CQ for this application?

                 Did you try using Magnetometer threshold function or Vector magnitude function ? Please see this app note. (AN4458)

Also it will be helpful if you could upload the schematics for better analysis.

Thanks

Aswin

0 Kudos

884 Views
tungdao
Contributor I

Hi Aswin,

The DRDY signal in INT1 is triggering occasionally. And sometimes it can be jammed, meaning that the I2C communication is hung and does not receive response from the sensor when I tried to ready the MOUT registers data.

I put 1ms in ResetDataInterrupt() because without it the interrupt was too fast and it jammed the I2C communication after a very short time. But I agree this delay shouldn't be there if the DRDY signal works as it should be (i.e. changed only when new data is available). Maybe I understand it incorrectly, so please correct me if I'm wrong on this: let's say if DRDY is set, I then read the MOUT registers data and the DRDY bit is cleared. Assuming nothing is changed in the magnetic field (no movement of the sensor and no magnet nearby), the DRDY bit should stay low, shouldn't it?

I haven't tried the threshold function and vector magnitude function yet. I'll give it a try and see if that works.

I used the frdm-stbc-agm01 board for testing. So there's no custom schematic involved. Wiring from the frdm-stbc-agm01 board to the CC3200 is as follows:

I2C-SCL1 --> SCL

I2C-SDA1 --> SDA

INT1-8700 --> INT (GPIO_13)

Vdd --> Vdd

Gnd --> Gnd

There are also few things I notice with the frdm-stbc-agm01 board that it exposes only the SA0 pin of the FXOS8700CQ, but not the SA1 pin so I cannot ground both pins like in the datasheet. And the test point for SA0 always gives about 1.7V even when I ground the SA0 pin using the breakout sockets (maybe this is the source of the instability?) The WhoAmI also does not always return 0xC7 even though I ran the same code over and over. Sometimes it returns 0x1D instead. And after few more tests yesterday, now it only returns 0x1D. It has been frustrating to work with the frdm-stbc-agm01 board.

I have tested the I2C communication using a MAG3110 and everything is working fine with this sensor. So the problem seems to be on the frdm-stbc-agm01 board.

Thanks.

0 Kudos