FXOS8700 magnetic interrupt

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

FXOS8700 magnetic interrupt

2,934 Views
diken
Contributor I

I am trying to configure the FXOS8700CQR in magnetic threshold interrupt mode. I am using SPI to communicate witth the sensor.

Whenever a magnet is in the vicinity of the sensor, the programmed magnetic threshold values is supposed to trigger an interrupt.

When the data is streaming I can clearly see the spikes on the signal passing the programmed threshold.

The interrupt pin does not go high however. I checked with a scope.

I don't see the magnetic interrupts happening.The problem is that the magnetic interrupts in the ISR are not triggered.

Even if I trigger them manually by the shaking the unit I cannot clear them. Pin stays always high.

Is there any application note with regard to the magnetic threshold interrupt specifically. (not the vector magnitude)?


void FXOS8700CQ_ConfigMagTHS(void){    
MAG_RST_HIGH();                         // Hard Reset , RST active HIGH   
__delay_ms(5);    
MAG_RST_LOW();                             
__delay_ms(1);                          

FXOS8700CQ_WriteByte(CTRL_REG2, SMOD_LOW_NOISE|SLPE_MASK|MOD_LOW_NOISE);      // Low noise, low power, auto-sleep mode enabled
FXOS8700CQ_WriteByte(CTRL_REG3, IPOL_MASK);                     // Active HIGH on INT, push-pull mode   
 FXOS8700CQ_WriteByte(CTRL_REG4, 0x00 );                         // No interrupt enabled here    
FXOS8700CQ_WriteByte(CTRL_REG5, 0x00 );                         // No interrupt routed to pin 2
FXOS8700CQ_WriteByte(ASLP_COUNT, 0x05);                         // 20 ms -  if not interrupt is asserted in 20 ms the system will go back to sleep mode
FXOS8700CQ_WriteByte(M_CTRL_REG1, M_ACAL_MASK| M_OSR_50_HZ | M_HMS0_MASK);     //  automatic calibration,  one shot magnetic reset, only mag active  
FXOS8700CQ_WriteByte(M_CTRL_REG2, M_MAXMIN_DIS_MASK | M_MAXMIN_DIS_THS_MASK | M_MAXMIN_RST_MASK | RST_DISABLED);        //Magnetic min/max enabled    
FXOS8700CQ_WriteByte(M_CTRL_REG3, M_ASLP_OSR_100_HZ | M_THS_XYZ_MASK | M_ST_Z_MASK | M_ST_XY_MASK);        // all updated when THS ISR happens       

FXOS8700CQ_WriteByte(M_THS_CFG, M_THS_ELE | M_THS_OAE | M_THS_WAKE_EN | M_THS_ZEFE | M_THS_YEFE | M_THS_XEFE| M_THS_WAKE_EN | M_THS_INT_EN );  //M_INT_threshold on INT2 pin  OR INT of all axes for threshold, latch disabled.

uint16_t magThreshold = 0x200;                               //counts;    
uint8_t magThresholdHi = (magThreshold & 0xFF00) >> 8;    
uint8_t magThresholdLo = magThreshold & 0xFF;    
FXOS8700CQ_WriteByte(M_THS_Z_MSB, magThresholdHi);        // Debounce countered cleared to zero when threshold is not longer true    
FXOS8700CQ_WriteByte(M_THS_Z_LSB, magThresholdLo);    
    
magThreshold = 0x200;                               //counts;    
magThresholdHi = (magThreshold & 0xFF00) >> 8;   
magThresholdLo = magThreshold & 0xFF;   
FXOS8700CQ_WriteByte(M_THS_X_MSB, magThresholdHi);        // Debounce countered cleared to zero when threshold is not longer true    
FXOS8700CQ_WriteByte(M_THS_X_LSB, magThresholdLo);    
 
magThreshold = 0x200;                               //counts;    
magThresholdHi = (magThreshold & 0xFF00) >> 8;   
magThresholdLo = magThreshold & 0xFF;   
FXOS8700CQ_WriteByte(M_THS_Y_MSB, magThresholdHi);        // Debounce countered cleared to zero when threshold is not longer true    
FXOS8700CQ_WriteByte(M_THS_Y_LSB, magThresholdLo);    
    
FXOS8700CQ_WriteByte(M_THS_COUNT, 1); //debounce sample counts required before a magnetic threshold event is triggered, depends on ODR 
FXOS8700CQ_WriteByte(CTRL_REG1, ASLP_RATE_20MS | DATA_RATE_100HZ |LNOISE_MASK );     // in sleep mode data rate 50Hz, awake ODR = 100Hz, low noise mode, in standby
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The code above is executed between:

FXOS8700CQ_StandbyMode();
...

FXOS8700CQ_ActiveMode();

On the interrupt I try to clear the interrupt and in the main () function I try to print the source but I don't see anything at all.

void  _INTInterrupt(void){    
MagTHSEvent = 1;   
magintsrc = FXOS8700CQ_ReadByte(M_INT_SRC);            
 //Read interrupt source to clear int    
srcmag = FXOS8700CQ_ReadByte(M_THS_SRC);   
magintsrc = FXOS8700CQ_ReadByte(M_INT_SRC);            
 //Read interrupt source to clear int

    ..... //Clear the INT interrupt flag 
}
Labels (1)
0 Kudos
8 Replies

1,953 Views
chipmc
Contributor I

@diken or @TomasVaverka 

I am looking to do a similar thing - count cars and I have some FXOS8700OS devices on-hand.  Is there an example of using the hardware interrupt for magnetic threshold detection I could use as a staring point?  

 

Thanks, Chip

0 Kudos

1,168 Views
alexmv24
Contributor I

Hello, were you able to carry out your project, I have a similar project, could you help me?

0 Kudos

2,348 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi,

I will try to reproduce your settings and get back to you soon. At first glance everything seems to be correct. Can you please try to test the magnetometer threshold function without using the sleep mode?

Best regards,

Tomas

0 Kudos

2,348 Views
diken
Contributor I

Hi Tomas,

I already tried disabling the sleep mode with the same results.

The sleep mode functionality is needed however since this is  a long term solution where you can't easily replace the batteries.

I also tried changing the threshold on z axis. Still the same issue.

When a magnetic object (ex headphone) is in the vicinity all 3 axis are above 100 counts.

As it stands right now the magnetometer streams data correctly however the interrupt functionality is not responsive and does not change as per spec even if taking into account the debouncing counter (M_THS_COUNT)

Regards,

Di

0 Kudos

2,348 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Di,

I have just done a simple test using the following settings (without the sleep mode) and it works well as you can see on the picture below.

void FXOS8700CQ_Init (void)
{
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_X_MSB_REG, 0x00); // Threshold value MSB  
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_X_LSB_REG, 0x80); // Threshold value LSB  
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_CFG_REG, 0xCB); // Event flag latch enabled, logic OR of enabled axes, only X-axis enabled, threshold interrupt enabled and routed to INT1 
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_COUNT_REG, 0x0A); // 100ms at 100Hz ODR and magnetometer mode only 
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_CTRL_REG1, 0x1D); // Max OSR, only magnetometer is active 
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG3, 0x00); // Push-pull, active low interrupt 
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG1, 0x19); // ODR = 100Hz, Active mode       
}
void PORTD_IRQHandler()
{
       PORTD_PCR4 |= PORT_PCR_ISF_MASK; // Clear the interrupt flag 
       M_Ths_Source = I2C_ReadRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_SRC_REG); // Read the M_THS_SRC register to clear the SRC_M_THS flag in the M_INT_SRC register and deassert the INT1 pin
}

