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

  • Are you using the BMD300 module? Have you tested if it works with the nRF52-DK?

  • Vishnu,

    I'm working on getting the nRF52 development board to read the mlx90615 sensor. I'm using P0.26 and P0.27. When I read the sensor RAM I get data for both Ta and To that indicates unrealitic temperature near1000C. The following is snippets from my code. Perhaps we can collaborate to overcome our issues.

        /**
     * @brief Function for handling data from temperature sensor.
     *
     * @param[in] temp          Temperature in Celsius degrees read from sensor.
     */
    
    /**
     * @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:  //< Transfer completed event.
                 mlx_xfer_done = true;
                 break;
    
            case NRF_DRV_TWI_EVT_ADDRESS_NACK:  //< Error event: NACK received after sending the address.
                 // handle addressing error code here
                 SEGGER_RTT_printf(0, "NACK received after sending the address \r\n");
                 break;
            
            case NRF_DRV_TWI_EVT_DATA_NACK:   //< Error event: NACK received after sending a data byte.
                 // handle addressing error code here
                 SEGGER_RTT_printf(0, "NACK received after sending a data byte \r\n");
                 break;
        }
    }
    
    
    /**
     * @brief TWI (SMBus) initialization.
     */
    void twi_init (void)
    {
        ret_code_t err_code;
      
        //Configure the I2C/SMBus to interface with the any slave device on the bus
        const nrf_drv_twi_config_t twi_mlx90615_config = {
           .scl                = SCL,
           .sda                = SDA,
           .frequency          = NRF_TWI_FREQ_100K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,  
         };
    
        //Initiate the TWI driver instance in Blocking mode (needs an event handler)     
        err_code = nrf_drv_twi_init(&mlx90615, &twi_mlx90615_config, twi_handler, NULL);
        APP_ERROR_CHECK(err_code);     
    
        //Enable the TWI driver instance
        nrf_drv_twi_enable(&mlx90615);
    }
    
    
    /**
     * @brief Function for reading data from temperature sensor.
     */
        float read_mlx90615_temp_data(const uint8_t commanded_reg )
    {
        ret_code_t err_code;
        uint8_t reg = commanded_reg;
        uint8_t templsb,tempmsb, pec;
        uint16_t tempraw;  
        float temperature;
    
        templsb=0;                                            //Clear variables 
        tempmsb=0;                                            //Clear variables 
        tempraw=0;                                            //Clear variables 
        pec = 0;                                              //Clear variables
        
        mlx_xfer_done = false;
      
        /* Writing to MLX90615 to select which register to read */
        err_code = nrf_drv_twi_tx(&mlx90615, MLX90615_ADDR, &reg, sizeof(reg), true);
        APP_ERROR_CHECK(err_code);
        while (mlx_xfer_done == false);
    
      
        mlx_xfer_done = false;
    
        /* Read LSB byte from the specified register from above */
        err_code = nrf_drv_twi_rx(&mlx90615, MLX90615_ADDR, &templsb, sizeof(templsb));
        APP_ERROR_CHECK(err_code);
        while (mlx_xfer_done == false);
        
        mlx_xfer_done = false;
    
        /* Read MSB byte from the specified register from above */
        err_code = nrf_drv_twi_rx(&mlx90615, MLX90615_ADDR, &tempmsb, sizeof(tempmsb));
        APP_ERROR_CHECK(err_code);
        while (mlx_xfer_done == false);
    
        mlx_xfer_done = false;
    
        /* Read Packet Error Code byte from the specified register from above */
        err_code = nrf_drv_twi_rx(&mlx90615, MLX90615_ADDR, &pec, sizeof(pec));
        APP_ERROR_CHECK(err_code);
        while (mlx_xfer_done == false);    
        
    
        tempraw = ((uint16_t)tempmsb << 8) | templsb;      // Make 16bit TempRAW from 2 8bit reads 
    
        temperature = ((tempraw * 0.02) - 273.15);
    
        return temperature;
    }
    
  • @joh2 : I changed the uart pins to some other pins in code and it works!!

    @cycledyne: Hi, try this code. I am posting the relevant sections only. Since the code doesn't fit in this comment section I am posting it as answer below.

  • This is the code which got working for MLX90615 sensor.

        typedef struct
    {
        uint8_t  x;
        uint8_t  y;
        uint8_t  z;
      //  uint8_t tilt;
    } sample_t;
    
    #define DEVICE_SCL_PIN 6
    #define DEVICE_SDA_PIN 7
    
    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          = NRF_TWI_FREQ_100K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH
        };
        
        err_code = nrf_drv_twi_init(&twi_instance, &twi_config, twi_handler, NULL);
        APP_ERROR_CHECK(err_code);
        
        nrf_drv_twi_enable(&twi_instance);
    }
    
    void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
    {   
    	static sample_t  m_sample;
    	uint8_t err_code,i;
        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);
                
    						if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TX)
                {
    							device_found = true;
                 m_xfer_done=false;
                    /* Read data from the specified address. */
                     nrf_drv_twi_rx(&twi_instance, 0x5B, (uint8_t*)&m_sample, sizeof(m_sample));
       
    							 
                }
    						else{
    			
    							obj_temp=receiveTemperature(&m_sample);
    							sprintf(Obj_temp,"%.2f",obj_temp);
    							m_xfer_done =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;        
        }   
    }
    
    int main(void)
    {
        uint32_t err_code;
        bool erase_bonds;
    		uint16_t length = 0;
        // Initialize.	
    		
        APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
        uart_init();
        
        buttons_leds_init(&erase_bonds);
        ble_stack_init();
        gap_params_init();
        services_init();
        advertising_init();
        conn_params_init();
    		
        printf("\r\nUART Start!\r\n");
        err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
        APP_ERROR_CHECK(err_code);
         twi_init();
    /////////////////////////////////////////////////////////////////////////////////////////////
    /// configure mlx90615
      //  uint8_t reg1[2] = {0x02, 0x01};
    
      //  nrf_drv_twi_tx(&twi_instance, 0x5B, reg1, sizeof(reg1), false); 
    /////////////////////////////////////////////////////////////////////////////////
        uint8_t dummy_data[] = {1};
    		uint8_t dummy_char =0x00;
    	uint8_t i=0;
        // Itterate through all possible 7-bit TWI addresses
    	//uint8_t err_code;
     uint8_t reg = 0;
    reg =0x27;   // FOR READING TEMPERATURE 0X27 AND 0X26 CAN BE USED Ta AND To
        // Enter main loop.
        for (;;)
        {	
    		m_xfer_done=false;	
    		
    		 err_code=nrf_drv_twi_tx(&twi_instance, 0x5B, &reg, sizeof(reg), true);   // sending register
    	//	printf("Error code=%d \r\n",err_code);
    		do{
    			__WFE();
    		}while(m_xfer_done==false);
    		if(m_xfer_done == true)
        {
           
    	   	err_code = ble_nus_string_send(&m_nus, Obj_temp, sizeof(Obj_temp));
    				nrf_delay_ms(1000);
    			
        }
    		
    		power_manage();
        }
    }
    
    float receiveTemperature(sample_t *p_new_sample) {
    		
    		uint8_t temp;
    
    		uint8_t dataLow = 0;                              // initially setting data low as zero
    	    uint8_t dataHigh = 0;                             // initially setting data high as zero
    
    		float celcius = 0.0;
    
    		// This combines high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps
    		double resolutionFactor = 0.02;                // resolution factor of the MLX90614
    		double temperature = 0x0000; 
    		int frac;                                      // data past the decimal point
    
    		dataHigh=p_new_sample->y;
    		dataLow=p_new_sample->x;
    		temperature = (double)(((dataHigh & 0x007F) << 8) | dataLow); // removes error bit of high byte by shifting and adds the low byte 
    		temperature= (temperature * resolutionFactor) ;//- 0.01;         // multiplying temperature value with resolutionFactor 
        celcius = (float)(temperature- 273.15);
    //	printf("Temp= %f \r\n",TemperatureFahrenheit(celcius));
    	
    		return celcius;                                               // return the value of temperature in celcius
    			
    	}
    
    float TemperatureFahrenheit(float celcius){                       // convert celcius into fahrenheit      
    		return (celcius*1.8) + 32;                                    // returns fahrenheit = (celcius*1.8) + 32;
    	}
    	
    
  • Thank you, I now see the error of my ways! The sensor readings are now realsitc!

Related