Hello,
I am trying to interface the MMA8653FCR1 via I2C. I have to configure the MMA to detect motion interrupts and give out a pulse on INT1. The pseudo code for the same is as follows
1) CTRL_REG1 = 0x00 // Put MMA in standby mode
2) INT_SOURCE = 0x04 // Activate Motion Interrupt
3) XYZ_DATA_CFG = 0x00 // 2g Mode
4) FF_MT_CFG = 0xf8 // Motion on all three axis
5) FF_MT_THS = 0x1f //Motion Threshold
6) CTRL_REG3 = 0x0a // Active High and Motion can Wake-up Controller
7) CTRL_REG4 = 0x04 //Enable Motion Interrupts
8) CTRL_REG5 = 0x02 // Interrupts on INT1
9) CTRL_REG1 = 0x01 // MMA Active.
I have tried the above code, the I2C library for my controller is working perfectly fine. The MMA however is unresponsive.
Could someone provide me with a link or sample code which can help.
Thanks,
Shalin
Hello Anthony,
Thanks a lot for the above help.
I am facing some issues though.
I am unable to read the WHO_AM_I register, it gives a value of 0x00.
When initially configured, the MMA8653 gives an interrupt by default(without motion). Below is the code for the same.
void MMA8653_init(void)
{
uint8 buffer_i2c2[2] = {0};
uint8 value = 0;
CyDelay(3);
int i , j;
buffer_i2c2[0]= M_WHO_AM_I;
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_i2c2, 1, I2C_I2C_MODE_COMPLETE_XFER );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT))
{}
(void) I2C_I2CMasterReadBuf(MMA_ADDR,&value, 1, \
I2C_I2C_MODE_COMPLETE_XFER);
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_RD_CMPLT));
value = value; //Value shown here displays 0x00
buffer_i2c2[0]=M_CTRL_REG1;
buffer_i2c2[1] = 0x00;
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_i2c2, 2, I2C_I2C_MODE_COMPLETE_XFER );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT))
{}
buffer_i2c2[0]=M_CTRL_REG2;
buffer_i2c2[1] = 0x07;
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_i2c2, 2, I2C_I2C_MODE_REPEAT_START );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT))
{}
buffer_i2c2[0]=M_CTRL_REG3;
buffer_i2c2[1] = 0x08;
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_i2c2, 2, I2C_I2C_MODE_REPEAT_START );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT))
{}
buffer_i2c2[0]=M_CTRL_REG4;
buffer_i2c2[1] = 0x04;
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_i2c2, 2, I2C_I2C_MODE_REPEAT_START );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT))
{}
buffer_i2c2[0]=M_CTRL_REG5;
buffer_i2c2[1] = 0x04;
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_i2c2, 2, I2C_I2C_MODE_REPEAT_START );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT))
{}
buffer_i2c2[0]=M_FF_MT_CFG;
buffer_i2c2[1] = 0x71;
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_i2c2, 2, I2C_I2C_MODE_REPEAT_START );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT))
{}
buffer_i2c2[0]=M_FF_MT_THS;
buffer_i2c2[1] = 0x12;
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_i2c2, 2, I2C_I2C_MODE_REPEAT_START );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT))
{}
buffer_i2c2[0]=M_FF_MT_COUNT;
buffer_i2c2[1] = 0x00;
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_i2c2, 2, I2C_I2C_MODE_REPEAT_START );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT))
{}
buffer_i2c2[0] = M_FF_MT_SRC;
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_data, 1, I2C_I2C_MODE_REPEAT_START );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT));
(void) I2C_I2CMasterReadBuf(MMA_ADDR, buffer_data, 1, \
I2C_I2C_MODE_COMPLETE_XFER);
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_RD_CMPLT));
buffer_i2c2[0]=M_CTRL_REG1;
buffer_i2c2[1] = 0x21;
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_i2c2, 2, I2C_I2C_MODE_REPEAT_START );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT))
{}
}
I am also clearing the interrupt in main,
if(MMA_intr == 1)
{
buffer_data[0] = M_FF_MT_SRC;
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_data, 1, I2C_I2C_MODE_COMPLETE_XFER);
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT));
(void) I2C_I2CMasterReadBuf(MMA_ADDR, buffer_data, 1, \
I2C_I2C_MODE_COMPLETE_XFER);
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_RD_CMPLT));
adxl_intr = 0;
LED_YELLOW_Write(0u);
}
Please help.
Shalin
Shalin,
If you can't read WHO_AM_I value stop trying to configure the sensor. You have to read this value to be sure the MMA works well. Maybe you have hardware issues.... And perhaps your I²C communication does not work...
Can you share with us your schematic & check if I²C is working well?
By the way, I suggest you to write an I2C_Read and an I2C_Write function, your code will be more legible ans easier to debug...
void MMA8653_SingleWrite(uint8_t register,uint8_t value )
{
uint8 buffer_i2c2[] = {register,value};
I2C_I2CMasterWriteBuf(MMA_ADDR, buffer_i2c2, 2, I2C_I2C_MODE_COMPLETE_XFER );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT));
}
uint8_t MMA8653_SingleRead(uint8_t register)
{
uint8_t value;
// Write register address
I2C_I2CMasterWriteBuf(MMA_ADDR, ®ister, 1, I2C_I2C_MODE_COMPLETE_XFER );
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT));
// Read returned value
I2C_I2CMasterReadBuf(MMA_ADDR, &value, 1, I2C_I2C_MODE_COMPLETE_XFER);
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_RD_CMPLT));
return value;
}
Thanks,
Anthony
Shalin,
Your problem should be your read function.
As written in the FXOS8700 datasheet I²C communication has to follow these rules:
Unfortunalty,you're using the I2C_MODE_COMPLETE_XFER which adds a stop condition at the end of the write operation...
You probably need to use I2C_MODE_NO_STOP for the first transfert (read operation). Should be a thing like that:
uint8_t MMA8653_SingleRead(uint8_t register)
{
uint8_t value;
// Write register address
I2C_I2CMasterWriteBuf(MMA_ADDR, ®ister, 1, I2C_MODE_NO_STOP);
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT));
// Read returned value
I2C_I2CMasterReadBuf(MMA_ADDR, &value, 1, I2C_I2C_MODE_COMPLETE_XFER);
while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_RD_CMPLT));
return value;
}
But, it's your job, MCU side I think.
Make the Read function working correctly and come back to me if you still have problems with motion detection/configuration.
Anthony
Hello Anthony,
Thanks for the prompt reply.
I had the wiring wrong, I am able to communicate with the MMA8653 now.
Could you please guide me as to how can I set up motion interrupts for the same. I read the datasheet and understood the working of the registers, is there a specific order with which I should address the MMA(Standby mode-->Set Threshold --> Set Interrupt source...etc).
Thanks,
Shalin
Hi Shalin,
I have prepared for you some code samples for MMA565x motion detection configuration.
////////////////////////////////////////////////////////////////////////////////
//! Define
////////////////////////////////////////////////////////////////////////////////
#define MMA8653FC_CTRL_REG1 0x2A
#define MMA8653FC_CTRL_REG2 0x2B
#define MMA8653FC_CTRL_REG3 0x2C
#define MMA8653FC_CTRL_REG4 0x2D
#define MMA8653FC_CTRL_REG5 0x2E
#define MMA8653FC_FF_MT_CFG 0x15
#define MMA8653FC_FF_MT_SRC 0x16
#define MMA8653FC_FF_MT_THS 0x17
#define MMA8653FC_FF_MT_COUNT 0x18
#define MMA8653FC_WHO_AM_I 0x0D
#define MMA8653FC_WHO_AM_I_VAL 0x5A
////////////////////////////////////////////////////////////////////////////////
//! Public methods
////////////////////////////////////////////////////////////////////////////////
bool MMA8653FC::init()
{
bool __b_result = false;
uint8_t __u8_temp;
if(bRead(MMA8653FC_WHO_AM_I,&__u8_temp,1)) //Check presence of the sensor
if(__u8_temp == MMA8653FC_WHO_AM_I_VAL) //Check Sensor ID answer
if(bWrite(MMA8653FC_CTRL_REG1 ,0x00 )) //Standby Mode
if(bWrite(MMA8653FC_CTRL_REG2 ,0x07 )) //Autosleep enabled / Low Power
if(bWrite(MMA8653FC_CTRL_REG3 ,0x08 )) //Wake from Motion interrupt / Active Low / PushPull
if(bWrite(MMA8653FC_CTRL_REG4 ,0x04 )) //Enable Motion interrupt
if(bWrite(MMA8653FC_CTRL_REG5 ,0x04 )) //Interrupt on INT1
if(bWrite(MMA8653FC_FF_MT_CFG ,0x71 )) //Event not latched/Motion/ Enable X/Y/Z detection on INT1
if(bWrite(MMA8653FC_FF_MT_THS ,0x12 )) //Set threshold value to 1.134g
if(bWrite(MMA8653FC_FF_MT_COUNT ,0x00 )) //Set number of debounce
if(bWrite(MMA8653FC_CTRL_REG1 ,0x21 )) //Set ODR to 200Hz & active mode
{
__b_result= true;
}
return __b_result ;
}
bool MMA8653FC::clearINTflag()
{
uint8_t __u8_result;
return bRead(MMA8652FC_FF_MT_SRC,&__u8_result,1);
}
Here the motion threshold is 1.134g on 3axis. You can change this value, but be carefull: gravity of earth is 1g! If you want more sensitivity, you probably need to disable an axis (MR_CFG register) or use the MMA8652 with Transient&HighPassFilter features.
When you catch a motion with your interrupt function, be sure to call "clearINTflag()" function to clear the INT flag.
For example:
void OnMotionDetected()
{
_t_led2 = 0;
printf("Motion detected!\n");
wait(0.1);
_t_accelerometer.clearINTflag();
_t_led2 = 1;
}
int main()
{
_t_pc.baud(115200);
_t_it.fall(&OnMotionDetected);
_t_pc.printf("Hello ");
_t_it.enable_irq();
if(_t_accelerometer.init())
{
while(true)
{
sleep();
}
}
else
{
while(true)
{
wait(0.05);
_t_led = !_t_led;
wait(0.05);
_t_led = !_t_led;
wait(0.05);
_t_led = !_t_led;
wait(1);
_t_led = !_t_led;
}
}
}
I hope it will help you!
Anthony
Shalin,
There is no specific order to configure the device. You have just to begin by putting the MMA in Standymode first, then configure all your registers and finish by switching it in Active Mode. In fact, register changes are saved and effective when the MMA moves from Standby mode to Active mode.
Step | Note | Reg | Value to write |
---|---|---|---|
1 | MMA8653FCR1 in standby mode | CTRL_REG1 (0x2A) | 0bXXXXXXX0 |
2 | Configure the device | .. | .. |
3 | MMA8653FCR1 in active mode | CTRL_REG1 (0x2A) | 0bXXXXXXX1 |
For motion interrupts on MMA8653, I have to check. I'm used to work with the MMA8652: motion detection can be easly enabled by using Transient Detection with High-Pass filter feature. Unfortunalty, MMA8653 doesn't get this fonction, so I will see if it's possible.
I will take a look at Motion Interrupt MMA8653 feature. If you progress on your side, keep me informed.
Thanks,
Anthony
Hi Shalin,
You have to make sure the I²C communication is working well. I suggest you to read the WHO_AM_I register (0x0D) which contains the Device ID (0x5A). If you don't read 0x5A, maybe you have a problem with I²C com (can be missed pull-up resistor, invalid frequency) or with the MMA . If you read the right value, it could be a configuration problem.
Let-me know if you're able to communicate with the MMA reading the Device ID. After ensuring that, next step is to check your motion detection configuration.
Anthony