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

Read and Write TWI Sensor Registers

Hi there,

I'm developing with the nRF52840 right now.

I'm trying to read some sensordata with TWI. The sensors are BMM150, BMI270 and BMP388.

Unfortunately, I already have problems with the my first sensor (BMM150), reading the Chip ID.

To read it, I have to set the Power Control Bit of the sensor. That seems to be working.

But when I want to read registers again, I only get zeros. Even for reading the Power Control Bit.


This is the function to write Registers:

bool writeRegister(uint8_t regNumber, uint8_t value){
  ret_code_t err_code;

  uint8_t valueBuffer[2];
  valueBuffer[0] = regNumber;
  valueBuffer[1] = value;
  err_code = nrf_drv_twi_tx(&m_twi, 0x10, valueBuffer, sizeof(valueBuffer), false);
  APP_ERROR_CHECK(err_code);
  return 1;
}


Read Registers:

uint8_t readRegister(uint8_t regNumber){
  ret_code_t err_code;

  uint8_t resultsWhoAmI;
  uint8_t whoAmIPointer = regNumber;
  err_code = nrf_drv_twi_tx(&m_twi, 0x10, &whoAmIPointer, 1, true);
  err_code = nrf_drv_twi_rx(&m_twi, 0x10, &resultsWhoAmI, 1);
  APP_ERROR_CHECK(err_code);

  return resultsWhoAmI;
}



Main to test reading the Chip ID. Later on I want to use the Bosch Sensortec API. But first I want this one to work:
int main(void)
{
    ret_code_t err_code;
    uint8_t address = 0x10;
    uint8_t read_data;
    uint8_t write_data;

 
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("Read Chip ID started");

    NRF_LOG_FLUSH();
    twi_init();

    // Read Power Control Bit
    read_data = readRegister(0x4B);
    uint8_t pwr_bit = read_data & 0b1;
    NRF_LOG_INFO("Read Power Control = %x", pwr_bit);
    NRF_LOG_FLUSH();

    write_data = read_data | 1;
    writeRegister(0x4B, write_data);
    NRF_LOG_INFO("Set Power Control Register to %x", write_data & 0b1);
    NRF_LOG_FLUSH();

    read_data = readRegister(0x4B);
    pwr_bit = read_data & 0b1;
    NRF_LOG_INFO("Read Power Control = %x", pwr_bit);
    NRF_LOG_FLUSH();


    read_data = readRegister(0x4C);
    uint8_t opMode = (read_data | 0b110) >> 1;
    NRF_LOG_INFO("Read MODE = %x", opMode);
    NRF_LOG_FLUSH();

    write_data = read_data | 0b00000110;
    writeRegister(0x4b, write_data);
    NRF_LOG_INFO("Set Mode Register to: %x", (write_data & 0b110)>>1);
    NRF_LOG_FLUSH();

    read_data = readRegister(0x4C);
    opMode = (read_data | 0b110) >> 1;
    NRF_LOG_INFO("Read MODE = %x", opMode);
    NRF_LOG_FLUSH();

    nrf_delay_ms(5000);

    read_data = readRegister(0x4B);
    pwr_bit = read_data & 0b1;
    NRF_LOG_INFO("Read Power Control = %x", pwr_bit);
    NRF_LOG_FLUSH();

    read_data = readRegister(0x40);
    NRF_LOG_INFO("Chip ID = %x", read_data);
    NRF_LOG_FLUSH();

}



This is the Output:

I've already read a couple of posts where others also had trouble reading on the bus after something was written. However, I couldn't find a solution.

Maybe somethings wrong with my code. I hope you could help me.


Thank you.







Parents
  • Hi Jørgen, 

    thanks for your reply.

    I got the twi_init() function from an SDK example: 

    /* TWI instance ID. */
    #define TWI_INSTANCE_ID     0
    
    /* TWI instance. */
    static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
    
    
    /**
     * @brief TWI initialization.
     */
    void twi_init (void)
    {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_config = {
           .scl                = SCL0_PIN,
           .sda                = SDA0_PIN,
           .frequency          = NRF_DRV_TWI_FREQ_100K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = true
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_twi_enable(&m_twi);
    }

    I also added an APP_ERROR_CHECK() to the first TX Operation in readRegister. It also returns NRF_SUCCESS.

    The logic analyzer returned the expected result: The SDA line stays on low level when reading the register.

    I tried the same code with an arduino and there it works without any issues.

    Could it be possible that the nRF52 doesn't release the bus and that's why it stays on low level?

    Do I have to change some configurations maybe?

Reply
  • Hi Jørgen, 

    thanks for your reply.

    I got the twi_init() function from an SDK example: 

    /* TWI instance ID. */
    #define TWI_INSTANCE_ID     0
    
    /* TWI instance. */
    static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
    
    
    /**
     * @brief TWI initialization.
     */
    void twi_init (void)
    {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_config = {
           .scl                = SCL0_PIN,
           .sda                = SDA0_PIN,
           .frequency          = NRF_DRV_TWI_FREQ_100K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = true
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_twi_enable(&m_twi);
    }

    I also added an APP_ERROR_CHECK() to the first TX Operation in readRegister. It also returns NRF_SUCCESS.

    The logic analyzer returned the expected result: The SDA line stays on low level when reading the register.

    I tried the same code with an arduino and there it works without any issues.

    Could it be possible that the nRF52 doesn't release the bus and that's why it stays on low level?

    Do I have to change some configurations maybe?

Children
  • Which pins are you using for SCL0_PIN/SDA0_PIN?

    Have you tried with ".clear_bus_init     = false"? I do not think this should make any difference, but it is not set in the twi_sensor example.

    Look like you changed the no_stop parameter to nrf_drv_twi_tx() in readRegister() between your initial post and the post with the full main.c file. I'm quite sure that this should be set to true for a read operation on this sensor.

    CMan1 said:
    The logic analyzer returned the expected result: The SDA line stays on low level when reading the register.

    Can you still post the logic trace? It may help explain what is causing this by looking at the previous transfers.

Related