I am using MMA955l pedometer sensor in STM32l4RTC MCU, which is connected to i2c and I need to read accelerometer data from chip. I did not find any sample source and going through datasheet and looking at examples I am following command sequence as :
aTxBuffer[0] = 0x00;
aTxBuffer[1] = 0x00;
aTxBuffer[2] = 0x00;
aTxBuffer[3] = 0x0C;
MMA955L_AcclDataTx(aTxBuffer, 4); //Read ID command
//Read Pedometer ID
MMA955L_AcclDataRx(aRxBuffer, 16);
Note: I get response as :
0x00 0x80 0x0c 0x0c 0x7a 0xed 0x25 0x5d 0x01 0x01 0x02 0x02 0x01 0x06 0x03 0x41 when I read 16 bytes of data.
//command to request_to_start register configuration
aTxBuffer[0] = 0x01;
aTxBuffer[1] = 0x10;
aTxBuffer[2] = 0x00;
aTxBuffer[3] = 0x04;
MMA955L_AcclDataTx(aTxBuffer, 4);
aTxBuffer[0] = 0x01;
aTxBuffer[1] = 0x20;
aTxBuffer[2] = 0x00;
aTxBuffer[3] = 0x04;
aTxBuffer[4] = 0xAA;
aTxBuffer[5] = 0xBB;
aTxBuffer[6] = 0xCC;
aTxBuffer[7] = 0xDD;
HAL_Delay(100);
MMA955L_AcclDataTx(aTxBuffer, 8);
//Interrupt_App_IDs register configuration
aTxBuffer[0] = 0x01;
aTxBuffer[1] = 0x20;
aTxBuffer[2] = 0x0C ;
aTxBuffer[3] = 0x04;
aTxBuffer[4] = 0x06;
aTxBuffer[5] = 0x00;
aTxBuffer[6] = 0x00;
aTxBuffer[7] = 0x00;
MMA955L_AcclDataTx(aTxBuffer, 8);
//Awake accelerometer
aTxBuffer[0] = 0x12;
aTxBuffer[1] = 0x20;
aTxBuffer[2] = 0x06;
aTxBuffer[3] = 0x01;
aTxBuffer[4] = 0x00;
MMA955L_AcclDataTx(aTxBuffer, 5);
//Put accel in legacy mode
aTxBuffer[0] = 0x18;
aTxBuffer[1] = 0x20;
aTxBuffer[2] = 0x00;
aTxBuffer[3] = 0x01;
aTxBuffer[4] = 0x10;
MMA955L_AcclDataTx(aTxBuffer, 5);
//Configure accelerometer xyz data
aTxBuffer[0] = 0x4;
aTxBuffer[1] = 0x20;
aTxBuffer[2] = 0x00;
aTxBuffer[3] = 0xC;
aTxBuffer[4] = 0x06;
aTxBuffer[5] = 0x00;
aTxBuffer[6] = 0x06;
aTxBuffer[7] = 0x01;
aTxBuffer[8] = 0x06;
aTxBuffer[9] = 0x02;
aTxBuffer[10] = 0x06;
aTxBuffer[11] = 0x03;
aTxBuffer[12] = 0x06;
aTxBuffer[13] = 0x04;
aTxBuffer[14] = 0x06;
aTxBuffer[15] = 0x05;
MMA955L_AcclDataTx(aTxBuffer, 16);
//Reading aggregated data
aTxBuffer[0] = 0x12;
aTxBuffer[1] = 0x20;
aTxBuffer[2] = 0x06;
aTxBuffer[3] = 0x01;
aTxBuffer[4] = 0x00;
MMA955L_AcclDataTx(aTxBuffer, 5);
//POst this read 6 bytes data
MMA955L_AcclDataRx(aRxBuffer, 6);
Note: Getting reply as 0x00 0x80 0x0c 0x0c 0x7a 0xed
Is that I am following proper steps or is that I need to change any ?
info : Here MMA955L_AcclDataTx is a function to transmit data to i2c slave and MMA955L_AcclDataRx is a function to receive i2c data from slave.
Regards,
Prasanna Prabhu
Hi,
I am working on pedometer( MMA9555L) which is interfaced with iMX6 processor.
I have the following questions:
1. Is the version information below correct?
2. How to configure MMA9555L for multiple applications ? For example I need both the directional data and pedometer data, is it possible to get both simultaneously?
Please share a sample code if you have.
Here is my application code.
txBuff[0] = 0x00;
txBuff[1] = 0x00;
txBuff[2] = 0x00;
txBuff[3] = 0x0C;
pedo_fd = open("/dev/i2c-2", O_RDWR)
pedo_ioc = ioctl(pedo_fd, I2C_SLAVE, 0x4C)
i2c_smbus_write_i2c_block_data(pedo_fd, 0X00, 0X04, txBuff);
i2c_smbus_read_i2c_block_data(pedo_fd, 0x00, rxBuff)
the output of read is as below:
0x0 0x80 0xc 0xc 0x5e 0xa3 0xa5 0x77 0x1 0x10x2 0x2 0x1 0x6 0x3 0x41
Thanks,
Chiru
Hi Satish,
Yes, the MMA9555 is operating at a supply voltage of 1.8V +/-5%. This is also the nominal voltage for all digital I/O pins so please align your board supply tree accordingly.
Keep in mind that the level of pin8 (RGPIO3) during reset determines which slave interface mode will be used by the device (set pin to high level for I2C mode).
At last, can you be more specific regarding "MMA not detecting" ? What command message do you send, what answer do you get if any... Any digital Scope plot of the I2C lines would help.
Regards, Jacques.
Hi Satish,
My apologies for the delayed response.
You may have in mind a more sophisticated communication Interface that what's proposed by MMA9555.
The Mailboxes can be considered simply as fixed address registers, just like any sensor device. Main difference is that their content depends on the Application ID that is invoked (unless "legacy mode" is used).
Finally as I have hard time to understand what kind of information your are missing, I put a brief guide for the Mailbox operation in the document attached.
I hope it will help, let me know otherwise.
Regards, Jacques.
Hi Satish,
I'm afraid, we can only provide FW support for our NXP MCU.
Nevertheless here are a few comments:
1/ 0x4C is the MMA9555 "7-bits" I2C slave address, this means that the R/W flag (LSB bit) is not included !
To get the "8-bits" address (which may be what the I2C driver is expected ?) you need to do a "1 bit left shift" and add R/W flag. So full 8-bits I2C Write address is twice this value = 0x98 (whereas Read address is 0x99)
2/ Pedometer Application Identifier (i.e. 0x15) is not a "sub-address", this is the value/data you need to write in MMA9555 mailbox address 0. Actually the "sub-address" is 0x00 for most of the Write & Read transactions. Again see MMA9555 documentation provided.
3/ if you still struggle, send me plots of the I2C signals during the Write/Read transactions
Regards, Jacques.
Thank you Jaques for your quick response.
On Tue, Apr 12, 2016 at 12:06 AM, JackITB <admin@community.freescale.com>
Hello Jaques,
I am working on pedometer (mma9555l).. Pedometer is not detecting in my board. I have tested the same board with arduno uno i2c scanner & with i2c poll function.. then also it not detecting mma.. same i2c code is working fr other slaves(max,Tmp).. I have gone through the data sheet of mma.. They have mentioned SCA SDA should be =1.8 v..
But in my board it showing 2.27V..
Is this reason for not detecting mma..?
Again i have tried with 1.8 v..den also mma is not detecting. How I should confirm that Mma9555l is working or not in my board . Please some one help how to solve this problem.
Regards
Satish
Hello JackITB,
Thank you Jaques for your reply. I am working on PIC24fj64ga004 MCU, Here i
am communicating with 3 slaves (MAX30100,MMA9555L & OLED) by i2c
communication. while communicating with slaves am passing device
address(slave address) to following functions (ie : int I2C1_M_Poll(0X4C)
then it is not reading data it is directly coming out of loop. If i pass
slave address of (MAX30100(ie =0XAE)) code is working, but i pass device
address for MMA9555L (ie= 0X4C)then it is not detecting anything. my
question is why this device address (ox4c) is not detecting what is my
mistake i code. please tell the proper way to write it.
As you mentioned in data sheet like (MMA9555l device address is 0x4c
and Pedometer Application Identifier is 0x15 this am considering
as sub-address ) and these parameters am passing in my I2c communication
what parameters i need to pass in these function so it work properly as am
passing
I2C1_M_Poll(unsigned int DevAddr); EX: (I2C1_M_Poll(0X4C);)
I2C1_M_Read(unsigned int DevAddr,unsigned int SubAddr, int ByteCnt, char
*buffer); EX: ( I2C1_M_Read(0X4D,0X15,1,bufffer))
I2C1_M_ReadByte(unsigned int);
I2C1_M_Write(0X4C,0X15,1,bufffer);
I2C1_M_WriteByte('a');
This is first time i am implimenting this i2c communication .Here
somewhere am doing wrong please explain steps what should i do after this
i2c communication.Hope this time you replay quickly.
#include <p24FJ64GA004.h>
#include "i2c.h"
#include "delay.h"
//Variables//
unsigned int I2Cflags;
//Function prototype;
void I2C_HWini(void);
void I2C_ModuleStart(void);
void I2C_SWini(void);
int I2C1_M_BusReset(void);
void I2C1_M_ClearErrors(void);
int I2C1_M_Poll(unsigned int);
int I2C1_M_Read(unsigned int, unsigned int, int, char *);
int I2C1_M_ReadByte(unsigned int);
int I2C1_M_RecoverBus(void);
int I2C1_M_Restart(void);
int I2C1_M_Start(void);
int I2C1_M_Stop(void);
int I2C1_M_Write(unsigned int,unsigned int, int, char *);
int I2C1_M_WriteByte(char);
//int MMMA9555L_data_Tx(char*,int);
void I2C_HWini() //Set pin drive modes //I2C - drive outputs so we can
manually clear lines
{
LATBbits.LATB8 = 1;
LATBbits.LATB9 = 1; //Start with bus in idle mode - both lines hig
ODCBbits.ODB2 = 1; //Open drain mode
ODCBbits.ODB3 = 1;
// TRISBbits.TRISB8 = 0; //SCL1 output
// TRISBbits.TRISB9 = 0; //SDA1
output
}
void I2C_ModuleStart()
{
OSCCON = 0X2200;
// OSCTUN = 0X0000;
CLKDIV = 0X0000;
I2C1CON = 0x1000; //Set all bits to known state
I2C1CONbits.I2CEN = 0; //Disable until everything set up. Pins will be std
IO.
I2C1BRG = 39; //I2C1BRG = (Fcy/Fscl-FCY/10E6)
I2C1CONbits.DISSLW = 0; //Enable slew rate control for 400kHz operation
IFS1bits.MI2C1IF = 0; //Clear I2C master int flag
I2C1CONbits.I2CEN = 1; //Enable I2C //For interrupt driven code
IEC1bits.MI2C1IE = 1; //Enable I2C master interrupt
}
void I2C_SWini()
{
unsigned int I2Cflags = 0;
SetI2C1BusDirty; //I2C bus in unknown state, go ahead and clear it
}
int I2C1_M_BusReset()
{
int i;
//Start with lines high - sets SCL high if not already there
LATBbits.LATB8 = 1; //PORTBbits.RG2 = 1 is equivalent
LATBbits.LATB9 = 1;
delay(1); //Need 5uS delay
if(PORTBbits.RB2 == 0) //Read if line actually went high
{
return I2C_Err_SCL_low; //SCL stuck low - is the pullup resistor loaded?
}
i=10; //SCL ok, toggle until SDA goes high.
while(i>0)
{
if(PORTBbits.RB3 == 1) //If SDA is high, then we are done
{
break;
}
LATBbits.LATB8 = 0; //SCL low
delay(1); //Need 5uS delay
LATBbits.LATB8 = 1; //SCL high
delay(1); //Need 5uS delay
i--;
}
if((PORTB & 0x000C) != 0x000C) //We are ok if SCL and SDA high
{
return I2C_Err_SDA_low;
}
LATBbits.LATB9 = 0; //SDA LOW while SCL HIGH -> START
delay(1); //Need 5uS delay
LATBbits.LATB9 = 1; //SDA HIGH while SCL HIGH -> STOP
delay(1); //Need 5uS delay
return I2C_OK;
}
void I2C1_M_ClearErrors()
{
I2C1CONbits.RCEN = 0; //Cancel receive request
I2C1STATbits.IWCOL = 0; //Clear write-collision flag
I2C1STATbits.BCL = 0; //Clear bus-collision flag
}
int I2C1_M_Poll(unsigned int DevAddr)
{
int retval;
int SlaveAddr;
SlaveAddr = (DevAddr << 1) | 0;
if(IsI2C1BusDirty)
{
I2C1_M_ClearErrors();
if(I2C1_M_RecoverBus()==I2C_OK)
{//Recovered
ClrI2C1BusDirty;
}
else
{
return I2C_Err_Hardware;
}
}
if(I2C1_M_Start() == I2C_OK)
{
retval = I2C1_M_WriteByte((char)SlaveAddr);
if(I2C1_M_Stop() == I2C_OK) //Even if we have an error sending, try to
close I2C
{
if(retval == I2C_ACK)
{
return I2C_OK;
}
else if(retval == I2C_Err_NAK)
{
return I2C_Err_BadAddr; //Check that correct device address is being used
}
else
{
return I2C_Err_CommFail;
}
}
}
//Get here then we had an error
SetI2C1BusDirty; //Set error flag
return I2C_Err_CommFail;
}
int I2C1_M_Read(unsigned int DevAddr,unsigned int SubAddr, int ByteCnt,
char *buffer)
{
int SlaveAddr;
int retval;
int i;
if(IsI2C1BusDirty) //Ignore requests until Poll cmd is called to fix err.
return I2C_Err_BusDirty;
if(I2C1_M_Start() != I2C_OK) //Start
{//Failed to open bus
SetI2C1BusDirty;
return I2C_Err_CommFail;
}
SlaveAddr = (DevAddr << 1) | 0; //Device Address + Write bit
retval = I2C1_M_WriteByte((char)SlaveAddr);
if(retval == I2C_Err_NAK)
{
//Bad Slave Address or I2C slave device stopped responding
I2C1_M_Stop();
SetI2C1BusDirty; //Will reset slave device
return I2C_Err_BadAddr;
}
else if(retval<0)
{
I2C1_M_Stop();
SetI2C1BusDirty;
return I2C_Err_CommFail;
}
if( I2C1_M_WriteByte((char)SubAddr) != I2C_OK) //Sub Addr
{
I2C1_M_Stop();
SetI2C1BusDirty;
return I2C_Err_CommFail;
}
if( I2C1_M_Restart() != I2C_OK) //Repeated start - switch to read mode
{
I2C1_M_Stop();
SetI2C1BusDirty;
return I2C_Err_CommFail;
}
SlaveAddr = (DevAddr << 1) | 0x01; //Device Address + Read bit
if( I2C1_M_WriteByte((char)SlaveAddr) != I2C_OK) //Slave Addr
{
I2C1_M_Stop();
SetI2C1BusDirty;
return I2C_Err_CommFail;
}
for(i=0;i<ByteCnt;i++) //Data
{
if(i==(ByteCnt-1) )
{
retval = I2C1_M_ReadByte(I2C_M_NACK); //NACK on last byte so slave knows
this is it
}
else
{
retval = I2C1_M_ReadByte(I2C_M_ACK);
}
if(retval >= 0)
{
buffer[i] = retval;
}
else
{
//Error while reading byte. Close connection and set error
flag.
I2C1_M_Stop();
SetI2C1BusDirty;
return I2C_Err_CommFail;
}
}
if(I2C1_M_Stop() != I2C_OK)
{//Failed to close bus
SetI2C1BusDirty;
return I2C_Err_CommFail;
}
return I2C_OK; //Success
}
int I2C1_M_ReadByte(unsigned int ACKflag)
{
int t;
if(ACKflag == I2C_M_NACK) //Set state in preparation for TX below
{
I2C1CONbits.ACKDT = 1;//NACK
}
else
{
I2C1CONbits.ACKDT = 0;//ACK
}
I2C1CONbits.RCEN = 1; //Start receive
t=0;//Timeout is processor speed dependent. @(4*8Mhz=16MIPS) and 8 bits, I
expect <=320.
//We could wait for RCEN to be cleared, but are really interested in
incoming byte, so look for I2C1STAT.RBF
while(!I2C1STATbits.RBF) //HW cleared when receive complete
{
t++;
if(t>8000)
{ //SCL stuck low
//RCEN cannot be cleared in SW. Will need to reset I2C interface, or wait
until SCL goes high.
return I2C_Err_RcvTimeout;
}
} //Tested: t=30
//I2C1STATbits.RBF will likely be set
//As the master we must ACK or NACK every byte, so slave knows if it
will send another byte.
//We have set the bit above, just need to send it
I2C1CONbits.ACKEN = 1; //Send ACK bit now
t=0; //Timeout is processor speed dependent.
@(4*8Mhz=16MIPS), I expect <=40.
while(I2C1CONbits.ACKEN) //HW cleared when complete
{
t++;
if(t>1000)
{//This will timeout if SCL stuck low
//ACKEN cannot be cleared in SW. I2C interface must be reset after this
error.
return I2C_Err_SCL_low;
}
}//Tested: t=4
if(I2C1STATbits.I2COV) //If an overflow occurred, it means we received a
new byte before reading last one
{
I2C1STATbits.I2COV = 0;
return I2C_Err_Overflow;
}
return I2C1RCV; //Reading this register clears RBF
}
int I2C1_M_RecoverBus()
{
int status;
I2C1CONbits.I2CEN = 0;
status = I2C1_M_BusReset();
if(status>0)
{//Fatal I2C error, nothing we can do about it
return I2C_Err_Hardware;
}
//That worked, bring I2C back online
I2C1CONbits.I2CEN = 1;
return I2C_OK;
}
int I2C1_M_Restart()
{
int t;
I2C1CONbits.RSEN = 1; //Initiate restart condition
t=0;
while(I2C1CONbits.RSEN) //HW cleared when complete
{
t++;
if(t>1000)
{
return I2C_Err_SCL_low;
}
}//Tested: t=5
if(I2C1STATbits.BCL)
{//SDA stuck low
I2C1STATbits.BCL = 0; //Clear error to regain control of I2C
return I2C_Err_BCL;
}
return I2C_OK;
}
int I2C1_M_Start()
{
int t;
I2C1CONbits.SEN = 1; //Initiate Start condition
Nop();
if(I2C1STATbits.BCL)
{//SCL or SDA stuck low
I2C1CONbits.SEN = 0; //Cancel request (will still be set if we had previous
BCL)
I2C1STATbits.BCL = 0; //Clear error to regain control of I2C
return I2C_Err_BCL;
}
if(I2C1STATbits.IWCOL)
{//Not sure how this happens but it occurred once, so trap here
I2C1CONbits.SEN = 0; //Clear just in case set
I2C1STATbits.IWCOL = 0; //Clear error
return I2C_Err_IWCOL;
}
t=0;
while(I2C1CONbits.SEN) //HW cleared when complete
{
t++;
if(t>1000)
{//Since SCL and SDA errors are trapped by BCL error above, this should
never happen
return I2C_Err_TimeoutHW;
}
}
if(I2C1STATbits.BCL)
{
I2C1STATbits.BCL = 0; //Clear error to regain control of I2C
return I2C_Err_BCL;
}
return I2C_OK;
}
int I2C1_M_Stop()
{
int t;
I2C1CONbits.PEN = 1; //Initiate stop condition
Nop();
if(I2C1STATbits.BCL)
{//Not sure if this can ever happen here
I2C1STATbits.BCL = 0; //Clear error
return I2C_Err_BCL; //Will need to reset I2C interface.
}
t=0;//Timeout is processor speed dependent. @(4*8Mhz=16MIPS), I expect
<=40.
while(I2C1CONbits.PEN) //HW cleared when complete
{
t++;
if(t>1000)
{//Will timeout if SCL stuck low
//PEN cannot be cleared in SW. Will need to reset I2C interface.
return I2C_Err_SCL_low;
}
}//Tested: t=5
return I2C_OK;
}
int I2C1_M_Write(unsigned int DevAddr,unsigned int SubAddr, int
ByteCnt, char *buffer)
{
int i;
int retval;
unsigned int SlaveAddr;
if(IsI2C1BusDirty) //Ignore requests until Poll cmd is called to fix err.
return I2C_Err_BusDirty;
if(I2C1_M_Start() != 0) //Start
{//Failed to open bus
SetI2C1BusDirty;
return I2C_Err_CommFail;
}
SlaveAddr = (DevAddr << 1) | 0; //Device Address + Write bit
retval = I2C1_M_WriteByte((char)SlaveAddr);
if(retval == I2C_Err_NAK)
{//Bad Slave Address or I2C slave device stopped responding
I2C1_M_Stop();
SetI2C1BusDirty; //Will reset slave device
return I2C_Err_BadAddr;
}
else if(retval<0)
{
I2C1_M_Stop();
SetI2C1BusDirty;
return I2C_Err_CommFail;
}
if( I2C1_M_WriteByte((char)SubAddr) != I2C_ACK) //Sub Addr
{
I2C1_M_Stop();
SetI2C1BusDirty;
return I2C_Err_CommFail;
}
for(i=0;i<ByteCnt;i++) //Data
{
if( I2C1_M_WriteByte(buffer[i]) != I2C_ACK)
{//Error while writing byte. Close connection and set error flag.
I2C1_M_Stop();
SetI2C1BusDirty;
return I2C_Err_CommFail;
}
}
if(I2C1_M_Stop() != I2C_OK)
{//Failed to close bus
SetI2C1BusDirty;
return I2C_Err_CommFail;
}
return I2C_OK;
}
int I2C1_M_WriteByte(char cData)
{
int t;
if(I2C1STATbits.TBF) //Is there already a byte waiting to send? //TBF
Transmission Buffer full
{
return I2C_Err_TBF;
}
I2C1TRN = cData; //Send byte
t=0;
while(I2C1STATbits.TRSTAT) //HW cleared when TX complete
{
t++;
if(t>8000)
{//This is bad because TRSTAT will still be set
return I2C_Err_SCL_low; //Must reset I2C interface, and possibly slave
devices
}
}//Testing: t=31
if(I2C1STATbits.BCL)
{
I2C1STATbits.BCL = 0; //Clear error to regain control of I2C
return I2C_Err_BCL;
}
//Done, now how did slave respond?
if(I2C1STATbits.ACKSTAT) //1=NACK
return I2C_Err_NAK; // NACK
else
return I2C_ACK; // ACK
}
Thanks & Regards
satish
On Fri, Apr 8, 2016 at 8:01 PM, JackITB <admin@community.freescale.com>
Hi Satish,
We usually don't provide sample code for MCUs not pertaining to NXP portfolio.
You should get some generic I2C driver code for the PIC MCU, then we can help you configure and operate MMA9555L (slave I2C address = 0x4C) according to your need.
All what it takes is to send some commands (writing consecutive bytes) and getting answers (reading consecutive bytes).
If you share your targeted settings, we'll provide the query/response command list.
Regards, Jacques.
Hi Jacques Trichet
Thank you for your reply. I have code for PIC MCU i2c driver, I have gone trough the data sheet of MMA955l pedometer In that they have given some configuration of mailbox implementation. My question is how to configure the mail box?. HOw it work it works? is it work like what we use in Linux (IPC mechanism) for synchronization or what?. if you have any source code for that mailbox configuration then please post here.
Thanks & Regards
satish Chauhan
Hi All,
I am working on PIC24FJ64GA004 MCU and on MMA9555L connected to IIC. Is there any sample source code available for the same ?
Hi Prasanna,
Actually I would recommend that you add a ~50ms delay after each command sent to MMA9555L. This will make sure that the sensor has enough time to execute the command prior receiving the next one.
Alternatively, you can set INT_O output line to toggle when command has been completed: W00 18 20 00 01 90
Regards, Jacques.
PS: you'll find attached the communication log I have with my set-up
This is weird.
Could you add a tempo (i.e. "wait 50ms") inside the while(1) loop, so that the reading is not overwhelming the slave interface.
If you still are not successful, best is to send us the slave port traffic log (time stamp, byte stream) for us to analyze.
Thank you Jaques for your reply. Is did send above commands but I did not receive accelerometer data changing on changing axes and instead all time same data is read as 0x04 0x80 0x0c 0x0c 0x06 0x00 0x06 0x02 0x06 0x04. Any suggestions ?
regards,
Prasanna
Hi Prasanna,
Let me try to analyze your configuration. I will use following convention (all in hexadecimal):
Wnn xx yy etc... to indicate a continuous write transaction starting at address nn, of bytes xx yy etc...
and Rnn xx yy etc... to indicate a continuous read transaction starting at address nn, yielding bytes xx yy etc...
Below are your sequence of commands and my associated comments.
1/ W00 00 00 00 0C => ok
2/ R00 00 80 0C 0C 7A etc... => ok
3/ W00 01 10 00 04 => query configuration bytes 00 to 04 (Request_to_start registers) of the Scheduler Application (cf "command/response" communication scheme)
If you read those registers: R00 01 80 04 04 00 00 00 00 they should be all at 00
4/ W00 01 20 00 04 AA BB CC DD => update configuration bytes 00 to 04 (Request_to_start registers) of the Scheduler Application
This command (from MMA9555L datasheet) is simply a dummy example so meaningless in your case.
5/ W00 01 20 0C 04 06 00 00 00 => write configuration bytes 0C to 0F (IRQ_Interrupt_AppIDs) of the Scheduler Application
This assigns IRQ interrupt to AppID 0x19 and 0x1A ( 06 00 00 00 <=> bits n° 25 & 26)
I don't think you need to change anything in the scheduler application settings so previous 3 commands are not necessary. And actually commands 4 & 5 are not relevant
6/ W00 12 20 06 01 00 => ok
7/ W00 18 20 00 01 10 => ok
8/ W00 04 20 00 0C 06 00 etc.. => ok
9/ W00 12 20 06 01 00 => redundant as already done by command 6/
10/ R00 00 08 0C 0C 7A ED => looks like the same as version application answer so something wrong in your sequence
Moreover, as you have configured the mailbox to "quickread" the AFE XYZ output data, you should directly read mailboxes 04 to 09
Doing so: R04 00 05 FF 9D 10 58 => I got X=0005, Y=FF9D, Z=1058 (demoboard in horizontal position)
So at least it's working fine at my side.
As a general recommendation (at least for troubleshooting), it may be worthwhile to check that command has completed successfully by reading first 4 mailboxes: 1st byte = AppID code, 2nd = COCO flag + error code if any (should be 80), 3rd = actual number of bytes read/written, 4th = requested number of bytes read/written
I suggest you implement the changes I mentioned, then let me know if you still face issues.
In that case, what can help is to log the I2C traffic between your Host MCU and MMA9555L.
Regards, Jacques.
Thank you Jacques for your kind response. As per your suggestions I did modify my application. These are the commands I am sending.
aTxBuffer[0] = 0x00;
aTxBuffer[1] = 0x00;
aTxBuffer[2] = 0x00;
aTxBuffer[3] = 0x0C;
MMA955L_AcclDataTx(aTxBuffer, 4); //Read ID command
//On Reading response
MMA955L_AcclDataRx(aRxBuffer, 16);
//Response buffer data:
0x00 0x80 0x0c 0x0c 0x7a 0xed 0x25 0x5d 0x01 0x01 0x02 0x02 0x01 0x06 0x03 0x41
//command to request_to_start register configuration
aTxBuffer[0] = 0x00;
aTxBuffer[1] = 0x01;
aTxBuffer[2] = 0x10;
aTxBuffer[3] = 0x00;
aTxBuffer[4] = 0x04;
MMA955L_AcclDataTx(aTxBuffer, 5);
//Read Response :
MMA955L_AcclDataRx(aRxBuffer, 8);
//Response data is on reading is 01 80 04 04 00 00 00 00
//Put module to awake if it was in sleep
aTxBuffer[0] = 0x00;
aTxBuffer[1] = 0x12;
aTxBuffer[2] = 0x20;
aTxBuffer[3] = 0x06;
aTxBuffer[4] = 0x01;
aTxBuffer[5] = 0x00;
MMA955L_AcclDataTx(aTxBuffer, 6);
//Put device in legacy mode
aTxBuffer[0] = 0x00;
aTxBuffer[1] = 0x18;
aTxBuffer[2] = 0x20;
aTxBuffer[3] = 0x00;
aTxBuffer[4] = 0x01;
aTxBuffer[5] = 0x10;
MMA955L_AcclDataTx(aRxBuffer, 6);
//Configure accelerometer
aTxBuffer[0] = 0x00;
aTxBuffer[1] = 0x04;
aTxBuffer[2] = 0x20;
aTxBuffer[3] = 0x00;
aTxBuffer[4] = 0x0c;
aTxBuffer[5] = 0x06;
aTxBuffer[6] = 0x00;
aTxBuffer[7] = 0x06;
aTxBuffer[8] = 0x01;
aTxBuffer[9] = 0x06;
aTxBuffer[10] = 0x02;
aTxBuffer[11] = 0x06;
aTxBuffer[12] = 0x03;
aTxBuffer[13] = 0x06;
aTxBuffer[14] = 0x04;
aTxBuffer[15] = 0x06;
aTxBuffer[16] = 0x05;
MMA955L_AcclDataTx(aTxBuffer, 17);
//read data continuosly
while(1)
{
MMA955L_AcclDataRx(aRxBuffer, 10);
}
//Response is 0x04 0x80 0x0c 0x0c 0x06 0x00 0x06 0x01 0x06 0x02 this looks like configure mailbox command is copied back toRX registers
//This data is always constant even if position of board is changed.
1> Should we configure any scheduler/ Analog Front End to get Accelerometer data (X,Y,Z) ??
2>Can you Provide us the sample code on which you got accelerometer axes data continuously getting updated on changing board position?
( I did probe the data lines and the data I am receiving is properly copied to buffer with proper clock cycles matching with the ones given in datasheet.)
Regards,
Prasanna
Hi Prasanna,
I'm afraid you got confused by my previous answer so let me clarify it, especially the convention I've used:
Wnn xx yy etc... to indicate a continuous write transaction starting at address nn, of bytes xx yy etc... (all in hexadecimal)
and Rnn xx yy etc... to indicate a continuous read transaction starting at address nn, yielding bytes xx yy etc...
So the command W00 12 20 06 01 00 reflects a write transaction starting at address 00 (which is Mailbox 0) of following 5 bytes
MB0 = 12
MB1 = 20
MB2 = 06
MB3 = 01
MB4 = 00
This means you should not embed "W00" in your TxBuffer (aTxBuffer[0] = 0x00) as it is simply the destination (mailbox/register address) of the first byte.
Similarly R04 00 05 FF 9D 10 58 reflects a Read transaction starting at address 04 (Mailbox 4) of 6 consecutive bytes
MB4 = 00
MB5 = 05
MB6 = FF
MB7 = 9D
MB8 = 10
MB9 = 58
=====================================
Having said that, I suggest the following commands:
aTxBuffer[0] = 0x00;
aTxBuffer[1] = 0x00;
aTxBuffer[2] = 0x00;
aTxBuffer[3] = 0x0C;
MMA955L_AcclDataTx(aTxBuffer, 4); //Read ID command
//On Reading response
MMA955L_AcclDataRx(aRxBuffer, 16);
//Response buffer data:
0x00 0x80 0x0c 0x0c 0x7a 0xed 0x25 0x5d 0x01 0x01 0x02 0x02 0x01 0x06 0x03 0x41
(this is mainly a sanity check that communication is fine)
//Put module to awake if it was in sleep
aTxBuffer[0] = 0x12;
aTxBuffer[1] = 0x20;
aTxBuffer[2] = 0x06;
aTxBuffer[3] = 0x01;
aTxBuffer[4] = 0x00;
MMA955L_AcclDataTx(aTxBuffer, 5);
//Put device in legacy mode
aTxBuffer[0] = 0x18;
aTxBuffer[1] = 0x20;
aTxBuffer[2] = 0x00;
aTxBuffer[3] = 0x01;
aTxBuffer[4] = 0x10;
MMA955L_AcclDataTx(aRxBuffer, 5);
//Configure accelerometer
aTxBuffer[0] = 0x04;
aTxBuffer[1] = 0x20;
aTxBuffer[2] = 0x00;
aTxBuffer[3] = 0x0c;
aTxBuffer[4] = 0x06;
aTxBuffer[5] = 0x00;
aTxBuffer[6] = 0x06;
aTxBuffer[7] = 0x01;
aTxBuffer[8] = 0x06;
aTxBuffer[9] = 0x02;
aTxBuffer[10] = 0x06;
aTxBuffer[11] = 0x03;
aTxBuffer[12] = 0x06;
aTxBuffer[13] = 0x04;
aTxBuffer[14] = 0x06;
aTxBuffer[15] = 0x05;
MMA955L_AcclDataTx(aTxBuffer, 16);
//read data continuously
while(1)
{
MMA955L_AcclDataRx(aRxBuffer, 10);
}
//Response data shall looks like 04 80 0C 0C Xhigh Xlow Yhigh Ylow Zhigh Zlow
MB0 = 04
MB1 = 80
MB2 = 0C
MB3 = 0C
First for mailboxes contain the answer to previous command so are useless
MB4 = Xdata high byte
MB5 = Xdata low byte
MB6 = Ydata high byte
MB7 = Ydata low byte
MB8 = Zdata high byte
MB9 = Zdata low byte
Note 1: the data will be updated at a 30.5Hz measurement recurrence
Note 2: you may configure INT_O pin to flag when new data is available (in order to trigger an interrupt at the host MCU)
Let me know if you are successful.
Regards, Jacques.