Nrf52840 one wire protocol usage with MAX17211 IC.

Hello Everyone,

                     I am trying to implement one wire protocol for interfacing MAX17211 fuel guage IC with NRF52840. I wand to know if there is any one wire library or any example which we can use to read the registers of MAX17211. Can we read the registers of MAX17211 directly from the data pin??Or we have to follow some particular signal pattern to read the data?

Thanks & Regards,

Snehal.

Parents
  • Hello,

    Looks like this Maxim IC also supports TWI (i2c), so is there any reason for selecting 1-wire over TWI in this case? With the 1-wire interface you would have to bit bang the protocol as explained in their app note here: https://www.maximintegrated.com/en/design/technical-documents/app-notes/1/126.html

    Best regards,

    Vidar

  • Hi Vidar,

               Actually the IC which we are using(MAX17211)  in our hardware supports only 1 wire. I asked the Maxim support team if we can communicate via I2c, so they replied that MAX17211 can be communicated using only One wire protocol. How can it be implemented in NRF52840 ??

    I saw the link which you had shared so driving the bus high and low and giving the reset pulse is possible with appropriate delays. That can be done. But if I want to read any register from the MAX17211, how to do that? How to sample the bus to read the data from a particular register?? 

    Also can I use this library "">github.com/.../Nordic-DS18B20" to read data from MAX17211?? will have to modify reg values?? Is it possible? 

    Regards,

    Snehal.

  • Hi Snehal,

    I don't see any problems with using nrf_delay_us() as long as you aren't using long delays.

    Regards,

    Vidar

  • Hi Vidar,

             yes you are right. we can use nrf_delay_us inside an rtos task. Thank you. I thought when rtos is used only vTaskDelay should be used for creating delays.I am going to test more with the IC max17211 today. will update you.

    Regards,

    Snehal

  • Hi Vidar,

               One more thing I wanted to ask is that on the same one wire line we have attached one more I2C based IC bq2429. so basically BQ2429 is I2c based and on the same line we have MAX17211 which is one wire based. So will it cause problems in getting data from the MAX17211?? 

    The pins used for BQ2429  are as follows:-

    #define PSF_SCL_PIN NRF_GPIO_PIN_MAP(1,9)
    #define PSF_SDA_PIN NRF_GPIO_PIN_MAP(0,11)

    The pins used for MAX17211 is as follows:-

    #define PSF_SDA_PIN NRF_GPIO_PIN_MAP(0,11)

    Thanks & Regards,

    Snehal.

  • Hi Snehal,

    I guess it may be ok to share it with the i2c clock line, but this is something you need to confirm yourself. Check the datasheets and see if you can use the same pullups, etc

  • Hi Vidar,

                 We have solved the issue with MAX17211, we tried to check the pulses but it seemed that there was some problem with the hardware. So the hardware guy has now replaced the ic from MAX17211 to MAX17201. This IC is pure I2C based and I am able to connect and read some data from the IC. When I read 8bit registers I dont have any issue. But when I am trying to read 16bit register from the IC, I am getting errors:-

    I have modified the code a bit in order to read 2bytes from register. I am not able to read 16bit registers. I tried to read NPACKCFG_REG but not able to read it properly.As well as while compiling I am getting warnings like this:-

    unsigned conversion from 'int' to 'uint8_t' {aka 'unsigned char'} changes value from '437' to '181' [-Woverflow]

    #define NPACKCFG_REG     0x1B5
    
    
    
    bool i2c_register_write_max17211(uint16_t register_address, uint16_t value)
    {
    
          ret_code_t err_code;
          uint8_t tx_data[4];
    
          tx_data[0] = ( (register_address >> 8)& 0xFF );
          tx_data[1] = register_address & 0xFF;
          tx_data[2] = ((value>>8)& 0xff);
          tx_data[3] = value & 0xFF;
    
          m_xfer_done = false;
        
          err_code = nrf_drv_twi_tx(&m_twi, MAX17211_WHO_AM_I, tx_data, sizeof(tx_data), false);
      //Wait until the transmission of the data is finished
        while (m_xfer_done == false)
        {
          }
    
       // if there is no error then return true else return false
        if (NRF_SUCCESS != err_code)
        {
            NRF_LOG_INFO("FAILED");
            return false;
        }
    
        NRF_LOG_INFO("SUCCESS");
    
        return true;	
    
    }
    
    bool i2c_register_read_max17211(uint8_t register_address, uint8_t destination[2], uint8_t number_of_bytes)
    {
        ret_code_t err_code;
        //uint8_t rx_buffer[2];
    
        //Set the flag to false to show the receiving is not yet completed
        m_xfer_done = false;
        
        // Send the Register address where we want to write the data
        err_code = nrf_drv_twi_tx(&m_twi, MAX17211_WHO_AM_I, &register_address, 1, true);
    	  
        //Wait for the transmission to get completed
        while (m_xfer_done == false){}
        //vTaskDelay(1000);
    
        // If transmission was not successful, exit the function with false as return value
        if (NRF_SUCCESS != err_code)
        {
            return false;
        }
    
        //set the flag again so that we can read data from the MPU6050's internal register
        m_xfer_done = false;
    	  
        // Receive the data from the MPU6050
        //err_code = nrf_drv_twi_rx(&m_twi, MAX17211_WHO_AM_I, destination, number_of_bytes);
        err_code = nrf_drv_twi_rx(&m_twi, MAX17211_WHO_AM_I, &destination[0], sizeof(destination));
    		
        //wait until the transmission is completed
        while (m_xfer_done == false){}
        //vTaskDelay(1000);
    
    
        // if data was successfully read, return true else return false
        if (NRF_SUCCESS != err_code)
        {
            return false;
        }
        
        //NRF_LOG_INFO("DATA IS %x",destination);
        return true;
    
    }

    Can you please help? Also Is my code proper for writing 16bit register?

