FXOS8700CQ Motion Detection and Interrupts

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

FXOS8700CQ Motion Detection and Interrupts

Jump to solution
2,925 Views
alejandrovelez
Contributor III

Greetings,

I'm trying to configure the FXOS8700CQ sensor with motion detection and interrupt in one of the two interrupt pins. So far I tried to do an example from the application note AN4070 made for a MMA8451 Sensor changing the register number for the FXOS8700CQ ones, but I still don't get the interrupt.

I follow the steps:

Example Steps for Configuring Motion Detection

X or Y > 3g using MFF Function 4g, 100 Hz ODR, Normal Mode

Step 1: Put the device into Standby Mode: Register 0x2A CTRL_REG1

IIC_RegWrite(0x2A, 0x18); //Set the device in 100 Hz ODR, Standby

Step 2: Set Configuration Register for Motion Detection by setting the “OR” condition OAE = 1, enabling

X, Y, and the latch

IIC_RegWrite(0x15, 0xD8)

Step 3: Threshold Setting Value for the Motion detection of > 3g //(I tried with less Threshold)

Note: The step count is 0.063g/ count

• 3g/0.063g = 47.6; //Round up to 48

IIC_RegWrite(0x17, 0x30)

Step 4: Set the debounce counter to eliminate false readings for 100 Hz sample rate with a requirement

of 100 ms timer.

Note: 100 ms/10 ms (steps) = 10 counts

IIC_RegWrite(0x18, 0x0A);

Step 5: Enable Motion/Freefall Interrupt Function in the System (CTRL_REG4)

IIC_RegWrite(0x2D, 0x04);

Step 6: Route the Motion/Freefall Interrupt Function to INT1 hardware pin (CTRL_REG5) //(I tried with int1 and int2)

IIC_RegWrite(0x2E, 0x04);

Step 7: Put the device in Active Mode

CTRL_REG1_Data = IIC_RegRead(0x2A);

CTRL_REG1_Data| = 0x01;

IIC_RegWrite(CTRL_REG1_Data);

Step 8: Write Interrupt Service Routine Reading the System Interrupt Status and the Motion/Freefall

Status

I did exactly, but with the correct register numbers for the FXOS8700CQ sensor.

I'm using a FRDM-K64F with its embedded accelerometer and Processor Expert for the I2C communication. The pins are correctly configured and the I2C communication works good but I don't get an interrupt when I move it.

Is there something that I'm missing?

Thanks for the help!

Labels (2)
0 Kudos
1 Solution
1,267 Views
anthonyduhamel
NXP Employee
NXP Employee

Alejandro,

I've just tested again my code, (I did  some updates), it works well.

In my FXOS8700.c file:

////////////////////////////////////////////////////////////////////////////////

//!                                Public functions

////////////////////////////////////////////////////////////////////////////////

bool bFXOS8700_Init()

