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

BMD300 I2C/TWI not working

Hi,

I am trying to communicate with MLX90615 (here) sensor using BMD300. nRF52 DK is used to program the device. I am testing with a sample code which detects any I2C compatible device which is connected to SDA and SCL. There is no activity happening on SCL and SDA pins! SCL pin is LOW and SDA pin remains HIGH. The main code is given below.

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

/*UART buffer size. */
#define UART_TX_BUF_SIZE 256
#define UART_RX_BUF_SIZE 1

#warning "!**** ARE YOU ABSOLUTELY SURE YOU HAVE CHOSEN THE CORRECT SCL AND SDA PINS? ****!"
#define DEVICE_SCL_PIN 6
#define DEVICE_SDA_PIN 7

nrf_drv_twi_t twi_instance = NRF_DRV_TWI_INSTANCE(0);

uint8_t device_address = 0; // Address used to temporarily store the current address being checked
bool device_found = false; 


/**
 * @brief UART events handler.
 */
static void uart_events_handler(app_uart_evt_t * p_event)
{
    switch (p_event->evt_type)
    {
        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        default:
            break;
    }
}


/**
 * @brief UART initialization.
 */
static void uart_config(void)
{
    uint32_t                     err_code;
    const app_uart_comm_params_t comm_params =
    {
        RX_PIN_NUMBER,
        TX_PIN_NUMBER,
        RTS_PIN_NUMBER,
        CTS_PIN_NUMBER,
        APP_UART_FLOW_CONTROL_DISABLED,
        false,
        UART_BAUDRATE_BAUDRATE_Baud38400
    };

    APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                       uart_events_handler,
                       APP_IRQ_PRIORITY_LOW,
                       err_code);

    APP_ERROR_CHECK(err_code);
}

/**
 * @brief TWI events handler.
 */
void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{   
    switch(p_event->type)
    {
        case NRF_DRV_TWI_EVT_DONE:
            // If EVT_DONE (event done) is received a device is found and responding on that particular address
     //       printf("\r\n!****************************!\r\nDevice found at 7-bit address: %#x!\r\n!****************************!\r\n\r\n", device_address);
            device_found = true;
            break;
        case NRF_DRV_TWI_EVT_ADDRESS_NACK:
      //      printf("No address ACK on address: %#x!\r\n", device_address);
            break;
        case NRF_DRV_TWI_EVT_DATA_NACK:
      //      printf("No data ACK on address: %#x!\r\n", device_address);
            break;
        default:
            break;        
    }   
}

/**
 * @brief UART initialization.
 */
void twi_init (void)
{
    ret_code_t err_code;
    
    const nrf_drv_twi_config_t twi_config = {
       .scl                = DEVICE_SCL_PIN,
       .sda                = DEVICE_SDA_PIN,
       .frequency          = TWI_FREQUENCY_FREQUENCY_K100,
       .interrupt_priority = TWI0_CONFIG_IRQ_PRIORITY
    };
    
    err_code = nrf_drv_twi_init(&twi_instance, &twi_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);
    
    nrf_drv_twi_enable(&twi_instance);
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    nrf_gpio_cfg_output(9);
    nrf_gpio_pin_set(9);
  //  uart_config();
  //  printf("\033[2J\033[;H\r\n* Example to find TWI devices connected to \r\n* the TWI bus and their addresses\r\n\r\n");
    twi_init();
    
    uint8_t dummy_data = 0x07;
    // Itterate through all possible 7-bit TWI addresses
    for(uint8_t i = 0; i <= 0x7F; i++)
    {
      //  device_address = i;
        // Send dummy data. If a device is present on this particular address a TWI EVT_DONE event is 
        // received in the twi event handler and a message is printed to UART
        nrf_drv_twi_tx(&twi_instance, 0x5B, &dummy_data, 1, true);
        // Delay 10 ms to allow TWI transfer to complete and UART to print messages before starting new transfer
        nrf_delay_ms(10);
    }
    if(device_found)
    {
        // Blinke LED_1 rapidly if device is found
      
        
            nrf_gpio_pin_toggle(9);
            nrf_delay_ms(100);
        
    }
    else
    {
        
    }
}

What are the basic settings for TWI ? Is the initialisation correct? What are the recommended troubleshooting methods? Does the SCL pin out anything even if MLX90615 not detected?

regards, Vishnu

  • Your code looks fine. As usual make sure that you have external pullup resistors attached and your I2C lines are high when idle. But most likely you've checked that already :)

    Be aware that some devices (like HTU21D, SI70XX temperature sensors) will send data NACK when you write something that doesn't look like a internal register address.

    Others (like most SMBus compatibles) will nack unless you exactly follow required sequence of operations (in case of SMBus TX-repeated start-TX-RX). There also poorly engineered ones that will lock up on writing non existing register address and power cycle is required to bring them back.

    So I'd record all TWI events on all addresses and carefully look trough all of them. Also reading 1 byte is more universal way of detecting devices as more will respond with ACK. Even then there's no warranty that your device will respond to anything but proper packet so I'd not give up unless there's no response on properly formatted read register command.

    I've also looked at the datasheet and noticed that this is a SMBus device. It's not guaranteed to work with TWI but still worth a shot. Just remember that SMBus responds only to valid frames and those are weird and vary a bit from device to device. So most likely there will be no response to I2C scanner. It might be easier to start by prototyping on a simpler platform like Arduino where you have complete synchronous control over what's happening in order to obtain at least on valid query/response packet.

  • OK. But the TWI lines remains high if I try to send some data without any sensor! That is what worrying me most. I simply loaded TWI_master_using_app_twi and I could see the clock and data lines are toggling (without connecting any sensor). Why is it so? Edit: Also the attached sensor requires minimum of 10KHz clock which is easily possible with nRF52.

  • so maybe you should try using TWI_master_using_app_twi or other twi example from the sdk as known good base for modifications. Depending on SDK version TWI instance has to be enabled and configured in either sdk_config.h (SDK12) or nrf_drv_config.h (previous versions).

  • Hi Keton, I am trying with the same and I am getting something. I hope it works.

  • Hi guys, I got it working. I could detect and collect data from the sensor. however if I change the pins to P0.6 an P0.7 it is not working. I have seen that those pins are configured for UART. But I commented Uart_config function and still TWI is not working!

Related