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!
Solved! Go to Solution.
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.
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:
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
Hi Alejandro,
For motion detection, I advise you to use the Acceleration Vector-Magnetitude detection feature inluded in the FXOS8700CQ device.
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
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
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.
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:
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
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).
Regards.
Great catch Alejandro.
I will inform the Processor Expert team.
Thanks!
Anthony