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

twi_sensor - override register value with TX and read it with RX - nrf52840 dk

Hello,

i have an issue with i2c on my nrf52840 dk. I attached the distance sensor vl53l1x to pin 27 (SCL) and 26 (SDA) and wanted to communicate via i2c with it. To test the connection, I planned to write to a register on the vl53l1x and read the value afterwards. Problem, no matter what I write via TX, I can't read the correct written value from the sensor register. It always reads a zero.

#include <stdio.h>
#include <string.h>
#include "boards.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "nrf_drv_twi.h"
#include "nrf_delay.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

/* TWI instance ID. */
#define TWI_INSTANCE_ID     0

#define VL53L1X_ADDR        0x29U //from scan

/* TWI instance. */
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);

uint8_t buffer = 8;


__STATIC_INLINE void data_handler(uint8_t newValue)
{
    NRF_LOG_INFO("New value: %d ", newValue);
}


void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
    NRF_LOG_INFO("handler!");
    switch (p_event->type)
    {
        case NRF_DRV_TWI_EVT_DONE:
            if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
            {
                data_handler(buffer);
            }
            break;
        default:
            break;
    }
}


void twi_init (void)
{
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_vl53l1x_config = {
       .scl                = ARDUINO_SCL_PIN,
       .sda                = ARDUINO_SDA_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_vl53l1x_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
}


void sensorInit(){

    uint8_t Addr = 0x30;

	uint8_t reg[2] = {Addr, 0x10};
	ret_code_t err_code;
	
	err_code = nrf_drv_twi_tx(&m_twi, VL53L1X_ADDR, &reg, sizeof(reg), false);
    APP_ERROR_CHECK(err_code);
}

void sensorRead(){

    uint8_t regAddr = 0x30;
	ret_code_t err_code;

    err_code = nrf_drv_twi_tx(&m_twi, VL53L1X_ADDR, regAddr, 1, false);
	
	err_code = nrf_drv_twi_rx(&m_twi, VL53L1X_ADDR, &buffer, sizeof(buffer));
	APP_ERROR_CHECK(err_code);
}


int main(void)
{
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("\r\nTWI sensor example started.");
    NRF_LOG_FLUSH();
    twi_init();  
    sensorInit();

    nrf_delay_ms(500);   

    while (true)
    {
        nrf_delay_ms(500);

        sensorRead();
     
        NRF_LOG_FLUSH();
        
    }
}

/** @} */

How I understand the i2c drv:

  1. I can send via tx an array like reg[2] = {Addr, value} with a new value to the sensor register. 
  2. If I want to read a register I need to point to it, by sending just the address via tx. Then read the sensor via rx and write the read value to a buffer.

Is this correct?

So it overrides the initialized value (8) of the buffer, therefore i think it is reading something but not the correct (written) value. I must have made a mistake somewhere?!

Ps: I use Linux, SDK17, nrf52840 DK, VL53L1X

Related