Problem communicating with MMA8452Q

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

Problem communicating with MMA8452Q

Jump to solution
3,134 Views
juanm
Contributor III

Hi! I'm having problems with this accelerometer. I'm using an FRDM KL25Z and I tested the onboard MMA8451Q with this code:

 

MMA8451Q - Bare metal example project

 

This code works great. The problem started when I wanted to try this code with the MMA8452Q. I modified the code so I can use it with the I2C1 module and I used PTC1 as SCL and PTC2 as SDA. Also, I used PTA5 for the interrupt. So, the configuration is like this:

 

/******************************************************************************

* MCU initialization function

******************************************************************************/

 

 

void MCU_Init(void)

{

  //I2C0 module initialization

  SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK; // Turn on clock to I2C0 module

  SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; // Turn on clock to Port C module

  PORTC_PCR1 = PORT_PCR_MUX(2); // PTC1 pin is I2C1 SCL line

  PORTC_PCR2 = PORT_PCR_MUX(2); // PTC2 pin is I2C1 SDA line

  I2C1_F  = 0x14; // SDA hold time = 2.125us, SCL start hold time = 4.25us, SCL stop hold time = 5.125us *

  I2C1_C1 = I2C_C1_IICEN_MASK;     // Enable I2C0 module

 

  //Configure the PTA5 pin (connected to the INT1 of the MMA8451Q) for falling edge interrupts

  SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; // Turn on clock to Port A module

  PORTA_PCR5 |= (0|PORT_PCR_ISF_MASK| // Clear the interrupt flag

   PORT_PCR_MUX(0x1)| // PTA5 is configured as GPIO

   PORT_PCR_IRQC(0xA)); // PTA5 is configured for falling edge interrupts

 

  //Enable PORTA interrupt on NVIC

  NVIC_ICPR |= 1 << ((INT_PORTA - 16)%32);

  NVIC_ISER |= 1 << ((INT_PORTA - 16)%32);

}

 

But this doesn't work. The program get stuck in the function I2C_Wait();

If I try to read the WHO AM I register, it always return 0xFF. I tried with two different accelerometers, and both fails.

 

I attach the complete code, maybe someone can test it.

 

PD: This is the breakout board that I'm using.

 

MMA8452 3-Axial Triaxial Digital Accelerometer Module for Arduino - Free Shipping - DealExtreme

Original Attachment has been moved to: MMA8452q_KL25.zip

Labels (1)
0 Kudos
1 Solution
1,806 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Juan,

How exactly are you interfacing a 3.3V MKL25Z128VLK4 MCU on the FRDM-KL25Z board with the breakout board? Looking at the schematic, they do not seem to be compatible. There is an on-board 3.3V regulator and MOSFET-based level shifters to interface the breakout board easily with 5V (Arduino) boards only.

Regards,

Tomas

View solution in original post

0 Kudos
6 Replies
1,806 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Juan,

Your source code seems to be properly modified to make use of the I2C1 module (PTC1 and PTC2 pins) and the PTA5 pin. You have also correctly adapted both the I2C.c and I2C.h files.

Is there a schematic of the breakout board you are using available? I was not able to find it. Please double check how is the SA0 pin connected and if necessary change the 7-bit I2C slave address accordingly. Also make sure the INT1 pin is connected properly.

I would also recommend to use a logic analyzer to know what is going on on the I2C bus.

Regards,

Tomas

1,806 Views
juanm
Contributor III

I have attached the schematic.

I tried with the SA0 pin to GND and also to 3.3V (and changed the code accordingly), but it's the same, also I checked the INT1 pin connection.

I don't have a logic analyzer, but I have access to an oscilloscope. I'm going to try this, and I will let you know.

Thank you very much for the answer.

0 Kudos
1,807 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Juan,

How exactly are you interfacing a 3.3V MKL25Z128VLK4 MCU on the FRDM-KL25Z board with the breakout board? Looking at the schematic, they do not seem to be compatible. There is an on-board 3.3V regulator and MOSFET-based level shifters to interface the breakout board easily with 5V (Arduino) boards only.

Regards,

Tomas

0 Kudos
1,806 Views
juanm
Contributor III

Well... I must be blind, I didn't see the level shifters! I adapted the code now to a JM128 Coldfire V1 running at 5V, and now it works great!

