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.

  • 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

Reply Children
No Data
Related