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

LSM6DSL problem to start via i2c

Hello!

I have a custom pcb with Lsm6dsl connect to nrf52832 via i2c.

I can write and read regs of Lsm6dsl well ( reg "who_am_I" return 0x6a as describe in datasheet ).

The problem appears when I try to write "ODR" (output data rate) bits in CTRL1_XL (10h) reg (for example 0x10). This bits must turn on an accelerometer. After the transaction, I can no longer access  Lsm6ds because it always return NRF_DRV_TWI_EVT_ADDRESS_NACK.. like there is no i2c slave on this address.

If I write other bits in CTRL1_XL (10h) reg that do not enable accelerometer (for example 0x0f) it work OK.

Can anybody help me, what it is the problem?

Here is programm code:

static const nrf_drv_twi_t m_twi_lsm6dsl = NRF_DRV_TWI_INSTANCE(0);

uint8_t address_acc = 0x6aU;
uint8_t reg_odr_sys_on[2] = {0x10U, 0x10U};
uint8_t who_am_i_buffer = 0;
uint8_t reg_who_am_i_buffer_read[1] = {0x0fU};

/**
* @brief TWI events handler.
*/
void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{ 
    ret_code_t err_code;

    switch(p_event->type)
    {
         case NRF_DRV_TWI_EVT_DONE:
         break;
         case NRF_DRV_TWI_EVT_ADDRESS_NACK: 
         break;
         case NRF_DRV_TWI_EVT_DATA_NACK: 
         break;
         default:
         break; 
    }
}

/**
* @brief twi initialization.
*/
void twi_init (void)
{
    ret_code_t err_code;
    
    const nrf_drv_twi_config_t twi_lsm6dsl_config = {
    .scl = 06,
    .sda = 07,
    .frequency = NRF_TWI_FREQ_100K,
    .interrupt_priority = APP_IRQ_PRIORITY_LOW
    };

    err_code = nrf_drv_twi_init(&m_twi_lsm6dsl, &twi_lsm6dsl_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);
    
    nrf_drv_twi_enable(&m_twi_lsm6dsl);
}

int main(void)
{

    twi_init();

    ret_code_t err_code;
    
    err_code = nrf_drv_twi_tx(&m_twi_lsm6dsl, address_acc, reg_who_am_i_buffer_read, sizeof(reg_who_am_i_buffer_read), false); 
    APP_ERROR_CHECK(err_code); 
    nrf_delay_ms(100);
    
    err_code = nrf_drv_twi_rx(&m_twi_lsm6dsl, address_acc, &who_am_i_buffer, sizeof(who_am_i_buffer));
    APP_ERROR_CHECK(err_code); 
    nrf_delay_ms(100);
    
    err_code = nrf_drv_twi_tx(&m_twi_lsm6dsl, address_acc, reg_odr_sys_on, sizeof(reg_odr_sys_on), false); 
    APP_ERROR_CHECK(err_code); 
    nrf_delay_ms(100);


    while(true)
    {
    }
}

Parents
  • Do you have a logic analyzer that you can use to capture what goes on on the bus?

    What happens if you remove the code reading from the who am I registers? The LSM6DSL's datasheet states that you need a repeated start condition between TX and RX operations and you don't have that. I'm not sure it if it is related though, and it is i odd that a read operation would work, but not subsequent write operations. 

    To use repeated start, please use:

    nrf_drv_twi_tx(..., ..., ..., ..., true); 

    before

    nrf_drv_twi_rx(..., ..., ..., ...); 

Reply
  • Do you have a logic analyzer that you can use to capture what goes on on the bus?

    What happens if you remove the code reading from the who am I registers? The LSM6DSL's datasheet states that you need a repeated start condition between TX and RX operations and you don't have that. I'm not sure it if it is related though, and it is i odd that a read operation would work, but not subsequent write operations. 

    To use repeated start, please use:

    nrf_drv_twi_tx(..., ..., ..., ..., true); 

    before

    nrf_drv_twi_rx(..., ..., ..., ...); 

Children
Related