Mag threshold.JPG

Can you please try to reproduce it?

Meanwhile I will try to implement the sleep mode.

Best regards,

Tomas

0 Kudos

2,348 Views
diken
Contributor I

Hi Tomas,

I implemented thefirst snippet without the asleep configuration and indeed it works.

The issue is with the 

M_THS_COUNT_REG

which determines the debouncing interval. Specifically the interrupt triggers very late with regards to the project requirements. Initially this was set to 1.

Would this sensor work, assuming you have to track very fast moving object such as cars. (transient magnetic fields)?

The datasheet suggests the minimum time is 20ms but from experimental results the delay is much larger than that.

Best,

Di

0 Kudos

2,348 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Di,

The time step used by the debounce counter depends on the chosen ODR and m_hms[1:0] bits.

pastedImage_17.png

So the only way to reduce the time step is to increase the ODR and eventually use only the magnetometer (m_hms[1:0] = 0b01).

Best regards,

Tomas

0 Kudos

2,348 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Di,

I successfully implemented the sleep mode, here is my code:

void FXOS8700CQ_Init (void)
{      
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_X_MSB_REG, 0x00); // Threshold value MSB  
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_X_LSB_REG, 0x80); // Threshold value LSB  
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_CFG_REG, 0xCF); // Event flag latch enabled, logic OR of enabled axes, only X-axis enabled, wake on magnetic threshold event, threshold interrupt enabled and routed to INT1 
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_COUNT_REG, 0x0A); // 100ms at 100Hz ODR and magnetometer mode only 
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_CTRL_REG1, 0x1D); // Max OSR, only magnetometer is active 
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG3, 0x00); // Push-pull, active low interrupt 
       
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG2, 0x04); // Auto-sleep mode enabled       
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, ASLP_COUNT_REG, 0x06);  // Auto-sleep counter set to 1.92s (6 x 0.32s = 1.92s) 
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG4, 0x80); // Auto-sleep/wake interrupt enabled
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG5, 0x80); // Route auto-sleep/wake interrupt to INT1
       
       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG1, 0x19); // ODR = 100Hz, Active mode
} 
      

void PORTD_IRQHandler()
{
       PORTD_PCR4 |= PORT_PCR_ISF_MASK; // Clear the interrupt flag 
       Int_Flag = 1; 
}

while(1)
{
    if (Int_Flag)
    {
        Int_Flag = 0;
                    
        Int_Source = I2C_ReadRegister(FXOS8700CQ_I2C_ADDRESS, M_INT_SRC_REG);
        if (Int_Source & 0x04)  // Magnetic threshold event detected?
        {
            M_Ths_Src = I2C_ReadRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_SRC_REG); // Read the M_THS_SRC register to clear the SRC_M_THS flag in the M_INT_SRC register and deassert the INT1 pin
            Event_Counter++;
        }
                    
        Int_Source = I2C_ReadRegister(FXOS8700CQ_I2C_ADDRESS, INT_SOURCE_REG);
        if (Int_Source & 0x80)  // Auto-sleep/wake interrupt?
        {
            Sysmod = I2C_ReadRegister(FXOS8700CQ_I2C_ADDRESS, SYSMOD_REG);
        }                   
     }
}

I hope it will help you.

Best regards,

Tomas

0 Kudos