Incorrect data received from the MMA8451Q accelerometer

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

Incorrect data received from the MMA8451Q accelerometer

1,305 Views
wojciech22a
Contributor II

Hi! I using KL25Z and KDS 3.0. I'm trying to write a program that will be send data from the accelerometer MMA8451Q and send this data via UART and blinking LED. I2C interface is configured correctly - when I read a register of "who I am" I received in response  "0x1A". I would like to receive the acceleration values ​​from each axis from the registers with addresses from 0x01 to 0x06. I wrote a program for reading 7 consecutive bytes starting at byte address of 0x00 but this program did not work properly. MMA8451Q automatically increases by 1 of byte address read out - that's why I sent you only the address of the first register. After  reset KL25Z is sending 7 bytes of values ​​"0x00 (status register), 0xC9 (value from OUT_X_MSB), 0xFC (OUT_X_LSB), 0x08 OUT_A (Y_MSB), 0xFC (OUT_Y_LSB), 0x7F (OUT_Z_MSB), 0x58 (OUT_Z_LSB). But in the every next   sequence of reading I get the following values: 0x00 (status register), 0xFF (value from OUT_X_MSB), 0xFF (OUT_X_LSB), 0xFF OUT_A (Y_MSB), 0xFF (OUT_Y_LSB), 0xFF (OUT_Z_MSB), 0xFF (OUT_Z_LSB).. These values are incorrect  because in the registers LSB first two bytes are reset. Please help.

#include "MKL25Z4.h"

static int i = 0;

void opz(int ile)

{

  int p;

  for(p=0;p<ile;p++)

  {

  }

}

void ledkonf(void)

{

  SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;

  PORTB_PCR19=PORTB_PCR19 &~(1<<10) &~(1<<9) | (1<<8);

  GPIOB_PDDR=GPIOB_PDDR | (1<<19);

}

void uartkonf(void)

{

  SIM_SCGC4=SIM_SCGC4| (1<<10);//enable uart0

  SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;//enable PORTA

  SIM_SOPT2 |= SIM_SOPT2_UART0SRC(1);

  PORTA_PCR1=PORTA_PCR1 &~(1<<10) | (1<<9) &~(1<<8);//010mask -uart

  PORTA_PCR2=PORTA_PCR2 &~(1<<10) | (1<<9) &~(1<<8);

  UART0_BDH=0x02;//9600 baud; OSR = 3; module clock 20.97152MHz SBR=546 = 1000100010

  UART0_BDL=0x22;

  UART0_C1 = 0x00;

  UART0_C2 = 0x00;

  UART0_C2=UART0_C2 | (1<<3);//TE bit on

  //UART0_S1=0xC0;

  UART0_C3 = 0x00;

  UART0_C4=0x03;//OSR-3

  UART0_C5=0x00;

}

void i2ckonf(void)

{

  SIM_SCGC4=SIM_SCGC4 | (1 << 6);

  SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK;

  PORTE_PCR24=PORTE_PCR24 | (1<<10) &~(1<<9) | (1<<8);

  PORTE_PCR25=PORTE_PCR25 | (1<<10) &~(1<<9) | (1<<8);

  I2C0_C1 = I2C0_C1 | (1 << 7);//Enable I2C

  I2C0_C1 = I2C0_C1 | (1 << 6);//Enable I2C inter

  I2C0_F=0x2D;

}

void swiec(void)

{

   opz(100000);

   GPIOB_PDOR=GPIOB_PDOR|(1<<19);

   opz(100000);

   GPIOB_PTOR=GPIOB_PTOR|(1<<19);

   opz(100000);

}

void Transmisja( unsigned char data )

{

while ( !( UART0_S1 & (1<<7)));

UART0_D = data;

}

unsigned char Odbior( void )

{

while ( !(UART0_S1 & (1<<5)) );

return UART0_D;

}

int main(void)

