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.

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

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

Children
No Data
Related