{

  bool __b_result = FALSE;

  uint8_t __u8_CmdResult = 0;

  if(!_b_IsFXOS8700Init)

  {

  I2C_Init (NULL);

  if(_bFXOS8700_Write(FXOS8700_CTRL_REG1,0x00)) // Pass to standby mode for writable operations

  if(_bFXOS8700_Read(FXOS8700_WHO_AM_I,&__u8_CmdResult)) // Check device communication

  if(__u8_CmdResult== FXOS8700_WHO_AM_I_VALUE) // Check device ID

  /* Acc-cell Config */

  if(_bFXOS8700_Write(FXOS8700_XYZ_DATA_CFG,0x02)) // ±0.976 mg/LSB

  /* M-cell Config */

  if(_bFXOS8700_Write(FXOS8700_M_CTRL_REG1,0x17)) // Hybrid mode (mag+acc)

  if(_bFXOS8700_Write(FXOS8700_M_CTRL_REG2,0x00))

  if(_bFXOS8700_Write(FXOS8700_M_CTRL_REG3,0x80))

  /* Sleep mode + wake mode config + interrupt*/

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG2,0x04 | 0x03)) // Autosleep on |LowPower

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG3,0x04|0x00)) // wake on vecm | active low | PushPull

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG4,0x02)) // VECM INT enable in sleep mode

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG5,0x02)) // INT on INT1 pin

  if( _bFXOS8700_Write(FXOS8700_ASLP_COUNT,0x06)) // Auto-sleep counter

  if( _bFXOS8700_Write(FXOS8700_TRIG_CFG, 0x00)) // FIFO not used

  /* Vector Magnitude config */

  if( _bFXOS8700_Write(FXOS8700_A_VECM_CFG,0x48)) // 0b0100 1000  current x/y/z accelerometer output data as initial reference values | vecm enable

  if( _bFXOS8700_Write(FXOS8700_A_VECM_THS_MSB,0x00)) // Threshold value MSB

  if( _bFXOS8700_Write(FXOS8700_A_VECM_THS_LSB,0x40)) // Threshold value LSB

  //---------------

  if(_bFXOS8700_Write(FXOS8700_CTRL_REG1,0x29)) // Active Mode + ODR max ->freq min

  {

    _b_IsFXOS8700Init = TRUE;

    __b_result  =TRUE;

    INT_MOTIONDECTECTION_Init(NULL);

  }

  }

    return __b_result;

}

void vFXOS8700_OnMotionDetected() // Called form Event.c

{

  bool __b_IsMotionDetected;

  uint8_t __u8_CmdResult = 0xFF;

  _bFXOS8700_Read(FXOS8700_INT_SOURCE,&__u8_CmdResult);// Read INT source to clear vecm int flag

  __b_IsMotionDetected =  ( ((__u8_CmdResult>>1)&0x01)==1); // Check if vecm has been setted by it

  if(__b_IsMotionDetected )

  {

    // Wake up the MCU

  }

}

Did you have well configured your INT component? I configure it for Falling Edge interrupt. For pin number, I'm using a FRDM-KL46Z, so it's not the rigth value, yours should be PTC6 (INT1) on FRDM-K46 QRC.

pastedImage_4.png

In my Event.c file

void INT_MOTIONDECTECTION_OnInterrupt(LDD_TUserData *UserDataPtr)

{

  vFXOS8700_OnMotionDetected();

}

By the end, I have checked the well working of INT with a scope:

trigg.PNG

Level is normally High. When a motion is detected, There is a falling edge: Interrup is catched by the code and cleared by vFXOS8700_OnMotionDetected() function by reading the FXOS8700 INT_SOURCE register.

I hope it will help you.

Regards,

Anthony

View solution in original post

0 Kudos
5 Replies
1,267 Views
anthonyduhamel
NXP Employee
NXP Employee

Hi Alejandro,

For motion detection, I advise you to use the Acceleration Vector-Magnetitude detection feature inluded in the FXOS8700CQ device.

VECM.PNG

Here a code sample for integration :

////////////////////////////////////////////////////////////////////////////////

//!                                Defines

////////////////////////////////////////////////////////////////////////////////

// Cfg register

#define FXOS8700_WHO_AM_I 0x0D

#define FXOS8700_CTRL_REG1 0x2A

#define FXOS8700_CTRL_REG2 0x2B

#define FXOS8700_CTRL_REG3 0x2C

#define FXOS8700_CTRL_REG4 0x2D

#define FXOS8700_CTRL_REG5 0x2E

#define FXOS8700_M_CTRL_REG1 0x5B

#define FXOS8700_M_CTRL_REG2 0x5C

#define FXOS8700_M_CTRL_REG3 0x5D

#define FXOS8700_XYZ_DATA_CFG 0x0E

// Interupts

#define FXOS8700_A_VECM_CFG        0x5F

#define FXOS8700_A_VECM_THS_MSB    0x60

#define FXOS8700_A_VECM_THS_LSB    0x61

#define FXOS8700_ASLP_COUNT 0x29

#define FXOS8700_TRIG_CFG 0x0A

// Data register

#define FXOS8700_M_OUT_X 0x33