{

    /* Write your code here */

    /* This for loop should be replaced. By default this loop allows a single stepping. */

  ledkonf();

  uartkonf();

  i2ckonf();

    for (;;) {

    unsigned char Kp='k';

    unsigned char x1[7];

    I2C0_C1 = I2C0_C1 | (1 << 5);//Start

    I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode

    I2C0_D=0x3A;//Slave adress of MMA8451Q -write

      while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission -  IICIF

     I2C0_S = I2C0_S | (1 << 1);//Set IICIF

       I2C0_D=0x00;//sending adress of first register

      while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission

     I2C0_S = I2C0_S | (1 << 1);//Set IICIF

       I2C0_C1 = I2C0_C1 | (1 << 2);//Rstart

        I2C0_D=0x3B;//Slave adress of MMA8451Q - read

       while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission -  IICIF

     I2C0_S = I2C0_S | (1 << 1);//Set IICIF

       I2C0_C1 = I2C0_C1 & ~(1 << 4);//RX mode

       Kp=I2C0_D;//dummy read

       while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

           I2C0_S = I2C0_S | (1 << 1);//Set IICIF

           x1[0]=I2C0_D;//status

          while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

          I2C0_S = I2C0_S | (1 << 1);//Set IICIF

          x1[1]=I2C0_D;//OUT_X_MSB

          while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

          I2C0_S = I2C0_S | (1 << 1);//Set IICIF

          x1[2]=I2C0_D;//OUT_X_LSB

          while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

                I2C0_S = I2C0_S | (1 << 1);//Set IICIF

                x1[3]=I2C0_D;//OUT_Y_MSB

                while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

               I2C0_S = I2C0_S | (1 << 1);//Set IICIF

               x1[4]=I2C0_D;//OUT_Y_LSB

                while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

               I2C0_S = I2C0_S | (1 << 1);//Set IICIF

      /////////////////////////////         ////

          I2C0_C1 = I2C0_C1 | (1 << 3);//set NACK

          x1[5]=I2C0_D;//OUT_Z_MSB

          while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

          I2C0_S = I2C0_S | (1 << 1);//Set IICIF

           I2C0_C1 = I2C0_C1 & ~(1 << 5);//STOP

           I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode

           x1[6]=I2C0_D;//OUT_Z_LSB

    Transmisja(x1[0]);//transmit via UART

    Transmisja(x1[1]);

    Transmisja(x1[2]);

    Transmisja(x1[3]);

    Transmisja(x1[4]);

    Transmisja(x1[5]);

    Transmisja(x1[6]);

       swiec();// blinking LED

    }

    /* Never leave main */

    return 0;

}

////////////////////////////////////////////////////////////////////////////////

// EOF

////////////////////////////////////////////////////////////////////////////////

Image from UART Terminal:

Rysyn.PNG

Labels (1)
Tags (1)
0 Kudos
6 Replies

931 Views
EarlOrlando
Senior Contributor II

Helo Wojciech,

Are you always receiving the same values after reset or these depend on the accelerometer position?

Best regards,

Earl.

0 Kudos

931 Views
wojciech22a
Contributor II

Yes. After the reset, the first portion of the data are always the same regardless of the position of the accelerometer during the reset.rysun2.PNG

Many times I reset the KL25Z in different positions -. but always values that were sent by the UART, were the same

0 Kudos

931 Views
EarlOrlando
Senior Contributor II

Hi Wojciech,

You need to activate the accelerometer by writing in the register 0x2A CTRL_REG1 register in the bit field 0 after configure the accelerometer (resolution, etc).

Best regards,

Earl Orlando.

931 Views
wojciech22a
Contributor II

Mark, Earl - thank for your help!

The first value which is being sending after reset, in my new program is being depending on the position of accelerometer during the reset. When the accelerometer is at different positions at the time of reset,  I receive the data with different values. Unfortunately but in every subsequent sequence of bytes, I receive incorrect data.

rysun3.PNG

rysun5.PNG

Program (main):

void mmakonf(void)

{

    I2C0_C1 = I2C0_C1 | (1 << 5);//Start

    I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode

    I2C0_D=0x3A;//Slave adress of MMA8451Q -write

     while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission -  IICIF

     I2C0_S = I2C0_S | (1 << 1);//Set IICIF

     I2C0_D=0x2A;//sending adress of first register

        while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission

        I2C0_S = I2C0_S | (1 << 1);//Set IICIF

        I2C0_D=0x01;//sending adress of first register

          while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission

        I2C0_S = I2C0_S | (1 << 1);//Set IICIF

    I2C0_C1 = I2C0_C1 & ~(1 << 5);//STOP

}

int main(void)

