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

TWI Fails to receive/send

Hello,

I've connected an ADXL345 accelerometer sensor via I2C to nrf52 board. I connected SDA > SDA, SCL > SCL, GND > GND and VCC > VDD (3.3V). Here's my code:

    twi_init();
	
	do {
		err_code = nrf_drv_twi_rx(&m_twi, 0x53, &sample_data, sizeof(sample_data));
		
		if (err_code != NRF_SUCCESS)
		{
				SEGGER_RTT_printf(0, "Fail!!");
		}
	} while (err_code != NRF_SUCCESS);
	
	if (err_code == NRF_SUCCESS)
	{
			SEGGER_RTT_printf(0, "Data successfully received from I2C!!");
	}

twi_init() and all other necessary code is from TWI Scanner example. Here's the output:

Fail!!Fail!!Fail!!Fail!!Fail!!Fail!!Fail!!Fail!!Fail!!Fail!!Fail!!Fail!!Fail!!Fail!!Fail!!Data successfully received from I2C!!

Sometimes it prints "Fail" only two times. I tried to connect VCC to 5V (since this ADXL345 board has an on-board power regulator) and things are a little bit better. Now it only fails once:

Fail!!Data successfully received from I2C!!

Do you have any idea what could be the problem? Maybe I'm missing some pull-up resistors? Or some configuration? Here's my init function:

  /* 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                = ARDUINO_SCL_PIN,
        .sda                = ARDUINO_SDA_PIN,
        .frequency          = NRF_TWI_FREQ_100K,
        .interrupt_priority = APP_IRQ_PRIORITY_HIGH
     };
 
     err_code = nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL);
     APP_ERROR_CHECK(err_code);

     nrf_drv_twi_enable(&m_twi);
 }

And here's my nrf_drv_config.h:

#define TWI0_ENABLED 1

#if (TWI0_ENABLED == 1)
#define TWI0_USE_EASY_DMA 0

#define TWI0_CONFIG_FREQUENCY    NRF_TWI_FREQ_100K
#define TWI0_CONFIG_SCL          0
#define TWI0_CONFIG_SDA          1
#define TWI0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW

#define TWI0_INSTANCE_INDEX      0
#endif

#define TWI1_ENABLED 0

#if (TWI1_ENABLED == 1)
#define TWI1_USE_EASY_DMA 0

#define TWI1_CONFIG_FREQUENCY    NRF_TWI_FREQ_100K
#define TWI1_CONFIG_SCL          0
#define TWI1_CONFIG_SDA          1
#define TWI1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW

#define TWI1_INSTANCE_INDEX      (TWI0_ENABLED)
#endif

#define TWI_COUNT                (TWI0_ENABLED + TWI1_ENABLED)

/* TWIS */
#define TWIS0_ENABLED 0

#if (TWIS0_ENABLED == 1)
		#define TWIS0_CONFIG_ADDR0        0
		#define TWIS0_CONFIG_ADDR1        0 /* 0: Disabled */
		#define TWIS0_CONFIG_SCL          0
		#define TWIS0_CONFIG_SDA          1
		#define TWIS0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW

		#define TWIS0_INSTANCE_INDEX      0
#endif

#define TWIS1_ENABLED 0

#if (TWIS1_ENABLED ==  1)
		#define TWIS1_CONFIG_ADDR0        0
		#define TWIS1_CONFIG_ADDR1        0 /* 0: Disabled */
		#define TWIS1_CONFIG_SCL          0
		#define TWIS1_CONFIG_SDA          1
		#define TWIS1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW

		#define TWIS1_INSTANCE_INDEX      (TWIS0_ENABLED)
#endif

#define TWIS_COUNT (TWIS0_ENABLED + TWIS1_ENABLED)
/* For more documentation see nrf_drv_twis.h file */
#define TWIS_ASSUME_INIT_AFTER_RESET_ONLY 0
/* For more documentation see nrf_drv_twis.h file */
#define TWIS_NO_SYNC_MODE 0

Thank you!

EDIT:

I'm sorry, I'm not really an expert with low level programming and I2C, I'm used to Arduino and object-oriented libraries for sensors :)

Now I wrote this code:

            uint8_t address = 0x53;
	uint8_t sample_data;
            uint8_t reg_addr = BW_RATE;
	
	twi_init();
	
	SEGGER_RTT_printf(0, "Sending register address 0x%02x to read from .... ", reg_addr);
	err_code = nrf_drv_twi_tx(&m_twi, address, &reg_addr, 1, true);
	
	if (err_code == NRF_SUCCESS)
	{
			SEGGER_RTT_printf(0, "SUCCESS!\n");
	}
	else {
			SEGGER_RTT_printf(0, "FAIL! Error code: %d\n", err_code);
	}
	
	SEGGER_RTT_printf(0, "Reading from I2C .... ", reg_addr);
	err_code = nrf_drv_twi_rx(&m_twi, address, &sample_data, sizeof(sample_data));
		
	if (err_code == NRF_SUCCESS)
	{
		SEGGER_RTT_printf(0, "SUCCESS! Data: 0x%02x\n", sample_data);
	}
	else {
			SEGGER_RTT_printf(0, "FAIL! Error code: %d\n", err_code);
	}
	
	SEGGER_RTT_printf(0, "Sending data 0x%xx to register 0x%02x .... ", reg_addr, 0x0A);
	uint8_t tx_data[2] = {BW_RATE,0x0A};		
	err_code = nrf_drv_twi_tx(&m_twi, 0x53, tx_data, sizeof(tx_data), true);
				
	if (err_code == NRF_SUCCESS)
	{
			SEGGER_RTT_printf(0, "SUCCESS!\n");
	}
	else {
			SEGGER_RTT_printf(0, "FAIL! Error code: %d\n", err_code);
	}
	
	SEGGER_RTT_printf(0, "Sending register address 0x%02x to read from .... ", reg_addr);
	err_code = nrf_drv_twi_tx(&m_twi, address, &reg_addr, 1, true);
	
	if (err_code == NRF_SUCCESS)
	{
			SEGGER_RTT_printf(0, "SUCCESS!\n");
	}
	else {
			SEGGER_RTT_printf(0, "FAIL! Error code: %d\n", err_code);
	}
	
	SEGGER_RTT_printf(0, "Reading from I2C .... ", reg_addr);
	err_code = nrf_drv_twi_rx(&m_twi, address, &sample_data, sizeof(sample_data));
		
	if (err_code == NRF_SUCCESS)
	{
		SEGGER_RTT_printf(0, "SUCCESS! Data: 0x%02x\n", sample_data);
	}
	else {
			SEGGER_RTT_printf(0, "FAIL! Error code: %d\n", err_code);
	}

And the result is this:

0> Sending register address 0x2C to read from .... FAIL! Error code: 3
0> Reading from I2C .... SUCCESS! Data: 0xE5
0> Sending data 0x0A to register 0x2C .... SUCCESS!
0> Sending register address 0x2C to read from .... SUCCESS!
0> Reading from I2C .... SUCCESS! Data: 0x0A

As you can see, it fails again at the first TX command. It works fine afterwards, though. And also it seems that the value has been correctly read at the first time, so seems that this first TX actually has passed through to sensor (the sensor knows which register to return value for), but for some reason, it returns error code 3.

Thank you!

Related