#define FXOS8700_OUT_X 0x01

#define FXOS8700_TEMP 0x51

#define FXOS8700_WHO_AM_I_VALUE 0xC7

////////////////////////////////////////////////////////////////////////////////

//!                                 Static members

////////////////////////////////////////////////////////////////////////////////

static bool _b_IsFXOS8700Init=FALSE;

////////////////////////////////////////////////////////////////////////////////

//!                                 Public functions

////////////////////////////////////////////////////////////////////////////////

bool bFXOS8700_Init()

{

  bool __b_result = FALSE;

  uint8_t __u8_CmdResult = 0;

  if(!_b_IsFXOS8700Init)

  {

  I2C_Init (NULL);

  if(_bFXOS8700_Write(FXOS8700_CTRL_REG1,0x00)) // Pass to standby mode for writable operations

  if(_bFXOS8700_Read(FXOS8700_WHO_AM_I,&__u8_CmdResult)) // Check device communication

  if(__u8_CmdResult== FXOS8700_WHO_AM_I_VALUE) // Check device ID

  if(_bFXOS8700_Write(FXOS8700_XYZ_DATA_CFG,0x02)) //±0.976 mg/LSB

  if(_bFXOS8700_Write(FXOS8700_M_CTRL_REG1,0x17))// Hybrid

  if(_bFXOS8700_Write(FXOS8700_M_CTRL_REG2,0x00))

  if(_bFXOS8700_Write(FXOS8700_M_CTRL_REG3,0x80))

  /* Sleep mode */

  if( _bFXOS8700_Write(FXOS8700_TRIG_CFG, 0x02))

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG2,0x04))//Autosleep on

  if( _bFXOS8700_Write(FXOS8700_ASLP_COUNT,0x06))//Auto-sleep trigg

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG4,0x02))//Autosleep IT enable

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG5,0x02))//IT on IT1 pin

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG3,0x07))//wake on vecm 1101

  if( _bFXOS8700_Write(FXOS8700_A_VECM_CFG,0x48))//A_VECM_CFG

  if( _bFXOS8700_Write(FXOS8700_A_VECM_THS_MSB,0x00))//A_VECM_THS_MSB 

  if( _bFXOS8700_Write(FXOS8700_A_VECM_THS_LSB,/0x40))//A_VECM_THS_LSB

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG3,0x04))//wake on vecm

  //---------------

  if(_bFXOS8700_Write(FXOS8700_CTRL_REG1,0x29)) // Active Mode + ODR max ->freq min

  if(_bFXOS8700_Read(0x0B,&__u8_CmdResult)) // Check WakeMode

  if((__u8_CmdResult&0x03)== 1) // ok

  {

  _b_IsFXOS8700Init = TRUE;

  __b_result  =TRUE;

  }

  }

    return __b_result;

}

Anthony

0 Kudos
1,267 Views
alejandrovelez
Contributor III

Hi Anthony

Thanks for the help

I have tried several codes, even yours.... my problem now is that I don't get a interrupt from the pins int1 or int2. When I poll the INT_SOURCE register  I can see that the respective interrupt bits are set and then I clear it by reading the interrupt source in the respective register. The code works with polling but I need and edge, rising or falling in the intx pin when the respective bit is asserted in the INT_SOURCE register because I need to work a processor in low power mode and then wake up it with an edge.

BR

0 Kudos
1,268 Views
anthonyduhamel
NXP Employee
NXP Employee

Alejandro,

I've just tested again my code, (I did  some updates), it works well.

In my FXOS8700.c file:

////////////////////////////////////////////////////////////////////////////////

//!                                Public functions

////////////////////////////////////////////////////////////////////////////////

bool bFXOS8700_Init()