{

    /* Write your code here */

    /* This for loop should be replaced. By default this loop allows a single stepping. */

  ledkonf();

  uartkonf();

  i2ckonf();

  mmakonf();

    for (;;) {

    unsigned char Kp='k';

    unsigned char x11;

    unsigned char x12;

  unsigned char x13;

  unsigned char x14;

  unsigned char x15;

  unsigned char x16;

  unsigned char x17;

  // Transmisja(Kp);

    swiec();//delay - without - program don't working

    I2C0_C1 = I2C0_C1 | (1 << 5);//Start

    I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode

    I2C0_D=0x3A;//Slave adress of MMA8451Q -write

      while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission -  IICIF

     I2C0_S = I2C0_S | (1 << 1);//Set IICIF

       I2C0_D=0x00;//sending adress of first register

      while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission

     I2C0_S = I2C0_S | (1 << 1);//Set IICIF

       I2C0_C1 = I2C0_C1 | (1 << 2);//Rstart

        I2C0_D=0x3B;//Slave adress of MMA8451Q - read

       while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission -  IICIF

     I2C0_S = I2C0_S | (1 << 1);//Set IICIF

       I2C0_C1 = I2C0_C1 & ~(1 << 4);//RX mode

       Kp=I2C0_D;//dummy read

       while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

           I2C0_S = I2C0_S | (1 << 1);//Set IICIF

           x11=I2C0_D;//status

          while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

          I2C0_S = I2C0_S | (1 << 1);//Set IICIF

          x12=I2C0_D;//OUT_X_MSB

          while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

          I2C0_S = I2C0_S | (1 << 1);//Set IICIF

          x13=I2C0_D;//OUT_X_LSB

          while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

                I2C0_S = I2C0_S | (1 << 1);//Set IICIF

                x14=I2C0_D;//OUT_Y_MSB

                while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

               I2C0_S = I2C0_S | (1 << 1);//Set IICIF

               x15=I2C0_D;//OUT_Y_LSB

                while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

               I2C0_S = I2C0_S | (1 << 1);//Set IICIF

      /////////////////////////////         ////

          I2C0_C1 = I2C0_C1 | (1 << 3);//set NACK

          x16=I2C0_D;//OUT_Z_MSB

          while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF

          I2C0_S = I2C0_S | (1 << 1);//Set IICIF

           I2C0_C1 = I2C0_C1 & ~(1 << 5);//STOP

           I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode

           x17=I2C0_D;//OUT_Z_LSB

    Transmisja(x11);//transmit via UART

    Transmisja(x12);

    Transmisja(x13);

    Transmisja(x14);

    Transmisja(x15);

    Transmisja(x16);

    Transmisja(x17);

       swiec();

    }

    /* Never leave main */

    return 0;

}

////////////////////////////////////////////////////////////////////////////////

// EOF

////////////////////////////////////////////////////////////////////////////////

0 Kudos

931 Views
mjbcswitzerland
Specialist V

Hi

Below is the MMA8451Q code from the uTasker project (for 8 or 14 bit mode) when operating in continuous read/polling mode.

You may see something that is missing in yours - you can also test it in the FRDM-KL25Z from µTasker Kinetis FRDM-KL25Z support and use the accelerometer to control a USB mouse.

Regards

Mark

static const unsigned char ucSetAccelerometerAddress[] = {MMA8451Q_WRITE_ADDRESS, ACC_START_ADDRESS}; // command to set address to read to the start address

static const unsigned char ucReadAccelerometerRegisters[] = {ACC_READ_LENGTH, MMA8451Q_READ_ADDRESS, OWN_TASK}; // command to start a read the defined amount of bytes with the task scheduled when the read has completed

static const unsigned char ucSetAccelerometerRead[] = {MMA8451Q_WRITE_ADDRESS, 0}; // command to set address to read to the first register address (status)

#if defined MMA8451Q_14BIT_RES

    #define RESULT_LENGTH 7

#else

    #define RESULT_LENGTH 4

#endif

static const unsigned char ucReadAccelerometerState[] = {RESULT_LENGTH, MMA8451Q_READ_ADDRESS, OWN_TASK}; // command to start a read the defined amount of bytes with the task scheduled when the read has completed

#if defined MMA8451Q_14BIT_RES

    static const unsigned char ucSetAccelerometerMode[] = {MMA8451Q_WRITE_ADDRESS, ACC_CONTROL_REGISTER, (ACC_CONTROL_REGISTER_ACTIVE | ACC_CONTROL_REGISTER_DATA_RATE_50Hz | ACC_CONTROL_REGISTER_SLEEP_RATE_6_25Hz | ACC_CONTROL_REGISTER_LNOISE)}; // command to set the 14-bit resolution mode

