This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

BQ27427: Reading the remaining capacity

Part Number: BQ27427
Other Parts Discussed in Thread: BQSTUDIO,

Hi all,

We have selected this part for the one of our applications.

And we are using this rechargeable battery https://thinkrobotics.com/products/16340-battery-3-7v-1300mah?variant=39334535266390

And i have initializing the fuel gauge with following configuration.

1. chemical ID : 0x1202 (4.2V)

2. Design capacity (700mAh)

3. Design Energy (2.59 Wh)

And I am continuously reading the remaining capacity for every ten seconds.

Issues:

1. I am getting constant remaining capacity value even when I applied some load. But after the power on reset I am getting reduced capacity value.

Eg: I am getting 615 mAh value continuously even when I applied some load. But after the power on reset, the remaining capacity value reduced to 600 mAh.

 

2. When charging this battery, remaining capacity value getting reduced. But after the power on reset, the remaining capacity value increased.

Eg: when charging this battery, remaining capacity value getting reduced from 615 mAh. But after the power on reset, the remaining capacity value increased to 630 mAh.

Please provide the suggestion.

Regards,

Aslam

  • Hello Aslam, 

    Can you please provide me with the log file and gg file obtained by bqStudio for this behavior? Additionally, have you completed a learning cycle? 

    Regards, 

    Jonny. 

  • Hi Jhonny,

    I am not using bqStudio to configure the values. I am directly giving I2C commands from the controller. Please find the code snippets below:

    void change_chemistry_profile(uint16_t chem_id )
    {
    //unseal the fuel gauge
    gauge_cmd_write(CTRL, UNSEAL_KEY);
    gauge_cmd_write(CTRL, UNSEAL_KEY);
    
    gauge_cfg_update();
    gauge_cmd_write(CTRL,chem_id);
    gauge_exit();
    
    gauge_cmd_write(CTRL, SEAL_KEY);
    
    }
    
    int change_battery_parameters(void)
    {
    uint8_t pData[DC_STATE_LENGTH]; //DC_STATE_LENGTH = 32
    int ret=1;
    //unseal the fuel gauge
    gauge_cmd_write(CTRL, UNSEAL_KEY);
    gauge_cmd_write(CTRL, UNSEAL_KEY);
    
    ret = gauge_read_data_class(DC_STATE, pData, DC_STATE_LENGTH);
    
    pData[6] = (DESIGN_CAPACITY & 0xFF00) >>8;
    pData[7] = DESIGN_CAPACITY & 0xFF;
    pData[8] = (DESIGN_ENERGY & 0xFF00) >>8;
    pData[9] = DESIGN_ENERGY & 0xFF;
    
    gauge_cfg_update(); // required for ROM gauge
    ret = gauge_write_data_class(DC_STATE, pData, DC_STATE_LENGTH);
    gauge_exit(); // required for ROM gauge
    
    // gauge_read_data_class(DC_STATE, pData, DC_STATE_LENGTH);
    
    //seal the fuel gauge
    gauge_cmd_write(CTRL, SEAL_KEY);
    
    return ret;
    }
    
    int gauge_read_data_class(uint8_t nDataClass, uint8_t *pData, uint8_t nLength)
    {
        uint8_t nRemainder = nLength;
        uint16_t nOffset = 0;
        uint8_t nDataBlock = 0x00;
        uint16_t nData;
    
        if (nLength < 1)
            return -1;
    
        do
        {
            nLength = nRemainder;
            if (nLength > 32)
            {
                nRemainder = nLength - 32;
                nLength = 32;
            }
            else nRemainder = 0;
    
            nData = (nDataBlock << 8) | nDataClass;
            gauge_cmd_write(CMD_DATA_CLASS, nData);
    
            //if (hal_i2c_gauge_read(CMD_BLOCK_DATA, pData, nLength) != nLength) return -1;
            hal_i2c_gauge_read(CMD_BLOCK_DATA, pData, nLength);
            pData += nLength;
            nDataBlock++;
        } while (nRemainder > 0);
    
        return 0;
    }
    
    //check_sum: calculate check sum for block transfer
    //pData: pointer to data block
    //nLength: length of data block
    uint8_t check_sum(uint8_t *pData, uint8_t nLength)
    {
        uint8_t nSum = 0x00;
        uint8_t n;
        for (n = 0; n < nLength; n++)
            nSum += pData[n];
        nSum = 0xFF - nSum;
        return nSum;
    }
    
    //gauge_write_data_class: write a data class
    //pHandle: handle to communications adapter
    //nDataClass: data class number
    //pData: buffer holding the whole data class (all blocks)
    //nLength: length of data class (all blocks)
    //return value: 0 = success
    int gauge_write_data_class(uint8_t nDataClass, uint8_t *pData,uint8_t nLength)
    {
        uint8_t nRemainder = nLength;
        uint16_t nOffset = 0;
        uint8_t pCheckSum[2] = {0x00, 0x00};
        uint16_t nData;
        uint8_t nDataBlock = 0x00;
        uint8_t temp_buff[8] = {0};
    
        if (nLength < 1)
            return 0;
    
        do
        {
            nLength = nRemainder;
            if (nLength < 32)
            {
                nRemainder = nLength - 32;
                nLength = 32;
            }
            else nRemainder = 0;
    
           // gauge_cmd_write(0x61, 0x00);  //enable block data memory
            temp_buff[0] = 0x00;
            hal_i2c_gauge_write(0x61,temp_buff,1);
    
           // nData = (nDataBlock << 8) | nDataClass;
            //gauge_cmd_write(CMD_DATA_CLASS, nData); //DataBlockClass() command
            temp_buff[0] = 0x52;
            hal_i2c_gauge_write(CMD_DATA_CLASS,temp_buff,1);
    
            //gauge_cmd_write(0x3F, 0x00);  //block offset location
            temp_buff[0] = 0x00;
            hal_i2c_gauge_write(0x3F,temp_buff,1);
    
           // if (gauge_write(pHandle, CMD_BLOCK_DATA, pData, nLength) != nLength)
             //   return -1;
    
            hal_i2c_gauge_write(CMD_BLOCK_DATA, pData, nLength);
    
            pCheckSum[0] = check_sum(pData, nLength);
            hal_i2c_gauge_write(CMD_CHECK_SUM, pCheckSum, 1);
            usleep(10000);
    
           // gauge_cmd_write(CMD_DATA_CLASS, nData);
            temp_buff[0] = 0x52;
            hal_i2c_gauge_write(CMD_DATA_CLASS,temp_buff,1);
    
            hal_i2c_gauge_read(CMD_CHECK_SUM, pCheckSum + 1, 1);
    
            if (pCheckSum[0] != pCheckSum[1])
                return -2;
            pData += nLength;
            nDataBlock++;
        } while (nRemainder > 0);
    
        return 0;
    }
    
    #define MAX_ATTEMPTS 5
    bool gauge_cfg_update(void)
    {
        uint16_t nFlags;
        int nAttempts = 0;
        gauge_control(SET_CFGUPDATE);
    
        do
        {
            nFlags = gauge_cmd_read(CMD_FLAGS);
            if (!(nFlags & CFGUPD)) usleep(500000);
        } while (!(nFlags & CFGUPD) && (nAttempts++ < MAX_ATTEMPTS));
    
        return (nAttempts < MAX_ATTEMPTS);
    }
    
    //gauge_exit: exit configuration update mode for rom gauges
    //pHandle: handle to communications adapter
    //nSubCmd: sub command to exit configuration update mode
    //return value: true = success, false = failure
    bool gauge_exit(void)
    {
        uint16_t nFlags;
        int nAttempts = 0;
    
        gauge_control(SOFT_RESET);
        do
        {
            nFlags = gauge_cmd_read(CMD_FLAGS);
            if (nFlags & CFGUPD) usleep(500000);
        } while ((nFlags & CFGUPD) && (nAttempts++ <MAX_ATTEMPTS));
    
        return (nAttempts < MAX_ATTEMPTS);
    }

    If I re-initialize the fuel gauge before every read, the value is coming as expected.

  • Hello Aslam, 

    I suspect the issue is with the configuration. When the gauge is POR, the gauge defaults to its default parameters, not the parameters you have programmed into the gauge. In order to be able to further debug this, I will need your configuration. 

    Regards, 

    Jonny. 

  • Hi Jhonny,

    During the POR, the gauge defaults to its default parameters. Thats happening correctly. And my configuration values also updating properly. Below are my configuration values:

    1. chemical ID : 0x1202 (4.2V)

    2. Design capacity (700mAh)

    3. Design Energy (2.59 Wh)

    The issue is that I have to give SOFT_RESET command to the gauge before any read (like SOC, remaining capacity etc), then only I am getting proper values. 

    If I am not giving SOFT_RESET command to the gauge before any read, I am not getting proper values.

    Is this expected behavior of this fuel gauge.

  • Hello, 

    After configuring the gauge, the SOFT_RESET subcommand is used to exit the CONFIG UPDATE mode to resume normal gauging. In order to be able to fully debug this, I will need the full gauge configuration, similar to that from the gg file. Additionally, how was the chemID matched? Typically we recommend using the GPCCHEM tool to ensure that the cell you are using is a good match with one of the three chemIDs to choose from in the bq27427. 

    Regards, 

    Jonny. 

  • Hi Jonny,

    I have only changed three configuration values of the fuel gauge, other values are same as default configuration parameter. And we have chosen this chemical ID based on battery datasheet.

     Below are the changed configuration values:

    1. chemical ID : 0x1202 (4.2V)

    2. Design capacity (700mAh)

    3. Design Energy (2.59 Wh)

    Is any other critical battery parameter there?

    I just need to read the SOC of the battery. No other functionalities are not needed for us now.

    And we have very less time for this task. 

    Currently, I need to give SOFT_RESET command to the gauge before any read (like SOC, remaining capacity etc), then only I am getting proper values. 

    Regards,

    Aslam

  • Hello Aslam, 

    At a minimum, the first parameters you need to set are listed below: 

    • Design Capacity
    • Charge Term Taper Current
    • Dsg Current Threshold
    • Chg Current Threshold
    • Quit Current 
    • Term Voltage

    Additionally, you will need to successfully perform a learning cycle, please see the Achieving The Successful Learning Cycle document for the steps to do this. You need to do this, and ensure that you have a good match for the ChemID before you can refer to the accuracy of the gauge.  

    Regards, 

    Jonny.