mma8451q: Wrong reading of x y z

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

mma8451q: Wrong reading of x y z

690 Views
s_russo
Contributor I

Hello,
I have a problem with the reading of x, y, z axes. My application uses the microcontroller STM32L152RE that communicates with te mma8451q accelerometer.
I do the following steps in order to read the OUT_X_MSB, OUT_X_LSB, OUT_Y_MSB, OUT_Y_LSB, OUT_Z_MSB, OUT_Z_LSB registers.

- Set the accelerometer:
1. Put the device in standy mode writing the value 0x00 in CTRL_REG1 register;
2. Set F_SETUP register = 0x00;
3. Set TRIG_CFG register = 0x00;
4. Set XYZ_DATA_CFG register = 0x00;
5. Set CTRL_REG2 register = 0x02;
6. Set HP_FILTER_CUTOFF register 0x00;
7. Set CTRL_REG3 register = 0x40;
8. Set CTRL_REG4 register = 0x00;
9. Set CTRL_REG5 register = 0x00;
10. Put the device in active mode writing the value 0x3D in CTRL_REG1 register.

- Read the OUT_X_MSB, OUT_X_LSB, OUT_Y_MSB, OUT_Y_LSB, OUT_Z_MSB, OUT_Z_LSB registers in the following way:
Read the ZYXDR bit of STATUS/F_STATUS register every 10 ms and when it becames equal to 1 read the x, y, z registers;
(For more details carry forward below a piece of script used:

/********************************************************************************************************************/
tx[0] = 0x02; // START CONDITION : SC
tx[1] = 0x38; // 001110 + (SA0=0) + (R/W = 0)
error = HAL_I2C_Master_Transmit(&hi2c1, MMA8451Q_SLAVE_ADDR << 1, tx, 2, 200);
if (error != HAL_OK)
return error;
HAL_Delay(5);

tx[0] = MMA8451Q_REGISTER_OUT_X_MSB;
error = HAL_I2C_Master_Transmit(&hi2c1, MMA8451Q_SLAVE_ADDR << 1, tx, 1, 100);
if (error != HAL_OK)
return error;
HAL_Delay(5);

tx[0] = 0x02; // REPEATED SC
tx[1] = 0x39; 
error = HAL_I2C_Master_Transmit(&hi2c1, MMA8451Q_SLAVE_ADDR << 1, tx, 2, 200);
if (error != HAL_OK)
return error;
HAL_Delay(5);

error = HAL_I2C_Master_Receive(&hi2c1, MMA8451Q_SLAVE_ADDR << 1, rx, 6, 640);
if (error != HAL_OK)
return error;
/********************************************************************************************************************/
)

The rx buffer contains the bytes of x, y and z axes. I convert the values with the following formula:

x = (((int16_t) (( (rx[1]<<8) | rx[0]) &0xFFFC ))/4); 
y = (((int16_t) (( (rx[3]<<8) | rx[2]) &0xFFFC ))/4);
z = (((int16_t) (( (rx[5]<<8) | rx[4]) &0xFFFC ))/4);

NB: This conversion is OK if:
r[1] = OUT_X_MSB, r[0] = OUT_X_LSB, r[3] = OUT_Y_MSB, r[2] = OUT_Y_LSB, r[5] = OUT_Z_MSB, r[4] = OUT_Z_LSB.
The value of z (close to 4000) is greater than x and y values (close to 0). 
BUT,
after a series of readings without moving the accelerometer the x values read are wrong because vary between only two values: 0 (or -1) and 60 (or 64). This behavior occurs mainly for the x axis but has also been seen for the y and z axis. I don't know the reason. Did i make a mistake on the settings?
Help me please.

Beest regards
Silvia

NB: The attached file contains the I2C communication with mma8451q when the reading OUT_X_MSB, OUT_X_LSB, OUT_Y_MSB, OUT_Y_LSB, OUT_Z_MSB, OUT_Z_LSB registers is requested.

Tags (1)
0 Kudos
1 Reply

610 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hello Silvia,

I do not see anything wrong with your settings except point 7. Are you really using the Sleep mode and the transient detection function as a wake-up? If not, write 0x00 to the CTRL_REG3 register, just to be sure, although it should not cause the behavior you are experiencing.

 

It sounds to me more like a timing issue or something like that. Could you please try to increase your polling period from 10ms to e.g. 1s? If ODR = 1.56Hz which corresponds to 640ms, 10ms period seems to me very fast and not needed.

Best regards,

Tomas

0 Kudos