{

  bool __b_result = FALSE;

  uint8_t __u8_CmdResult = 0;

  if(!_b_IsFXOS8700Init)

  {

  I2C_Init (NULL);

  if(_bFXOS8700_Write(FXOS8700_CTRL_REG1,0x00)) // Pass to standby mode for writable operations

  if(_bFXOS8700_Read(FXOS8700_WHO_AM_I,&__u8_CmdResult)) // Check device communication

  if(__u8_CmdResult== FXOS8700_WHO_AM_I_VALUE) // Check device ID

  /* Acc-cell Config */

  if(_bFXOS8700_Write(FXOS8700_XYZ_DATA_CFG,0x02)) // ±0.976 mg/LSB

  /* M-cell Config */

  if(_bFXOS8700_Write(FXOS8700_M_CTRL_REG1,0x17)) // Hybrid mode (mag+acc)

  if(_bFXOS8700_Write(FXOS8700_M_CTRL_REG2,0x00))

  if(_bFXOS8700_Write(FXOS8700_M_CTRL_REG3,0x80))

  /* Sleep mode + wake mode config + interrupt*/

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG2,0x04 | 0x03)) // Autosleep on |LowPower

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG3,0x04|0x00)) // wake on vecm | active low | PushPull

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG4,0x02)) // VECM INT enable in sleep mode

  if( _bFXOS8700_Write(FXOS8700_CTRL_REG5,0x02)) // INT on INT1 pin

  if( _bFXOS8700_Write(FXOS8700_ASLP_COUNT,0x06)) // Auto-sleep counter

  if( _bFXOS8700_Write(FXOS8700_TRIG_CFG, 0x00)) // FIFO not used

  /* Vector Magnitude config */

  if( _bFXOS8700_Write(FXOS8700_A_VECM_CFG,0x48)) // 0b0100 1000  current x/y/z accelerometer output data as initial reference values | vecm enable

  if( _bFXOS8700_Write(FXOS8700_A_VECM_THS_MSB,0x00)) // Threshold value MSB

  if( _bFXOS8700_Write(FXOS8700_A_VECM_THS_LSB,0x40)) // Threshold value LSB

  //---------------

  if(_bFXOS8700_Write(FXOS8700_CTRL_REG1,0x29)) // Active Mode + ODR max ->freq min

  {

    _b_IsFXOS8700Init = TRUE;

    __b_result  =TRUE;

    INT_MOTIONDECTECTION_Init(NULL);

  }

  }

    return __b_result;

}

void vFXOS8700_OnMotionDetected() // Called form Event.c

{

  bool __b_IsMotionDetected;

  uint8_t __u8_CmdResult = 0xFF;

  _bFXOS8700_Read(FXOS8700_INT_SOURCE,&__u8_CmdResult);// Read INT source to clear vecm int flag

  __b_IsMotionDetected =  ( ((__u8_CmdResult>>1)&0x01)==1); // Check if vecm has been setted by it

  if(__b_IsMotionDetected )

  {

    // Wake up the MCU

  }

}

Did you have well configured your INT component? I configure it for Falling Edge interrupt. For pin number, I'm using a FRDM-KL46Z, so it's not the rigth value, yours should be PTC6 (INT1) on FRDM-K46 QRC.

pastedImage_4.png

In my Event.c file

void INT_MOTIONDECTECTION_OnInterrupt(LDD_TUserData *UserDataPtr)

{

  vFXOS8700_OnMotionDetected();

}

By the end, I have checked the well working of INT with a scope:

trigg.PNG

Level is normally High. When a motion is detected, There is a falling edge: Interrup is catched by the code and cleared by vFXOS8700_OnMotionDetected() function by reading the FXOS8700 INT_SOURCE register.

I hope it will help you.

Regards,

Anthony

0 Kudos
1,267 Views
alejandrovelez
Contributor III

Thanks Anthony, I adjusted your code to my needs and it works.

One of the problems that I was having is that there is an error in KDS 3.0 Processor Expert. The pin FXOS8700CQ_INT1 doesn't correspond to the one that is connected to de chip (PTC6).

pastedImage_0.png

Regards.

0 Kudos
1,267 Views
anthonyduhamel
NXP Employee
NXP Employee

Great catch Alejandro.

I will inform the Processor Expert team.

Thanks!

Anthony

0 Kudos