Reply
  • Hi Vidar,

                 We have solved the issue with MAX17211, we tried to check the pulses but it seemed that there was some problem with the hardware. So the hardware guy has now replaced the ic from MAX17211 to MAX17201. This IC is pure I2C based and I am able to connect and read some data from the IC. When I read 8bit registers I dont have any issue. But when I am trying to read 16bit register from the IC, I am getting errors:-

    I have modified the code a bit in order to read 2bytes from register. I am not able to read 16bit registers. I tried to read NPACKCFG_REG but not able to read it properly.As well as while compiling I am getting warnings like this:-

    unsigned conversion from 'int' to 'uint8_t' {aka 'unsigned char'} changes value from '437' to '181' [-Woverflow]

    #define NPACKCFG_REG     0x1B5
    
    
    
    bool i2c_register_write_max17211(uint16_t register_address, uint16_t value)
    {
    
          ret_code_t err_code;
          uint8_t tx_data[4];
    
          tx_data[0] = ( (register_address >> 8)& 0xFF );
          tx_data[1] = register_address & 0xFF;
          tx_data[2] = ((value>>8)& 0xff);
          tx_data[3] = value & 0xFF;
    
          m_xfer_done = false;
        
          err_code = nrf_drv_twi_tx(&m_twi, MAX17211_WHO_AM_I, tx_data, sizeof(tx_data), false);
      //Wait until the transmission of the data is finished
        while (m_xfer_done == false)
        {
          }
    
       // if there is no error then return true else return false
        if (NRF_SUCCESS != err_code)
        {
            NRF_LOG_INFO("FAILED");
            return false;
        }
    
        NRF_LOG_INFO("SUCCESS");
    
        return true;	
    
    }
    
    bool i2c_register_read_max17211(uint8_t register_address, uint8_t destination[2], uint8_t number_of_bytes)
    {
        ret_code_t err_code;
        //uint8_t rx_buffer[2];
    
        //Set the flag to false to show the receiving is not yet completed
        m_xfer_done = false;
        
        // Send the Register address where we want to write the data
        err_code = nrf_drv_twi_tx(&m_twi, MAX17211_WHO_AM_I, &register_address, 1, true);
    	  
        //Wait for the transmission to get completed
        while (m_xfer_done == false){}
        //vTaskDelay(1000);
    
        // If transmission was not successful, exit the function with false as return value
        if (NRF_SUCCESS != err_code)
        {
            return false;
        }
    
        //set the flag again so that we can read data from the MPU6050's internal register
        m_xfer_done = false;
    	  
        // Receive the data from the MPU6050
        //err_code = nrf_drv_twi_rx(&m_twi, MAX17211_WHO_AM_I, destination, number_of_bytes);
        err_code = nrf_drv_twi_rx(&m_twi, MAX17211_WHO_AM_I, &destination[0], sizeof(destination));
    		
        //wait until the transmission is completed
        while (m_xfer_done == false){}
        //vTaskDelay(1000);
    
    
        // if data was successfully read, return true else return false
        if (NRF_SUCCESS != err_code)
        {
            return false;
        }
        
        //NRF_LOG_INFO("DATA IS %x",destination);
        return true;
    
    }

    Can you please help? Also Is my code proper for writing 16bit register?

