Hi Tomas,
I am still on my first attempt at getting the MMA8652 chip going. I can talk to the chip and get Who_AM_I back, but I can get no further.
Now I am working through the example code, but when I run the below example with "Enable DRDY Interrupt = 0x01" the interrupt I/O pin is pulled constantly low, it never resets. When I set "Enable DRDY Interrupt = 0x00" my interrupt pin stays high no matter how i move the chip. Are any other initialisation steps required, or can you think what else I may need to test.
Thanks
rocketman46
void MMA8652FC_Init (void)
{
I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG2, 0x40); // Reset all POR values
Pause(0x631); // ~1ms delay
I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, XYZ_DATA_CFG_REG, 0x00); // +/-2g range with ~0.977mg/LSB
I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG2, 0x02); // High Resolution mode
I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG3, 0x00); // Push-pull, active low interrupt
I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG4, 0x01); // Enable DRDY interrupt
I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG5, 0x01); // DRDY interrupt INT1 - PTA5
I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG1, 0x39); // ODR = 1.56Hz, Active mode
}
Hi,
The SRC_DRDY bit is cleared and consequently the INT1 pin deasserted by reading all the X, Y, Z output data registers (0x01 – 0x06) as shown in the picture below.
If you are having problems to implement a multiple bytes read function, you can try to read these registers separately using a single byte read function which seems to be working if you can read the WHO_AM_I reg.
It is also necessary to acknowledge an IRQ in your ISR 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 DRDY interrupts from the MMA8652FC.
I am doing it as follows in my example code.
/******************************************************************************
* PORT A Interrupt handler
******************************************************************************/
void PORTA_IRQHandler()
{
PORTA_PCR5 |= PORT_PCR_ISF_MASK; // Clear the interrupt flag
DataReady = 1;
}
if (DataReady) // Is a new set of data ready?
{
DataReady = 0;
I2C_ReadMultiRegisters(MMA8652FC_I2C_ADDRESS, OUT_X_MSB_REG, 6, AccelData); // Read data output registers 0x01-0x06
// 12-bit accelerometer data
Xout_12_bit = ((short) (AccelData[0]<<8 | AccelData[1])) >> 4; // Compute 12-bit X-axis acceleration output value
Yout_12_bit = ((short) (AccelData[2]<<8 | AccelData[3])) >> 4; // Compute 12-bit Y-axis acceleration output value
Zout_12_bit = ((short) (AccelData[4]<<8 | AccelData[5])) >> 4; // Compute 12-bit Z-axis acceleration output value
// Accelerometer data converted to g's
Xout_g = ((float) Xout_12_bit) / SENSITIVITY_2G; // Compute X-axis output value in g's
Yout_g = ((float) Yout_12_bit) / SENSITIVITY_2G; // Compute Y-axis output value in g's
Zout_g = ((float) Zout_12_bit) / SENSITIVITY_2G; // Compute Z-axis output value in g's
}
I hope it helps.
Regards,
Tomas
Hi Tomas,
Thanks for your help, but I still cannot get the chip working correctly.
I have tried reading the X, Y, Z output data registers (0x01 – 0x06) with multi_byte_read, and single_byte_read to clear the interrupt but my I/O pin stays low and the interrupt is not cleared.
The un-calibrated output from the X, Y, Z registers without using interrupts, is shown below. This confirms I can read the data back OK.
AccelData X, Y, Z -7 -8 1042
Lastly do you recommend an external pull-up resistor on the interrupt pin or is the MCU pull-up OK?
Thanks,
Hi,
If you are using a pull-up resistor on the interrupt pin, do not forget to set the PP_OD bit (1 = open drain) in the CTRL_REG3. Also make sure that your MCU interrupt pin is configured as GPIO with an interrupt on falling edge.
You may also try using the push-pull configuration (PP_OD = 0) and do not care about the pull-up resistor.
Regards,
Tomas
Hi Tomas,
I have tried those changes and it is still not working. Am I correct in thinking, when the chip is moved in either X, Y or Z an interrupt event occurs. This is what I am looking for. Maybe your example is not doing this?
Thanks for your help
Hi,
Since you are using the DRDY interrupt, an interrupt event occurs when a new set of acceleration data has been generated and is available to be read (each 0.64s @ 1.56Hz ODR):
However, based on your description, you should use either the motion or transient functions to generate an interrupt when the acceleration exceeds a set threshold. Please take a closer look at our AN4070 and AN4071 for more information and example settings.
I hope it helps.
Regards,
Tomas
Tomas,
Are both of these datasheets relevant to the MMA8652, because they quote the MMA8451?
Thanks,
Rocketman46
Hi,
Yes, both the motion and transient detection functions are the same on both devices so you can use these app notes as reference material.
Regards,
Tomas