This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Accelerometer giving out random output

Hello. I am using a nrf51822 with sdk 10 and softdevice 130. It has an accelerometer mma8653 to read the orientation of the chip, I am trying to get the x,y and z co-ordinates from it using i2c method and have a nrf_drv_twi example as reference but the accelerometer is giving out random data which changes when I change the chips orientation. Since it is giving out no error on compliation and debugging, i guess there must be some problem in the code logic. I am putting the code up here. Kindly tell if there is some error in the logic or some other issue


#define MMA8653_BASE_ADDRESS 0x1D          
const uint8_t ACTIVE_MASK  = 0x01;
const uint8_t STDBY_MASK   = 0x00;    
#define RST_MASK 0x40
static uint8_t m_device_address;                                                                            //!< Device address in bits [7:1]
const uint8_t access_data                = 0x01;                                        // Data X0,X1,Y0,Y1,Z0 and Z1   
uint8_t command_who_am_i[2]              = {0x0D, 0x5A};    
uint8_t command_data_active[2]       = {0x2A, ACTIVE_MASK};         // Set MMA to active    
uint8_t command_data_stdby[2]        = {0x2A, STDBY_MASK};          // Set MMA to standby    
uint8_t command_data_intaxi[2]       = {0x15, 0xD8};                      // Enable axis
uint8_t command_data_thres[2]        = {0x17, 0x4F};                        // thres
uint8_t command_data_interrupt[2]    = {0x2C, 0x00};                      // Set interrupt polarity 
uint8_t command_enscr_config[2]      = {0x2D, 0x04};                  // int source config  
uint8_t command_int_route[2]             = {0x2E, 0x04};                  // interrupt route config 
uint8_t access_int_source                = 0x16;                          // Interupt Source address
uint8_t control_reg_1[2]                         = {0x2A,0x20};
uint8_t control_reg_2                              = 0x20;                                                                                  

//const uint8_t stdby[2]                                   = {0x2D,
                                                                                       //0x00};                   // Interrupt Map  
    static const nrf_drv_twi_t * p_twi_master;

 ret_code_t mma8653_I2C_register_write(uint8_t slave_addr,uint8_t * pdata, uint32_t bytes)
{
    ret_code_t ret_code;
    
    ret_code = nrf_drv_twi_tx(p_twi_master, slave_addr, pdata, bytes , false);
    
    return ret_code;
}

ret_code_t mma8653_I2C_register_read(uint8_t slave_addr, uint8_t reg_addr,  uint8_t * pdata, uint32_t bytes)
{   
    ret_code_t ret_code;
    
    ret_code = nrf_drv_twi_tx(p_twi_master,slave_addr, &reg_addr,1,false);
    
    if(ret_code != NRF_SUCCESS)
    {
        return ret_code;
    }
    
    ret_code = nrf_drv_twi_rx(p_twi_master,slave_addr, pdata, bytes, false);
    
    return ret_code;
}
 
ret_code_t mma8653_init(const nrf_drv_twi_t * p_twi_instance)
{
    nrf_drv_twi_enable(p_twi_instance);
    m_device_address = MMA8653_BASE_ADDRESS;
    ret_code_t ret_code;

    p_twi_master = p_twi_instance;

    //ret_code = mma8653_I2C_register_write(m_device_address, &control_reg_2, sizeof(&control_reg_2) ); 

    ret_code = mma8653_I2C_register_write(m_device_address, command_data_active, sizeof(command_data_active) );
    ret_code = mma8653_I2C_register_write(m_device_address, command_data_stdby, sizeof(command_data_stdby) );
    ret_code = mma8653_I2C_register_write(m_device_address, command_data_intaxi, sizeof(command_data_intaxi) );
    ret_code = mma8653_I2C_register_write(m_device_address, command_data_thres, sizeof(command_data_thres) );
    ret_code = mma8653_I2C_register_write(m_device_address, command_data_interrupt, sizeof(command_data_interrupt) );
    ret_code = mma8653_I2C_register_write(m_device_address, command_enscr_config, sizeof(command_enscr_config) );
    ret_code = mma8653_I2C_register_write(m_device_address, command_int_route, sizeof(command_int_route) );
    ret_code = mma8653_I2C_register_write(m_device_address, command_data_active, sizeof(command_data_active) );
}