Children
  • Hi,

    sne_333 said:
    I have modified the code a bit in order to read 2bytes from register. I am not able to read 16bit registers. I tried to read NPACKCFG_REG but not able to read it properly.

    What do you mean by not being able to read it properly? Are you getting the NRF_DRV_TWI_EVT_DONE event after you have called nrf_drv_twi_rx(), or are you getting a NRF_DRV_TWI_EVT_ADDRESS_NACK or NRF_DRV_TWI_EVT_DATA_NACK event?

    sne_333 said:
    unsigned conversion from 'int' to 'uint8_t' {aka 'unsigned char'} changes value from '437' to '181' [-Woverflow]

    Please show me where you are getting this warning.

  • I am getting warning as shown below:-

    #define NPACKCFG_REG     0x1B5

    when i try to read NPACKCFG_REG some conversion is happening.

    There are actually 2 slaves on the same i2c instance.

    I2c1_slave address = 0x6B

    I2c2_slave address = 0x6C

    I am able to communicate with slave 1 but when i try to communicate with slave 2 it gets hanged while sending data through nrf_drv_twi_tx in i2c_register_read_max17211 function.

    /*****************************************************************************
    * Copyright (c) [2021], Netobjex INC
    * All rights reserved.
    *
    * File:    task_psf_comm.c
    * Summary: PSF Control Task
    *
    */
    
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    
    #include "error_defs.h"
    
    #include "task_psf_comm.h"
    #include "FreeRTOS.h"
    #include "task.h"
    #include "semphr.h"
    #include "timers.h"
    
    #include "tasks.h"
    #include "boards.h"
    #include "nrf_gpio.h"
    #include "nrf_drv_gpiote.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "main.h"
    #include "task_led_button.h"
    
    #include "product_config.h"
    #include "nrf_drv_twi.h"
    #include "psf_i2c.h"
    #include "bq24292i.h"
    #include "max17211_i2c.h"
    
    
    /* I2C SLAVE 1*/
    #define BQ2429_ADDRESS_LEN  1         //BQ2429
    #define BQ2429_ADDRESS     (0xD6>>1)  //BQ2429 Device Address
    #define BQ2429_WHO_AM_I     0x6BU     //BQ2429 ID
    
    /* I2C SLAVE 2*/
    #define MAX17201_ADDRESS_LEN  1         
    #define MAX17201_ADDR     (0xD8>>1) //(0xD8>>1)  
    #define MAX17201_WHO_AM_I   0x6CU   
    
    #define TWI_INSTANCE_ID     0 //snehal
    
    
    
    
    /* TWI instance. */
    static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
    static volatile bool m_xfer_done = false;
    
    //Event Handler
    void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
    {
        //Check the event to see what type of event occurred
        switch (p_event->type)
        {
            //If data transmission or receiving is finished
    	case NRF_DRV_TWI_EVT_DONE:
            m_xfer_done = true;//Set the flag
            break;
            
            default:
            // do nothing
              break;
        }
    }
    
    void twi_init (void)
    {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_config = {
           .scl                = PSF_SCL_PIN,
           .sda                = PSF_SDA_PIN,
           .frequency          = NRF_DRV_TWI_FREQ_400K, 
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = false
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_config, twi_handler, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_twi_enable(&m_twi);
    }
    
    
    
    bool bq2429i_i2c_init(void)
    {
        ret_code_t err_code;
        uint8_t address = 0x6B;  
        uint8_t sample_data = 0x00;
    
        err_code = nrf_drv_twi_rx(&m_twi,address,&sample_data,sizeof(sample_data));
        if(err_code == NRF_SUCCESS)
        {
           NRF_LOG_INFO("SUCCESS");
           return true;
        }
        else
        {
           NRF_LOG_INFO("FAILED");
           return false;
        }
    
    }
    
    
    bool max17211_i2c_init(void)
    {
        ret_code_t err_code;
        uint8_t address = 0x6C;  
        uint8_t sample_data = 0x00;
    
        err_code = nrf_drv_twi_rx(&m_twi,address,&sample_data,sizeof(sample_data));
        if(err_code == NRF_SUCCESS)
        {
           NRF_LOG_INFO("SUCCESS");
           return true;
        }
        else
        {
           NRF_LOG_INFO("FAILED");
           return false;
        }
    
    }
    
    
    /*
      A Function to read data from the MPU6050
    */ 
    bool i2c_register_read(uint8_t register_address, uint8_t * destination, uint8_t number_of_bytes)
    {
        ret_code_t err_code;
    
        //Set the flag to false to show the receiving is not yet completed
        m_xfer_done = false;
        
        // Send the Register address where we want to write the data
        err_code = nrf_drv_twi_tx(&m_twi, BQ2429_ADDRESS, &register_address, 1, true);
    	  
        //Wait for the transmission to get completed
        while (m_xfer_done == false){}
        //vTaskDelay(1000);
    
        // If transmission was not successful, exit the function with false as return value
        if (NRF_SUCCESS != err_code)
        {
            return false;
        }
    
        //set the flag again so that we can read data from the MPU6050's internal register
        m_xfer_done = false;
    	  
        // Receive the data from the MPU6050
        err_code = nrf_drv_twi_rx(&m_twi, BQ2429_ADDRESS, destination, number_of_bytes);
    		
        //wait until the transmission is completed
        while (m_xfer_done == false){}
        //vTaskDelay(1000);
    
    	
        // if data was successfully read, return true else return false
        if (NRF_SUCCESS != err_code)
        {
            return false;
        }
        
        //NRF_LOG_INFO("DATA IS %x",destination);
        return true;
    }
    
    /*
       A function to write a Single Byte to MPU6050's internal Register
    */ 
    bool i2c_register_write(uint8_t register_address, uint8_t value)
    {
        ret_code_t err_code;
        uint8_t tx_buf[BQ2429_ADDRESS_LEN+1];
    	
        //Write the register address and data into transmit buffer
        tx_buf[0] = register_address;
        tx_buf[1] = value;
    
        //Set the flag to false to show the transmission is not yet completed
        m_xfer_done = false;
        
        //Transmit the data over TWI Bus
        err_code = nrf_drv_twi_tx(&m_twi, BQ2429_ADDRESS, tx_buf, BQ2429_ADDRESS_LEN+1, false);
        
        //Wait until the transmission of the data is finished
        while (m_xfer_done == false)
        {
          }
    
        // if there is no error then return true else return false
        if (NRF_SUCCESS != err_code)
        {
            NRF_LOG_INFO("FAILED");
            return false;
        }
    
       // NRF_LOG_INFO("SUCCESS");
    
        return true;	
    }
    
    
    bool i2c_register_write_max17211(uint16_t register_address, uint16_t value)
    {
    
          ret_code_t err_code;
          uint8_t tx_data[4];
    
          tx_data[0] = ( (register_address >> 8)& 0xFF );
          tx_data[1] = register_address & 0xFF;
          tx_data[2] = ((value>>8)& 0xff);
          tx_data[3] = value & 0xFF;
    
          m_xfer_done = false;
        
          err_code = nrf_drv_twi_tx(&m_twi, MAX17201_WHO_AM_I, tx_data, sizeof(tx_data), false);
      //Wait until the transmission of the data is finished
        while (m_xfer_done == false)
        {  }
        //vTaskDelay(1000);
    
       // if there is no error then return true else return false
        if (NRF_SUCCESS != err_code)
        {
            NRF_LOG_INFO("FAILED");
            return false;
        }
    
        NRF_LOG_INFO("SUCCESS");
    
        return true;	
    
    }
    
    bool i2c_register_read_max17211(uint8_t register_address, uint8_t destination[2], uint8_t number_of_bytes)
    {
       // uint8_t address = 0x6C;  
    
        ret_code_t err_code;
    
        //Set the flag to false to show the receiving is not yet completed
        m_xfer_done = false;
        
        // Send the Register address where we want to write the data
        err_code = nrf_drv_twi_tx(&m_twi, MAX17201_WHO_AM_I, &register_address, 1, true);
    	  
        //Wait for the transmission to get completed
        while (m_xfer_done == false){}
    
        // If transmission was not successful, exit the function with false as return value
        if (NRF_SUCCESS != err_code)
        {
            return false;
        }
    
        //set the flag again so that we can read data from the MPU6050's internal register
        m_xfer_done = false;
    	  
        // Receive the data from the MPU6050
        //err_code = nrf_drv_twi_rx(&m_twi, MAX17211_WHO_AM_I, destination, number_of_bytes);
        err_code = nrf_drv_twi_rx(&m_twi, MAX17201_WHO_AM_I, &destination[0], sizeof(destination));
    		
        //wait until the transmission is completed
        while (m_xfer_done == false){}
    
    
        // if data was successfully read, return true else return false
        if (NRF_SUCCESS != err_code)
        {
            return false;
        }
        
        //NRF_LOG_INFO("DATA IS %x",destination);
        return true;
    
    }
    
    

    With slave 1 i have no issues reading and writing the data.

    What might be the issue that I am not getting m_xfer_done= true after sending data to the 2nd slave?? 

  • Vidar Berg said:
    are you getting a NRF_DRV_TWI_EVT_ADDRESS_NACK or NRF_DRV_TWI_EVT_DATA_NACK event?

    You are only handling the NRF_DRV_TWI_EVT_DONE event in your twi_handler(), and ignoring NRF_DRV_TWI_EVT_ADDRESS_NACK and NRF_DRV_TWI_EVT_DATA_NACK. Please add these events to your handler and see if either of these are triggered.

    Your screenshot does not show the source file from where you are getting the "unsigned conversion from 'int' to 'uint8_t' {aka 'unsigned char'} changes value from '437' to '181' [-Woverflow]" warning from.

Related