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.

  • 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.

Reply Children
No Data
Related