ret_code_t mma8653_xyz_read(uint16_t * x_value, int16_t * y_value, int16_t * z_value)
{
    m_device_address = MMA8653_BASE_ADDRESS;
    ret_code_t ret_code;

    uint8_t rx_buffer[6];
    rx_buffer[0] = 0x00;

    ret_code = mma8653_I2C_register_read(m_device_address,access_data, &rx_buffer[1], sizeof(rx_buffer));

    *x_value = (rx_buffer[1]<<8)|rx_buffer[0];
    *y_value = (rx_buffer[3]<<8)|rx_buffer[2];
    *z_value = (rx_buffer[5]<<8)|rx_buffer[4];
    return ret_code;
}
Parents
  • Hi,

    When you read your X, Y, and Z values it looks like you read the Most Significant Byte (MSB) of the X-value first (at address 0x01). Hence your values are stored in rx_buffer like this:

    rx_buffer[0] = X value MSB
    rx_buffer[1] = X value LSB
    rx_buffer[2] = Y value MSB
    rx_buffer[3] = Y value LSB
    rx_buffer[4] = Z value MSB
    rx_buffer[5] = Z value LSB
    

    So when you write

    *x_value = (rx_buffer[1]<<8)|rx_buffer[0];
    

    You shift the least significant byte 8 bits to the left. Try to write this instead:

    *x_value = (rx_buffer[0]<<8)|rx_buffer[1];
    *y_value = (rx_buffer[2]<<8)|rx_buffer[3];
    *z_value = (rx_buffer[4]<<8)|rx_buffer[5];
    

    EDIT:

    Also it seems like you have a bug in mma8653_xyz_read(). uint16_t * x_value should be int16_t * x_value. I.e. use signed integers.

Reply
  • Hi,

    When you read your X, Y, and Z values it looks like you read the Most Significant Byte (MSB) of the X-value first (at address 0x01). Hence your values are stored in rx_buffer like this:

    rx_buffer[0] = X value MSB
    rx_buffer[1] = X value LSB
    rx_buffer[2] = Y value MSB
    rx_buffer[3] = Y value LSB
    rx_buffer[4] = Z value MSB
    rx_buffer[5] = Z value LSB
    

    So when you write

    *x_value = (rx_buffer[1]<<8)|rx_buffer[0];
    

    You shift the least significant byte 8 bits to the left. Try to write this instead:

    *x_value = (rx_buffer[0]<<8)|rx_buffer[1];
    *y_value = (rx_buffer[2]<<8)|rx_buffer[3];
    *z_value = (rx_buffer[4]<<8)|rx_buffer[5];
    

    EDIT:

    Also it seems like you have a bug in mma8653_xyz_read(). uint16_t * x_value should be int16_t * x_value. I.e. use signed integers.

Children
  • Hey Martin, thanks for the reply, I tried the way you suggested but it it shows random value. I have called the read function several times in main.c so that i can see the variation in the values there itself in watch1. the values change for the 1st function call but even after realigning the chip the value remains same. 1 more thing, i tried getting the device id instead of the accelerometer reading and it does not show the device address as well. So, i think there is a different problem. Thanks for helping :)

  • Are you able to read and write from the chip at all? I can see that you enable the TWI, but have you initiated it with the proper configuration somewhere? Here is a simple example you can use to check your connections and to see how you configure the TWI.

  • Hey Martin, the i2c works fine with other chips, tried it with capacitive touch module, read and write work fine there. here is the link for a new folder with just mma code. could you please try it out and tell about the error. the rx_buffer goes straight to 0xFF. Thanks in advance. drive.google.com/open

  • What do you mean with "rx_buffer goes straight to 0xFF"?

    In your main while loop you call MMA_I2C_data_read(). There you call MMA_I2C_register_read(MMA_ADDR, 0x19, rx_buffer, sizeof(rx_buffer));. This will start a read from address 0x19. According to this datasheet address 0x19 is reserved, and it looks like it should return 0x00?

    Have you checked if any of the TWI function calls return any errors? You can do it like described here.

  • I meant the read values off from any registers go to 0xFF rather than an expected value. We tried to read the device ID on 0x0D assuming we would get 0x5A but there too we got 0xFF. Which is why I tried with 0x19 as the datasheet said that the read would return 0x00 but there too I'm only getting 0xFF or 0xFE. I erased the softdevice and connected the TWI pins to arduino and implemented the TWI there and the device is working just fine. Also implemented the 'I2C device scan' for arduino and it shows the device being ack but when in comes to implement TWI resistors, mounted a new chip, also have tried just with the chip and nRF51 Dev board too, no luck. Which, is why I am not being able to exactly locate where the issue could be.

Related