#else

    static const unsigned char ucSetAccelerometerMode[] = {MMA8451Q_WRITE_ADDRESS, ACC_CONTROL_REGISTER, (ACC_CONTROL_REGISTER_ACTIVE | ACC_CONTROL_REGISTER_DATA_RATE_50Hz | ACC_CONTROL_REGISTER_SLEEP_RATE_6_25Hz | ACC_CONTROL_REGISTER_LNOISE | ACC_CONTROL_REGISTER_F_READ)}; // command to set the 8 bit (fast) mode

#endif

// Initialisation

//

iAccelerometerState = ACC_INITIALISING;

fnWrite(IICPortID, (unsigned char *)ucSetAccelerometerAddress, sizeof(ucSetAccelerometerAddress)); // write the register address to read from

fnRead(IICPortID, (unsigned char *)ucReadAccelerometerRegisters, 0); // start the read process of the required amount of bytes

// On each reception

//

    #define ACC_DISPLAY_FILTER  100

    switch (iAccelerometerState) {

    case ACC_INITIALISING:

        if (fnRead(IICPortID, ucInputMessage, ACC_READ_LENGTH) != 0) {   // if the read has completed

            int i = 0;

            int iLine;

            fnDebugMsg("3-axis accelerometer:\r\n");

            while (i < ACC_READ_LENGTH) {

                for (iLine = 0; iLine < 15; iLine++) {

                    fnDebugHex(ucInputMessage[i], (sizeof(ucInputMessage[i]) | WITH_LEADIN | WITH_SPACE)); // display the received register contents

                    if (++i >= ACC_READ_LENGTH) {

                        break;

                    }

                }

                fnDebugMsg("\r\n");

            }

            // We now set the operating mode

            //

            fnWrite(IICPortID, (unsigned char *)ucSetAccelerometerMode, sizeof(ucSetAccelerometerMode)); // write the operating mode

            // Followed by the first status read

            //

            fnWrite(IICPortID, (unsigned char *)ucSetAccelerometerRead, sizeof(ucSetAccelerometerRead)); // write the register address to read

            fnRead(IICPortID, (unsigned char *)ucReadAccelerometerState, 0); // start the read process of the status

            iAccelerometerState = ACC_X_Y_Z;

        }

        break;

    case ACC_X_Y_Z:                                                      // we are expecting status data from the accelerometer to arrive

        if (fnRead(IICPortID, ucInputMessage, RESULT_LENGTH) != 0) {     // if the result read has completed

            static int iDisplayRate = 0;

            if (++iDisplayRate >= ACC_DISPLAY_FILTER) {

                int i = 0;

                fnDebugMsg("3-axis state:");                             // display the status on a regular basis

                while (i < RESULT_LENGTH) {                              // display 4 values

    #if defined MMA8451Q_14BIT_RES

                    if (i == 0) {

                         fnDebugHex(ucInputMessage[i], (sizeof(ucInputMessage[i]) | WITH_LEADIN | WITH_SPACE)); // display the received register contents

                    }

                    else {

                        unsigned short usValue = ucInputMessage[i++];

                        usValue <<= 8;

                        usValue |= ucInputMessage[i];

                        fnDebugHex(usValue, (sizeof(usValue) | WITH_LEADIN | WITH_SPACE)); // display the received register contents

                    }

    #else                                                                // status, x, y, z with 8 bit resolution

                    fnDebugHex(ucInputMessage[i], (sizeof(ucInputMessage[i]) | WITH_LEADIN | WITH_SPACE)); // display the received register contents

    #endif

                    i++;

                }

                fnDebugMsg("\r\n");

                iDisplayRate = 0;

            }

          //fnWrite(IICPortID, (unsigned char *)ucSetAccelerometerRead, sizeof(ucSetAccelerometerRead)); // write the register address to read (it is not necessary to set the address pointer since it operates in overflow mode)

            fnRead(IICPortID, (unsigned char *)ucReadAccelerometerState, 0); // start the read process of the next status

        }

        break;

    }

0 Kudos

931 Views
mjbcswitzerland
Specialist V

Hello

Have you configured the sensor by writing to its control register (0x21)?

Regards

Mark

Kinetis: µTasker Kinetis support

KL25: µTasker Kinetis FRDM-KL25Z support  / µTasker Kinetis TWR-KL25Z48M support

For the complete "out-of-the-box" Kinetis experience and faster time to market