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.

Compiler/BQ27441-G1: Default value of design capacity in BQ27441-G1B

Part Number: BQ27441-G1

Tool/software: TI C/C++ Compiler


Dear Forum, 

I am using a BQ27441 G1B, I have connected it to a microcontroller board (Tiva TM4C123G) using I2C. To initialize the BQ27441 we need to follow 14 steps indicated in the technical reference, sec - 3.1, pg 14, but, I'm still having trouble making these steps work. In step 8, I indicated the value of design capacity that we should expect for type G1B, but not for type G1A. In the code, we set this value to 0xAC to force the if operation, but during the code the read values do not match the one shown in the reference manual and so I can not read the main battery characteristics.

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "inc/hw_i2c.h"
#include "inc/uartstdio.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/i2c.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom_map.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/uart.h"

#define BQ27441_ADDR 0x55

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

#define I2C_MODE Master
#define I2C0SDA
#define I2C0SCL
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

void InitI2C0(void);
void UART_Init();
void I2CSendString(uint32_t slave_addr, char array[]);
uint32_t I2CReceive(uint32_t slave_addr, uint8_t reg);
void bq27441_init();

int main(void)
{

    SysCtlClockSet(
        SYSCTL_USE_PLL    // Use interpnal PLL (internal PLL will multiply frequency to reach 400 MHz according to datasheet)
      | SYSCTL_XTAL_16MHZ // Configure PLL to use a source frequency of 16 MHz
      | SYSCTL_SYSDIV_2_5 // Divide PLL output frequency by 5 to reach 80 MHz final frequency
      | SYSCTL_OSC_MAIN   // Tell microcontroller to use main (external) crystal oscillator
    );

    UART_Init();

    SysCtlDelay(20000000);


    while(1)
    {
        bq27441_init();

    }

}

//initialize I2C module 0
void InitI2C0(void){

    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);

    //reset module
    SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    // Configure the pin muxing for I2C0 functions on port B2 and B3.
    GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    GPIOPinConfigure(GPIO_PB3_I2C0SDA);

    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

   I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);

   
    HWREG(I2C0_BASE + I2C_O_FIFOCTL) = 80008000;
}

void UART_Init()
{
    //Baud Rate: 9600

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0);

    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_1);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0));

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0));

    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    UARTStdioConfig(0, 9600, SysCtlClockGet()/5);
}


void I2CSendString(uint32_t slave_addr, char array[])
{

    I2CMasterSlaveAddrSet(I2C0_BASE, slave_addr, false);
    I2CMasterDataPut(I2C0_BASE, array[0]);

    //0x81, apenas para finalizar o array
    if(array[1] == 0x81)
    {
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);

        while(I2CMasterBusy(I2C0_BASE));
    }
    else
    {
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);

        while(I2CMasterBusy(I2C0_BASE));

        uint8_t i = 1;

        while(array[i + 1] != 0x81)
        {
            I2CMasterDataPut(I2C0_BASE, array[i++]);

            I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);

            while(I2CMasterBusy(I2C0_BASE));

        }

        I2CMasterDataPut(I2C0_BASE, array[i]);

        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);

        while(I2CMasterBusy(I2C0_BASE));
    }
}

//read specified register on slave device
uint32_t I2CReceive(uint32_t slave_addr, uint8_t reg)
{
    //specify that we are writing (a register address) to the
    //slave device
    I2CMasterSlaveAddrSet(I2C0_BASE, slave_addr, false); 

    //specify register to be read
    I2CMasterDataPut(I2C0_BASE, reg); 

    //send control byte and register address byte to slave device
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START); 

    //wait for MCU to finish transaction
    while(I2CMasterBusy(I2C0_BASE));

    //specify that we are going to read from slave device
    I2CMasterSlaveAddrSet(I2C0_BASE, slave_addr, true); 

    //send control byte and read from the register we
    //specified
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE); 

    //wait for MCU to finish transaction
    while(I2CMasterBusy(I2C0_BASE));

    //return data pulled from the specified register
    return I2CMasterDataGet(I2C0_BASE); 
}