One more question, I was reading AN4069 and I noticed that I have to change the calibration routine in order for it to work correctly with the mma8452 in 2g mode and 12 bits. But this isn't very clear to me.

/******************************************************************************

* Simple offset calibration

******************************************************************************/

void Calibrate (void)

{

  unsigned char reg_val = 0;

  while (!reg_val) // Wait for a first set of data

  {

  reg_val = I2C_ReadRegister(MMA845x_I2C_ADDRESS, STATUS_REG) & 0x08;

  }

 

  I2C_ReadMultiRegisters(MMA845x_I2C_ADDRESS, OUT_X_MSB_REG, 6, AccData); // Read data output registers 0x01-0x06

 

  Xout_14_bit = ((short) (AccData[0]<<8 | AccData[1])) >> 2; // Compute 14-bit X-axis output value

  Yout_14_bit = ((short) (AccData[2]<<8 | AccData[3])) >> 2; // Compute 14-bit Y-axis output value

  Zout_14_bit = ((short) (AccData[4]<<8 | AccData[5])) >> 2; // Compute 14-bit Z-axis output value

 

  Xoffset = Xout_14_bit / 8 * (-1); // Compute X-axis offset correction value

  Yoffset = Yout_14_bit / 8 * (-1); // Compute Y-axis offset correction value

  Zoffset = (Zout_14_bit - SENSITIVITY_2G) / 8 * (-1); // Compute Z-axis offset correction value

 

  I2C_WriteRegister(MMA845x_I2C_ADDRESS, CTRL_REG1, 0x00); // Standby mode to allow writing to the offset registers

  I2C_WriteRegister(MMA845x_I2C_ADDRESS, OFF_X_REG, Xoffset);

  I2C_WriteRegister(MMA845x_I2C_ADDRESS, OFF_Y_REG, Yoffset);

  I2C_WriteRegister(MMA845x_I2C_ADDRESS, OFF_Z_REG, Zoffset);

  I2C_WriteRegister(MMA845x_I2C_ADDRESS, CTRL_REG3, 0x00); // Push-pull, active low interrupt

  I2C_WriteRegister(MMA845x_I2C_ADDRESS, CTRL_REG4, 0x01); // Enable DRDY interrupt

  I2C_WriteRegister(MMA845x_I2C_ADDRESS, CTRL_REG5, 0x01); // DRDY interrupt routed to INT1 - PTA14

  I2C_WriteRegister(MMA845x_I2C_ADDRESS, CTRL_REG1, 0x3D); // ODR = 1.56Hz, Reduced noise, Active mode

}

I have made the following changes (marked in bold):

  Xout_12_bit = ((short) (AccData[0]<<8 | AccData[1])) >> 4; // Compute 12-bit X-axis output value

  Yout_12_bit = ((short) (AccData[2]<<8 | AccData[3])) >> 4; // Compute 12-bit Y-axis output value

  Zout_12_bit = ((short) (AccData[4]<<8 | AccData[5])) >> 4; // Compute 12-bit Z-axis output value

 

  Xoffset = Xout_12_bit / 2 * (-1); // Compute X-axis offset correction value

  Yoffset = Yout_12_bit / 2 * (-1); // Compute Y-axis offset correction value

  Zoffset = (Zout_12_bit - SENSITIVITY_2G) / 2 * (-1); // Compute Z-axis offset correction value

Can you please tell me if this changes are correct?

Thanks, and sorry for the troubles.

0 Kudos
1,806 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Juan,

Glad to hear that you have got it working with the JM128.

The changes you made are correct. The resolution of all three offset registers (0x2F – 0x31) is ~2mg (1.953125mg) per LSB, so if calibration is done in the ±2g mode (0.9765625mg/count), the 12-bit output data needs to be divided by 2 and then multiplied by -1 to shift the offset to zero. If you calibrated in the ±4g mode (1.953125mg/count), then all you would have to do is multiply the 12-bit output data by -1. In the ±8g mode (3.90625mg/count), the 12-bit output data needs to be multiplied by 2 and -1.

I hope it makes sense. If you have any other questions, just let me know.


Regards,

Tomas

1,806 Views
juanm
Contributor III

Thank you very much! You have been very helpfull.

0 Kudos