void bq27441_init()
{

    uint8_t flag_out[10], block_data_checksum_data[10], data[100], design_capacity_data[10];
    uint16_t design_capacity;

    float voltage = 0.0, remaining_batt_cap = 0.0, full_charge_cap = 0.0, soc = 0.0, temp = 0.0, current = 0.0;

    InitI2C0();

    char writeData[3] = {0x00, 0x04, 0x81};
    char unseal_data[4] = {0x00, 0x00, 0x80, 0x81};
    char cfgupdate_data[4] = {0x00, 0x13, 0x00, 0x81};
    char flag_data[2] = {0x06, 0x81};
    char block_data_control[3] = {0x61, 0x00, 0x81};
    char data_block_class[3] = {0x3E, 0x52, 0x81};
    char data_block[3] = {0x3F, 0x00, 0x81};
    char block_data_checksum[2] = {0x60, 0x81};
    char design_capacity_loc[2] = { 0x4A,/*  0x4B,*/ 0x81};
    char soft_reset[4] = {0x00, 0x42, 0x00, 0x81};
    char seal_data[3] = {0x00, 0x20, 0x00, 0x81};

    //Step 1
    I2CSendString(BQ27441_ADDR, unseal_data);
    I2CSendString(BQ27441_ADDR, unseal_data);
    SysCtlDelay(133333);
    UARTprintf("The gauge seems to be unsealed. \n");

    //Step 2
    I2CSendString(BQ27441_ADDR, cfgupdate_data);
    SysCtlDelay(133333);

    //Step 3
    flag_out[0] = I2CReceive(BQ27441_ADDR, flag_data[0]);
    UARTprintf("The _out is: %x \n", flag_out[0]);  

    if (CHECK_BIT(flag_out[0], 4)) {
        UARTprintf("The gauge is ready to be configured \n");

        //Step 4
        I2CSendString(BQ27441_ADDR, block_data_control);
        SysCtlDelay(133333);

        //Step 5
        I2CSendString(BQ27441_ADDR, data_block_class);
        SysCtlDelay(133333);

        //Step 6
        I2CSendString(BQ27441_ADDR, data_block);
        SysCtlDelay(133333);

       //Step 7
        block_data_checksum_data[0] = I2CReceive(BQ27441_ADDR, block_data_checksum[0]);
        UARTprintf("The checksum_data: %x \n", block_data_checksum_data[0]);

        if (block_data_checksum_data[0] == 0xAC) {

            UARTprintf("The checksum is as expected. Config will proceed. \n");

            //Step 8
            design_capacity_data[0] = I2CReceive(BQ27441_ADDR, design_capacity_loc[0]);
            UARTprintf("The design capacity data is: %d mAh \n", design_capacity_data[0]);

            /*
            design_capacity = design_capacity_data[0]*16*16 + design_capacity_data[1]; //two values?
            SysCtlDelay(133333);
            UARTprintf("The current design capacity is: %d mAh \n", design_capacity);
            */

            //Step 12
            I2CSendString(BQ27441_ADDR, soft_reset);
            SysCtlDelay(1000);


            //Step 13
            flag_out[0] = I2CReceive(BQ27441_ADDR, flag_data[0]);
            UARTprintf("The _out is: %x \n", flag_out[0]);

            //Step 14
            if(!CHECK_BIT(flag_out[0], 4)) {
                UARTprintf("CFGUPDTE has been exited, configuration done. \n");
                I2CSendString(BQ27441_ADDR, seal_data);
                SysCtlDelay(5);
                UARTprintf("Gauge has been sealed and is ready for operation \n");
            }
        }
    }

    
    while(true){

        int t;
        for (t=0;t<100;t++){

            //Leitura dos registros do dispositivo
            I2CSendString(BQ27441_ADDR, writeData);
            I2CReceive(BQ27441_ADDR, data[t]);
        }
    }

    voltage = data[4]*16*16 + data[3];
    remaining_batt_cap = data[12]*16*16 + data[11];
    full_charge_cap = data[14]*16*16 + data[13];
    soc = (remaining_batt_cap/full_charge_cap)*100;
    temp = (data[2]*16*16 + data[1])/10.0 - 273.0;
    current = data[16]*16*16 + data[15];


    UARTprintf("Voltage: %d  mV\n", voltage);
    UARTprintf("Current: %f  mA\n", current);
    UARTprintf("Remaining Battery Capacity: %f  mAh\n", remaining_batt_cap);
    UARTprintf("Full Charge Capacity: %f mAh\n", full_charge_cap);
    UARTprintf("State of Charge: %f p.c. \n", soc);
    UARTprintf("Temperature: %f  Deg C\n", temp);   

}